Check browser compatibility for HTML5 History API support? - javascript

Is there any way to check a browser whether it supports 'HTML5 History API' using JavaScript.
Do I have to check all the browsers and its versions with a long list of condition in if statement.
Or simply like checking any object of function using 'if' statement is enough???...

Checking for the existence of a pushState() method on the global history object should be sufficient.
function supports_history_api() {
return !!(window.history && history.pushState);
}
For more general HTML 5 feature detection I'd look at Modernizer
http://diveintohtml5.info/detect.html#modernizr
This will insulate your code from the messy specifics of each test, making the code more readable and less error prone. With the Modernizer script on your page you'd just do:
if (Modernizr.history) {
// history management works!
} else {
// no history support :(
// fall back to a scripted solution like History.js
}

Checking for history.pushState and history.replaceState objects existence should be sufficient, as it's generally sufficient with feature detection in general.

You can use canisuse.js script to detect if your browsers supports history or not
caniuse.history()

You can check weather or not a function is registered:
if (typeof history.pushState != 'undefined') {
//Enabled
}
Then just replace //Enabled with whatever you wish to do if it's supported.

Related

Javascript, detect touch devices

I'm using this function to detect if the device is a touch device:
function is_touch_device()
{
return !!('ontouchstart' in window) || !!('onmsgesturechange' in window);
};
Got this function from here: What's the best way to detect a 'touch screen' device using JavaScript?
But since Chrome 25 (25.0.1364) it returns true on my desktop which isn't a touch device.
Also I've updated IE9 to IE10 and it returns true in IE!
Searched around but couldn't find anything useful to fix this except using a something like this: http://detectmobilebrowsers.com/
What do you recommend?
I'm looking forward to your responses!
The code works just fine, the browser is able to understand touch events, just because your screen isn't touchable doesn't mean that the browser doesn't support the functionality. What you are looking to test is a hardware capability which isn't really testable. You can always use different ways though of seeing if the user is actual using a touch interface after touching it once, such as this article describes, or many others that larger libraries use such as Modernizer.
As a reference the code actually used in the article above is:
function isTouchDevice() {
var el = document.createElement('div');
el.setAttribute('ongesturestart', 'return;');
if(typeof el.ongesturestart == "function"){
return true;
}else {
return false
}
}
This seems to work:
function isTouchEnabled() { return !!document.createTouch; }
You could use Modernizr to detect touch capability.
This question is very similar to What's the best way to detect a 'touch screen' device using JavaScript? and should perhaps be considered a duplicate.
i was experiencing a false positive IE10 touch issue as well when I was visiting the site i've been working on from my laptop. The original is_touch_device method, i used basically the same thing. I modified the latter half of that statement to be the following:
function is_touch_device()
{
return !!('ontouchstart' in window) || (!!('onmsgesturechange' in window) && !!window.navigator.maxTouchPoints);
}
window.navigator.maxTouchPoints seems to be something specific in IE10 based on this post: http://msdn.microsoft.com/en-us/library/hh772144(v=vs.85).aspx
You can use 51dergees.mobi for detection on the server appropriately changing page view. It has HasTouchScreen, IsSmartPhone, IsTablet properties etc.

Detect whether postMessage can send objects?

