UNPKG

dojox

Version:

Dojo eXtensions, a rollup of many useful sub-projects and varying states of maturity – from very stable and robust, to alpha and experimental. See individual projects contain README files for details.

309 lines (295 loc) 9.84 kB
(typeof define === "undefined" ? function(deps, def) { def(); } : define)([ "dojo/_base/config", "dojo/_base/lang", "dojo/_base/window", "require" ], function(config, lang, win, require){ // module: // dojox/mobile/deviceTheme var dm = lang && lang.getObject("dojox.mobile", true) || {}; var DeviceTheme = function(){ // summary: // Automatic theme loader. // description: // This module detects the user agent of the browser and loads the // appropriate theme files. It can be enabled by simply including // the dojox/mobile/deviceTheme script in your application as follows: // // | <script src="dojox/mobile/deviceTheme.js"></script> // | <script src="dojo/dojo.js" data-dojo-config="parseOnLoad: true"></script> // // Using the script tag as above is the recommended way to load the // deviceTheme. Trying to load it using the AMD loader can lead to styles // being applied too late, because the loading of the theme files would // be performed asynchronously by the browser, so you could not assume // that the loading has been completed when your widgets are initialized. // However, loading deviceTheme using the script tag has the drawback that // deviceTheme.js cannot be included in a build. // // You can also pass an additional query parameter string: // theme={theme id} to force a specific theme through the browser // URL input. The available theme ids are Android, Holodark (theme introduced in Android 3.0), // BlackBerry, Custom, iPhone, and iPad. The theme names are case-sensitive. If the given // id does not match, the iOS7 theme is used. // // | http://your.server.com/yourapp.html // automatic detection // | http://your.server.com/yourapp.html?theme=Android // forces Android theme // | http://your.server.com/yourapp.html?theme=Holodark // forces Holodark theme // | http://your.server.com/yourapp.html?theme=BlackBerry // forces Blackberry theme // | http://your.server.com/yourapp.html?theme=Custom // forces Custom theme // | http://your.server.com/yourapp.html?theme=iPhone // forces iPhone theme // | http://your.server.com/yourapp.html?theme=iPad // forces iPad theme // | http://your.server.com/yourapp.html?theme=ios7 // forces iOS 7 theme // // To simulate a particular device from the application code, the user agent // can be forced by setting dojoConfig.mblUserAgent as follows: // // | <script src="dojox/mobile/deviceTheme.js" data-dojo-config="mblUserAgent: 'Holodark'"></script> // | <script src="dojo/dojo.js" data-dojo-config="parseOnLoad: true"></script> // // By default, an all-in-one theme file (e.g. themes/ios7/ios7.css) is // loaded. The all-in-one theme files contain style sheets for all the // dojox/mobile widgets regardless of whether they are used in your // application or not. // // If you want to choose what theme files to load, you can specify them // via dojoConfig or data-dojo-config as shown in the following example: // // | <script src="dojox/mobile/deviceTheme.js" // | data-dojo-config="mblThemeFiles:['base','Button']"></script> // | <script src="dojo/dojo.js" data-dojo-config="parseOnLoad: true"></script> // // In the case of this example, if iphone is detected, for example, the // following files will be loaded: // // | dojox/mobile/themes/ios7/base.css // | dojox/mobile/themes/ios7/Button.css // // If you want to load style sheets for your own custom widgets, you can // specify a package name along with a theme file name in an array. // // | ['base',['com.acme','MyWidget']] // // In this case, the following files will be loaded. // // | dojox/mobile/themes/ios7/base.css // | com/acme/themes/ios7/MyWidget.css // // If you specify '@theme' as a theme file name, it will be replaced with // the theme folder name (e.g. 'ios7'). For example, // // | ['@theme',['com.acme','MyWidget']] // // will load the following files: // // | dojox/mobile/themes/ios7/ios7.css // | com/acme/themes/ios7/MyWidget.css if(!win){ win = window; win.doc = document; win._no_dojo_dm = dm; } config = config || win.mblConfig || {}; var scripts = win.doc.getElementsByTagName("script"); for(var i = 0; i < scripts.length; i++){ var n = scripts[i]; var src = n.getAttribute("src") || ""; if(src.match(/\/deviceTheme\.js/i)){ config.baseUrl = src.replace("deviceTheme\.js", "../../dojo/"); var conf = (n.getAttribute("data-dojo-config") || n.getAttribute("djConfig")); if(conf){ var obj = eval("({ " + conf + " })"); for(var key in obj){ config[key] = obj[key]; } } break; }else if(src.match(/\/dojo\.js/i)){ config.baseUrl = src.replace("dojo\.js", ""); break; } } this.loadCssFile = function(/*String*/file){ // summary: // Loads the given CSS file programmatically. var link = win.doc.createElement("link"); link.href = file; link.type = "text/css"; link.rel = "stylesheet"; var head = win.doc.getElementsByTagName('head')[0]; head.insertBefore(link, head.firstChild); dm.loadedCssFiles.push(link); }; this.toUrl = function(/*String*/path){ // summary: // A wrapper for require.toUrl to support non-dojo usage. return require ? require.toUrl(path) : config.baseUrl + "../" + path; }; this.setDm = function(/*Object*/_dm){ // summary: // Replaces the dojox/mobile object. // description: // When this module is loaded from a script tag, dm is a plain // local object defined at the beginning of this module. // common.js will replace the local dm object with the // real dojox/mobile object through this method. dm = _dm; }; this.themeMap = config.themeMap || [ // summary: // A map of user-agents to theme files. // description: // The first array element is a regexp pattern that matches the // userAgent string. // // The second array element is a theme folder name. // // The third array element is an array of css file paths to load. // // The matching is performed in the array order, and stops after the // first match. [ "Holodark", "holodark", [] ], [ "Android [3-9]", "holodark", [] ], [ "Android", "android", [] ], [ "BlackBerry", "blackberry", [] ], [ "BB10", "blackberry", [] ], [ "ios7", "ios7", [] ], [ "iPhone;.*OS ([7-9]|1[0-9])_", "ios7", [] ], [ "iPad;.*OS ([7-9]|1[0-9])_", "ios7", [] ], [ "iPhone", "iphone", [] ], [ "iPad", "iphone", [this.toUrl("dojox/mobile/themes/iphone/ipad.css")] ], [ "WindowsPhone", "windows", [] ], [ "Windows Phone", "windows", [] ], [ "Trident", "ios7", [] ], [ "Custom", "custom", [] ], [ ".*", "ios7", [] ] ]; dm.loadedCssFiles = []; this.loadDeviceTheme = function(/*String?*/userAgent){ // summary: // Loads a device-specific theme according to the user-agent // string. // description: // This function is automatically called when this module is // evaluated. var t = config.mblThemeFiles || dm.themeFiles || ["@theme"]; var i, j; var m = this.themeMap; var ua = userAgent || config.mblUserAgent || (location.search.match(/theme=(\w+)/) ? RegExp.$1 : navigator.userAgent); for(i = 0; i < m.length; i++){ if(ua.match(new RegExp(m[i][0]))){ var theme = m[i][1]; if(theme == "windows" && config.mblDisableWindowsTheme){ continue; } var cls = win.doc.documentElement.className; cls = cls.replace(new RegExp(" *" + dm.currentTheme + "_theme"), "") + " " + theme + "_theme"; win.doc.documentElement.className = cls; dm.currentTheme = theme; var files = [].concat(m[i][2]); for(j = 0; j < t.length; j++){ var isArray = (t[j] instanceof Array || typeof t[j] == "array"); var path; if(!isArray && t[j].indexOf('/') !== -1){ path = t[j]; }else{ var pkg = isArray ? (t[j][0]||"").replace(/\./g, '/') : "dojox/mobile"; var name = (isArray ? t[j][1] : t[j]).replace(/\./g, '/'); var f = "themes/" + theme + "/" + (name === "@theme" ? theme : name) + ".css"; path = pkg + "/" + f; } files.unshift(this.toUrl(path)); } //remove old css files for(var k = 0; k < dm.loadedCssFiles.length; k++){ var n = dm.loadedCssFiles[k]; n.parentNode.removeChild(n); } dm.loadedCssFiles = []; for(j = 0; j < files.length; j++){ // dojox.mobile mirroring support var cssFilePath = files[j].toString(); if(config["dojo-bidi"] == true && cssFilePath.indexOf("_rtl") == -1){ var rtlCssList = "android.css blackberry.css custom.css iphone.css holodark.css base.css Carousel.css ComboBox.css IconContainer.css IconMenu.css ListItem.css RoundRectCategory.css SpinWheel.css Switch.css TabBar.css ToggleButton.css ToolBarButton.css ProgressIndicator.css Accordion.css GridLayout.css FormLayout.css"; var cssName = cssFilePath.substr(cssFilePath.lastIndexOf('/') + 1); if(rtlCssList.indexOf(cssName) != -1){ this.loadCssFile(cssFilePath.replace(".css","_rtl.css")); } } this.loadCssFile(files[j].toString()); } if(userAgent && dm.loadCompatCssFiles){ dm.loadCompatCssFiles(); } break; } } }; }; // Singleton. (TODO: can we replace DeviceTheme class and singleton w/a simple hash of functions?) var deviceTheme = new DeviceTheme(); deviceTheme.loadDeviceTheme(); window.deviceTheme = dm.deviceTheme = deviceTheme; return deviceTheme; });