[483] | 1 | define([ |
---|
| 2 | "dojo/_base/array", |
---|
| 3 | "dojo/_base/config", |
---|
| 4 | "dojo/_base/connect", |
---|
| 5 | "dojo/_base/event", |
---|
| 6 | "dojo/_base/lang", |
---|
| 7 | "dojo/_base/window", |
---|
| 8 | "dojo/dom-class", |
---|
| 9 | "dojo/dom-construct", |
---|
| 10 | "dojo/dom-style", |
---|
| 11 | "./sniff" |
---|
| 12 | ], function(array, config, connect, event, lang, win, domClass, domConstruct, domStyle, has){ |
---|
| 13 | |
---|
| 14 | var dm = lang.getObject("dojox.mobile", true); |
---|
| 15 | |
---|
| 16 | // module: |
---|
| 17 | // dojox/mobile/iconUtils |
---|
| 18 | |
---|
| 19 | var IconUtils = function(){ |
---|
| 20 | // summary: |
---|
| 21 | // Utilities to create an icon (image, CSS sprite image, or DOM Button). |
---|
| 22 | |
---|
| 23 | this.setupSpriteIcon = function(/*DomNode*/iconNode, /*String*/iconPos){ |
---|
| 24 | // summary: |
---|
| 25 | // Sets up CSS sprite for a foreground image. |
---|
| 26 | if(iconNode && iconPos){ |
---|
| 27 | var arr = array.map(iconPos.split(/[ ,]/),function(item){return item-0}); |
---|
| 28 | var t = arr[0]; // top |
---|
| 29 | var r = arr[1] + arr[2]; // right |
---|
| 30 | var b = arr[0] + arr[3]; // bottom |
---|
| 31 | var l = arr[1]; // left |
---|
| 32 | domStyle.set(iconNode, { |
---|
| 33 | position: "absolute", |
---|
| 34 | clip: "rect("+t+"px "+r+"px "+b+"px "+l+"px)", |
---|
| 35 | top: (iconNode.parentNode ? domStyle.get(iconNode, "top") : 0) - t + "px", |
---|
| 36 | left: -l + "px" |
---|
| 37 | }); |
---|
| 38 | domClass.add(iconNode, "mblSpriteIcon"); |
---|
| 39 | } |
---|
| 40 | }; |
---|
| 41 | |
---|
| 42 | this.createDomButton = function(/*DomNode*/refNode, /*Object?*/style, /*DomNode?*/toNode){ |
---|
| 43 | // summary: |
---|
| 44 | // Creates a DOM button. |
---|
| 45 | // description: |
---|
| 46 | // DOM button is a simple graphical object that consists of one or |
---|
| 47 | // more nested DIV elements with some CSS styling. It can be used |
---|
| 48 | // in place of an icon image on ListItem, IconItem, and so on. |
---|
| 49 | // The kind of DOM button to create is given as a class name of |
---|
| 50 | // refNode. The number of DIVs to create is searched from the style |
---|
| 51 | // sheets in the page. However, if the class name has a suffix that |
---|
| 52 | // starts with an underscore, like mblDomButtonGoldStar_5, then the |
---|
| 53 | // suffixed number is used instead. A class name for DOM button |
---|
| 54 | // must starts with 'mblDomButton'. |
---|
| 55 | // refNode: |
---|
| 56 | // A node that has a DOM button class name. |
---|
| 57 | // style: |
---|
| 58 | // A hash object to set styles to the node. |
---|
| 59 | // toNode: |
---|
| 60 | // A root node to create a DOM button. If omitted, refNode is used. |
---|
| 61 | |
---|
| 62 | if(!this._domButtons){ |
---|
| 63 | if(has("webkit")){ |
---|
| 64 | var findDomButtons = function(sheet, dic){ |
---|
| 65 | // summary: |
---|
| 66 | // Searches the style sheets for DOM buttons. |
---|
| 67 | // description: |
---|
| 68 | // Returns a key-value pair object whose keys are DOM |
---|
| 69 | // button class names and values are the number of DOM |
---|
| 70 | // elements they need. |
---|
| 71 | var i, j; |
---|
| 72 | if(!sheet){ |
---|
| 73 | var _dic = {}; |
---|
| 74 | var ss = win.doc.styleSheets; |
---|
| 75 | for (i = 0; i < ss.length; i++){ |
---|
| 76 | ss[i] && findDomButtons(ss[i], _dic); |
---|
| 77 | } |
---|
| 78 | return _dic; |
---|
| 79 | } |
---|
| 80 | var rules = sheet.cssRules || []; |
---|
| 81 | for (i = 0; i < rules.length; i++){ |
---|
| 82 | var rule = rules[i]; |
---|
| 83 | if(rule.href && rule.styleSheet){ |
---|
| 84 | findDomButtons(rule.styleSheet, dic); |
---|
| 85 | }else if(rule.selectorText){ |
---|
| 86 | var sels = rule.selectorText.split(/,/); |
---|
| 87 | for (j = 0; j < sels.length; j++){ |
---|
| 88 | var sel = sels[j]; |
---|
| 89 | var n = sel.split(/>/).length - 1; |
---|
| 90 | if(sel.match(/(mblDomButton\w+)/)){ |
---|
| 91 | var cls = RegExp.$1; |
---|
| 92 | if(!dic[cls] || n > dic[cls]){ |
---|
| 93 | dic[cls] = n; |
---|
| 94 | } |
---|
| 95 | } |
---|
| 96 | } |
---|
| 97 | } |
---|
| 98 | } |
---|
| 99 | return dic; |
---|
| 100 | } |
---|
| 101 | this._domButtons = findDomButtons(); |
---|
| 102 | }else{ |
---|
| 103 | this._domButtons = {}; |
---|
| 104 | } |
---|
| 105 | } |
---|
| 106 | |
---|
| 107 | var s = refNode.className; |
---|
| 108 | var node = toNode || refNode; |
---|
| 109 | if(s.match(/(mblDomButton\w+)/) && s.indexOf("/") === -1){ |
---|
| 110 | var btnClass = RegExp.$1; |
---|
| 111 | var nDiv = 4; |
---|
| 112 | if(s.match(/(mblDomButton\w+_(\d+))/)){ |
---|
| 113 | nDiv = RegExp.$2 - 0; |
---|
| 114 | }else if(this._domButtons[btnClass] !== undefined){ |
---|
| 115 | nDiv = this._domButtons[btnClass]; |
---|
| 116 | } |
---|
| 117 | var props = null; |
---|
| 118 | if(has("bb") && config["mblBBBoxShadowWorkaround"] !== false){ |
---|
| 119 | // Removes box-shadow because BlackBerry incorrectly renders it. |
---|
| 120 | props = {style:"-webkit-box-shadow:none"}; |
---|
| 121 | } |
---|
| 122 | for(var i = 0, p = node; i < nDiv; i++){ |
---|
| 123 | p = p.firstChild || domConstruct.create("div", props, p); |
---|
| 124 | } |
---|
| 125 | if(toNode){ |
---|
| 126 | setTimeout(function(){ |
---|
| 127 | domClass.remove(refNode, btnClass); |
---|
| 128 | }, 0); |
---|
| 129 | domClass.add(toNode, btnClass); |
---|
| 130 | } |
---|
| 131 | }else if(s.indexOf(".") !== -1){ // file name |
---|
| 132 | domConstruct.create("img", {src:s}, node); |
---|
| 133 | }else{ |
---|
| 134 | return null; |
---|
| 135 | } |
---|
| 136 | domClass.add(node, "mblDomButton"); |
---|
| 137 | !!style && domStyle.set(node, style); |
---|
| 138 | return node; |
---|
| 139 | }; |
---|
| 140 | |
---|
| 141 | this.createIcon = function(/*String*/icon, /*String?*/iconPos, /*DomNode?*/node, /*String?*/title, /*DomNode?*/parent, /*DomNode?*/refNode, /*String?*/pos){ |
---|
| 142 | // summary: |
---|
| 143 | // Creates or updates an icon node |
---|
| 144 | // description: |
---|
| 145 | // If node exists, updates the existing node. Otherwise, creates a new one. |
---|
| 146 | // icon: |
---|
| 147 | // Path for an image, or DOM button class name. |
---|
| 148 | title = title || ""; |
---|
| 149 | if(icon && icon.indexOf("mblDomButton") === 0){ |
---|
| 150 | // DOM button |
---|
| 151 | if(!node){ |
---|
| 152 | node = domConstruct.create("div", null, refNode || parent, pos); |
---|
| 153 | }else{ |
---|
| 154 | if(node.className.match(/(mblDomButton\w+)/)){ |
---|
| 155 | domClass.remove(node, RegExp.$1); |
---|
| 156 | } |
---|
| 157 | } |
---|
| 158 | node.title = title; |
---|
| 159 | domClass.add(node, icon); |
---|
| 160 | this.createDomButton(node); |
---|
| 161 | }else if(icon && icon !== "none"){ |
---|
| 162 | // Image |
---|
| 163 | if(!node || node.nodeName !== "IMG"){ |
---|
| 164 | node = domConstruct.create("img", { |
---|
| 165 | alt: title |
---|
| 166 | }, refNode || parent, pos); |
---|
| 167 | } |
---|
| 168 | node.src = (icon || "").replace("${theme}", dm.currentTheme); |
---|
| 169 | this.setupSpriteIcon(node, iconPos); |
---|
| 170 | if(iconPos && parent){ |
---|
| 171 | var arr = iconPos.split(/[ ,]/); |
---|
| 172 | domStyle.set(parent, { |
---|
| 173 | position: "relative", |
---|
| 174 | width: arr[2] + "px", |
---|
| 175 | height: arr[3] + "px" |
---|
| 176 | }); |
---|
| 177 | domClass.add(parent, "mblSpriteIconParent"); |
---|
| 178 | } |
---|
| 179 | connect.connect(node, "ondragstart", event, "stop"); |
---|
| 180 | } |
---|
| 181 | return node; |
---|
| 182 | }; |
---|
| 183 | |
---|
| 184 | this.iconWrapper = false; |
---|
| 185 | this.setIcon = function(/*String*/icon, /*String*/iconPos, /*DomNode*/iconNode, /*String?*/alt, /*DomNode*/parent, /*DomNode?*/refNode, /*String?*/pos){ |
---|
| 186 | // summary: |
---|
| 187 | // A setter function to set an icon. |
---|
| 188 | // description: |
---|
| 189 | // This function is intended to be used by icon setters (e.g. _setIconAttr) |
---|
| 190 | // icon: |
---|
| 191 | // An icon path or a DOM button class name. |
---|
| 192 | // iconPos: |
---|
| 193 | // The position of an aggregated icon. IconPos is comma separated |
---|
| 194 | // values like top,left,width,height (ex. "0,0,29,29"). |
---|
| 195 | // iconNode: |
---|
| 196 | // An icon node. |
---|
| 197 | // alt: |
---|
| 198 | // An alt text for the icon image. |
---|
| 199 | // parent: |
---|
| 200 | // Parent node of the icon. |
---|
| 201 | // refNode: |
---|
| 202 | // A node reference to place the icon. |
---|
| 203 | // pos: |
---|
| 204 | // The position of the icon relative to refNode. |
---|
| 205 | if(!parent || !icon && !iconNode){ return null; } |
---|
| 206 | if(icon && icon !== "none"){ // create or update an icon |
---|
| 207 | if(!this.iconWrapper && icon.indexOf("mblDomButton") !== 0 && !iconPos){ // image |
---|
| 208 | if(iconNode && iconNode.tagName === "DIV"){ |
---|
| 209 | domConstruct.destroy(iconNode); |
---|
| 210 | iconNode = null; |
---|
| 211 | } |
---|
| 212 | iconNode = this.createIcon(icon, null, iconNode, alt, parent, refNode, pos); |
---|
| 213 | domClass.add(iconNode, "mblImageIcon"); |
---|
| 214 | }else{ // sprite or DOM button |
---|
| 215 | if(iconNode && iconNode.tagName === "IMG"){ |
---|
| 216 | domConstruct.destroy(iconNode); |
---|
| 217 | iconNode = null; |
---|
| 218 | } |
---|
| 219 | iconNode && domConstruct.empty(iconNode); |
---|
| 220 | if(!iconNode){ |
---|
| 221 | iconNode = domConstruct.create("div", null, refNode || parent, pos); |
---|
| 222 | } |
---|
| 223 | this.createIcon(icon, iconPos, null, null, iconNode); |
---|
| 224 | if(alt){ |
---|
| 225 | iconNode.title = alt; |
---|
| 226 | } |
---|
| 227 | } |
---|
| 228 | domClass.remove(parent, "mblNoIcon"); |
---|
| 229 | return iconNode; |
---|
| 230 | }else{ // clear the icon |
---|
| 231 | domConstruct.destroy(iconNode); |
---|
| 232 | domClass.add(parent, "mblNoIcon"); |
---|
| 233 | return null; |
---|
| 234 | } |
---|
| 235 | }; |
---|
| 236 | }; |
---|
| 237 | |
---|
| 238 | // Return singleton. (TODO: can we replace IconUtils class and singleton w/a simple hash of functions?) |
---|
| 239 | return new IconUtils(); |
---|
| 240 | }); |
---|