diff options
Diffstat (limited to 'catapult/third_party/polymer/components/iron-iconset-svg/iron-iconset-svg.html')
-rw-r--r-- | catapult/third_party/polymer/components/iron-iconset-svg/iron-iconset-svg.html | 242 |
1 files changed, 242 insertions, 0 deletions
diff --git a/catapult/third_party/polymer/components/iron-iconset-svg/iron-iconset-svg.html b/catapult/third_party/polymer/components/iron-iconset-svg/iron-iconset-svg.html new file mode 100644 index 00000000..ab07e88c --- /dev/null +++ b/catapult/third_party/polymer/components/iron-iconset-svg/iron-iconset-svg.html @@ -0,0 +1,242 @@ +<!-- +@license +Copyright (c) 2015 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--> + +<link rel="import" href="../polymer/polymer.html"> +<link rel="import" href="../iron-meta/iron-meta.html"> + +<script> + /** + * The `iron-iconset-svg` element allows users to define their own icon sets + * that contain svg icons. The svg icon elements should be children of the + * `iron-iconset-svg` element. Multiple icons should be given distinct id's. + * + * Using svg elements to create icons has a few advantages over traditional + * bitmap graphics like jpg or png. Icons that use svg are vector based so + * they are resolution independent and should look good on any device. They + * are stylable via css. Icons can be themed, colorized, and even animated. + * + * Example: + * + * <iron-iconset-svg name="my-svg-icons" size="24"> + * <svg> + * <defs> + * <g id="shape"> + * <rect x="12" y="0" width="12" height="24" /> + * <circle cx="12" cy="12" r="12" /> + * </g> + * </defs> + * </svg> + * </iron-iconset-svg> + * + * This will automatically register the icon set "my-svg-icons" to the iconset + * database. To use these icons from within another element, make a + * `iron-iconset` element and call the `byId` method + * to retrieve a given iconset. To apply a particular icon inside an + * element use the `applyIcon` method. For example: + * + * iconset.applyIcon(iconNode, 'car'); + * + * @element iron-iconset-svg + * @demo demo/index.html + * @implements {Polymer.Iconset} + */ + Polymer({ + is: 'iron-iconset-svg', + + properties: { + + /** + * The name of the iconset. + */ + name: { + type: String, + observer: '_nameChanged' + }, + + /** + * The size of an individual icon. Note that icons must be square. + */ + size: { + type: Number, + value: 24 + }, + + /** + * Set to true to enable mirroring of icons where specified when they are + * stamped. Icons that should be mirrored should be decorated with a + * `mirror-in-rtl` attribute. + * + * NOTE: For performance reasons, direction will be resolved once per + * document per iconset, so moving icons in and out of RTL subtrees will + * not cause their mirrored state to change. + */ + rtlMirroring: { + type: Boolean, + value: false + } + }, + + attached: function() { + this.style.display = 'none'; + }, + + /** + * Construct an array of all icon names in this iconset. + * + * @return {!Array} Array of icon names. + */ + getIconNames: function() { + this._icons = this._createIconMap(); + return Object.keys(this._icons).map(function(n) { + return this.name + ':' + n; + }, this); + }, + + /** + * Applies an icon to the given element. + * + * An svg icon is prepended to the element's shadowRoot if it exists, + * otherwise to the element itself. + * + * If RTL mirroring is enabled, and the icon is marked to be mirrored in + * RTL, the element will be tested (once and only once ever for each + * iconset) to determine the direction of the subtree the element is in. + * This direction will apply to all future icon applications, although only + * icons marked to be mirrored will be affected. + * + * @method applyIcon + * @param {Element} element Element to which the icon is applied. + * @param {string} iconName Name of the icon to apply. + * @return {?Element} The svg element which renders the icon. + */ + applyIcon: function(element, iconName) { + // insert svg element into shadow root, if it exists + element = element.root || element; + // Remove old svg element + this.removeIcon(element); + // install new svg element + var svg = this._cloneIcon(iconName, + this.rtlMirroring && this._targetIsRTL(element)); + if (svg) { + var pde = Polymer.dom(element); + pde.insertBefore(svg, pde.childNodes[0]); + return element._svgIcon = svg; + } + return null; + }, + + /** + * Remove an icon from the given element by undoing the changes effected + * by `applyIcon`. + * + * @param {Element} element The element from which the icon is removed. + */ + removeIcon: function(element) { + // Remove old svg element + element = element.root || element; + if (element._svgIcon) { + Polymer.dom(element).removeChild(element._svgIcon); + element._svgIcon = null; + } + }, + + /** + * Measures and memoizes the direction of the element. Note that this + * measurement is only done once and the result is memoized for future + * invocations. + */ + _targetIsRTL: function(target) { + if (this.__targetIsRTL == null) { + if (target && target.nodeType !== Node.ELEMENT_NODE) { + target = target.host; + } + + this.__targetIsRTL = target && + window.getComputedStyle(target)['direction'] === 'rtl'; + } + + return this.__targetIsRTL; + }, + + /** + * + * When name is changed, register iconset metadata + * + */ + _nameChanged: function() { + new Polymer.IronMeta({type: 'iconset', key: this.name, value: this}); + this.async(function() { + this.fire('iron-iconset-added', this, {node: window}); + }); + }, + + /** + * Create a map of child SVG elements by id. + * + * @return {!Object} Map of id's to SVG elements. + */ + _createIconMap: function() { + // Objects chained to Object.prototype (`{}`) have members. Specifically, + // on FF there is a `watch` method that confuses the icon map, so we + // need to use a null-based object here. + var icons = Object.create(null); + Polymer.dom(this).querySelectorAll('[id]') + .forEach(function(icon) { + icons[icon.id] = icon; + }); + return icons; + }, + + /** + * Produce installable clone of the SVG element matching `id` in this + * iconset, or `undefined` if there is no matching element. + * + * @return {Element} Returns an installable clone of the SVG element + * matching `id`. + */ + _cloneIcon: function(id, mirrorAllowed) { + // create the icon map on-demand, since the iconset itself has no discrete + // signal to know when it's children are fully parsed + this._icons = this._icons || this._createIconMap(); + return this._prepareSvgClone(this._icons[id], this.size, mirrorAllowed); + }, + + /** + * @param {Element} sourceSvg + * @param {number} size + * @param {Boolean} mirrorAllowed + * @return {Element} + */ + _prepareSvgClone: function(sourceSvg, size, mirrorAllowed) { + if (sourceSvg) { + var content = sourceSvg.cloneNode(true), + svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg'), + viewBox = content.getAttribute('viewBox') || '0 0 ' + size + ' ' + size, + cssText = 'pointer-events: none; display: block; width: 100%; height: 100%;'; + + if (mirrorAllowed && content.hasAttribute('mirror-in-rtl')) { + cssText += '-webkit-transform:scale(-1,1);transform:scale(-1,1);'; + } + + svg.setAttribute('viewBox', viewBox); + svg.setAttribute('preserveAspectRatio', 'xMidYMid meet'); + svg.setAttribute('focusable', 'false'); + // TODO(dfreedm): `pointer-events: none` works around https://crbug.com/370136 + // TODO(sjmiles): inline style may not be ideal, but avoids requiring a shadow-root + svg.style.cssText = cssText; + svg.appendChild(content).removeAttribute('id'); + return svg; + } + return null; + } + + }); + +</script> |