Reading window.history.state object in Webkit - javascript

Safari and Chrome (and, I'm guessing, all Webkit browsers) do not respond to window.history.state which is specified in the evolving HTML5 standard here and is implemented in Firefox.
Is there a workaround to read it? Perhaps it is possible to trigger a popstate event in code and return the state from the event handler?

I ran into this issue yesterday. I didn't need a cross browser solution since the target platform is running an oldish version of WebKit, so I created a quick and simple polyfill for history.state in WebKit:
// Polyfill for history.state in older webkit engines
if (!history.hasOwnProperty('state')) {
(function (push, rep) {
// history.state is always initialised to null
history.state = null;
history.pushState = function (state) {
push.apply(history, arguments);
history.state = state;
};
history.replaceState = function (state) {
rep.apply(history, arguments);
history.state = state;
};
window.addEventListener('popstate', function (e) {
history.state = e.state;
}, true);
})(history.pushState, history.replaceState);
}

window.history.state is not implemented in webkit broswers currently. There is a request for it, but no steps towards implementation were done so far.
There is a project called history.js which is aiming to provide cross-compatible history management experience.
History.js gracefully supports the HTML5 History/State APIs (pushState, replaceState, onPopState) in all browsers. Including continued support for data, titles, replaceState. Supports jQuery, MooTools and Prototype. For HTML5 browsers this means that you can modify the URL directly, without needing to use hashes anymore. For HTML4 browsers it will revert back to using the old onhashchange functionality.
From that project, History.getState() seems to do what is requested.

Related

Are there any browser provided APIs to capture a screenshot of the dom of a page directly?

I do not find any APIs to directly support the dom capture.
But the html2canvas and kendo.drawing.drawDom libraries take a lot of resources which potentially impacts the performance of my application.
I am not able to run these in the Worker since the dom is needed for these libraries to work but Worker does not share the dom.
Since most browsers show the thumbnails view for recently visited pages(Firefox has the screenshot utility too) can we use this support?
My requirement is to capture the dom of a page opened ( in the background , otherwise it will impact app performane) when a user navigates to a page. I would not have control over the browser(it can be any browser) or the amount of time user going to stay on the page (the page may be hidden state [display: none or visibility: hidden]). I am using Jquery-3.1.1 and Kendo.Ui.
There is (to my knowledge) no official API to use the browsers' ScreenShot features.
Libraries that do parse and redraw the whole DOM are still the only cross-browser way to do it.
The nearest API is the being defined MediaCapture one.
Currently, only Firefox gives us access to something similar, through the MediaDevices.getUserMedia API, and chrome allows privileged code (extensions) to use an other implementation.
So for Firefox, you can already do something like
async function takeScreenshot() {
const stream = await navigator.mediaDevices.getUserMedia(
{
video: {
mediaSource: 'window'
}
}
);
const vid = document.createElement('video');
vid.srcObject = stream;
await vid.play();
const canvas = document.createElement('canvas');
canvas.width = vid.videoWidth;
canvas.height = vid.videoHeight;
canvas.getContext('2d').drawImage(vid, 0,0);
stream.getTracks().forEach(t=>t.stop());
return new Promise((res, rej) => {
canvas.toBlob(res);
});
}
Fiddle since I guess it won't work in over-protected StackSnippet®.
Ok, since I do not have 50 reputation to comment the answer.. this is just an extension of #Kaiido's answer.
If you want to make the fiddle work in Chrome, just change getUserMedia() for getDisplayMedia() on the second line of code (it will still work on Firefox).
Personally, I think getDisplayMedia() is probably more appropriate to use in this case, getDisplayMedia vs getUserMedia.

What is the correct way to handle native cancelling of getUserMedia screenshare?

I am using screenshare with getUserMedia for a web application I am developing.
I am currently using Chrome with a Chrome extension using the API below to achieve the functionality, but the functionality is also possible in Firefox and may become natively available(I believe it was possible in the past) via getDisplayMedia or other means in the future.
https://developer.chrome.com/extensions/desktopCapture
During screenshare, a native dialog is shown at the bottom of the browser to stop the screenshare. I would like for a way to handle this event, but I am unaware of a common, standard way to achieve this. Is there an appropriate way to do this(preferably in all APIs), or should I achieve this by track events?
I am not quite sure as to how Chrome unspecified implementation behaves, but yes, you would normally have to listen to your VideoTrack's onended event.
This snippet should work only in FF, which are the only one allowing non-chrome pages to access this feature.
navigator.mediaDevices.getUserMedia({video: {mediaSource: 'screen'}}).then(stream => {
document.getElementById('vid').srcObject = stream;
const v_track = stream.getVideoTracks()[0];
v_track.onended = e => console.log('stopped');
}).catch(console.error);
<video id="vid" autoplay></video>
And in case it doesn't even work (because of StackSnippets© heavy security rules), here is a fiddle.

How to make a cross-browser on-window-unload request?

I have a Flash game that I'm trying to save the state of when the user closes the browser tab. It is using the following jquery code:
//Called from Flash when window closes
function sendRequest(url, params) {
$.ajax({
type: "POST",
async: false,
url: url,
data: params
})
}
$(window).unload(function() {
//Make Flash attempt to save the game when the window closes.
//Flash gets the necessary data and calls sendRequest()
document["flashGame"].saveBeforeUnload();
});
Firefox: Works correctly
Chrome: Works correctly when reloading but not when closing tabs or closing the browser
IE (all versions): Does not work at all
I want it to work in all browsers correctly, but most important is Chrome (not many of our users have IE).
Flash is correctly calling sendRequest (in all browsers, tested with an alert), so I don't believe the problems come from Flash, but it might.
The short answer is that you can't.
The onbeforeunload event was initially introduced by Microsoft to allow a standard confirmation dialog. It is now supported in the original form by most browsers and in most case a short, non interactive, function is allowed to execute (for example you may log your state in the localStorage). But, as described in the cross-browser jQuery API, this is unreliable :
The exact handling of the unload event has varied from version to
version of browsers. For example, some versions of Firefox trigger the
event when a link is followed, but not when the window is closed. In
practical usage, behavior should be tested on all supported browsers,
and contrasted with the proprietary beforeunload event.
As there are many potential security problems related to the execution of a task when the user asked to end the page (and thus the script), this will probably be unreliable until (and if) a serious normalization effort is done to precise what exactly can be done in a onbeforeunload callback.
For the predictable future, it's recommended to not depend on onbeforeunload but to use other schemes, for example constant background saving or a big "save" button.
Try window.onbeforeunload. I found this in the jQueryBug Tracker as a possible solution:
window.onbeforeunload = function() { return "text"; }

Detecting browsers that don't support onunload/onbeforeunload

Of all the browsers, it seems that only Opera doesn't support onunload/onbeforeunload events. (It's been fifteen years now, Opera!) Solutions for this issue have been covered many times, here for example: onbeforeunload support detection
Unfortunately, as of Opera 11.51, ("onbeforeunload" in window) == true, but the actual onbeforeunload event is never executed!
My web application needs to send data to server when a user leaves the page; I'm using a synchronous ajax request for this. It looks like I have to resort to using a "Save" button somewhere on the page to cover up for Opera issues. However, I don't want this button to confuse users whose browsers are capable of auto-saving through ajax, so I'd really like the button to only show up in Opera.
Is my only choice browser-detection? The problem is, Opera has an option to disguise itself as other browsers anyway.
I can't reproduce your finding that 'onbeforeunload' in window is true in Opera 11.5x. This is the best way to do it and should still work. Are you sure you haven't left in some definition somewhere, e.g. you've written
onbeforeunload = function (){ ... }
later in the same script that does the feature detection? If you do alert(window.onbeforeunload), what do you see? Could you share a link to the page with the problem?
Opera screwed the pooch on this one. I detect for Opera by looking for window.opera and if it exists, I deny Opera what it can't handle.
Using unload is no good I think, because it occurs too late in the game. Sometimes onbeforeunload is the only thing that'll do the trick. Once again, I just look for opera on the window object, and, if it exists, deny it the things it can't do. :)
PPK talks about it here: http://www.quirksmode.org/js/detect.html
For anyone stumbling across this post, this is a code snippet I use for detecting onbeforeunload support and if the browser doesn't support it I switch to onunload (note the use of jquery, obviously not required). In my case I use this code (and a little extra) to check if any AJAX requests are still active and stop the user navigating away. Keep in mind that using onunload isn't ideal because the browser will still navigate away from the page but at least it gives you a chance to warn the user that data might have been lost and they should go back and check.
You'll notice I'm using the isEventSupported() function available at https://github.com/kangax/iseventsupported for cross browser support detecting available events.
// If the browser supports 'onbeforeunload'
if (isEventSupported('beforeunload', window)) {
$(window).on('beforeunload', function(){
return 'This page is still sending or receiving data from our server, if you recently submitted data on this page please wait a little longer before leaving.';
});
}
// The browser doesn't support 'onbeforeunload' (Such as Opera), do the next best thing 'onunload'.
else {
$(window).on('unload', function(){
alert('This page was still sending or receiving data from our server when you navigated away from it, we would recommend navigating back to the page and ensure your data was submitted.');
});
}
See my answer to a similar / duplicated question. Basically, it sets up detection on the very first page on your domain and stores that detection result for all subsequent pages in localStorage. Including working example code.

Overriding history.pushState leads to error in opera 11

I'm injecting the following code into a webpage via a greasemonkey script/opera extension to trap the history.pushState command, so I can do some processing whenever it's fired and still allow the pushState command to continue afterwards.
(function(history){
var pushState = history.pushState;
history.pushState = function(state) {
if (typeof history.onpushstate == "function") {
history.onpushstate({state: state});
}
alert('pushstate called')
return pushState.apply(history, arguments);
}
})(window.history);
the code works fine in FF4 and Chrome, but in Opera 11, I get the following error, if the page calls a history.replaceState command:
Uncaught exception: TypeError: 'window.history.replaceState' is not a function
Does anyone know how I can fix the above code to work with Opera as well as Chrome and Firefox?
In Opera 11.00, Revision 1156, the history API supported are these
>>> history.
back, current, forward, go, length, navigationMode
The full HTML5 history API is not yet covered by Opera 11.00. In general if you would like to discover, explore what is supported, you can easily use the console mode of dragonfly, the Web developer tool.
According to When can I use … Opera doesn't support the History API yet, so that's why you get that exception.
I figured out the solution, just check for history.replacestate before executing the above code, if it doesn't exist, don't execute the code, simple.

Categories

Resources