239 lines
7.6 KiB
JavaScript
239 lines
7.6 KiB
JavaScript
define("dojox/mobile/iconUtils", [
|
|
"dojo/_base/array",
|
|
"dojo/_base/config",
|
|
"dojo/_base/connect",
|
|
"dojo/_base/event",
|
|
"dojo/_base/lang",
|
|
"dojo/_base/window",
|
|
"dojo/dom-class",
|
|
"dojo/dom-construct",
|
|
"dojo/dom-style",
|
|
"./sniff"
|
|
], function(array, config, connect, event, lang, win, domClass, domConstruct, domStyle, has){
|
|
|
|
var dm = lang.getObject("dojox.mobile", true);
|
|
|
|
// module:
|
|
// dojox/mobile/iconUtils
|
|
|
|
var IconUtils = function(){
|
|
// summary:
|
|
// Utilities to create an icon (image, CSS sprite image, or DOM Button).
|
|
|
|
this.setupSpriteIcon = function(/*DomNode*/iconNode, /*String*/iconPos){
|
|
// summary:
|
|
// Sets up CSS sprite for a foreground image.
|
|
if(iconNode && iconPos){
|
|
var arr = array.map(iconPos.split(/[ ,]/),function(item){return item-0});
|
|
var t = arr[0]; // top
|
|
var r = arr[1] + arr[2]; // right
|
|
var b = arr[0] + arr[3]; // bottom
|
|
var l = arr[1]; // left
|
|
domStyle.set(iconNode, {
|
|
clip: "rect("+t+"px "+r+"px "+b+"px "+l+"px)",
|
|
top: (iconNode.parentNode ? domStyle.get(iconNode, "top") : 0) - t + "px",
|
|
left: -l + "px"
|
|
});
|
|
domClass.add(iconNode, "mblSpriteIcon");
|
|
}
|
|
};
|
|
|
|
this.createDomButton = function(/*DomNode*/refNode, /*Object?*/style, /*DomNode?*/toNode){
|
|
// summary:
|
|
// Creates a DOM button.
|
|
// description:
|
|
// DOM button is a simple graphical object that consists of one or
|
|
// more nested DIV elements with some CSS styling. It can be used
|
|
// in place of an icon image on ListItem, IconItem, and so on.
|
|
// The kind of DOM button to create is given as a class name of
|
|
// refNode. The number of DIVs to create is searched from the style
|
|
// sheets in the page. However, if the class name has a suffix that
|
|
// starts with an underscore, like mblDomButtonGoldStar_5, then the
|
|
// suffixed number is used instead. A class name for DOM button
|
|
// must starts with 'mblDomButton'.
|
|
// refNode:
|
|
// A node that has a DOM button class name.
|
|
// style:
|
|
// A hash object to set styles to the node.
|
|
// toNode:
|
|
// A root node to create a DOM button. If omitted, refNode is used.
|
|
|
|
if(!this._domButtons){
|
|
if(has("webkit")){
|
|
var findDomButtons = function(sheet, dic){
|
|
// summary:
|
|
// Searches the style sheets for DOM buttons.
|
|
// description:
|
|
// Returns a key-value pair object whose keys are DOM
|
|
// button class names and values are the number of DOM
|
|
// elements they need.
|
|
var i, j;
|
|
if(!sheet){
|
|
var _dic = {};
|
|
var ss = win.doc.styleSheets;
|
|
for (i = 0; i < ss.length; i++){
|
|
ss[i] && findDomButtons(ss[i], _dic);
|
|
}
|
|
return _dic;
|
|
}
|
|
var rules = sheet.cssRules || [];
|
|
for (i = 0; i < rules.length; i++){
|
|
var rule = rules[i];
|
|
if(rule.href && rule.styleSheet){
|
|
findDomButtons(rule.styleSheet, dic);
|
|
}else if(rule.selectorText){
|
|
var sels = rule.selectorText.split(/,/);
|
|
for (j = 0; j < sels.length; j++){
|
|
var sel = sels[j];
|
|
var n = sel.split(/>/).length - 1;
|
|
if(sel.match(/(mblDomButton\w+)/)){
|
|
var cls = RegExp.$1;
|
|
if(!dic[cls] || n > dic[cls]){
|
|
dic[cls] = n;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return dic;
|
|
}
|
|
this._domButtons = findDomButtons();
|
|
}else{
|
|
this._domButtons = {};
|
|
}
|
|
}
|
|
|
|
var s = refNode.className;
|
|
var node = toNode || refNode;
|
|
if(s.match(/(mblDomButton\w+)/) && s.indexOf("/") === -1){
|
|
var btnClass = RegExp.$1;
|
|
var nDiv = 4;
|
|
if(s.match(/(mblDomButton\w+_(\d+))/)){
|
|
nDiv = RegExp.$2 - 0;
|
|
}else if(this._domButtons[btnClass] !== undefined){
|
|
nDiv = this._domButtons[btnClass];
|
|
}
|
|
var props = null;
|
|
if(has("bb") && config["mblBBBoxShadowWorkaround"] !== false){
|
|
// Removes box-shadow because BlackBerry incorrectly renders it.
|
|
props = {style:"-webkit-box-shadow:none"};
|
|
}
|
|
for(var i = 0, p = node; i < nDiv; i++){
|
|
p = p.firstChild || domConstruct.create("div", props, p);
|
|
}
|
|
if(toNode){
|
|
setTimeout(function(){
|
|
domClass.remove(refNode, btnClass);
|
|
}, 0);
|
|
domClass.add(toNode, btnClass);
|
|
}
|
|
}else if(s.indexOf(".") !== -1){ // file name
|
|
domConstruct.create("img", {src:s}, node);
|
|
}else{
|
|
return null;
|
|
}
|
|
domClass.add(node, "mblDomButton");
|
|
!!style && domStyle.set(node, style);
|
|
return node;
|
|
};
|
|
|
|
this.createIcon = function(/*String*/icon, /*String?*/iconPos, /*DomNode?*/node, /*String?*/title, /*DomNode?*/parent, /*DomNode?*/refNode, /*String?*/pos){
|
|
// summary:
|
|
// Creates or updates an icon node
|
|
// description:
|
|
// If node exists, updates the existing node. Otherwise, creates a new one.
|
|
// icon:
|
|
// Path for an image, or DOM button class name.
|
|
title = title || "";
|
|
if(icon && icon.indexOf("mblDomButton") === 0){
|
|
// DOM button
|
|
if(!node){
|
|
node = domConstruct.create("div", null, refNode || parent, pos);
|
|
}else{
|
|
if(node.className.match(/(mblDomButton\w+)/)){
|
|
domClass.remove(node, RegExp.$1);
|
|
}
|
|
}
|
|
node.title = title;
|
|
domClass.add(node, icon);
|
|
this.createDomButton(node);
|
|
}else if(icon && icon !== "none"){
|
|
// Image
|
|
if(!node || node.nodeName !== "IMG"){
|
|
node = domConstruct.create("img", {
|
|
alt: title
|
|
}, refNode || parent, pos);
|
|
}
|
|
node.src = (icon || "").replace("${theme}", dm.currentTheme);
|
|
this.setupSpriteIcon(node, iconPos);
|
|
if(iconPos && parent){
|
|
var arr = iconPos.split(/[ ,]/);
|
|
domStyle.set(parent, {
|
|
width: arr[2] + "px",
|
|
height: arr[3] + "px"
|
|
});
|
|
domClass.add(parent, "mblSpriteIconParent");
|
|
}
|
|
connect.connect(node, "ondragstart", event, "stop");
|
|
}
|
|
return node;
|
|
};
|
|
|
|
this.iconWrapper = false;
|
|
this.setIcon = function(/*String*/icon, /*String*/iconPos, /*DomNode*/iconNode, /*String?*/alt, /*DomNode*/parent, /*DomNode?*/refNode, /*String?*/pos){
|
|
// summary:
|
|
// A setter function to set an icon.
|
|
// description:
|
|
// This function is intended to be used by icon setters (e.g. _setIconAttr)
|
|
// icon:
|
|
// An icon path or a DOM button class name.
|
|
// iconPos:
|
|
// The position of an aggregated icon. IconPos is comma separated
|
|
// values like top,left,width,height (ex. "0,0,29,29").
|
|
// iconNode:
|
|
// An icon node.
|
|
// alt:
|
|
// An alt text for the icon image.
|
|
// parent:
|
|
// Parent node of the icon.
|
|
// refNode:
|
|
// A node reference to place the icon.
|
|
// pos:
|
|
// The position of the icon relative to refNode.
|
|
if(!parent || !icon && !iconNode){ return null; }
|
|
if(icon && icon !== "none"){ // create or update an icon
|
|
if(!this.iconWrapper && icon.indexOf("mblDomButton") !== 0 && !iconPos){ // image
|
|
if(iconNode && iconNode.tagName === "DIV"){
|
|
domConstruct.destroy(iconNode);
|
|
iconNode = null;
|
|
}
|
|
iconNode = this.createIcon(icon, null, iconNode, alt, parent, refNode, pos);
|
|
domClass.add(iconNode, "mblImageIcon");
|
|
}else{ // sprite or DOM button
|
|
if(iconNode && iconNode.tagName === "IMG"){
|
|
domConstruct.destroy(iconNode);
|
|
iconNode = null;
|
|
}
|
|
iconNode && domConstruct.empty(iconNode);
|
|
if(!iconNode){
|
|
iconNode = domConstruct.create("div", null, refNode || parent, pos);
|
|
}
|
|
this.createIcon(icon, iconPos, null, null, iconNode);
|
|
if(alt){
|
|
iconNode.title = alt;
|
|
}
|
|
}
|
|
domClass.remove(parent, "mblNoIcon");
|
|
return iconNode;
|
|
}else{ // clear the icon
|
|
domConstruct.destroy(iconNode);
|
|
domClass.add(parent, "mblNoIcon");
|
|
return null;
|
|
}
|
|
};
|
|
};
|
|
|
|
// Return singleton. (TODO: can we replace IconUtils class and singleton w/a simple hash of functions?)
|
|
return new IconUtils();
|
|
});
|