window.parent.postMessage to #Listener - stenciljs

We have a requirement that we load a separate page as a modal (yay, right?)
The embedded page uses window.parent.postMessage(messageString, '*') to signal actions have been completed.
I want to use stenciljs's #Listener
I have a working modal with an iframe to the other page, using the old school window.addEventListener('message', myMessageHandlingDelegate).
however, I really would like to use the #Listener attribute/decorator to handle the result of the posted message. I tried #Listener('message') but the code was not added....
is there away to get a stenciljs listener to catch messages posted from child Iframes?

The #Listen decorator is used to add listener to JavaScript custom events (https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent) or to events emitted by a Stencil child component. That means that you can't use Message API (using window.postMessage or listening to the message event) with that decorator. You can still use the addEventListener to the message event like you indicated in the question.

I used the following code in the stenciljs custom component to get this working:
#Listen('message', { target: 'window' })
handleMessage(ec) {
console.log("Event from iFrame triggered");
}

Related

Trigger polling using htmx.trigger

I'm trying to trigger a polling behavior on a div using JavaScript.
This is the div.
<div id="myId" hx-get="https://xxxx" hx-swap="innerHTML"></div>
This is the trigger function.
htmx.trigger(
htmx.find(`#myId`),
"every 300ms"
);
But it's not working. Is there a way to obtain this behavior?
You can have your JavaScript set up the polling interval. Then you can trigger a custom event and have your div listen for it.
To have the server stop the client polling, put a different custom event in the Response Headers and listen for it on the client. Included is how you would add the response header if your server was ASP.NET, since I'm not sure what you are running server-side. Also innerHTML is the default hx-swap target, so could be omitted.
HTMX:
<div id="myId" hx-get="https://xxxx" hx-trigger="myEvent"></div>
JS:
// start polling
function startpolling(){
var myPoller= setInterval(function () { htmx.trigger("myId","myEvent"); }, 300);
}
// stop polling
document.body.addEventListener("stopPolling", function(evt){
clearInterval(myPoller);
})
ASP.NET Server code:
HttpContext.Response.Headers.Add("HX-Trigger", "stopPolling");

window.addEventListener('load', (event) => {...}); on NuxtLink (nuxt-link) or RouterLink (router-link) click

