What browsers support the window.postMessage call now? - javascript

What are all the browsers that support the window.postMessage call now? I am looking for browsers that support it natively, not through an iFrame hack.

Can I use cross-document messaging
FF3+, IE8+, Chrome, Safari(5?), Opera10+

IE8 does not allow postMessage across windows/tabs
http://blogs.msdn.com/b/ieinternals/archive/2009/09/16/bugs-in-ie8-support-for-html5-postmessage-sessionstorage-and-localstorage.aspx
for more info check here
http://www.openajax.org/member/wiki/Browser_Variation_of_the_Hub_Reference_Implementation_%28Illustrative%29

postMessage is supported in IE8+ HOWEVER
Remember that IE9 and below require data to be passed in string form and not as an object.
IE doesn't like you to call postMessage as soon as page loads (I'm assuming this has to do with the iframe you are posting to needing time to load).
Use a setTimeout to wait one or two seconds before calling postMessage.
It took me hours to figure this out and IE wasn't giving me any error message, it was just silently doing nothing until I added the setTimeout.
If you want to start with a demo which actually does work in IE, check out this nifty tutorial by Ilya Kantor

For what it's worth recently I ran into some odd webkit browser/versions out in the wild that did NOT support postMessage. I was using IE(8) detection as my means for seeking an alternative. Instead, I probably should have just done some something like this:
if(window.postMessage){
console.log('Supports post message');
}
Or likely a bit cleaner:
var pm_is_supported = typeof(window.postMessage) == 'function';

All latest browsers supports that e.g. IE 11, Edge, Firefox 57+, Dafari 11+, iOS Safari 10.2+, Opera mini, Chrome for android, UC Browser etc.
https://caniuse.com/#search=document%20messaging

Related

How can I use the BroadcastChannel API or something similar in Safari 10+?

Problem:
I need a client-side Javascript solution (jQuery is fine) where an event in one browser window/tab can be broadcast to other windows/tabs on the same domain. For example, if a cart is updated in tab A, tabs B and C get notified so we can update some info on the page, or notify the user that page is stale, or something like that.
What I've tried:
The BroadcastChannel API fits my needs perfectly, but does not work in IE 11 or Safari.
So I tried this polyfill so I could use the BroadcastChannel API everywhere. It worked in IE, but not in Safari (I believe BroadcastChannel remained undefined).
I then tried sysend.js , which uses BroadCastChannel if it's available, otherwise fakes it using localStorage. Their demo page works fine in Safari, but on my site, I found it worked in Safari 9, but not 10-12 (tested using BrowserStack and one real Mac running Safari 12). Debugging their script, it seems the storage event that's supposed to fire when localStorage in a different tab is changed simply doesn't fire. But this is actually only a problem when you have document.domain set, which I do.
I believe this is the same as this old Chrome bug. But whereas Chrome had that issue from 2012-2017, Safari apparently introduced it around 2017?
I haven't found anyone else discussing this bug in Safari, but I can prove this pretty easily. Open two tabs that use the same document.domain value and run these scripts:
Tab A:
$(window).on("storage", function (e) {
alert('storage was modified');
});
Tab B:
localStorage.setItem("test", "123");
In Safari 9, Tab A will pop the alert. In Safari 10+, it won't.
If I remove the document.domain, it works. Note that we are using document.domain on these pages, but they are actually on the same domain in this case. However document.domain is needed for other scenarios across the site, so I can't remove it.
I also tried looking at store.js. It has an event system, but it only seemed to work within the same tab (in any browser). Unless I'm missing something.
So, is there any BroadcastChannel polyfill or similar library that actually works in Safari 10+ when you have a document.domain set? Or any other way to do this?
Notes:
I'm aware that BroadcastChannel and the "storage" event for localStorage only fire for tabs other than the current one. That is not my issue, and is actually desirable to me.
I've also seen posts that make me believe an alternate solution relying on localStorage likely will not work in Private Browsing mode in Safari. EDIT: It appears this was fixed in Safari 11 so it does work, but in my tests it didn't share localStorage with any other tabs, even other Private tabs in the same window. So that's not much help. Ideally, a solution would account for this as well, but at this point I'd be happy with anything that worked in Safari 10+ for me. I did see an example in the store.js project where they said they made it so it would fallback to cookies in that case, so it sounds possible at least.
I tried to think about other ways to do this with a setInterval that checks the localStorage for updates every few seconds or something. Even in theory that seems really hacky and unreliable (how would you know when all pages have "received" the update so you can clear it out?). And how would you know when to do it this hacky way instead of one of the preferred methods using localStorage? Safari 10+ is going to report that it supports localStorage so you can't really feature detect it, right? It "supports" it, it just doesn't work correctly.
I found a workaround, but I'll leave this question open because I'd still love to see a better answer.
As a last resort, I ended up toggling between two different ways of performing the messaging, depending on browser.
Basically, if it's Safari I use https://github.com/pubkey/broadcast-channel (you can get the minified vanilla JS version from https://github.com/pubkey/broadcast-channel/blob/master/dist/lib/browser.min.js). This seems to work in all versions even when you have a document.domain set. I think it uses indexDB in this case, which seems like total overkill, but I don't seem to have a choice.
It also works in Safari private windows in newer versions of Safari. I have try catches in place in all my script for older versions of Safari in private mode where it would otherwise throw errors.
If it's not Safari, I use sysend.js which uses BroadcastChannel by default and falls back to localStorage for cases like IE 11.

