source: Dev/trunk/src/client/dojox/mobile/deviceTheme.js @ 532

Last change on this file since 532 was 483, checked in by hendrikvanantwerpen, 11 years ago

Added Dojo 1.9.3 release.

File size: 9.4 KB
Line 
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});
Note: See TracBrowser for help on using the repository browser.