Zepto fallback to jQuery
Asked Answered
W

10

26

I'm using ZeptoJS for my web app, but I'd like to fall back to jQuery if the browser doesn't support Zepto. Since IE is the only major browser not supported at the moment, I'm tempted to detect IE:

if(navigator.appName == 'Microsoft Internet Explorer'){
    // load jquery
} else {
    // load zepto
}

but I'd prefer to specificly detect Zepto support and use jQuery in other cases. Is there a feature detection way to do this?

Wholehearted answered 4/1, 2012 at 11:14 Comment(4)
I've got some good IE detection answers here, but I'd be really interested in detection that matches zepto's browsers more accurately.Wholehearted
what did you end up using. I see their example for IE detection,<script> document.write('<script src=' + ('proto' in {} ? 'zepto' : 'jquery') + '.js><\/script>') </script>Athapaskan
@Athapaskan Thats __proto__ :)Federicofedirko
yes it is @alex, thank you, don't know why i did not notice that.Athapaskan
R
8

This might be a crazy idea (I'm not sure if Zepto will even load on an unsupported browser), but what about using Zepto's own browser detection to see if it's on an unsupported browser?

$.os.ios      // => true if running on Apple iOS
$.os.android  // => true if running on Android
$.os.webos    // => true if running on HP/Palm WebOS
$.os.touchpad // => true if running on a HP TouchPad
$.os.version  // => string with version number, "4.0", "3.1.1", "2.1", etc.
$.os.iphone   // => true if running on iPhone
$.os.ipad     // => true if running on iPad
$.os.blackberry // => true if running on BlackBerry

Maybe you could do something like this:

var isSupported = false;
for (os in $.os) {
    if ($.os[os] == true) { isSupported = true; }
}

This won't catch chrome/firefox, which work fine with Zepto, but it does match the Zepto team's intentions for the thing, which may or may not be better.

Reader answered 17/2, 2012 at 16:9 Comment(5)
This is not the way to go as you will have to load zepto even if you are not going to use it.Toile
@Toile I guess that won't be a big problem since the library is very lightweight. Anyway, the answer below, which is the point you make, has much more votes. I guess that should be the accepted answer.Inoperative
I think the downside of loading Zepto when not needed is real, but using isIE as the switch for jquery is not ideal--other non-ie browsers do not support Zepto. Probably better to only load Zepto on Modernizr.isTouch these days.Reader
@SimpleAsCouldBe Modernizr.isTouch is certainly set on IE mobile (windows phone)Toile
Good point, @gagarine. I'm trying to think what the best method would be now, I've used jQuery for my past couple projects. There is no valid capability detection. I suppose the best bet is to try to match your conditional to the intention of the library. The library intends to support webkit, so a testing the UA (gasp) for webkit might be a valid approach here.Reader
D
20

You can also use JS trick described here to detect whether browser is IE, and use a modern asynchronous script loading library to load the required lib. Yepnope example:

yepnope({
  test: !+"\v1", // IE?
  yep: 'jquery.js',
  nope: 'zepto.js'
});
Dyestuff answered 4/1, 2012 at 21:13 Comment(2)
@Rocket: Bad news. Conditional statements should be used then.Dyestuff
I'm using test: navigator.appName.match(/Explorer/) now.Dyestuff
K
16

Rather than doing that with Javascript, I'd take it one step ahead and use conditional statements. This could look like:

<!--[if lt IE 8 ]>
    <script src="//ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.js"></script>
<![endif]-->

<!--[if !IE]>
    <script src="/js/zepto.js"></script>
<![endif]-->

This goes right into your HTML files. The above snippet will load jQuery, if the browser is Internet Explorer 7 and below. Otherwise it'll include zepto.js.

Kamchatka answered 4/1, 2012 at 11:20 Comment(4)
Alsos make sure to only load zepto an if not IE block.Altorelievo
Thanks - I tested Zepto 0.8 in IE9 and it didn't seem to work, so I think I'll have to have a blanket IE -> jQueryWholehearted
Should be <![if !IE]> or Zepto will be stripped as a comment.Nutty
As per a comment now on the Zepto site, conditional comments are not supported in IE 10, so it would be best to avoid this. They have a solution detailed on their homepage for IE. zeptojs.comCentigrade
S
12

As Zepto Documentation said, if you need to detect Internet Explorer you can use this code:

  if ('__proto__' in {}) {
    // IS NOT IE

  } else {
    // IS IE

  }

Zepto use it to fall back on jQuery, but I have use it as browser detection too.

Sum answered 24/5, 2012 at 10:31 Comment(7)
That's a horrible way to detect for IE (and it's in the Zepto documentation).Federicofedirko
This works for IE indeed, however, Firefox 3.6 gives true for this check (and is definitely not compatible with Zepto).Sublime
@Federicofedirko why do you say it is a horrible way?Scarper
@Scarper Because it is flaky as anything. It will also exist in a future IE (though arguably maybe that IE will be good enough by then).Federicofedirko
+1. If this is their recommended code, they have their reasons. As OP stated, he'd rather detect "Zepto support" than IE directly, and it sounds like this is Zepto's preferred way of doing so. Future IE will probably work, which is, I'm sure, a good thing.Perrie
Zepto doesn't work in IE because IE doesn't support __prototype__, so this is exactly the right way to check.Bewilderment
The point is not to detect whether or not it's IE; the point is that Zepto relies on __proto__ and IE does not have __proto__, so this is actually the correct way to check for this. Looking at anything from navigator is ridiculous, because you're essentially just making a guess as to whether or not the library will work in that browser as opposed to knowing exactly whether or not it will work. For example this will also fall back to jQuery on browsers like Opera, and won't fall back in (apparently) IE11Sergo
R
8

