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