You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
308 lines
9.6 KiB
308 lines
9.6 KiB
(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; |
|
});
|
|
|