├── .gitignore ├── .travis.yml ├── bower.json ├── appveyor.yml ├── package.json ├── test ├── index.js └── userAgents.js ├── README.md └── detect-browser.js /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | coverage/ 3 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - "0.12" 4 | - "0.11" 5 | - "0.10" 6 | - "iojs" 7 | - "iojs-v1.0.4" 8 | - "iojs-v3.2.0" 9 | 10 | script: "npm run-script test-travis" 11 | after_success: "cat ./coverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js" -------------------------------------------------------------------------------- /bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "browser-detector", 3 | "version": "4.0.1", 4 | "homepage": "https://github.com/smali-kazmi/detect-mobile-browser", 5 | "authors": [ 6 | "SM@K " 7 | ], 8 | "description": "A plugin to detect mobile browser in frontend and backend", 9 | "main": "detect-browser.js", 10 | "moduleType": [ 11 | "amd", 12 | "globals", 13 | "node" 14 | ], 15 | "keywords": [ 16 | "mobile", 17 | "browser" 18 | ], 19 | "license": "MIT", 20 | "ignore": [ 21 | "**/.*", 22 | "node_modules", 23 | "bower_components", 24 | "test", 25 | "tests" 26 | ] 27 | } 28 | -------------------------------------------------------------------------------- /appveyor.yml: -------------------------------------------------------------------------------- 1 | environment: 2 | matrix: 3 | # node.js 4 | - nodejs_version: "0.10" 5 | - nodejs_version: "0.11" 6 | - nodejs_version: "0.12" 7 | # io.js 8 | - nodejs_version: "1.0" 9 | - nodejs_version: "4.0" 10 | 11 | # Install scripts. (runs after repo cloning) 12 | install: 13 | # Get the latest stable version of Node.js or io.js 14 | - ps: Install-Product node $env:nodejs_version 15 | # install modules 16 | - npm install 17 | 18 | # Post-install test scripts. 19 | test_script: 20 | # Output useful info for debugging. 21 | - node --version 22 | - npm --version 23 | # run tests 24 | - npm test 25 | 26 | # Don't actually build. 27 | build: off 28 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "detect-mobile-browser", 3 | "version": "5.0.1", 4 | "description": "It is a very simple & small javascript plugin to detect all major modern mobile browsers.", 5 | "main": "detect-browser.js", 6 | "scripts": { 7 | "test": "mocha test", 8 | "test-travis": "./node_modules/istanbul/lib/cli.js cover ./node_modules/mocha/bin/_mocha -- -R spec ./test/*" 9 | }, 10 | "repository": { 11 | "type": "git", 12 | "url": "https://smali-kazmi@github.com/smali-kazmi/detect-mobile-browser.git" 13 | }, 14 | "keywords": [ 15 | "mobile", 16 | "browser", 17 | "smartphone", 18 | "tablet", 19 | "phone", 20 | "mobile", 21 | "useragent" 22 | ], 23 | "author": "SM@K (http://smak.pk/)", 24 | "license": "MIT", 25 | "bugs": { 26 | "url": "https://github.com/smali-kazmi/detect-mobile-browser/issues" 27 | }, 28 | "devDependencies": { 29 | "coveralls": "*", 30 | "mocha": "*", 31 | "mocha-lcov-reporter": "*", 32 | "istanbul": "*" 33 | }, 34 | "spm": { 35 | "main": "detect-browser.js" 36 | }, 37 | "homepage": "https://github.com/smali-kazmi/detect-mobile-browser" 38 | } 39 | -------------------------------------------------------------------------------- /test/index.js: -------------------------------------------------------------------------------- 1 | var assert = require("assert"); 2 | var userAgents = require('./userAgents'); 3 | var SmartPhone = require('../detect-browser')(false); 4 | 5 | describe('SmartPhone', function() { 6 | 7 | describe('check all SmartPhone function as per userAgents', function(){ 8 | 9 | userAgents.forEach(function(ua){ 10 | 11 | it('it should check: ' + ua['call'], function(){ 12 | SmartPhone.setUserAgent(ua['userAgent']); 13 | assert.notEqual(null, SmartPhone[ua['call']]()); 14 | }); 15 | 16 | }); 17 | }); 18 | 19 | describe('check module as a middleware', function(){ 20 | var mw = null; 21 | var req = null; 22 | var res = null; 23 | 24 | beforeEach(function(){ 25 | mw = require('../detect-browser')(true); 26 | req = { 27 | headers: { 28 | 'user-agent': 'blah blah' 29 | } 30 | }; 31 | res = { 32 | locals: {} 33 | }; 34 | }); 35 | 36 | it('it should contain SmartPhone object', function(done){ 37 | mw(req, res, function(){ 38 | assert.equal(false, res.locals.SmartPhone.isAny()); 39 | done() 40 | }); 41 | }); 42 | }); 43 | 44 | describe('check module all function as a middleware', function(){ 45 | 46 | userAgents.forEach(function(ua){ 47 | 48 | it('it should check: ' + ua['call'], function(done){ 49 | var mw = null; 50 | var req = null; 51 | var res = null; 52 | 53 | 54 | mw = require('../detect-browser')(true); 55 | req = { 56 | headers: { 57 | 'user-agent': 'blah blah' 58 | } 59 | }; 60 | res = { 61 | locals: {} 62 | }; 63 | 64 | req.headers['user-agent'] = ua['userAgent']; 65 | mw(req, res, function(){ 66 | assert.notEqual(null, res.locals.SmartPhone[ua['call']]()); 67 | done() 68 | }); 69 | }); 70 | 71 | }); 72 | 73 | }); 74 | 75 | 76 | }); -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![Build][build-image]][build-url] 2 | [![NPM Version][npm-image]][npm-url] 3 | [![NPM Downloads][downloads-image]][downloads-url] 4 | [![Inline docs][docs-image]][docs-url] 5 | [![Coverage Status](https://coveralls.io/repos/smali-kazmi/detect-mobile-browser/badge.svg?branch=master&service=github)](https://coveralls.io/github/smali-kazmi/detect-mobile-browser?branch=master) 6 | [![NPM][npm-download-image]][npm-url] 7 | 8 | Detect Mobile Browser 9 | ===================== 10 | 11 | Small plugin to detect mobile browser 12 | 13 | **Usage Frontend:-** 14 | 15 | ```javascript 16 | alert(SmartPhone.isAndroid()); 17 | ``` 18 | 19 | OR 20 | 21 | ```javascript 22 | alert(SmartPhone.isAny()); 23 | ``` 24 | 25 | OR (browserify): 26 | 27 | ```javascript 28 | var SmartPhone = require('detect-mobile-browser')(false); 29 | module.exports = (function($) { 30 | $(document).ready(function() { 31 | alert(SmartPhone.isAny()); 32 | }); 33 | })(jQuery); 34 | ``` 35 | 36 | **Usage Backend:-** 37 | 38 | Use as an ExpressJS middleware 39 | 40 | ```javascript 41 | var mobileBrowser = require('detect-mobile-browser'); 42 | 43 | ... 44 | ... 45 | 46 | app.use(mobileBrowser()); 47 | 48 | app.get('/', function (req, res){ 49 | ... 50 | ... 51 | //in req 52 | console.log(req.SmartPhone.isAny()); 53 | 54 | ... 55 | ... 56 | 57 | //in res locals to use in templates 58 | console.log(res.locals.SmartPhone.isAny()); 59 | 60 | ... 61 | ... 62 | 63 | }); 64 | 65 | ``` 66 | 67 | 68 | 69 | ## Bower 70 | 71 | $ bower install browser-detector --save 72 | 73 | ## NPM 74 | 75 | $ npm install detect-mobile-browser --save 76 | 77 | ## SPM 78 | 79 | $ spm install detect-mobile-browser --save 80 | 81 | ## List of detection functions: 82 | 83 | - isAndroid 84 | - isBlackBerry 85 | - isBlackBerryPlayBook 86 | - isBlackBerry10 87 | - isIOS 88 | - isIPhone 89 | - isIPad 90 | - isIPod 91 | - isOpera 92 | - isWindows 93 | - isWindowsMobile 94 | - isWindowsDesktop 95 | - isFireFox 96 | - isNexus 97 | - isKindleFire 98 | - isPalm 99 | - isAny 100 | 101 | [npm-image]: https://img.shields.io/npm/v/detect-mobile-browser.svg 102 | [npm-download-image]: https://nodei.co/npm/detect-mobile-browser.png?downloads=true&downloadRank=true 103 | [npm-url]: https://www.npmjs.com/package/detect-mobile-browser 104 | [downloads-image]: https://img.shields.io/npm/dm/detect-mobile-browser.svg 105 | [downloads-url]: https://www.npmjs.com/package/detect-mobile-browser 106 | [docs-image]: http://inch-ci.org/github/smali-kazmi/detect-mobile-browser.svg?branch=master 107 | [docs-url]: http://inch-ci.org/github/smali-kazmi/detect-mobile-browser 108 | [build-image]: https://api.travis-ci.org/smali-kazmi/detect-mobile-browser.svg?branch=master 109 | [build-url]: https://travis-ci.org/smali-kazmi/detect-mobile-browser 110 | -------------------------------------------------------------------------------- /test/userAgents.js: -------------------------------------------------------------------------------- 1 | module.exports = [ 2 | { 3 | 'call': 'isAndroid', 4 | 'userAgent': 'Mozilla/5.0 (Linux; U; Android 4.3; en-us; SM-N900T Build/JSS15J) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30' 5 | }, 6 | { 7 | 'call': 'isBlackBerry', 8 | 'userAgent': 'Mozilla/5.0 (BlackBerry; U; RIM Tablet OS 2.1.0; en-US) AppleWebKit/536.2+ (KHTML like Gecko) Version/7.2.1.0 Safari/536.2+' 9 | }, 10 | { 11 | 'call': 'isBlackBerryPlayBook', 12 | 'userAgent': 'Mozilla/5.0 (PlayBook; U; RIM Tablet OS 2.1.0; en-US) AppleWebKit/536.2+ (KHTML like Gecko) Version/7.2.1.0 Safari/536.2+' 13 | }, 14 | { 15 | 'call': 'isBlackBerry10', 16 | 'userAgent': 'Mozilla/5.0 (BB10; Touch) AppleWebKit/537.10+ (KHTML, like Gecko) Version/10.0.9.2372 Mobile Safari/537.10+' 17 | }, 18 | { 19 | 'call': 'isIPhone', 20 | 'userAgent': 'Mozilla/5.0 (iPhone; CPU iPhone OS 7_0 like Mac OS X; en-us) AppleWebKit/537.51.1 (KHTML, like Gecko) Version/7.0 Mobile/11A465 Safari/9537.53' 21 | }, 22 | { 23 | 'call': 'isIPad', 24 | 'userAgent': 'Mozilla/5.0 (iPad; CPU OS 7_0 like Mac OS X) AppleWebKit/537.51.1 (KHTML, like Gecko) Version/7.0 Mobile/11A465 Safari/9537.53' 25 | }, 26 | { 27 | 'call': 'isIPod', 28 | 'userAgent': 'Mozilla/5.0 (iPod; U; CPU like Mac OS X; en) AppleWebKit/420.1 (KHTML, like Gecko) Version/3.0 Mobile/3A101a Safari/419.3' 29 | }, 30 | { 31 | 'call': 'isOpera', 32 | 'userAgent': 'Opera/9.80 (J2ME/MIDP; Opera Mini/9.80 (S60; SymbOS; Opera Mobi/23.348; U; en) Presto/2.5.25 Version/10.54' 33 | }, 34 | { 35 | 'call': 'isWindowsMobile', 36 | 'userAgent': 'Mozilla/5.0 (compatible; MSIE 9.0; Windows Phone OS 7.5; Trident/5.0; IEMobile/9.0' 37 | }, 38 | { 39 | 'call': 'isWindowsDesktop', 40 | 'userAgent': 'Mozilla/5.0 (compatible; MSIE 9.0; Windows Phone OS 7.5; Trident/5.0; WPDesktop/9.0' 41 | }, 42 | { 43 | 'call': 'isFireFox', 44 | 'userAgent': 'Mozilla/5.0 (Mobile; rv:14.0) Gecko/14.0 Firefox/14.0' 45 | }, 46 | { 47 | 'call': 'isNexus', 48 | 'userAgent': 'Mozilla/5.0 (Linux; Android 4.4.4; en-us; Nexus 4 Build/JOP40D) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2307.2 Mobile Safari/537.36' 49 | }, 50 | { 51 | 'call': 'isKindleFire', 52 | 'userAgent': 'Mozilla/5.0 (Linux; U; Android 2.3.4; en-us; Kindle Fire Build/GINGERBREAD) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1' 53 | }, 54 | { 55 | 'call': 'isPalm', 56 | 'userAgent': 'Mozilla/4.0 (compatible; MSIE 6.0; Windows 95; PalmSource; Blazer 3.0) 16; 160x160' 57 | }, 58 | { 59 | 'call': 'isAny', 60 | 'userAgent': 'Mozilla/5.0 (iPhone; CPU iPhone OS 7_0 like Mac OS X; en-us) AppleWebKit/537.51.1 (KHTML, like Gecko) Version/7.0 Mobile/11A465 Safari/9537.53' 61 | }, 62 | { 63 | 'call': 'isWindows', 64 | 'userAgent': 'Mozilla/5.0 (compatible; MSIE 9.0; Windows Phone OS 7.5; Trident/5.0; IEMobile/9.0' 65 | }, 66 | { 67 | 'call': 'isIOS', 68 | 'userAgent': 'Mozilla/5.0 (iPad; CPU OS 7_0 like Mac OS X) AppleWebKit/537.51.1 (KHTML, like Gecko) Version/7.0 Mobile/11A465 Safari/9537.53' 69 | } 70 | ]; -------------------------------------------------------------------------------- /detect-browser.js: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | * @auther SM@K 4 | * @description website: smak.pk 5 | */ 6 | 7 | (function() { 8 | var root = this; 9 | 10 | var SmartPhone = function(obj) { 11 | if (obj instanceof SmartPhone) 12 | return obj; 13 | if (!(this instanceof SmartPhone)) 14 | return new SmartPhone(obj); 15 | this._wrapped = obj; 16 | }; 17 | 18 | SmartPhone.userAgent = null; 19 | SmartPhone.getUserAgent = function() { 20 | return this.userAgent; 21 | }; 22 | 23 | SmartPhone.setUserAgent = function(userAgent) { 24 | this.userAgent = userAgent; 25 | }; 26 | 27 | SmartPhone.isAndroid = function() { 28 | return this.getUserAgent().match(/Android/i); 29 | }; 30 | 31 | SmartPhone.isBlackBerry = function() { 32 | return this.getUserAgent().match(/BlackBerry/i); 33 | }; 34 | 35 | SmartPhone.isBlackBerryPlayBook = function() { 36 | return this.getUserAgent().match(/PlayBook/i); 37 | }; 38 | 39 | SmartPhone.isBlackBerry10 = function() { 40 | return this.getUserAgent().match(/BB10/i); 41 | }; 42 | 43 | SmartPhone.isIOS = function() { 44 | return this.isIPhone() || this.isIPad() || this.isIPod(); 45 | }; 46 | 47 | SmartPhone.isIPhone = function() { 48 | return this.getUserAgent().match(/iPhone/i); 49 | }; 50 | 51 | SmartPhone.isIPad = function() { 52 | return this.getUserAgent().match(/iPad/i); 53 | }; 54 | 55 | SmartPhone.isIPod = function() { 56 | return this.getUserAgent().match(/iPod/i); 57 | }; 58 | 59 | SmartPhone.isOpera = function() { 60 | return this.getUserAgent().match(/Opera Mini/i); 61 | }; 62 | 63 | SmartPhone.isWindows = function() { 64 | return this.isWindowsDesktop() || this.isWindowsMobile(); 65 | }; 66 | 67 | SmartPhone.isWindowsMobile = function() { 68 | return this.getUserAgent().match(/IEMobile/i); 69 | }; 70 | 71 | SmartPhone.isWindowsDesktop = function() { 72 | return this.getUserAgent().match(/WPDesktop/i); 73 | }; 74 | 75 | SmartPhone.isFireFox = function() { 76 | return this.getUserAgent().match(/Firefox/i); 77 | }; 78 | 79 | SmartPhone.isNexus = function() { 80 | return this.getUserAgent().match(/Nexus/i); 81 | }; 82 | 83 | SmartPhone.isKindleFire = function() { 84 | return this.getUserAgent().match(/Kindle Fire/i); 85 | }; 86 | 87 | SmartPhone.isPalm = function() { 88 | return this.getUserAgent().match(/PalmSource|Palm/i); 89 | }; 90 | 91 | SmartPhone.isAny = function() { 92 | var foundAny = false; 93 | var getAllMethods = Object.getOwnPropertyNames(SmartPhone).filter(function(property) { 94 | return typeof SmartPhone[property] == 'function'; 95 | }); 96 | 97 | for (var index in getAllMethods) { 98 | if (getAllMethods[index] === 'setUserAgent' || getAllMethods[index] === 'getUserAgent' || 99 | getAllMethods[index] === 'isAny' || getAllMethods[index] === 'isWindows' || 100 | getAllMethods[index] === 'isIOS') { 101 | continue; 102 | } 103 | if (SmartPhone[getAllMethods[index]]()) { 104 | foundAny = true; 105 | break; 106 | } 107 | } 108 | return foundAny; 109 | }; 110 | 111 | if(typeof window === 'function' || typeof window === 'object') { 112 | SmartPhone.setUserAgent(navigator.userAgent); 113 | } 114 | 115 | if (typeof exports !== 'undefined') { 116 | 117 | var middleware = function(isMiddleware) { 118 | 119 | isMiddleware = isMiddleware === (void 0) ? true : isMiddleware; 120 | 121 | if(isMiddleware) { 122 | return function(req, res, next) { 123 | 124 | var userAgent = req.headers['user-agent'] || ''; 125 | SmartPhone.setUserAgent(userAgent); 126 | req.SmartPhone = SmartPhone; 127 | 128 | if ('function' === typeof res.locals) { 129 | res.locals({SmartPhone: SmartPhone}); 130 | } else { 131 | res.locals.SmartPhone = SmartPhone; 132 | } 133 | 134 | next(); 135 | }; 136 | } else { 137 | return SmartPhone; 138 | } 139 | 140 | }; 141 | 142 | if (typeof module !== 'undefined' && module.exports) { 143 | exports = module.exports = middleware; 144 | } 145 | exports = middleware; 146 | } else { 147 | root.SmartPhone = SmartPhone; 148 | } 149 | 150 | }.call(this)); 151 | --------------------------------------------------------------------------------