history.pushState does not trigger 'popstate' event - html

Why
window.addEventListener('popstate', () => alert('pop'));
window.history.pushState(null, '', '/foo');
does not alert pop ?
NB: Testing on latest chrome
--
According to MDN:
A popstate event is dispatched to the window every time the active history entry changes. If the history entry being activated was created by a call to pushState or affected by a call to replaceState, the popstate event's state property contains a copy of the history entry's state object.
So why my pushState does not trigger the popstate event?

You can manually trigger popstate event on window every time you call history.pushState().
history.pushState(state, '', url);
var popStateEvent = new PopStateEvent('popstate', { state: state });
dispatchEvent(popStateEvent);

The paragraph you reference is a little ambiguous. Reading the example on the same page, it is clear that popstate is only triggered when the user clicks the back button, not when the script calls pushState().

You are reading MDN's "guide page" which is not meant to be normative.
Consider reading MDN's "documentation page" for WindowEventHandlers.onpopstate instead:
Note that just calling history.pushState() or history.replaceState() won't trigger a popstate event. The popstate event is only triggered by doing a browser action such as a clicking on the back button (or calling history.back() in JavaScript). And the event is only triggered when the user navigates between two history entries for the same document.
Another undocumented way of triggering popstate is by direct manipulation of the window.location object.
// this also triggers popstate
window.location.hash = "#some-new-hash"

My solution:
var url = "http://awesome.website.net/route/to/paradise";
window.history.pushState({}, "", url);
window.history.pushState({}, "", url); // yes twice
window.history.back();
It will trigger a soft-navigation via 'popstate' event and no HTTP request.

Document https://developer.mozilla.org/en-US/docs/Web/Events/popstate says:
Note that just calling history.pushState() or history.replaceState() won't trigger a popstate event. The popstate event will been triggered by doing a browser action such as a click on the back or forward button (or calling history.back() or history.forward() in JavaScript).

I ran into this too... I think the event only fires if you have something at the top level of your data object that is distinct from the previous state.
Try this:
var data = {rand: Math.random()};
window.history.pushState(data, '', '/foo');

Related

Cannot add event listener for "EVENT_EDITMODE_CREATION_END" in MarkupsCore extension

I tried to add event listener for event "EVENT_EDITMODE_CREATION_END" in MarkupsCore extension:
markupsExtension.addEventListener('EVENT_EDITMODE_CREATION_END', () => {console.log('Test');});
But the event hander has never been executed when adding/editing markups in the viewer.
I know "EVENT_EDITMODE_CREATION_END" is not listed in the forge official documentation
https://forge.autodesk.com/en/docs/viewer/v2/reference/javascript/markupscore/
Can anyone please help? Thanks.
This is because the EVENT_EDITMODE_CREATION_END event is dispatched on the specific "edit mode" object, not on the markups extension object. In order to get notified of the event, you would have to subscribe to the event on the markupsExt.editMode object whenever the mode changes, for example, like so:
markupsExt.editMode.addEventListener('EVENT_EDITMODE_CREATION_END', function (ev) { console.log('Markup creation ended!'); });

Chrome 56 mobile addEventListener "click" not working

I encounter a problem where click event on Link Element (A tag), or any other DOM Element, is not calling handler/callback function.
it doesn't matter which parent in the hierarchy I am getting it not getting this event.
no Event.stopImmediatePropagation or Event.stopPropagation exist.
the reason why is Chrome 56, they change some of the events and stop transforming Mouse Events to Touch Events.
see here: https://developers.google.com/web/updates/2016/12/chrome-56-deprecations#mouse_on_android_stops_firing_touchevents
to solve the issue just use touchstart event for mobile where you used click before. or if you need only one click you can do:
Element.addEventListener("click", callback);
Element.addEventListener("touchstart", callback);
function callback(event) {
Element.removeEventListener("click", callback);
Element.removeEventListener("touchstart", callback);
// do something
}
now, to have a simulate click you need to check 300ms pass between "touchstart" and "touchend". if it less you have a click.
Note: the "click" event occur after "touchstart"

How to detect menu button press in TVOS app using TVJS

