1
2
3    Polymer('core-iconset', {
4
5      /**
6       * The URL of the iconset image.
7       *
8       * @attribute src
9       * @type string
10       * @default ''
11       */
12      src: '',
13
14      /**
15       * The width of the iconset image. This must only be specified if the
16       * icons are arranged into separate rows inside the image.
17       *
18       * @attribute width
19       * @type number
20       * @default 0
21       */
22      width: 0,
23
24      /**
25       * A space separated list of names corresponding to icons in the iconset
26       * image file. This list must be ordered the same as the icon images
27       * in the image file.
28       *
29       * @attribute icons
30       * @type string
31       * @default ''
32       */
33      icons: '',
34
35      /**
36       * The size of an individual icon. Note that icons must be square.
37       *
38       * @attribute iconSize
39       * @type number
40       * @default 24
41       */
42      iconSize: 24,
43
44      /**
45       * The horizontal offset of the icon images in the inconset src image.
46       * This is typically used if the image resource contains additional images
47       * beside those intended for the iconset.
48       *
49       * @attribute offsetX
50       * @type number
51       * @default 0
52       */
53      offsetX: 0,
54      /**
55       * The vertical offset of the icon images in the inconset src image.
56       * This is typically used if the image resource contains additional images
57       * beside those intended for the iconset.
58       *
59       * @attribute offsetY
60       * @type number
61       * @default 0
62       */
63      offsetY: 0,
64      type: 'iconset',
65
66      created: function() {
67        this.iconMap = {};
68        this.iconNames = [];
69        this.themes = {};
70      },
71
72      ready: function() {
73        // TODO(sorvell): ensure iconset's src is always relative to the main
74        // document
75        if (this.src && (this.ownerDocument !== document)) {
76          this.src = this.resolvePath(this.src, this.ownerDocument.baseURI);
77        }
78        this.super();
79        this.updateThemes();
80      },
81
82      iconsChanged: function() {
83        var ox = this.offsetX;
84        var oy = this.offsetY;
85        this.icons && this.icons.split(/\s+/g).forEach(function(name, i) {
86          this.iconNames.push(name);
87          this.iconMap[name] = {
88            offsetX: ox,
89            offsetY: oy
90          }
91          if (ox + this.iconSize < this.width) {
92            ox += this.iconSize;
93          } else {
94            ox = this.offsetX;
95            oy += this.iconSize;
96          }
97        }, this);
98      },
99
100      updateThemes: function() {
101        var ts = this.querySelectorAll('property[theme]');
102        ts && ts.array().forEach(function(t) {
103          this.themes[t.getAttribute('theme')] = {
104            offsetX: parseInt(t.getAttribute('offsetX')) || 0,
105            offsetY: parseInt(t.getAttribute('offsetY')) || 0
106          };
107        }, this);
108      },
109
110      // TODO(ffu): support retrived by index e.g. getOffset(10);
111      /**
112       * Returns an object containing `offsetX` and `offsetY` properties which
113       * specify the pixel locaion in the iconset's src file for the given
114       * `icon` and `theme`. It's uncommon to call this method. It is useful,
115       * for example, to manually position a css backgroundImage to the proper
116       * offset. It's more common to use the `applyIcon` method.
117       *
118       * @method getOffset
119       * @param {String|Number} icon The name of the icon or the index of the
120       * icon within in the icon image.
121       * @param {String} theme The name of the theme.
122       * @returns {Object} An object specifying the offset of the given icon
123       * within the icon resource file; `offsetX` is the horizontal offset and
124       * `offsetY` is the vertical offset. Both values are in pixel units.
125       */
126      getOffset: function(icon, theme) {
127        var i = this.iconMap[icon];
128        if (!i) {
129          var n = this.iconNames[Number(icon)];
130          i = this.iconMap[n];
131        }
132        var t = this.themes[theme];
133        if (i && t) {
134          return {
135            offsetX: i.offsetX + t.offsetX,
136            offsetY: i.offsetY + t.offsetY
137          }
138        }
139        return i;
140      },
141
142      /**
143       * Applies an icon to the given element as a css background image. This
144       * method does not size the element, and it's often necessary to set
145       * the element's height and width so that the background image is visible.
146       *
147       * @method applyIcon
148       * @param {Element} element The element to which the background is
149       * applied.
150       * @param {String|Number} icon The name or index of the icon to apply.
151       * @param {Number} scale (optional, defaults to 1) A scaling factor
152       * with which the icon can be magnified.
153       * @return {Element} The icon element.
154       */
155      applyIcon: function(element, icon, scale) {
156        var offset = this.getOffset(icon);
157        scale = scale || 1;
158        if (element && offset) {
159          var icon = element._icon || document.createElement('div');
160          var style = icon.style;
161          style.backgroundImage = 'url(' + this.src + ')';
162          style.backgroundPosition = (-offset.offsetX * scale + 'px') +
163             ' ' + (-offset.offsetY * scale + 'px');
164          style.backgroundSize = scale === 1 ? 'auto' :
165             this.width * scale + 'px';
166          if (icon.parentNode !== element) {
167            element.appendChild(icon);
168          }
169          return icon;
170        }
171      }
172
173    });
174
175