[483] | 1 | (typeof define === "undefined" ? function(deps, def) { def(); } : define)([ |
---|
| 2 | "dojo/_base/config", |
---|
| 3 | "dojo/_base/lang", |
---|
| 4 | "dojo/_base/window", |
---|
| 5 | "require" |
---|
| 6 | ], function(config, lang, win, require){ |
---|
| 7 | |
---|
| 8 | // module: |
---|
| 9 | // dojox/mobile/deviceTheme |
---|
| 10 | |
---|
| 11 | var dm = lang && lang.getObject("dojox.mobile", true) || {}; |
---|
| 12 | |
---|
| 13 | var DeviceTheme = function(){ |
---|
| 14 | // summary: |
---|
| 15 | // Automatic theme loader. |
---|
| 16 | // description: |
---|
| 17 | // This module detects the user agent of the browser and loads the |
---|
| 18 | // appropriate theme files. It can be enabled by simply including |
---|
| 19 | // the dojox/mobile/deviceTheme script in your application as follows: |
---|
| 20 | // |
---|
| 21 | // | <script src="dojox/mobile/deviceTheme.js"></script> |
---|
| 22 | // | <script src="dojo/dojo.js" data-dojo-config="parseOnLoad: true"></script> |
---|
| 23 | // |
---|
| 24 | // Using the script tag as above is the recommended way to load the |
---|
| 25 | // deviceTheme. Trying to load it using the AMD loader can lead to styles |
---|
| 26 | // being applied too late, because the loading of the theme files would |
---|
| 27 | // be performed asynchronously by the browser, so you could not assume |
---|
| 28 | // that the loading has been completed when your widgets are initialized. |
---|
| 29 | // However, loading deviceTheme using the script tag has the drawback that |
---|
| 30 | // deviceTheme.js cannot be included in a build. |
---|
| 31 | // |
---|
| 32 | // You can also pass an additional query parameter string: |
---|
| 33 | // theme={theme id} to force a specific theme through the browser |
---|
| 34 | // URL input. The available theme ids are Android, Holodark (theme introduced in Android 3.0), |
---|
| 35 | // BlackBerry, Custom, iPhone, and iPad. The theme names are case-sensitive. If the given |
---|
| 36 | // id does not match, the iPhone theme is used. |
---|
| 37 | // |
---|
| 38 | // | http://your.server.com/yourapp.html // automatic detection |
---|
| 39 | // | http://your.server.com/yourapp.html?theme=Android // forces Android theme |
---|
| 40 | // | http://your.server.com/yourapp.html?theme=Holodark // forces Holodark theme |
---|
| 41 | // | http://your.server.com/yourapp.html?theme=BlackBerry // forces Blackberry theme |
---|
| 42 | // | http://your.server.com/yourapp.html?theme=Custom // forces Custom theme |
---|
| 43 | // | http://your.server.com/yourapp.html?theme=iPhone // forces iPhone theme |
---|
| 44 | // | http://your.server.com/yourapp.html?theme=iPad // forces iPad theme |
---|
| 45 | // |
---|
| 46 | // To simulate a particular device from the application code, the user agent |
---|
| 47 | // can be forced by setting dojoConfig.mblUserAgent as follows: |
---|
| 48 | // |
---|
| 49 | // | <script src="dojox/mobile/deviceTheme.js" data-dojo-config="mblUserAgent: 'Holodark'"></script> |
---|
| 50 | // | <script src="dojo/dojo.js" data-dojo-config="parseOnLoad: true"></script> |
---|
| 51 | // |
---|
| 52 | // By default, an all-in-one theme file (e.g. themes/iphone/iphone.css) is |
---|
| 53 | // loaded. The all-in-one theme files contain style sheets for all the |
---|
| 54 | // dojox/mobile widgets regardless of whether they are used in your |
---|
| 55 | // application or not. |
---|
| 56 | // |
---|
| 57 | // If you want to choose what theme files to load, you can specify them |
---|
| 58 | // via dojoConfig or data-dojo-config as shown in the following example: |
---|
| 59 | // |
---|
| 60 | // | <script src="dojox/mobile/deviceTheme.js" |
---|
| 61 | // | data-dojo-config="mblThemeFiles:['base','Button']"></script> |
---|
| 62 | // | <script src="dojo/dojo.js" data-dojo-config="parseOnLoad: true"></script> |
---|
| 63 | // |
---|
| 64 | // In the case of this example, if iphone is detected, for example, the |
---|
| 65 | // following files will be loaded: |
---|
| 66 | // |
---|
| 67 | // | dojox/mobile/themes/iphone/base.css |
---|
| 68 | // | dojox/mobile/themes/iphone/Button.css |
---|
| 69 | // |
---|
| 70 | // If you want to load style sheets for your own custom widgets, you can |
---|
| 71 | // specify a package name along with a theme file name in an array. |
---|
| 72 | // |
---|
| 73 | // | ['base',['com.acme','MyWidget']] |
---|
| 74 | // |
---|
| 75 | // In this case, the following files will be loaded. |
---|
| 76 | // |
---|
| 77 | // | dojox/mobile/themes/iphone/base.css |
---|
| 78 | // | com/acme/themes/iphone/MyWidget.css |
---|
| 79 | // |
---|
| 80 | // If you specify '@theme' as a theme file name, it will be replaced with |
---|
| 81 | // the theme folder name (e.g. 'iphone'). For example, |
---|
| 82 | // |
---|
| 83 | // | ['@theme',['com.acme','MyWidget']] |
---|
| 84 | // |
---|
| 85 | // will load the following files: |
---|
| 86 | // |
---|
| 87 | // | dojox/mobile/themes/iphone/iphone.css |
---|
| 88 | // | com/acme/themes/iphone/MyWidget.css |
---|
| 89 | |
---|
| 90 | if(!win){ |
---|
| 91 | win = window; |
---|
| 92 | win.doc = document; |
---|
| 93 | win._no_dojo_dm = dm; |
---|
| 94 | } |
---|
| 95 | config = config || win.mblConfig || {}; |
---|
| 96 | var scripts = win.doc.getElementsByTagName("script"); |
---|
| 97 | for(var i = 0; i < scripts.length; i++){ |
---|
| 98 | var n = scripts[i]; |
---|
| 99 | var src = n.getAttribute("src") || ""; |
---|
| 100 | if(src.match(/\/deviceTheme\.js/i)){ |
---|
| 101 | config.baseUrl = src.replace("deviceTheme\.js", "../../dojo/"); |
---|
| 102 | var conf = (n.getAttribute("data-dojo-config") || n.getAttribute("djConfig")); |
---|
| 103 | if(conf){ |
---|
| 104 | var obj = eval("({ " + conf + " })"); |
---|
| 105 | for(var key in obj){ |
---|
| 106 | config[key] = obj[key]; |
---|
| 107 | } |
---|
| 108 | } |
---|
| 109 | break; |
---|
| 110 | }else if(src.match(/\/dojo\.js/i)){ |
---|
| 111 | config.baseUrl = src.replace("dojo\.js", ""); |
---|
| 112 | break; |
---|
| 113 | } |
---|
| 114 | } |
---|
| 115 | |
---|
| 116 | this.loadCssFile = function(/*String*/file){ |
---|
| 117 | // summary: |
---|
| 118 | // Loads the given CSS file programmatically. |
---|
| 119 | var link = win.doc.createElement("link"); |
---|
| 120 | link.href = file; |
---|
| 121 | link.type = "text/css"; |
---|
| 122 | link.rel = "stylesheet"; |
---|
| 123 | var head = win.doc.getElementsByTagName('head')[0]; |
---|
| 124 | head.insertBefore(link, head.firstChild); |
---|
| 125 | dm.loadedCssFiles.push(link); |
---|
| 126 | }; |
---|
| 127 | |
---|
| 128 | this.toUrl = function(/*String*/path){ |
---|
| 129 | // summary: |
---|
| 130 | // A wrapper for require.toUrl to support non-dojo usage. |
---|
| 131 | return require ? require.toUrl(path) : config.baseUrl + "../" + path; |
---|
| 132 | }; |
---|
| 133 | |
---|
| 134 | this.setDm = function(/*Object*/_dm){ |
---|
| 135 | // summary: |
---|
| 136 | // Replaces the dojox/mobile object. |
---|
| 137 | // description: |
---|
| 138 | // When this module is loaded from a script tag, dm is a plain |
---|
| 139 | // local object defined at the begining of this module. |
---|
| 140 | // common.js will replace the local dm object with the |
---|
| 141 | // real dojox/mobile object through this method. |
---|
| 142 | dm = _dm; |
---|
| 143 | }; |
---|
| 144 | |
---|
| 145 | this.themeMap = config.themeMap || [ |
---|
| 146 | // summary: |
---|
| 147 | // A map of user-agents to theme files. |
---|
| 148 | // description: |
---|
| 149 | // The first array element is a regexp pattern that matches the |
---|
| 150 | // userAgent string. |
---|
| 151 | // |
---|
| 152 | // The second array element is a theme folder name. |
---|
| 153 | // |
---|
| 154 | // The third array element is an array of css file paths to load. |
---|
| 155 | // |
---|
| 156 | // The matching is performed in the array order, and stops after the |
---|
| 157 | // first match. |
---|
| 158 | [ |
---|
| 159 | "Holodark", |
---|
| 160 | "holodark", |
---|
| 161 | [] |
---|
| 162 | ], |
---|
| 163 | [ |
---|
| 164 | "Android 3", |
---|
| 165 | "holodark", |
---|
| 166 | [] |
---|
| 167 | ], |
---|
| 168 | [ |
---|
| 169 | "Android 4", |
---|
| 170 | "holodark", |
---|
| 171 | [] |
---|
| 172 | ], |
---|
| 173 | [ |
---|
| 174 | "Android", |
---|
| 175 | "android", |
---|
| 176 | [] |
---|
| 177 | ], |
---|
| 178 | [ |
---|
| 179 | "BlackBerry", |
---|
| 180 | "blackberry", |
---|
| 181 | [] |
---|
| 182 | ], |
---|
| 183 | [ |
---|
| 184 | "BB10", |
---|
| 185 | "blackberry", |
---|
| 186 | [] |
---|
| 187 | ], |
---|
| 188 | [ |
---|
| 189 | "iPhone", |
---|
| 190 | "iphone", |
---|
| 191 | [] |
---|
| 192 | ], |
---|
| 193 | [ |
---|
| 194 | "iPad", |
---|
| 195 | "iphone", |
---|
| 196 | [this.toUrl("dojox/mobile/themes/iphone/ipad.css")] |
---|
| 197 | ], |
---|
| 198 | [ |
---|
| 199 | "WindowsPhone", |
---|
| 200 | "windows", |
---|
| 201 | [] |
---|
| 202 | ], |
---|
| 203 | [ |
---|
| 204 | "MSIE [6-9]", |
---|
| 205 | "iphone", |
---|
| 206 | [] |
---|
| 207 | ], |
---|
| 208 | [ |
---|
| 209 | "Trident", |
---|
| 210 | "windows", |
---|
| 211 | [] |
---|
| 212 | ], |
---|
| 213 | [ |
---|
| 214 | "Custom", |
---|
| 215 | "custom", |
---|
| 216 | [] |
---|
| 217 | ], |
---|
| 218 | [ |
---|
| 219 | ".*", |
---|
| 220 | "iphone", |
---|
| 221 | [] |
---|
| 222 | ] |
---|
| 223 | ]; |
---|
| 224 | |
---|
| 225 | dm.loadedCssFiles = []; |
---|
| 226 | this.loadDeviceTheme = function(/*String?*/userAgent){ |
---|
| 227 | // summary: |
---|
| 228 | // Loads a device-specific theme according to the user-agent |
---|
| 229 | // string. |
---|
| 230 | // description: |
---|
| 231 | // This function is automatically called when this module is |
---|
| 232 | // evaluated. |
---|
| 233 | var t = config.mblThemeFiles || dm.themeFiles || ["@theme"]; |
---|
| 234 | var i, j; |
---|
| 235 | var m = this.themeMap; |
---|
| 236 | var ua = userAgent || config.mblUserAgent || (location.search.match(/theme=(\w+)/) ? RegExp.$1 : navigator.userAgent); |
---|
| 237 | for(i = 0; i < m.length; i++){ |
---|
| 238 | if(ua.match(new RegExp(m[i][0]))){ |
---|
| 239 | var theme = m[i][1]; |
---|
| 240 | if(theme == "windows" && config.mblDisableWindowsTheme){ |
---|
| 241 | continue; |
---|
| 242 | } |
---|
| 243 | var cls = win.doc.documentElement.className; |
---|
| 244 | cls = cls.replace(new RegExp(" *" + dm.currentTheme + "_theme"), "") + " " + theme + "_theme"; |
---|
| 245 | win.doc.documentElement.className = cls; |
---|
| 246 | dm.currentTheme = theme; |
---|
| 247 | var files = [].concat(m[i][2]); |
---|
| 248 | for(j = 0; j < t.length; j++){ |
---|
| 249 | var isArray = (t[j] instanceof Array || typeof t[j] == "array"); |
---|
| 250 | var path; |
---|
| 251 | if(!isArray && t[j].indexOf('/') !== -1){ |
---|
| 252 | path = t[j]; |
---|
| 253 | }else{ |
---|
| 254 | var pkg = isArray ? (t[j][0]||"").replace(/\./g, '/') : "dojox/mobile"; |
---|
| 255 | var name = (isArray ? t[j][1] : t[j]).replace(/\./g, '/'); |
---|
| 256 | var f = "themes/" + theme + "/" + |
---|
| 257 | (name === "@theme" ? theme : name) + ".css"; |
---|
| 258 | path = pkg + "/" + f; |
---|
| 259 | } |
---|
| 260 | files.unshift(this.toUrl(path)); |
---|
| 261 | } |
---|
| 262 | //remove old css files |
---|
| 263 | for(var k = 0; k < dm.loadedCssFiles.length; k++){ |
---|
| 264 | var n = dm.loadedCssFiles[k]; |
---|
| 265 | n.parentNode.removeChild(n); |
---|
| 266 | } |
---|
| 267 | dm.loadedCssFiles = []; |
---|
| 268 | for(j = 0; j < files.length; j++){ |
---|
| 269 | // dojox.mobile mirroring support |
---|
| 270 | var cssFilePath = files[j].toString(); |
---|
| 271 | if(config["dojo-bidi"] == true && cssFilePath.indexOf("_rtl") == -1){ |
---|
| 272 | 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"; |
---|
| 273 | var cssName = cssFilePath.substr(cssFilePath.lastIndexOf('/') + 1); |
---|
| 274 | if(rtlCssList.indexOf(cssName) != -1){ |
---|
| 275 | this.loadCssFile(cssFilePath.replace(".css","_rtl.css")); |
---|
| 276 | } |
---|
| 277 | } |
---|
| 278 | this.loadCssFile(files[j].toString()); |
---|
| 279 | } |
---|
| 280 | |
---|
| 281 | if(userAgent && dm.loadCompatCssFiles){ |
---|
| 282 | dm.loadCompatCssFiles(); |
---|
| 283 | } |
---|
| 284 | break; |
---|
| 285 | } |
---|
| 286 | } |
---|
| 287 | }; |
---|
| 288 | }; |
---|
| 289 | |
---|
| 290 | // Singleton. (TODO: can we replace DeviceTheme class and singleton w/a simple hash of functions?) |
---|
| 291 | var deviceTheme = new DeviceTheme(); |
---|
| 292 | |
---|
| 293 | deviceTheme.loadDeviceTheme(); |
---|
| 294 | window.deviceTheme = dm.deviceTheme = deviceTheme; |
---|
| 295 | |
---|
| 296 | return deviceTheme; |
---|
| 297 | }); |
---|