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 | }); |
---|