I'm looking for a neat way to detect whether postMessage in the browser supports the sending and receiving of objects or just strings. I figure that someone out there must have wrote something that does this but I have not managed to find a solution.
I'm using postMessage to send data to/from a WebWorker. Whilst detecting whether the browser supports workers is straight-forward, detecting whether objects can be send via postMessage has proved more difficult.
I'd like to write a simple detection function. So, if the browser supports the sending of objects to use that. If only strings are allowed I can fallback to using JSON.stringify(). I'll probably assign the function to a dojo/has test (although this is not relevant to the question/answer).
What have other people done to solve this problem? Any advice would be great, I'm new to both WebWorkers and postMessage. Thanks in advance.
I found an even easier way to detect if postMessage only supports strings or if it supports other types. Simply add a custom toString-method on the object. When trying to send an object with postMessage in IE8 and IE9 they will be converted to a string with the toString-method on the object. Since browsers that support sending objects doesn't call toString we can use this to our advantage. This test is not async, so you'll get the result instantly. Haven't tested this with web-workers, but I suppose you can use the same technique.
var onlyStrings = false;
try{window.postMessage({toString:function(){onlyStrings=true;}},"*");}catch(e){}
console.log("Browser only supports postMessage with strings? " + onlyStrings);
Tested in IE8, IE9, IE10 and latest version of Chrome, Firefox, Safari and Opera:
http://jsbin.com/igowoFaj/1/edit?js,console
Update: Did a BrowserScope test with many more tests and browsers. Conclusion is that it's safe to send clonable objects, arrays, numbers, pixel data and array buffers if onlyStrings is false. In theory all browsers that allow sending objects should use the structured clone algorithm, but the Android browser and Opera Mobile has quirks. The BrowserScope test result is a bit hard to read, because a 0 for send_xxx is only problematic if the browser actually has support for that type, so check supports_xxx too. If they are equal it's ok, but it's a bug if the browser has support but can't send (when onlyStrings is false).
You could try to perform an action BEFORE resuming your script. You could try this:
dummy_task.js
self.onmessage = function(event) {
self.postMessage(event.data);
};
javascript
workerSupportObject(callback);
function workerSupportObject(callback) {
var callbackIsCalled = false; // to make sure callback isn't run twice
var worker = new Worker('dummy_task.js'); // create a worker
// create event
worker.onmessage = function(event) {
// if the value is the same as we sent, it probably works
if(!callbackIsCalled) callback.call(null, event.data.value === 'dummy');
callbackIsCalled = true;
};
try {
// send dummy JSON data
worker.postMessage({'value': 'dummy'});
} catch(e) {
// oh... an error... clearly that's a no.
if(!callbackIsCalled) callback(null, false);
callbackIsCalled = true;
}
}
function callback(objectSupported) {
console.log('Worker supports objects: ', objectSupported);
}
I wanted to know the same thing. I created this script to detect if an object could be passed in postMessage by a simple callback to the current window. You will see IE 9 return false, IE 10 returns true.
http://jsfiddle.net/milesplit/DvqqH/
var supportsPostObject = false;
(function(){
var callback = function(e) {
supportsPostObject = (typeof(e.data)!='string');
};
(window.addEventListener) ?
window.addEventListener('message', callback) :
window.attachEvent('onmessage', callback);
('postMessage' in window) && window.postMessage({}, '*');
})();
setTimeout(function(){
alert(supportsPostObject);
}, 0);
postMessage also works between iframes; assuming that the behavior is the same between workers and frames, you should try the following or something like it:
<html>
<body>
<iframe id='if'>
</iframe>
<script>
var iframe = document.getElementById('if');
var iframeScript = iframe.contentDocument.createElement("script");
iframeScript.appendChild(
iframe.contentDocument.createTextNode(
'window.addEventListener("message", function(e) {console.log(e.data);}); console.log("listener attached");'));
iframe.contentDocument.body.appendChild(iframeScript);
iframe.contentWindow.postMessage("asdf", "*");
iframe.contentWindow.postMessage({'whatAmI': 'an object, maybe?'}, "*");
</script>
</body>
</html>
You may need to replace console or console.log to be able to see results, but on Chrome, this gets me
listener attached about:blank (1):1
asdf about:blank (1):1
Object {whatAmI: "an object, maybe?"} about:blank (1):1
when I save it to a local file and open it up.
The jsfiddle version (and the version which uses an actual worker) are left as an exercise for the reader. :)

Why is $.browser deprecated - and what is a better alternative?

