| OLD | NEW |
| (Empty) |
| 1 | |
| 2 | |
| 3 Polymer({ | |
| 4 | |
| 5 is: 'iron-iconset', | |
| 6 | |
| 7 properties: { | |
| 8 | |
| 9 /** | |
| 10 * The URL of the iconset image. | |
| 11 * | |
| 12 * @attribute src | |
| 13 * @type string | |
| 14 * @default '' | |
| 15 */ | |
| 16 src: { | |
| 17 type: String, | |
| 18 observer: '_srcChanged' | |
| 19 }, | |
| 20 | |
| 21 /** | |
| 22 * The name of the iconset. | |
| 23 * | |
| 24 * @attribute name | |
| 25 * @type string | |
| 26 * @default 'no-name' | |
| 27 */ | |
| 28 name: { | |
| 29 type: String, | |
| 30 observer: '_nameChanged' | |
| 31 }, | |
| 32 | |
| 33 /** | |
| 34 * The width of the iconset image. This must only be specified if the | |
| 35 * icons are arranged into separate rows inside the image. | |
| 36 * | |
| 37 * @attribute width | |
| 38 * @type number | |
| 39 * @default 0 | |
| 40 */ | |
| 41 width: { | |
| 42 type: Number, | |
| 43 value: 0 | |
| 44 }, | |
| 45 | |
| 46 /** | |
| 47 * A space separated list of names corresponding to icons in the iconset | |
| 48 * image file. This list must be ordered the same as the icon images | |
| 49 * in the image file. | |
| 50 * | |
| 51 * @attribute icons | |
| 52 * @type string | |
| 53 * @default '' | |
| 54 */ | |
| 55 icons: { | |
| 56 type: String | |
| 57 }, | |
| 58 | |
| 59 /** | |
| 60 * The size of an individual icon. Note that icons must be square. | |
| 61 * | |
| 62 * @attribute size | |
| 63 * @type number | |
| 64 * @default 24 | |
| 65 */ | |
| 66 size: { | |
| 67 type: Number, | |
| 68 value: 24 | |
| 69 }, | |
| 70 | |
| 71 /** | |
| 72 * The horizontal offset of the icon images in the inconset src image. | |
| 73 * This is typically used if the image resource contains additional images | |
| 74 * beside those intended for the iconset. | |
| 75 * | |
| 76 * @attribute offset-x | |
| 77 * @type number | |
| 78 * @default 0 | |
| 79 */ | |
| 80 _offsetX: { | |
| 81 type: Number, | |
| 82 value: 0 | |
| 83 }, | |
| 84 | |
| 85 /** | |
| 86 * The vertical offset of the icon images in the inconset src image. | |
| 87 * This is typically used if the image resource contains additional images | |
| 88 * beside those intended for the iconset. | |
| 89 * | |
| 90 * @attribute offset-y | |
| 91 * @type number | |
| 92 * @default 0 | |
| 93 */ | |
| 94 _offsetY: { | |
| 95 type: Number, | |
| 96 value: 0 | |
| 97 }, | |
| 98 | |
| 99 /** | |
| 100 * Array of fully-qualified names of icons in this set. | |
| 101 */ | |
| 102 iconNames: { | |
| 103 type: Array, | |
| 104 notify: true | |
| 105 } | |
| 106 | |
| 107 }, | |
| 108 | |
| 109 hostAttributes: { | |
| 110 // non-visual | |
| 111 style: 'display: none;' | |
| 112 }, | |
| 113 | |
| 114 ready: function() { | |
| 115 // theme data must exist at ready-time | |
| 116 this._themes = this._mapThemes(); | |
| 117 }, | |
| 118 | |
| 119 /** | |
| 120 * Applies an icon to the given element as a css background image. This | |
| 121 * method does not size the element, and it's usually necessary to set | |
| 122 * the element's height and width so that the background image is visible. | |
| 123 * | |
| 124 * @method applyIcon | |
| 125 * @param {Element} element The element to which the icon is applied. | |
| 126 * @param {String|Number} icon The name or index of the icon to apply. | |
| 127 * @param {String} theme (optional) The name or index of the icon to apply. | |
| 128 * @param {Number} scale (optional, defaults to 1) Icon scaling factor. | |
| 129 */ | |
| 130 applyIcon: function(element, icon, theme, scale) { | |
| 131 this._validateIconMap(); | |
| 132 var offset = this._getThemedOffset(icon, theme); | |
| 133 if (element && offset) { | |
| 134 this._addIconStyles(element, this._srcUrl, offset, scale || 1, | |
| 135 this.size, this.width); | |
| 136 } | |
| 137 }, | |
| 138 | |
| 139 /** | |
| 140 * Remove an icon from the given element by undoing the changes effected | |
| 141 * by `applyIcon`. | |
| 142 * | |
| 143 * @param {Element} element The element from which the icon is removed. | |
| 144 */ | |
| 145 removeIcon: function(element) { | |
| 146 this._removeIconStyles(element.style); | |
| 147 }, | |
| 148 | |
| 149 _mapThemes: function() { | |
| 150 var themes = Object.create(null); | |
| 151 Polymer.dom(this).querySelectorAll('property[theme]') | |
| 152 .forEach(function(property) { | |
| 153 var offsetX = window.parseInt( | |
| 154 property.getAttribute('offset-x'), 10 | |
| 155 ) || 0; | |
| 156 var offsetY = window.parseInt( | |
| 157 property.getAttribute('offset-y'), 10 | |
| 158 ) || 0; | |
| 159 themes[property.getAttribute('theme')] = { | |
| 160 offsetX: offsetX, | |
| 161 offsetY: offsetY | |
| 162 }; | |
| 163 }); | |
| 164 return themes; | |
| 165 }, | |
| 166 | |
| 167 _srcChanged: function(src) { | |
| 168 // ensure `srcUrl` is always relative to the main document | |
| 169 this._srcUrl = this.ownerDocument !== document | |
| 170 ? this.resolveUrl(src) : src; | |
| 171 this._prepareIconset(); | |
| 172 }, | |
| 173 | |
| 174 _nameChanged: function(name) { | |
| 175 this._prepareIconset(); | |
| 176 }, | |
| 177 | |
| 178 _prepareIconset: function() { | |
| 179 new Polymer.IronMeta({type: 'iconset', key: this.name, value: this}); | |
| 180 }, | |
| 181 | |
| 182 _invalidateIconMap: function() { | |
| 183 this._iconMapValid = false; | |
| 184 }, | |
| 185 | |
| 186 _validateIconMap: function() { | |
| 187 if (!this._iconMapValid) { | |
| 188 this._recomputeIconMap(); | |
| 189 this._iconMapValid = true; | |
| 190 } | |
| 191 }, | |
| 192 | |
| 193 _recomputeIconMap: function() { | |
| 194 this.iconNames = this._computeIconNames(this.icons); | |
| 195 this.iconMap = this._computeIconMap(this._offsetX, this._offsetY, | |
| 196 this.size, this.width, this.iconNames); | |
| 197 }, | |
| 198 | |
| 199 _computeIconNames: function(icons) { | |
| 200 return icons.split(/\s+/g); | |
| 201 }, | |
| 202 | |
| 203 _computeIconMap: function(offsetX, offsetY, size, width, iconNames) { | |
| 204 var iconMap = {}; | |
| 205 if (offsetX !== undefined && offsetY !== undefined) { | |
| 206 var x0 = offsetX; | |
| 207 iconNames.forEach(function(iconName) { | |
| 208 iconMap[iconName] = { | |
| 209 offsetX: offsetX, | |
| 210 offsetY: offsetY | |
| 211 }; | |
| 212 if ((offsetX + size) < width) { | |
| 213 offsetX += size; | |
| 214 } else { | |
| 215 offsetX = x0; | |
| 216 offsetY += size; | |
| 217 } | |
| 218 }, this); | |
| 219 } | |
| 220 return iconMap; | |
| 221 }, | |
| 222 | |
| 223 /** | |
| 224 * Returns an object containing `offsetX` and `offsetY` properties which | |
| 225 * specify the pixel location in the iconset's src file for the given | |
| 226 * `icon` and `theme`. It's uncommon to call this method. It is useful, | |
| 227 * for example, to manually position a css backgroundImage to the proper | |
| 228 * offset. It's more common to use the `applyIcon` method. | |
| 229 * | |
| 230 * @method getThemedOffset | |
| 231 * @param {String|Number} identifier The name of the icon or the index of | |
| 232 * the icon within in the icon image. | |
| 233 * @param {String} theme The name of the theme. | |
| 234 * @returns {Object} An object specifying the offset of the given icon | |
| 235 * within the icon resource file; `offsetX` is the horizontal offset and | |
| 236 * `offsetY` is the vertical offset. Both values are in pixel units. | |
| 237 */ | |
| 238 _getThemedOffset: function(identifier, theme) { | |
| 239 var iconOffset = this._getIconOffset(identifier); | |
| 240 var themeOffset = this._themes[theme]; | |
| 241 if (iconOffset && themeOffset) { | |
| 242 return { | |
| 243 offsetX: iconOffset.offsetX + themeOffset.offsetX, | |
| 244 offsetY: iconOffset.offsetY + themeOffset.offsetY | |
| 245 }; | |
| 246 } | |
| 247 return iconOffset; | |
| 248 }, | |
| 249 | |
| 250 _getIconOffset: function(identifier) { | |
| 251 // TODO(sjmiles): consider creating offsetArray (indexed by Number) | |
| 252 // and having iconMap map names to indices, then and index is just | |
| 253 // iconMap[identifier] || identifier (be careful of zero, store indices | |
| 254 // as 1-based) | |
| 255 return this.iconMap[identifier] || | |
| 256 this.iconMap[this.iconNames[Number(identifier)]]; | |
| 257 }, | |
| 258 | |
| 259 _addIconStyles: function(element, url, offset, scale, size, width) { | |
| 260 var style = element.style; | |
| 261 style.backgroundImage = 'url(' + url + ')'; | |
| 262 style.backgroundPosition = | |
| 263 (-offset.offsetX * scale + 'px') + ' ' + | |
| 264 (-offset.offsetY * scale + 'px'); | |
| 265 style.backgroundSize = (scale === 1) ? 'auto' : width * scale + 'px'; | |
| 266 style.width = size + 'px'; | |
| 267 style.height = size + 'px'; | |
| 268 element.setAttribute('role', 'img'); | |
| 269 }, | |
| 270 | |
| 271 _removeIconStyles: function(style) { | |
| 272 style.background = ''; | |
| 273 } | |
| 274 | |
| 275 }); | |
| 276 | |
| OLD | NEW |