I need to know when a document(screen) is popped off the stack in an Apple tvOS app. I thought detecting the Menu button press would be the simplest way, but I'm using TVJS and have not been able to figure out how to write the event handler.
Please help me write an event handler that will fire on document removal, menu button press or offer an alternative solution.
Subscribe to the event unload - it's triggered whenever a page disappears after being popped from the stack:
doc.addEventListener("unload", Presenter.onUnload.bind(Presenter));
[...]
onUnload: function(event) {
console.log("onUnload");
},
There is such thing of a handler for onDocumentRemoval or similar. What you can do, instead, is create a global select handler:
doc.addEventListener("select", self.doThing.bind(self));
And then check if the fired event comes from one of the buttons used to remove an element of the stack (let's suppose those buttons have a class named delete:
doThing: function(event){
var element = event.target;
if (element.getAttribute("class").contains("delete")){
//enter code here
}
EDIT 1:
I found the possible events the TVMLKit handles (I know it is in Swift/Objective-C, but the events are the same):
TVElementTypePlay
A play event has been dispatched.
TVElementTypeSelect
A select event has been dispatched.
TVElementTypeHoldSelect
A hold event has been dispatched.
TVElementTypeHighlight
A highlight event has been dispatched.
TVElementTypeChange
A change event has been dispatched.
Those events are only attachable to a template as far as I could test. I guessed the change event would be perfect if I could attach it to the navigationDocument to listen for changes, but those two options won't work and both fire errors:
Attached to the global:
navigationDocument.addEventListener("change", function(event){console.log(event)});
Attached to the documents array:
navigationDocument.documents.addEventListener("change", function(event){console.log(event)});
There is no built-in method for those above to listen for any change. The event, though, will work on a template listening to internal changes. But it won't fire when the template is pushed to or popped from the stack.
I am guessing you will need to re-design your app in order to achieve what you are looking for.

Is it Possible to invoke keyboard Function keys using Chrome Extensions

I am working on Chrome Extensions. I want to know that is it Possible to invoke keyboard Function keys using Chrome Extensions.
Thanks,
NVN.
EDIT: Do you want to simulate function key presses on a page or listen for physical key presses from the user? If you want want to procedurally trigger function key actions, you can't. As Rob pointed out, scripted events only activate scripted event listeners, and do not trigger default behavior.
In order to detect function key presses, you need to bind your events to keyup -- not to keypress, which doesn't fire for several non-printable keystrokes, like function keys and arrow keys.
document.documentElement.addEventListener("keyup", function(e) {
if(e.keyCode == 113) {
// if F2 is pressed...
// F1 is keycode 112, and it increments from there
}
});
Some function keys do things already (F1 opens help, F5 refreshes, etc.). If you have a good reason for preventing this behavior (e.g. you're making an immersive full-screen app like a VNC viewer that shouldn't exhibit normal browser behavior), you can use preventDefault on keydown to stop that potentially disruptive action:
document.documentElement.addEventListener("keydown", function(e) {
if(e.keyCode == 112) {
// if F1 is pressed, don't open help
e.preventDefault();
}
});
To see how to handle key presses for your Chrome extension, see my answer on Activate extension via short cut key; that should be exactly what you need for the rest. Briefly:
the code I gave above goes in a content script that gets added to each page
the event handlers functions perform some action, either within the content script on the page or by passing a message to the background page

How to hook a keyboard event handler onto an INPUT element with jQuery?

I want to attach my own key event handler to an INPUT that already has another event handler attached to onkeydown. Essentially, I want to receive a key event before all the other handlers and check if the user pressed a certain key -- if yes, I want to perform some functions and discard the event, if no, I want to pass it along to the other handler(s).
How can I do this with jQuery?
If you are loading a 3rd party script or jQuery addon you can just load your script or function first. If you do that then you can use something like this without the mess of unbinding and rebinding event handlers.
// your possible interceptor code
$("#awesome").keydown(function(e) {
if (e.keyCode < 70) {
e.stopImmediatePropagation();
console.log("BLOCKED!!!");
};
});
// possible 3rd party event code loaded after your code
$("#awesome").keydown(function(e) {
console.log("3rd party:"+e.keyCode);
});
Example webpage => http://mikegrace.s3.amazonaws.com/forums/stack-overflow/example-key-event-interception.html
Example output of Firebug console
jQuery stopImmediatePropagation() documentation
According to the jQuery bind() documentation:
"When an event reaches an element, all handlers bound to that event type for the element are fired. If there are multiple handlers registered, they will always execute in the order in which they were bound."
So it looks like you will have to unbind the other handlers, bind yours and then add the others back if you want yours to run first.
There is some good information in this thread with respect to that:
jQuery: Unbind event handlers to bind them again later