I am going to use the simplest example to explain what I mean.
window.addEventListener('load', (event) => {
console.log('page is fully loaded');
});
When the page loads for the first time the client side console logs 'page is fully loaded'. But when I click on a NuxtLink or RouterLink, I don't get a repeated log entry for the new page load.
If I use a standard link, then the console logs 'page is fully loaded' on page I visit, as it should. But it doesn't have the nice speedy page load as NuxtLink or RouterLink accomplishes.
In Rails, it has a similar feature called Turbolinks, but you can use .on('page:load',... to grab each page load.
Does anyone know how to fire the window-load per page load?
The <nuxt-link> component is similar to the <router-link> component.
In HTML5 history mode, router-link will intercept the click event so that the browser doesn't try to reload the page. This means that onload will only be triggered when the app is first loaded.
If you need to refresh and load the page every time you link to a new route, you can do this:
window.location.href = 'your link'
By linking to the page in this way, you can find from the network panel in the browser console that every time you load a page of type text/html from the server.

How to call setAllowUniversalAccessFromFileURLs from WebSettings in nativescript?

In Android native development, to allow XMLHttpRequests in some scenarios when we need to request javascript files from an webview, one way to do that is setting setAllowUniversalAccessFromFileURLs(true) on WebSettings instance (on API Level 17+).
Is there a way to do that on nativescript?
The error displayed is:
XMLHttpRequest cannot load file:///data/data/.... Cross origin
requests are only supported for protocol schemes: http, data, https.",
source:
file:///data/data/com.yourdomain.appname/files/app/app/frameworks/nativescript.framework/app/components/login/
Just quickly looking at the Android docs you could get the WebSettings for the webview with: https://developer.android.com/reference/android/webkit/WebView.html#getSettings()
So in the loaded event for your webview instance, attach an event handler and in that JS code do something like this:
function webViewLoaded(args) {
if (args.object.android) {
var webView = args.object.android;
webView.getSettings().setAllowUniversalAccessFromFileURLs(true);
}
}

UIWebView and unload event

I'm loading local html contents into a UIWebView.
The javascript code of the loaded contents includes this event listener:
window.addEventListener("unload", function(){
// do something here;
});
That javascript code it is only executed when (before) the UIWebView component is released (e.g. when navigating back to another view controller) but it is not executed when another page is loaded. For example:
document.addEventListener("click", function(){ document.location = "www.google.com"; });
window.addEventListener("unload", function(){ alert("bye bye"); });
If executing this piece of code in safari, when I click on the document, before navigating to google.com, it would display the alert box. If I run the same code in UIWebView, the unload listener it is not executed. However, If I delete the UIWebView, the code is then executed.
My need is to have the same as in Safari, that is the unload method to be executed also when navigating away from the page.
I too have had problems in the past with JavaScript code that doesn't behave the same way in a desktop browser than in a UIWebView. I honestly don't know why it isn't working the way you want it to, but here I offer you a work around:
Instead of using the unload listener you have in JavaScript, try using UIWebViewDelegate's method webView:shouldStartLoadWithRequest:navigationType:. This method gets called whenever the user requests to load a new page (or content).
If you then need to execute more JavaScript code you could use UIWebView's method stringByEvaluatingJavaScriptFromString:.
Hope this helps!
Thanks to LuisCien solution above (please vote his post if you like the solution), I managed to solve the issue by manually generating and dispatching the unload event from objective-c side. This does not require any modification on my client side code (javascript) that now behaves the same in UIWebView and any other web browser. Here is the piece of code to add to your view controller:
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType
{
[webView stringByEvaluatingJavaScriptFromString:#"var e=document.createEvent('Event'); e.initEvent('unload', true, true); window.dispatchEvent(e);"];
return YES;
}

How to use jQuery's .on with Rails ajax link?

I'm having a bunch of problems getting jQuery's .on to work with my Rails ajax link.
Specifically, I've got this link:
<div id="item_7_tools" class="item_tools">
<a rel="nofollow" id="book_item_7" data-remote="true" data-method="post" class="book_link" href="bookings">Book this item</a>
</div>
I've trimmed some of the text in the HTML, but suffice to say that that, and my controller response work.
I click "Book this item", it goes off to the controller, the controller does its magic, and sends back my partial that replaces the contents of that div.
So I'm now trying to replace the contents with an ajax spinner while the loading is working, and that's where its going pear-shape.
I'm trying this initial bunch of jQuery code just to make sure I've got my javascript working:
$('div.item_tools')
.on('click', 'a', function() {
console.log("clicky click")
})
.on('ajax:beforeSend', "a", function() {
console.log('the a in div.item_tools is sending its ajax command');
})
.on('ajax:complete', "a", function() {
console.log('ajax request completed');
})
My understanding of that, is that when I then click any link (a) that lives within an element with the item_tools class, it will bubble up to this function, and then log the message into the console. Similarly, a link that has triggered an ajax request will get the same treatment...
(And assuming I can get that to work, then I'll go to work doing the ajax loader spinner).
The behaviour I'm seeing instead, is that when I click the link, there are no messages appearing in my console (trying this on both firefox and chrome), and my ajax link goes off and does its stuff correctly. Just completely ignoring the javascript...
Is this because my clicking the ajax link somehow has blocked the click event from bubbling up? I know that there's a way to do that, but I don't think I've done it anywhere knowingly. Unless OOTB rails/ujs does that?
So my questions:
Is there a way to tell what has had a binding attached to it?
What am I doing wrong with my javascript?
Thanks!
I use this all the time... and it seems to work fine.
Have you tried adding one that's .on('ajax:success')?
Besides that try putting the . for each line on the previous line...? It's possible that it gets to $('div.item_tools') and then auto-inserts a semi-colon as per javascript's standard... Although if that were the case I'd expect it to give you a JS error about the . on the next line. In any case try changing it to:
$('div.item_tools').
on('click', 'a', function() {
console.log("clicky click")
}).
on('ajax:beforeSend', "a", function() {
console.log('the a in div.item_tools is sending its ajax command');
}).
on('ajax:complete', "a", function() {
console.log('ajax request completed');
})
If worse comes to worse try just doing:
$("a").on("ajax:success", function(){
console.log('ajax:success done');
})
And see if it works without the event delegation...
Then change it to this:
$(document).on("ajax:success", "a", function(){
console.log("ajax:success with delegation to document");
})
And see if delegation works all the way up to document instead of just your item_tools
Are you sure that you've named everything right? it's div.item_tools a in your markup?
Turns out that the javascript was being triggered before the DOM had loaded, which meant that stuff weren't being bound...
$(function () {
$('div.item_tools')
.on('click', 'a', function itemToolsAjaxy() {
console.log("clicky click");
})
.on('ajax:beforeSend', "a", function() {
console.log('the a in div.item_tools is sending its ajax command');
$(this).closest('div').html('<img src=/assets/ajax-loader.gif>');
})
});
Added the $(function()) right at the beginning and it delayed the binding until after the DOM had loaded, and then it started working.
Figured this out by using the Chrome developer tools to stick a break on the div.item_tools selector and watched as the browser hit that even before the DOM had been loaded. /facepalm
(I removed the .on('ajax:complete') callback, because it turns out that there's a known limitation where the original trigger element no longer exists because it had been replaced, so there's nothing to perform the callback on. Not relevant to my original problem, but I thought I'd mention it.)
As far as i'm aware, you can either do ajax stuff 2 ways:
By using :remote => true
By using jQuery's $.ajax (or $.post).
With number 2, make sure to change your href='#'
My suggeston is to remove the :remote => true and manually make a jQuery ajax call. That way you can use beforeSend, complete, etc.
If i'm way off track here, someone please help clarify things for me as well.