Update Polymer and pull in iron-list
[chromium-blink-merge.git] / third_party / polymer / v1_0 / components-chromium / iron-iconset-svg / iron-iconset-svg-extracted.js
blobe7fd402ab0a46dce812c1400087edcfa2c04505f
2   /**
3    * The `iron-iconset-svg` element allows users to define their own icon sets
4    * that contain svg icons. The svg icon elements should be children of the
5    * `iron-iconset-svg` element. Multiple icons should be given distinct id's.
6    *
7    * Using svg elements to create icons has a few advantages over traditional
8    * bitmap graphics like jpg or png. Icons that use svg are vector based so they
9    * are resolution independent and should look good on any device. They are
10    * stylable via css. Icons can be themed, colorized, and even animated.
11    *
12    * Example:
13    *
14    *     <iron-iconset-svg name="my-svg-icons" size="24">
15    *       <svg>
16    *         <defs>
17    *           <g id="shape">
18    *             <rect x="50" y="50" width="50" height="50" />
19    *             <circle cx="50" cy="50" r="50" />
20    *           </g>
21    *         </defs>
22    *       </svg>
23    *     </iron-iconset-svg>
24    *
25    * This will automatically register the icon set "my-svg-icons" to the iconset
26    * database.  To use these icons from within another element, make a
27    * `iron-iconset` element and call the `byId` method
28    * to retrieve a given iconset. To apply a particular icon inside an
29    * element use the `applyIcon` method. For example:
30    *
31    *     iconset.applyIcon(iconNode, 'car');
32    *
33    * @element iron-iconset-svg
34    * @demo demo/index.html
35    */
36   Polymer({
38     is: 'iron-iconset-svg',
40     properties: {
42       /**
43        * The name of the iconset.
44        *
45        * @attribute name
46        * @type string
47        */
48       name: {
49         type: String,
50         observer: '_nameChanged'
51       },
53       /**
54        * The size of an individual icon. Note that icons must be square.
55        *
56        * @attribute iconSize
57        * @type number
58        * @default 24
59        */
60       size: {
61         type: Number,
62         value: 24
63       }
65     },
67     /**
68      * Construct an array of all icon names in this iconset.
69      *
70      * @return {!Array} Array of icon names.
71      */
72     getIconNames: function() {
73       this._icons = this._createIconMap();
74       return Object.keys(this._icons).map(function(n) {
75         return this.name + ':' + n;
76       }, this);
77     },
79     /**
80      * Applies an icon to the given element.
81      *
82      * An svg icon is prepended to the element's shadowRoot if it exists,
83      * otherwise to the element itself.
84      *
85      * @method applyIcon
86      * @param {Element} element Element to which the icon is applied.
87      * @param {string} iconName Name of the icon to apply.
88      * @return {Element} The svg element which renders the icon.
89      */
90     applyIcon: function(element, iconName) {
91       // insert svg element into shadow root, if it exists
92       element = element.root || element;
93       // Remove old svg element
94       this.removeIcon(element);
95       // install new svg element
96       var svg = this._cloneIcon(iconName);
97       if (svg) {
98         var pde = Polymer.dom(element);
99         pde.insertBefore(svg, pde.childNodes[0]);
100         return element._svgIcon = svg;
101       }
102       return null;
103     },
105     /**
106      * Remove an icon from the given element by undoing the changes effected
107      * by `applyIcon`.
108      *
109      * @param {Element} element The element from which the icon is removed.
110      */
111     removeIcon: function(element) {
112       // Remove old svg element
113       if (element._svgIcon) {
114         Polymer.dom(element).removeChild(element._svgIcon);
115         element._svgIcon = null;
116       }
117     },
119     /**
120      *
121      * When name is changed, register iconset metadata
122      *
123      */
124     _nameChanged: function() {
125       new Polymer.IronMeta({type: 'iconset', key: this.name, value: this});
126     },
128     /**
129      * Create a map of child SVG elements by id.
130      *
131      * @return {!Object} Map of id's to SVG elements.
132      */
133     _createIconMap: function() {
134       // Objects chained to Object.prototype (`{}`) have members. Specifically,
135       // on FF there is a `watch` method that confuses the icon map, so we
136       // need to use a null-based object here.
137       var icons = Object.create(null);
138       Polymer.dom(this).querySelectorAll('[id]')
139         .forEach(function(icon) {
140           icons[icon.id] = icon;
141         });
142       return icons;
143     },
145     /**
146      * Produce installable clone of the SVG element matching `id` in this
147      * iconset, or `undefined` if there is no matching element.
148      *
149      * @return {Element} Returns an installable clone of the SVG element
150      * matching `id`.
151      */
152     _cloneIcon: function(id) {
153       // create the icon map on-demand, since the iconset itself has no discrete
154       // signal to know when it's children are fully parsed
155       this._icons = this._icons || this._createIconMap();
156       return this._prepareSvgClone(this._icons[id], this.size);
157     },
159     /**
160      * @param {Element} sourceSvg
161      * @param {number} size
162      * @return {Element}
163      */
164     _prepareSvgClone: function(sourceSvg, size) {
165       if (sourceSvg) {
166         var svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
167         svg.setAttribute('viewBox', ['0', '0', size, size].join(' '));
168         svg.setAttribute('preserveAspectRatio', 'xMidYMid meet');
169         // TODO(dfreedm): `pointer-events: none` works around https://crbug.com/370136
170         // TODO(sjmiles): inline style may not be ideal, but avoids requiring a shadow-root
171         svg.style.cssText = 'pointer-events: none; display: block; width: 100%; height: 100%;';
172         svg.appendChild(sourceSvg.cloneNode(true)).removeAttribute('id');
173         return svg;
174       }
175       return null;
176     }
178   });