PageSourceSearch

https://wpt.fyi/node_modules/@polymer/iron-iconset-svg/iron-iconset-svg.js

js wpt.fyi collected 2026-09-24 08:47:07 UTC 8,565 bytes, 257 lines download raw bytes

1/**
2@license
3Copyright (c) 2015 The Polymer Project Authors. All rights reserved.
4This code may only be used under the BSD style license found at
5http://polymer.github.io/LICENSE.txt The complete set of authors may be found at
6http://polymer.github.io/AUTHORS.txt The complete set of contributors may be
7found at http://polymer.github.io/CONTRIBUTORS.txt Code distributed by Google as
8part of the polymer project is also subject to an additional IP rights grant
9found at http://polymer.github.io/PATENTS.txt
10*/
11import '/node_modules/@polymer/polymer/polymer-legacy.js';
12
13import {IronMeta} from '/node_modules/@polymer/iron-meta/iron-meta.js';
14import {Polymer} from '/node_modules/@polymer/polymer/lib/legacy/polymer-fn.js';
15import {dom} from '/node_modules/@polymer/polymer/lib/legacy/polymer.dom.js';
16/**
17 * The `iron-iconset-svg` element allows users to define their own icon sets
18 * that contain svg icons. The svg icon elements should be children of the
19 * `iron-iconset-svg` element. Multiple icons should be given distinct id's.
20 *
21 * Using svg elements to create icons has a few advantages over traditional
22 * bitmap graphics like jpg or png. Icons that use svg are vector based so
23 * they are resolution independent and should look good on any device. They
24 * are stylable via css. Icons can be themed, colorized, and even animated.
25 *
26 * Example:
27 *
28 *     <iron-iconset-svg name="my-svg-icons" size="24">
29 *       <svg>
30 *         <defs>
31 *           <g id="shape">
32 *             <rect x="12" y="0" width="12" height="24" />
33 *             <circle cx="12" cy="12" r="12" />
34 *           </g>
35 *         </defs>
36 *       </svg>
37 *     </iron-iconset-svg>
38 *
39 * This will automatically register the icon set "my-svg-icons" to the iconset
40 * database.  To use these icons from within another element, make a
41 * `iron-iconset` element and call the `byId` method
42 * to retrieve a given iconset. To apply a particular icon inside an
43 * element use the `applyIcon` method. For example:
44 *
45 *     iconset.applyIcon(iconNode, 'car');
46 *
47 * @element iron-iconset-svg
48 * @demo demo/index.html
49 * @implements {Polymer.Iconset}
50 */
51Polymer({
52  is: 'iron-iconset-svg',
53
54  properties: {
55
56    /**
57     * The name of the iconset.
58     */
59    name: {type: String, observer: '_nameChanged'},
60
61    /**
62     * The size of an individual icon. Note that icons must be square.
63     */
64    size: {type: Number, value: 24},
65
66    /**
67     * Set to true to enable mirroring of icons where specified when they are
68     * stamped. Icons that should be mirrored should be decorated with a
69     * `mirror-in-rtl` attribute.
70     *
71     * NOTE: For performance reasons, direction will be resolved once per
72     * document per iconset, so moving icons in and out of RTL subtrees will
73     * not cause their mirrored state to change.
74     */
75    rtlMirroring: {type: Boolean, value: false},
76
77    /**
78     * Set to true to measure RTL based on the dir attribute on the body or
79     * html elements (measured on document.body or document.documentElement as
80     * available).
81     */
82    useGlobalRtlAttribute: {type: Boolean, value: false}
83  },
84
85  created: function() {
86    this._meta = new IronMeta({type: 'iconset', key: null, value: null});
87  },
88
89  attached: function() {
90    this.style.display = 'none';
91  },
92
93  /**
94   * Construct an array of all icon names in this iconset.
95   *
96   * @return {!Array} Array of icon names.
97   */
98  getIconNames: function() {
99    this._icons = this._createIconMap();
100    return Object.keys(this._icons).map(function(n) {
101      return this.name + ':' + n;
102    }, this);
103  },
104
105  /**
106   * Applies an icon to the given element.
107   *
108   * An svg icon is prepended to the element's shadowRoot if it exists,
109   * otherwise to the element itself.
110   *
111   * If RTL mirroring is enabled, and the icon is marked to be mirrored in
112   * RTL, the element will be tested (once and only once ever for each
113   * iconset) to determine the direction of the subtree the element is in.
114   * This direction will apply to all future icon applications, although only
115   * icons marked to be mirrored will be affected.
116   *
117   * @method applyIcon
118   * @param {Element} element Element to which the icon is applied.
119   * @param {string} iconName Name of the icon to apply.
120   * @return {?Element} The svg element which renders the icon.
121   */
122  applyIcon: function(element, iconName) {
123    // Remove old svg element
124    this.removeIcon(element);
125    // install new svg element
126    var svg = this._cloneIcon(
127        iconName, this.rtlMirroring && this._targetIsRTL(element));
128    if (svg) {
129      // insert svg element into shadow root, if it exists
130      var pde = dom(element.root || element);
131      pde.insertBefore(svg, pde.childNodes[0]);
132      return element._svgIcon = svg;
133    }
134    return null;
135  },
136
137  /**
138   * Remove an icon from the given element by undoing the changes effected
139   * by `applyIcon`.
140   *
141   * @param {Element} element The element from which the icon is removed.
142   */
143  removeIcon: function(element) {
144    // Remove old svg element
145    if (element._svgIcon) {
146      dom(element.root || element).removeChild(element._svgIcon);
147      element._svgIcon = null;
148    }
149  },
150
151  /**
152   * Measures and memoizes the direction of the element. Note that this
153   * measurement is only done once and the result is memoized for future
154   * invocations.
155   */
156  _targetIsRTL: function(target) {
157    if (this.__targetIsRTL == null) {
158      if (this.useGlobalRtlAttribute) {
159        var globalElement =
160            (document.body && document.body.hasAttribute('dir')) ?
161            document.body :
162            document.documentElement;
163
164        this.__targetIsRTL = globalElement.getAttribute('dir') === 'rtl';
165      } else {
166        if (target && target.nodeType !== Node.ELEMENT_NODE) {
167          target = target.host;
168        }
169
170        this.__targetIsRTL =
171            target && window.getComputedStyle(target)['direction'] === 'rtl';
172      }
173    }
174
175    return this.__targetIsRTL;
176  },
177
178  /**
179   *
180   * When name is changed, register iconset metadata
181   *
182   */
183  _nameChanged: function() {
184    this._meta.value = null;
185    this._meta.key = this.name;
186    this._meta.value = this;
187
188    this.async(function() {
189      this.fire('iron-iconset-added', this, {node: window}
189);
190    });
191  },
192
193  /**
194   * Create a map of child SVG elements by id.
195   *
196   * @return {!Object} Map of id's to SVG elements.
197   */
198  _createIconMap: function() {
199    // Objects chained to Object.prototype (`{}`) have members. Specifically,
200    // on FF there is a `watch` method that confuses the icon map, so we
201    // need to use a null-based object here.
202    var icons = Object.create(null);
203    dom(this).querySelectorAll('[id]').forEach(function(icon) {
204      icons[icon.id] = icon;
205    });
206    return icons;
207  },
208
209  /**
210   * Produce installable clone of the SVG element matching `id` in this
211   * iconset, or `undefined` if there is no matching element.
212   *
213   * @return {Element} Returns an installable clone of the SVG element
214   * matching `id`.
215   */
216  _cloneIcon: function(id, mirrorAllowed) {
217    // create the icon map on-demand, since the iconset itself has no discrete
218    // signal to know when it's children are fully parsed
219    this._icons = this._icons || this._createIconMap();
220    return this._prepareSvgClone(this._icons[id], this.size, mirrorAllowed);
221  },
222
223  /**
224   * @param {Element} sourceSvg
225   * @param {number} size
226   * @param {Boolean} mirrorAllowed
227   * @return {Element}
228   */
229  _prepareSvgClone: function(sourceSvg, size, mirrorAllowed) {
230    if (sourceSvg) {
231      var content = sourceSvg.cloneNode(true),
232          svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg'),
233          viewBox =
234              content.getAttribute('viewBox') || '0 0 ' + size + ' ' + size,
235          cssText =
236              'pointer-events: none; display: block; width: 100%; height: 100%;';
237
238      if (mirrorAllowed && content.hasAttribute('mirror-in-rtl')) {
239        cssText +=
240            '-webkit-transform:scale(-1,1);transform:scale(-1,1);transform-origin:center;';
241      }
242
243      svg.setAttribute('viewBox', viewBox);
244      svg.setAttribute('preserveAspectRatio', 'xMidYMid meet');
245      svg.setAttribute('focusable', 'false');
246      // TODO(dfreedm): `pointer-events: none` works around
247      // https://crbug.com/370136
248      // TODO(sjmiles): inline style may not be ideal, but avoids requiring a
249      // shadow-root
250      svg.style.cssText = cssText;
251      svg.appendChild(content).removeAttribute('id');
252      return svg;
253    }
254    return null;
255  }
256
257});

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.