This might be a crazy idea (I'm not sure if Zepto will even load on an unsupported browser), but what about using Zepto's own browser detection to see if it's on an unsupported browser?

$.os.ios      // => true if running on Apple iOS
$.os.android  // => true if running on Android
$.os.webos    // => true if running on HP/Palm WebOS
$.os.touchpad // => true if running on a HP TouchPad
$.os.version  // => string with version number, "4.0", "3.1.1", "2.1", etc.
$.os.iphone   // => true if running on iPhone
$.os.ipad     // => true if running on iPad
$.os.blackberry // => true if running on BlackBerry

Maybe you could do something like this:

var isSupported = false;
for (os in $.os) {
    if ($.os[os] == true) { isSupported = true; }
}

This won't catch chrome/firefox, which work fine with Zepto, but it does match the Zepto team's intentions for the thing, which may or may not be better.

Reader answered 17/2, 2012 at 16:9 Comment(5)
This is not the way to go as you will have to load zepto even if you are not going to use it.Toile
@Toile I guess that won't be a big problem since the library is very lightweight. Anyway, the answer below, which is the point you make, has much more votes. I guess that should be the accepted answer.Inoperative
I think the downside of loading Zepto when not needed is real, but using isIE as the switch for jquery is not ideal--other non-ie browsers do not support Zepto. Probably better to only load Zepto on Modernizr.isTouch these days.Reader
@SimpleAsCouldBe Modernizr.isTouch is certainly set on IE mobile (windows phone)Toile
Good point, @gagarine. I'm trying to think what the best method would be now, I've used jQuery for my past couple projects. There is no valid capability detection. I suppose the best bet is to try to match your conditional to the intention of the library. The library intends to support webkit, so a testing the UA (gasp) for webkit might be a valid approach here.Reader
T
8

Don't use the conditional comments, it's not going to be supported by IE10. This is the recommended approach from the zepto documentation:

Load Zepto on modern browser and jQuery on IE

<script>
document.write('<script src=' +
('__proto__' in {} ? 'zepto' : 'jquery') +
'.js><\/script>')
</script>

Zepto doesn't work in IE because IE doesn't support prototype, so this is exactly the right way to check.

The script above do a dynamical load but the logic is

<script>
if ('__proto__' in {}) {
  // This is NOT IE

  } else {
    // This is IE

  }
</script>
Toile answered 4/4, 2012 at 12:22 Comment(2)
In your conditional comment example both IE9 and IE10 get no script at all.Perrie
@ZachL thanks. I removed the conditional comment example because is anyway not supported by IE10..Toile
G
5
<script>
  document.write('<script src=' + ('__proto__' in {} ? 'zepto' : 'jquery') + '.js><\/script>')
</script>

This is the recommended method on zepto.js official site. See http://zeptojs.com/#download

Guise answered 29/6, 2012 at 8:52 Comment(0)
C
1

While many of the existing answers work fine when loading Zepto.js via an additional request, I have a situation where I know Zepto will suffice most of the time and I just want to merge it in with my scripts and lazily load jQuery if needed. I put together a small wrapper for Zepto will do just that.

It runs the "offical" '__proto__' in ... test and lazy loads jQuery if it fails. If it succeeds, then it continues loading Zepto.

I found that IE8 would blow up if Zepto was even loaded. This fixes that by skipping the rest of the module.

For the optimistic case, there isn't any additional script requests. For the jQuery path, well, those users weren't exactly getting the fast experience anyway.

Carbonate answered 29/3, 2013 at 20:16 Comment(0)
B
1

This is an old topic, but it's what came up for me, and I was not happy with the solution overall. Someone in a comment above mentioned that the official zepto test will result in zepto going to FireFix 3.6 instead of JQuery, which I would prefer to avoid if at all possible.

So, my thought was...test to see if it supports some HTML5 feature AND if it's not IE. This may mean that the larger jQuery will go to more browsers than it should, but I would prefer "working" bloated code to a quick download of nothing. So, anyway, taking the isCanvasSupported() method from Modernizer and the __proto__ test recommended by zepto, I'm thinking this might be a good solution (haven't had a chance to actually test yet):

   var isHtml5AndNotIE     = function() {
        var elem = document.createElement('canvas');
        return '__proto__' in {} && !!(elem.getContext && elem.getContext('2d'));
    };

Then, just use that method in the document.write() as in the examples above or wherever you are defining the path to jquery/zepto.

The only two browser versions that I could see in a quick cross-reference that support canvas but aren't supported by zepto are: * IOS Safari 3.2 (4+ is supported by Zepto) * Android 2.1 (2.2+ is supported by Zepto)

http://zeptojs.com/#platforms

http://caniuse.com/#feat=canvas

Berar answered 12/8, 2013 at 14:32 Comment(1)
I created an open-source skeleton that uses RequireJS, Bootstrap 3, and Zepto with a JQuery fallback using the above method, which you can use as an example if you happen to come across this site and are looking for a RequireJS solution to this problem like I was originally: github.com/kevinknelson/bootstrap-mobileBerar
J
0

This is the way I do it:

<script type="text/javascript">
if(top.execScript){ // true only in IE
    document.write("<script src='/js/jquery.js'>\x3C/script>");
}
else{
    document.write("<script src='/js/zepto.min.js'>\x3C/script>");
}
</script>
Jolt answered 7/3, 2012 at 18:53 Comment(1)
Thanks Timbo, but I'd be really interested in something that specifically looks for Zepto compatibility rather than improving my 'detect IE' hackWholehearted
T
0

You should raise the bar a bit so not only IE8 will get jQuery, but also other older browsers. Zepto for example requires features such as Array.prototype.some.

Zepto requires much the same features as picoQuery (which is an alternative to Zepto). In picoQuery, they do like this:

if (Array.isArray) {
   // Modern browser
   // (FF4+, IE9+, Safari 5+, Opera 10.5+, Konq 4.9+, Chrome 5+, etc)
   document.write("<script src='/js/zepto.min.js'></script>");
}
else {
   document.write("<script src='/js/jquery.js'></script>");
}

From compatibility tables we have that any browser that supports Array.isArray also supports querySelectorAll(), addEventListener(), dispatchevent, Array.prototype.indexOf and Array.prototype.some - all which are used in Zepto

picoQuery describes this choice here: http://picoquery.com/the_fallback

Trenatrenail answered 7/12, 2016 at 12:26 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.