Is there a way to detect iOS safari while filtering out iOS Chrome, Firefox and other browsers?

So for those who worked on iOS web applications probably know that due to Apple's policy, Chrome and other mobile browsers on iOS use a very ancient javascript engine. This is why we need to disable some of the rendering for Chrome and other none-safari browsers for iOS.
I had been reading this question and there is no useful answer there. Here are some of my approaches (failed):
Use is_iOS = navigator.userAgent.match(/(iPad|iPhone|iPod)/g) to detect if the browser is on iOS. And then use:
is_FF = navigator.userAgent.match(/(firefox)/g) and is_Chrome = navigator.userAgent.match(/(chrome)/g)
to kill off those firefox and chrome browsers.
I then realized all the browsers share identical user agent string with iOS safari. So I imagine the method should be running a javascript function that only Safari can run and then determine if the browser is Safari.
So, there's two schools of thought when choosing which native functionality you should use while working in browsers. One school of thought is checking the userAgent as you are doing here and using/removing features based on the userAgent.
The problem with checking userAgent is that it gets complicated really fast. You have already run into an interesting problem, but what will happen when you find that ie8 does not have the feature you are looking for?
A better solution may be to check if the feature exists in its current context without worrying about userAgent. A great example would be the new HTML5 audio element. Based on browser support, we can tell that it does not exist in ie8 nor Safari < 4.0. Instead of checking if the browser matches the ones mentioned here you can just check if the feature exists. As we know that the audio element is an instance of the Audio class. We can simply check:
if (window.Audio) {
//load and play the HTML5 audio element here
}
That is much simpler than checking the userAgent.

Detecting any and all versions of Internet Explorer

