How to watch for changes in window.location with Dart? - dart

I would like to watch for changes in window.location with Dart but haven't found how to do it. Is there an event I can use or some other way to do it?

I'm guessing you want when the hash changes, because if window.location is changed it loads a new page. Try this:
import "dart:html";
window.onHashChange.listen((HashChangeEvent e) {
//Do stuff
});
window.onPopState.listen((PopStateEvent e) {
//Do stuff
});
PopStateEvent API: http://api.dartlang.org/docs/releases/latest/dart_html/PopStateEvent.html
A popstate event is dispatched to the window every time the active history entry changes between two history entries for the same document. If the history entry being activated was created by a call to history.pushState() or was affected by a call to history.replaceState(), the popstate event's state property contains a copy of the history entry's state object.
https://developer.mozilla.org/en-US/docs/Web/API/Window.onpopstate

Related

Have Stimulus wait for Dom changes using MutationObserver custom event listener before continuing

I am writing a Stimulus controller that has a function which needs wot wait for DOM changes before it can continue (As a Turbo Stream response needs to update a frame). Before the DOM change, it can't find the target, but it should be able to AFTER the DOM change.
I have successfully enabled MutationObserver, which is able to tell me that the child element was added--but this happens after the function/action is looking for it.
Therefore I found this article on how to use Mutation Observer to add a custom Event Listener.
I've gotten it to work as far as until the last step, where we code the Promise.
When I run the code, I get
undefined is not an object (evaluating "el.innerText.includes(text)
I tried changing it to
document.getElementByTagName(el).innerText.includes(text)
But that returned that it's not a function.
The instantiation of the MutationObserver is inside my connect() method:
connect() {
const observer = new MutationObserver( list => {
const evt = new CustomEvent('dom-changed', {detail: list});
document.body.dispatchEvent(evt)
});
observer.observe(document.body, {attributes: true, childList: true, subtree: true});
}
the waitforText(el, text, maxWait=5000) function is a controller action currently.
I then run this.waitForText("h1", "Settings for") inside the function I need it to wait. I'm merely using a h1 for testing before I put it on an element that is within the same frame as that h1.

Knowing when KML file has loaded and features added (OpenLayers3)?

I see that ol.source.KML (untick "Stable only") fires the events addfeature,
change and removefeature. However, I just need to know when the KML was retrieved over the network and all its features added. Is there an event like "loaded" or similar in OpenLayers 3?
I need to execute some code when the KML has been added. Waiting for document.ready is not enough as the KML file is loaded (over network) afterwards.
Listen to change event, check if the source state is ready, then do what you want, not forgetting to deregister your listener.
var key = source.on('change', function() {
if (source.getState() == 'ready') {
source.unByKey(key);
// do something with the source
}
});

How do you return a Future based off a Stream you don't control in Dart?

I have a situation where I'm expecting a single value from a Stream, but because it's one provided by the browser I can't rely on simply calling streamSub.single. Currently, I'm creating an explicit StreamController so that I can easily generate a Future from it while guaranteeing that it will only get a single response. However, that ends up being a lot more overhead than I was expecting to have to set up, making me think I'm missing something. The current code follows:
StreamController<String> streamCtrlr = new StreamController<String>();
var popup = window.open(targetUrl, "Auth Window");
//The popup above will call window.opener.postMessage, so listen for messages
StreamSubscription sub = window.onMessage.listen(null);
sub.onData((Event){
/* Logic goes here */
sub.cancel();
popup.close();
streamCtrlr.add(Event.data);
streamCtrlr.close();
});
return streamCtrlr.stream.single;
How can this be re-written so that the intermediary StreamController isn't required?
Why can't you rely on calling streamSub.single? Is it because there might be more than one message?
Your example code picks the first event in all cases, so to get the same behavior, you can use window.onMessage.first instead of window.onMessage.single.
It will still cause an error if there is no first event (but I don't think that can happen with DOM event handlers - they never send a done event), and otherwise it will give a future that is completed with the first event.
You also want to extract the event data, so you will probably want:
return window.onMessage.first.then((event) {
/* Logic goes here */
popup.close();
return event.data;
});

When I add a stream subscription on a DOM element, and then remove the element later, will dart:html take care of the subscription, too?

Often, I create an element from which I need to listen to (Mouse)Events. Then, later, I don't need the button anymore, so I remove it. Like this:
var button = new ButtonElement()
..onClick.listen((_) => print("Clicked!"));
// ... somewhere else in the code or in the callback above
button.remove();
Should I also take care of the onClick subscription (to prevent memory leaks) or is that handled for me?
I suspect this will not be done automatically by removing the element from the DOM, as you might re-insert it at another point. The source code for remove() is fairly simple:
Node remove() {
// TODO(jmesserly): is parent == null an error?
if (parentNode != null) {
parentNode.nodes.remove(this);
}
return this;
}
However, if there are no other references to the object and the Element class gets cleaned up by the garbage collector, then I expect the subscriptions will go with it (though I don't know enough to know how to confirm this from the source!).

JQuery passing arguments for On Change for an item added to DOM via AJAX

I have multiple HTML fragments that are inserted into my DOM as the result of AJAX call-backs.
Each of these fragments will contain a text box whose class is "quantity".
What I want to do is to create an "on change" event handler that fires whenever one of these textbox's text value is changed. However, when that event is fired/handled, I need to know WHICH specific textbox was updated.
Okay, using jQuery, I have the following that fires in my "Lists.initHandlers" method:
$(document).on('change', $('#divABC').find(".quantity"), List.quantityChanged);
And my "List.quantityChanged" event handler happily fires when I update the quanity.
The problem is that when I reference "this" within the event handler, I get the whole document, and not the element that triggered the event.
I have tried to capture the element using syntax similar to:
$(document).on('change', $('#divABC').find(".quantity"), {ctrl: this}, List.quantityChanged);
but when I attempt this, the handler is never fired (even when I change the signature to expect an argument).
Any guidance here would be most appreciated.
Thanks
Griff
Try this:
$('.quantity').live('change', function(){
alert('New value: ' + $(this).val());
});
Pass this to your function:
$(document).on('change', $('#divABC').find(".quantity"), function () {
List.quantityChanged(this);
});

Resources