So I know $.browser has been deprecated and "frowned upon", since jQuery 1.3, but it continues to exist & work in the code.
It's still using the plain javascript: navigator.userAgent to determine the browser being used, as well as the version.
Now is there something about these I don't know about navigator itself, that I shouldn't be using either $.browser or plain vanilla JS to get the browser/version? I just want to make sure when they have IE8 (for example), they really do have it, and I'm not processing the wrong code.
What other alternatives do we have for browser sniffing? I know about $.support, I use modernizr, but sometimes I need just need the down and dirty browser version, instead of seeing what the browser is capable of handling (I think that is a completely different problem solver).
You kind of answer the question yourself. The ideal is to check for feature support. As more browsers and devices come onto the market this approach should scale.
However if you want to do something 'down and dirty' then browser detection of course works, but only so far as you will know your code works in the existing set of browsers (or even just those you've tested your code with).
Generally it's recommended not to try to guess what the browser is but to check if a function is available. There are too many browsers and variants.
To check if a function is available, you simply do this :
if (!Array.prototype.map) {
// not available, shut down computer !
If a "must" to know which browser on the page for me, I use this personally;
(function() {
var re_browsers = {
firefox: /firefox\/([\d\.]+)/,
chrome: /chrome\/([\d\.]+)/,
safari: /webkit.*?version\/([\d\.]+)/,
opera: /opera.*?version\/([\d\.]+)/,
ie: /msie\s+([\d\.]+)/
// ...
};
var ua = window.navigator.userAgent.toLowerCase(), k, re, browser = {};
for (k in re_browsers) {
if (re = re_browsers[k].exec(ua)) {
break;
}
}
browser[k] = true;
browser["version"] = parseFloat(re && re[1]);
browser["versionOrig"] = re[1];
jQuery.extend({browser: browser});
})();

Javascript FileReader detection in Safari

I'm aware of the fact that the FileReader Object is not available in Safari 5.0.5. I have a script that uses it and thought that i'd just be able to detect whether the object exists to run some alternate code, as is suggested here,
http://www.quirksmode.org/js/support.html
So my code is,
if( FileReader )
{
//do this
}else{
//the browser doesn't support the FileReader Object, so do this
}
The problem is, i've tested it in Safari and once it hits the if statement i get this error and the script stops running.
ReferenceError: Can't find variable: FileReader
So obviously that's not the best way to deal with it then? Any idea why this doesn't work?
I believe in your case you can get away with a simpler check:
if(window.FileReader) {
//do this
} else {
//the browser doesn't support the FileReader Object, so do this
}
check for the type if you really wanna be granular and picky.
You can write if (typeof FileReader !== "undefined")
You can also use the Modernizr library to check for you.
Or you can do something like this.
if('FileReader' in window) {
// FileReader support is available
} else {
// No support available
}

Javascript : onHashchange Test

I'm trying to check if the browser supports onHashChange or not to hide some code from it if not, in this way:
if(window.onhashchange){
...code...
} else {
...other code...
}
I tried this too:
if(typeof window.onhashchange === "function"){
alert("Supports");
} else {
alert("Doesn't Supports");
}
As described on Quirksmode this should work but if I do an alert for example in true state in Safari than alerts me but Safari is not supporting onHashChange :S
What's the problem with it? If I'm not on the right way how should I check it?
You can detect this event by using the in operator:
if ("onhashchange" in window) {
//...
}
See also:
onhashchange - MDC
Detecting event support without browser sniffing
Emulating onhashchange without setInterval
Be warned that you're better off using feature detection rather than existence inference (such as "onhashchange" in window).
#xkit explained to me a good feature test to work around the fact that although IE7 doesn't support onhashchange it would still return true for existence inference such as if("onhashchange" in window){/code/} when using IE7 Standard Document Mode in IE8.
What #xkit suggested was setting a flag (such as var isSet = true;) within a handler function for the onhashchange event. Then changing window.location.hash using JavaScript and see if the flag was set.
It's likely that the version of Safari that you're using has added support for the onhashchange event since the time that that Quirksmode article was written. Tests should still be valid; try it in other browsers you know not to support the event.
Edit: also, you should use the method described by #CMS instead, as the event will not contain a function by default; thus both of those tests will fail.
if (window.onhashchange !== undefined) alert('Supports onhashchange');

Categories