There used to be a nice way to tell if a web browser is IE or not, by using this technique in HTML:
<!--[if IE]>
Non-IE browsers ignore this
<![endif]-->
or
<!--[if !IE]-->
IE ignores this
<!--[endif]-->
but this doesn't work anymore in IE 10.
Any idea what to use instead to tell IE from other web browsers (using HTML or JavaScript)?
PS. I need to be able to tell ANY version of IE from non-IE web browser.
I appreciate all your insight, but none of it answers my actual question. Again, I am not asking about the feature detection. All I need to know is if the web browser is IE or not. The following uses JavaScript and seems to work for all current versions of IE (including IE10):
<![if IE]>
<script type='text/javascript'>
if(/*#cc_on!#*/false)
var bIsIE = 1;
</script>
<![endif]>
and then to check if it's IE, do this from JavaScript:
if (typeof (bIsIE) != 'undefined')
{
//The web browser is IE
}
else
{
//The web browser is not IE
}
Obviously the code above assumes that the web browser has JavaScript enabled. But in my case the browser detection is relevant only if it has scripts enabled.
Every version of Internet Explorer is different from the others, just as every version of Chrome, Firefox, and Opera are different from their predecessors. You don't target vendors such as "Microsoft", "Google", or "Mozilla" when you develop websites—you target features.
Rather than asking "I'd like to use ::after, is this browser a Microsoft browser?" You should instead ask "Does this browser support pseudo-elements on the :: prefix?" This is feature-detection, and it's nearly always perfectly on target. Rather than guessing what a browser is capable of by its vendor, you determine what it's capable of by what it can actually do.
This may not be the answer you were looking for, but it's the correct answer nonetheless. If you're asking how to identify all Microsoft browsers, you are approaching the problem (or what you perceive to be a problem) incorrectly.
For proper solutions, I would encourage you to use tools like jQuery and Modernizr. These will handle API normalization, shimming of newer elements in older browsers, as well as feature-detection. This is the correct way to do things, and had developers been taking this approach from the beginning you may not have such a distaste for Internet Explorer today.
The link you give in your question - doesn't work anymore - which is to Windows Internet Explorer Engineering Team Blog leads to the following statement
Conditional Comments
<!--[if IE]>
This content is ignored in IE10 and other browsers.
In older versions of IE it renders as part of the page.
<![endif]-->
This means conditional comments can still be used, but will only
target older versions of IE. If you need to distinguish between more
recent browsers, use feature detection instead.
It seems to me that the IE team are strongly pushing for the use of feature detection rather than browser detection as the quote from the feature detection link above shows.
Same Markup: Core Guidelines
**DO**
Feature Detection
Test whether a browser supports a feature before using it.
Behavior Detection
Test for known issues before applying a workaround.
**DON'T**
Detect Specific Browsers
Also known as browser detection. Don't use the identity of a browser (e.g. navigator.userAgent) to alter page behavior.
Assume Unrelated Features
Don't perform feature detection for one feature, and then proceed to use a different feature.
So it appears that the Windows Internet Explorer Engineering Team are setting IE up so that you will not be able to use browser detection for IE10 and above.
EDIT
I do not use IE10 but does
navigator.appName=='Microsoft Internet Explorer';
work in IE10?
It isn't enough to just say IE10 is good enough and ignore the problem. It really depends on what you are trying to do. For most purposes feature detection would likely handle what you need. The far, far more complicated route is to start user agent detection by pulling in the user agent string from the HTTP request header. If you aren't careful with this you can go wrong pretty quickly.
To view your current user agent string in a browser JS console:
console.log(navigator.userAgent);
Here is a list of reported user agent strings across all kinds of browsers:
http://www.zytrax.com/tech/web/browser_ids.htm
Note that all MS Explorer agent strings will contain "MSIE," but first you have to weed out browsers like Opera that will also include the "MSIE" string in some cases.
This function returns true if the client browser is Internet Explorer, tested on versions 9-10-11.
function isIE(v) {
var ie;
ie = RegExp('msie' + (!isNaN(v)?('\\s'+v):''), 'i').test(navigator.userAgent);
if (!ie) { ie = !!navigator.userAgent.match(/Trident.*rv[ :]*11\./) }
return ie;
}
// Example
var ie = isIE();
var ie9 = isIE(9);
var ie10 = isIE(10);
NOTE: the function is incomplete and won't allow for isIE(11)

Browser support for stopImmediatePropagation?

IE support for stopPropagation() is lacking, and requires workarounds, but I can't tell if the same thing is true for stopImmediatePropagation()- is it safe for all browsers, or does it requires its own set of workarounds?
I was wondering for the browser support of JavaScript's event.stopImmediatePropagation as well, so I decided to test it by checking whether the following method exists:
Event.prototype.stopImmediatePropagation
It's supported on the following desktop browsers:
Internet Explorer 9+
Firefox 10+
Chrome 6+
Safari 5.0+
Opera 15+ (Presto doesn't support stopImmediatePropagation)
The stopPropagation mentioned on the other answer is related to the method natively available on browser for the event object , while the stopPropagation() method of jQuery works fine in all browser (since it's a wrapper for the same task, taking into account the browser capabilities in which this method is run)

is top.document cross browser?

I'm writing a javascript that relies on top.document but I'm not sure if I can assume all the major browsers supports it or not.
Is top.document cross-browser compatible?
According to W3Schools, window.top is supported in IE (since v4), FF (v1), and Opera (v9). I can personally vouch for it working in Safari as I just tried their example code in my own browser. :-)
I've never used it, but I believe it is.
Nested frames are so passe.
Check out this handy Quirksmode article on the topic.

Categories