Skip to content

Commit

Permalink
Merge pull request #33 from kaimallea/fixes
Browse files Browse the repository at this point in the history
Fix Facebook UA checks; update dev dependencies
  • Loading branch information
kaimallea committed Jul 4, 2015
2 parents b277a8d + 849debe commit c25c862
Show file tree
Hide file tree
Showing 5 changed files with 72 additions and 12 deletions.
10 changes: 5 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ I couldn't do detection on the back-end, because the entire site was cached and

So I resorted to UA sniffing.

I tried to keep the script small (**currently ~1.3k bytes, minified**) and simple, because it would need to execute in the `<head>`, which is generally a bad idea, since JS blocks downloading and rendering of anything else while it parses and executes. In the case of mobile redirection, I don't mind so much, because I want to start the redirect as soon as possible, before the device has a chance to start downloading and rendering stuff. For non-mobile platforms, the script should execute fast, so the browser can quickly get back to downloading and rendering.
I tried to keep the script small (**currently ~1.4k bytes, minified**) and simple, because it would need to execute in the `<head>`, which is generally a bad idea, since JS blocks downloading and rendering of anything else while it parses and executes. In the case of mobile redirection, I don't mind so much, because I want to start the redirect as soon as possible, before the device has a chance to start downloading and rendering stuff. For non-mobile platforms, the script should execute fast, so the browser can quickly get back to downloading and rendering.

## How it works

Expand Down Expand Up @@ -75,7 +75,7 @@ The following properies of the `isMobile` object will either be `true` or `false

## Example Usage

I include the minified version of the script, inline, and at the top of the `<head>`. Cellular connections tend to suck, so it would be wasteful overhead to open another connection, just to download <1kb of JS:
I include the minified version of the script, inline, and at the top of the `<head>`. Cellular connections tend to suck, so it would be wasteful overhead to open another connection, just to download ~1.4kb of JS:


```html
Expand All @@ -84,8 +84,8 @@ I include the minified version of the script, inline, and at the top of the `<he
<head>
<meta charset="utf-8">
<script>
// Minified version of isMobile included in the HTML since it's <1kb
(function(i){var e=/iPhone/i,n=/iPod/i,o=/iPad/i,t=/(?=.*\bAndroid\b)(?=.*\bMobile\b)/i,r=/Android/i,d=/BlackBerry/i,s=/Opera Mini/i,a=/IEMobile/i,b=/(?=.*\bFirefox\b)(?=.*\bMobile\b)/i,h=RegExp("(?:Nexus 7|BNTV250|Kindle Fire|Silk|GT-P1000)","i"),c=function(i,e){return i.test(e)},l=function(i){var l=i||navigator.userAgent;this.apple={phone:c(e,l),ipod:c(n,l),tablet:c(o,l),device:c(e,l)||c(n,l)||c(o,l)},this.android={phone:c(t,l),tablet:!c(t,l)&&c(r,l),device:c(t,l)||c(r,l)},this.other={blackberry:c(d,l),opera:c(s,l),windows:c(a,l),firefox:c(b,l),device:c(d,l)||c(s,l)||c(a,l)||c(b,l)},this.seven_inch=c(h,l),this.any=this.apple.device||this.android.device||this.other.device||this.seven_inch},v=i.isMobile=new l;v.Class=l})(window);
// Minified version of isMobile included in the HTML since it's small
!function(a){var b=/iPhone/i,c=/iPod/i,d=/iPad/i,e=/(?=.*\bAndroid\b)(?=.*\bMobile\b)/i,f=/Android/i,g=/IEMobile/i,h=/(?=.*\bWindows\b)(?=.*\bARM\b)/i,i=/BlackBerry/i,j=/BB10/i,k=/Opera Mini/i,l=/(?=.*\bFirefox\b)(?=.*\bMobile\b)/i,m=new RegExp("(?:Nexus 7|BNTV250|Kindle Fire|Silk|GT-P1000)","i"),n=function(a,b){return a.test(b)},o=function(a){var o=a||navigator.userAgent,p=o.split("[FBAN");return"undefined"!=typeof p[1]&&(o=p[0]),this.apple={phone:n(b,o),ipod:n(c,o),tablet:!n(b,o)&&n(d,o),device:n(b,o)||n(c,o)||n(d,o)},this.android={phone:n(e,o),tablet:!n(e,o)&&n(f,o),device:n(e,o)||n(f,o)},this.windows={phone:n(g,o),tablet:n(h,o),device:n(g,o)||n(h,o)},this.other={blackberry:n(i,o),blackberry10:n(j,o),opera:n(k,o),firefox:n(l,o),device:n(i,o)||n(j,o)||n(k,o)||n(l,o)},this.seven_inch=n(m,o),this.any=this.apple.device||this.android.device||this.windows.device||this.other.device||this.seven_inch,this.phone=this.apple.phone||this.android.phone||this.windows.phone,this.tablet=this.apple.tablet||this.android.tablet||this.windows.tablet,"undefined"==typeof window?this:void 0},p=function(){var a=new o;return a.Class=o,a};"undefined"!=typeof module&&module.exports&&"undefined"==typeof window?module.exports=o:"undefined"!=typeof module&&module.exports&&"undefined"!=typeof window?module.exports=p():"function"==typeof define&&define.amd?define("isMobile",[],a.isMobile=p()):a.isMobile=p()}(this);
// My own arbitrary use of isMobile, as an example
Expand Down Expand Up @@ -121,4 +121,4 @@ I include the minified version of the script, inline, and at the top of the `<he
```
var isMobile = require('ismobilejs');
console.log(isMobile(req.headers['user-agent']).any);
```
```
8 changes: 7 additions & 1 deletion isMobile.js
Original file line number Diff line number Diff line change
Expand Up @@ -53,11 +53,17 @@

var IsMobileClass = function(userAgent) {
var ua = userAgent || navigator.userAgent;
// Facebook mobile app's integrated browser adds a bunch of strings that
// match everything. Strip it out if it exists.
var tmp = ua.split('[FBAN');
if (typeof tmp[1] !== 'undefined') {
ua = tmp[0];
}

this.apple = {
phone: match(apple_phone, ua),
ipod: match(apple_ipod, ua),
tablet: match(apple_tablet, ua),
tablet: !match(apple_phone, ua) && match(apple_tablet, ua),
device: match(apple_phone, ua) || match(apple_ipod, ua) || match(apple_tablet, ua)
};
this.android = {
Expand Down
2 changes: 1 addition & 1 deletion isMobile.min.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

14 changes: 9 additions & 5 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,16 +9,20 @@
"useragent"
],
"homepage": "https://github.com/kaimallea/isMobile",
"license": "CC0",
"license": "CC0-1.0",
"author": {
"name": "Kai Mallea",
"email": "[email protected]"
},
"repository": {
"type": "git",
"url": "https://github.com/kaimallea/isMobile.git"
},
"main": "./isMobile",
"devDependencies": {
"grunt": "0.4.x",
"grunt-contrib-jshint": "0.8.x",
"grunt-contrib-uglify": "0.3.x",
"grunt-contrib-jasmine": "0.6.x"
"grunt-contrib-jshint": "0.11.x",
"grunt-contrib-uglify": "0.9.x",
"grunt-contrib-jasmine": "0.8.x"
}
}
}
50 changes: 50 additions & 0 deletions tests/spec/AppleSpec.js
Original file line number Diff line number Diff line change
Expand Up @@ -90,4 +90,54 @@ describe("Apple", function(){

});

describe("Facebook iPhone App UserAgent", function() {

beforeEach(function() {
userAgent = "Mozilla/5.0 (iPhone; CPU OS 8_1 like Mac OS X) AppleWebKit/600.1.4 (KHTML, like Gecko) Mobile/12B410 [FBAN/FBIOS;FBAV/20.1.0.15.10;FBBV/5758778;FBDV/iPad5,4;FBMD/iPad;FBSN/iPhone OS;FBSV/8.1;FBSS/2; FBCR/;FBID/tablet;FBLC/fi_FI;FBOP/1]";
mobile = new isMobile.Class(userAgent);
});

it("should be an iPhone", function() {
expect(mobile.apple.phone).toBe(true);
});

it("should not be an iPad", function() {
expect(mobile.apple.tablet).not.toBe(true);
});

it("should not be an iPod", function() {
expect(mobile.apple.ipod).not.toBe(true);
});

it("should be an Apple device", function() {
expect(mobile.apple.device).toBe(true);
});

});

describe("Facebook iPad App UserAgent", function() {

beforeEach(function() {
userAgent = "Mozilla/5.0 (iPad; CPU OS 8_1 like Mac OS X) AppleWebKit/600.1.4 (KHTML, like Gecko) Mobile/12B410 [FBAN/FBIOS;FBAV/20.1.0.15.10;FBBV/5758778;FBDV/iPad5,4;FBMD/iPad;FBSN/iPhone OS;FBSV/8.1;FBSS/2; FBCR/;FBID/tablet;FBLC/fi_FI;FBOP/1]";
mobile = new isMobile.Class(userAgent);
});

it("should not be an iPhone", function() {
expect(mobile.apple.phone).not.toBe(true);
});

it("should be an iPad", function() {
expect(mobile.apple.tablet).toBe(true);
});

it("should not be an iPod", function() {
expect(mobile.apple.ipod).not.toBe(true);
});

it("should be an Apple device", function() {
expect(mobile.apple.device).toBe(true);
});

});

});

0 comments on commit c25c862

Please sign in to comment.