| OLD | NEW |
| 1 <!DOCTYPE html><html><head><!-- | 1 <!DOCTYPE html><html><head><!-- |
| 2 @license | 2 @license |
| 3 Copyright (c) 2016 The Polymer Project Authors. All rights reserved. | 3 Copyright (c) 2016 The Polymer Project Authors. All rights reserved. |
| 4 This code may only be used under the BSD style license found at http://polymer.g
ithub.io/LICENSE.txt | 4 This code may only be used under the BSD style license found at http://polymer.g
ithub.io/LICENSE.txt |
| 5 The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt | 5 The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt |
| 6 The complete set of contributors may be found at http://polymer.github.io/CONTRI
BUTORS.txt | 6 The complete set of contributors may be found at http://polymer.github.io/CONTRI
BUTORS.txt |
| 7 Code distributed by Google as part of the polymer project is also | 7 Code distributed by Google as part of the polymer project is also |
| 8 subject to an additional IP rights grant found at http://polymer.github.io/PATEN
TS.txt | 8 subject to an additional IP rights grant found at http://polymer.github.io/PATEN
TS.txt |
| 9 --><!-- | 9 --><!-- |
| 10 @license | 10 @license |
| (...skipping 14629 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 14640 type: String, | 14640 type: String, |
| 14641 } | 14641 } |
| 14642 }, | 14642 }, |
| 14643 | 14643 |
| 14644 signIn: function(){ | 14644 signIn: function(){ |
| 14645 this.$.request.generateRequest(); | 14645 this.$.request.generateRequest(); |
| 14646 }, | 14646 }, |
| 14647 | 14647 |
| 14648 }); | 14648 }); |
| 14649 </script> | 14649 </script> |
| 14650 </dom-module> |
| 14651 |
| 14652 <script> |
| 14653 |
| 14654 (function() { |
| 14655 |
| 14656 // monostate data |
| 14657 var metaDatas = {}; |
| 14658 var metaArrays = {}; |
| 14659 var singleton = null; |
| 14660 |
| 14661 Polymer.IronMeta = Polymer({ |
| 14662 |
| 14663 is: 'iron-meta', |
| 14664 |
| 14665 properties: { |
| 14666 |
| 14667 /** |
| 14668 * The type of meta-data. All meta-data of the same type is stored |
| 14669 * together. |
| 14670 */ |
| 14671 type: { |
| 14672 type: String, |
| 14673 value: 'default', |
| 14674 observer: '_typeChanged' |
| 14675 }, |
| 14676 |
| 14677 /** |
| 14678 * The key used to store `value` under the `type` namespace. |
| 14679 */ |
| 14680 key: { |
| 14681 type: String, |
| 14682 observer: '_keyChanged' |
| 14683 }, |
| 14684 |
| 14685 /** |
| 14686 * The meta-data to store or retrieve. |
| 14687 */ |
| 14688 value: { |
| 14689 type: Object, |
| 14690 notify: true, |
| 14691 observer: '_valueChanged' |
| 14692 }, |
| 14693 |
| 14694 /** |
| 14695 * If true, `value` is set to the iron-meta instance itself. |
| 14696 */ |
| 14697 self: { |
| 14698 type: Boolean, |
| 14699 observer: '_selfChanged' |
| 14700 }, |
| 14701 |
| 14702 /** |
| 14703 * Array of all meta-data values for the given type. |
| 14704 */ |
| 14705 list: { |
| 14706 type: Array, |
| 14707 notify: true |
| 14708 } |
| 14709 |
| 14710 }, |
| 14711 |
| 14712 hostAttributes: { |
| 14713 hidden: true |
| 14714 }, |
| 14715 |
| 14716 /** |
| 14717 * Only runs if someone invokes the factory/constructor directly |
| 14718 * e.g. `new Polymer.IronMeta()` |
| 14719 * |
| 14720 * @param {{type: (string|undefined), key: (string|undefined), value}=} co
nfig |
| 14721 */ |
| 14722 factoryImpl: function(config) { |
| 14723 if (config) { |
| 14724 for (var n in config) { |
| 14725 switch(n) { |
| 14726 case 'type': |
| 14727 case 'key': |
| 14728 case 'value': |
| 14729 this[n] = config[n]; |
| 14730 break; |
| 14731 } |
| 14732 } |
| 14733 } |
| 14734 }, |
| 14735 |
| 14736 created: function() { |
| 14737 // TODO(sjmiles): good for debugging? |
| 14738 this._metaDatas = metaDatas; |
| 14739 this._metaArrays = metaArrays; |
| 14740 }, |
| 14741 |
| 14742 _keyChanged: function(key, old) { |
| 14743 this._resetRegistration(old); |
| 14744 }, |
| 14745 |
| 14746 _valueChanged: function(value) { |
| 14747 this._resetRegistration(this.key); |
| 14748 }, |
| 14749 |
| 14750 _selfChanged: function(self) { |
| 14751 if (self) { |
| 14752 this.value = this; |
| 14753 } |
| 14754 }, |
| 14755 |
| 14756 _typeChanged: function(type) { |
| 14757 this._unregisterKey(this.key); |
| 14758 if (!metaDatas[type]) { |
| 14759 metaDatas[type] = {}; |
| 14760 } |
| 14761 this._metaData = metaDatas[type]; |
| 14762 if (!metaArrays[type]) { |
| 14763 metaArrays[type] = []; |
| 14764 } |
| 14765 this.list = metaArrays[type]; |
| 14766 this._registerKeyValue(this.key, this.value); |
| 14767 }, |
| 14768 |
| 14769 /** |
| 14770 * Retrieves meta data value by key. |
| 14771 * |
| 14772 * @method byKey |
| 14773 * @param {string} key The key of the meta-data to be returned. |
| 14774 * @return {*} |
| 14775 */ |
| 14776 byKey: function(key) { |
| 14777 return this._metaData && this._metaData[key]; |
| 14778 }, |
| 14779 |
| 14780 _resetRegistration: function(oldKey) { |
| 14781 this._unregisterKey(oldKey); |
| 14782 this._registerKeyValue(this.key, this.value); |
| 14783 }, |
| 14784 |
| 14785 _unregisterKey: function(key) { |
| 14786 this._unregister(key, this._metaData, this.list); |
| 14787 }, |
| 14788 |
| 14789 _registerKeyValue: function(key, value) { |
| 14790 this._register(key, value, this._metaData, this.list); |
| 14791 }, |
| 14792 |
| 14793 _register: function(key, value, data, list) { |
| 14794 if (key && data && value !== undefined) { |
| 14795 data[key] = value; |
| 14796 list.push(value); |
| 14797 } |
| 14798 }, |
| 14799 |
| 14800 _unregister: function(key, data, list) { |
| 14801 if (key && data) { |
| 14802 if (key in data) { |
| 14803 var value = data[key]; |
| 14804 delete data[key]; |
| 14805 this.arrayDelete(list, value); |
| 14806 } |
| 14807 } |
| 14808 } |
| 14809 |
| 14810 }); |
| 14811 |
| 14812 Polymer.IronMeta.getIronMeta = function getIronMeta() { |
| 14813 if (singleton === null) { |
| 14814 singleton = new Polymer.IronMeta(); |
| 14815 } |
| 14816 return singleton; |
| 14817 }; |
| 14818 |
| 14819 /** |
| 14820 `iron-meta-query` can be used to access infomation stored in `iron-meta`. |
| 14821 |
| 14822 Examples: |
| 14823 |
| 14824 If I create an instance like this: |
| 14825 |
| 14826 <iron-meta key="info" value="foo/bar"></iron-meta> |
| 14827 |
| 14828 Note that value="foo/bar" is the metadata I've defined. I could define more |
| 14829 attributes or use child nodes to define additional metadata. |
| 14830 |
| 14831 Now I can access that element (and it's metadata) from any `iron-meta-query`
instance: |
| 14832 |
| 14833 var value = new Polymer.IronMetaQuery({key: 'info'}).value; |
| 14834 |
| 14835 @group Polymer Iron Elements |
| 14836 @element iron-meta-query |
| 14837 */ |
| 14838 Polymer.IronMetaQuery = Polymer({ |
| 14839 |
| 14840 is: 'iron-meta-query', |
| 14841 |
| 14842 properties: { |
| 14843 |
| 14844 /** |
| 14845 * The type of meta-data. All meta-data of the same type is stored |
| 14846 * together. |
| 14847 */ |
| 14848 type: { |
| 14849 type: String, |
| 14850 value: 'default', |
| 14851 observer: '_typeChanged' |
| 14852 }, |
| 14853 |
| 14854 /** |
| 14855 * Specifies a key to use for retrieving `value` from the `type` |
| 14856 * namespace. |
| 14857 */ |
| 14858 key: { |
| 14859 type: String, |
| 14860 observer: '_keyChanged' |
| 14861 }, |
| 14862 |
| 14863 /** |
| 14864 * The meta-data to store or retrieve. |
| 14865 */ |
| 14866 value: { |
| 14867 type: Object, |
| 14868 notify: true, |
| 14869 readOnly: true |
| 14870 }, |
| 14871 |
| 14872 /** |
| 14873 * Array of all meta-data values for the given type. |
| 14874 */ |
| 14875 list: { |
| 14876 type: Array, |
| 14877 notify: true |
| 14878 } |
| 14879 |
| 14880 }, |
| 14881 |
| 14882 /** |
| 14883 * Actually a factory method, not a true constructor. Only runs if |
| 14884 * someone invokes it directly (via `new Polymer.IronMeta()`); |
| 14885 * |
| 14886 * @param {{type: (string|undefined), key: (string|undefined)}=} config |
| 14887 */ |
| 14888 factoryImpl: function(config) { |
| 14889 if (config) { |
| 14890 for (var n in config) { |
| 14891 switch(n) { |
| 14892 case 'type': |
| 14893 case 'key': |
| 14894 this[n] = config[n]; |
| 14895 break; |
| 14896 } |
| 14897 } |
| 14898 } |
| 14899 }, |
| 14900 |
| 14901 created: function() { |
| 14902 // TODO(sjmiles): good for debugging? |
| 14903 this._metaDatas = metaDatas; |
| 14904 this._metaArrays = metaArrays; |
| 14905 }, |
| 14906 |
| 14907 _keyChanged: function(key) { |
| 14908 this._setValue(this._metaData && this._metaData[key]); |
| 14909 }, |
| 14910 |
| 14911 _typeChanged: function(type) { |
| 14912 this._metaData = metaDatas[type]; |
| 14913 this.list = metaArrays[type]; |
| 14914 if (this.key) { |
| 14915 this._keyChanged(this.key); |
| 14916 } |
| 14917 }, |
| 14918 |
| 14919 /** |
| 14920 * Retrieves meta data value by key. |
| 14921 * @param {string} key The key of the meta-data to be returned. |
| 14922 * @return {*} |
| 14923 */ |
| 14924 byKey: function(key) { |
| 14925 return this._metaData && this._metaData[key]; |
| 14926 } |
| 14927 |
| 14928 }); |
| 14929 |
| 14930 })(); |
| 14931 </script> |
| 14932 |
| 14933 |
| 14934 <dom-module id="iron-icon" assetpath="/res/imp/bower_components/iron-icon/"> |
| 14935 <template> |
| 14936 <style> |
| 14937 :host { |
| 14938 @apply(--layout-inline); |
| 14939 @apply(--layout-center-center); |
| 14940 position: relative; |
| 14941 |
| 14942 vertical-align: middle; |
| 14943 |
| 14944 fill: var(--iron-icon-fill-color, currentcolor); |
| 14945 stroke: var(--iron-icon-stroke-color, none); |
| 14946 |
| 14947 width: var(--iron-icon-width, 24px); |
| 14948 height: var(--iron-icon-height, 24px); |
| 14949 } |
| 14950 </style> |
| 14951 </template> |
| 14952 |
| 14953 <script> |
| 14954 |
| 14955 Polymer({ |
| 14956 |
| 14957 is: 'iron-icon', |
| 14958 |
| 14959 properties: { |
| 14960 |
| 14961 /** |
| 14962 * The name of the icon to use. The name should be of the form: |
| 14963 * `iconset_name:icon_name`. |
| 14964 */ |
| 14965 icon: { |
| 14966 type: String, |
| 14967 observer: '_iconChanged' |
| 14968 }, |
| 14969 |
| 14970 /** |
| 14971 * The name of the theme to used, if one is specified by the |
| 14972 * iconset. |
| 14973 */ |
| 14974 theme: { |
| 14975 type: String, |
| 14976 observer: '_updateIcon' |
| 14977 }, |
| 14978 |
| 14979 /** |
| 14980 * If using iron-icon without an iconset, you can set the src to be |
| 14981 * the URL of an individual icon image file. Note that this will take |
| 14982 * precedence over a given icon attribute. |
| 14983 */ |
| 14984 src: { |
| 14985 type: String, |
| 14986 observer: '_srcChanged' |
| 14987 }, |
| 14988 |
| 14989 /** |
| 14990 * @type {!Polymer.IronMeta} |
| 14991 */ |
| 14992 _meta: { |
| 14993 value: Polymer.Base.create('iron-meta', {type: 'iconset'}), |
| 14994 observer: '_updateIcon' |
| 14995 } |
| 14996 |
| 14997 }, |
| 14998 |
| 14999 _DEFAULT_ICONSET: 'icons', |
| 15000 |
| 15001 _iconChanged: function(icon) { |
| 15002 var parts = (icon || '').split(':'); |
| 15003 this._iconName = parts.pop(); |
| 15004 this._iconsetName = parts.pop() || this._DEFAULT_ICONSET; |
| 15005 this._updateIcon(); |
| 15006 }, |
| 15007 |
| 15008 _srcChanged: function(src) { |
| 15009 this._updateIcon(); |
| 15010 }, |
| 15011 |
| 15012 _usesIconset: function() { |
| 15013 return this.icon || !this.src; |
| 15014 }, |
| 15015 |
| 15016 /** @suppress {visibility} */ |
| 15017 _updateIcon: function() { |
| 15018 if (this._usesIconset()) { |
| 15019 if (this._img && this._img.parentNode) { |
| 15020 Polymer.dom(this.root).removeChild(this._img); |
| 15021 } |
| 15022 if (this._iconName === "") { |
| 15023 if (this._iconset) { |
| 15024 this._iconset.removeIcon(this); |
| 15025 } |
| 15026 } else if (this._iconsetName && this._meta) { |
| 15027 this._iconset = /** @type {?Polymer.Iconset} */ ( |
| 15028 this._meta.byKey(this._iconsetName)); |
| 15029 if (this._iconset) { |
| 15030 this._iconset.applyIcon(this, this._iconName, this.theme); |
| 15031 this.unlisten(window, 'iron-iconset-added', '_updateIcon'); |
| 15032 } else { |
| 15033 this.listen(window, 'iron-iconset-added', '_updateIcon'); |
| 15034 } |
| 15035 } |
| 15036 } else { |
| 15037 if (this._iconset) { |
| 15038 this._iconset.removeIcon(this); |
| 15039 } |
| 15040 if (!this._img) { |
| 15041 this._img = document.createElement('img'); |
| 15042 this._img.style.width = '100%'; |
| 15043 this._img.style.height = '100%'; |
| 15044 this._img.draggable = false; |
| 15045 } |
| 15046 this._img.src = this.src; |
| 15047 Polymer.dom(this.root).appendChild(this._img); |
| 15048 } |
| 15049 } |
| 15050 |
| 15051 }); |
| 15052 |
| 15053 </script> |
| 15054 |
| 15055 </dom-module> |
| 15056 <script> |
| 15057 /** |
| 15058 * The `iron-iconset-svg` element allows users to define their own icon sets |
| 15059 * that contain svg icons. The svg icon elements should be children of the |
| 15060 * `iron-iconset-svg` element. Multiple icons should be given distinct id's. |
| 15061 * |
| 15062 * Using svg elements to create icons has a few advantages over traditional |
| 15063 * bitmap graphics like jpg or png. Icons that use svg are vector based so |
| 15064 * they are resolution independent and should look good on any device. They |
| 15065 * are stylable via css. Icons can be themed, colorized, and even animated. |
| 15066 * |
| 15067 * Example: |
| 15068 * |
| 15069 * <iron-iconset-svg name="my-svg-icons" size="24"> |
| 15070 * <svg> |
| 15071 * <defs> |
| 15072 * <g id="shape"> |
| 15073 * <rect x="12" y="0" width="12" height="24" /> |
| 15074 * <circle cx="12" cy="12" r="12" /> |
| 15075 * </g> |
| 15076 * </defs> |
| 15077 * </svg> |
| 15078 * </iron-iconset-svg> |
| 15079 * |
| 15080 * This will automatically register the icon set "my-svg-icons" to the iconset |
| 15081 * database. To use these icons from within another element, make a |
| 15082 * `iron-iconset` element and call the `byId` method |
| 15083 * to retrieve a given iconset. To apply a particular icon inside an |
| 15084 * element use the `applyIcon` method. For example: |
| 15085 * |
| 15086 * iconset.applyIcon(iconNode, 'car'); |
| 15087 * |
| 15088 * @element iron-iconset-svg |
| 15089 * @demo demo/index.html |
| 15090 * @implements {Polymer.Iconset} |
| 15091 */ |
| 15092 Polymer({ |
| 15093 is: 'iron-iconset-svg', |
| 15094 |
| 15095 properties: { |
| 15096 |
| 15097 /** |
| 15098 * The name of the iconset. |
| 15099 */ |
| 15100 name: { |
| 15101 type: String, |
| 15102 observer: '_nameChanged' |
| 15103 }, |
| 15104 |
| 15105 /** |
| 15106 * The size of an individual icon. Note that icons must be square. |
| 15107 */ |
| 15108 size: { |
| 15109 type: Number, |
| 15110 value: 24 |
| 15111 } |
| 15112 |
| 15113 }, |
| 15114 |
| 15115 attached: function() { |
| 15116 this.style.display = 'none'; |
| 15117 }, |
| 15118 |
| 15119 /** |
| 15120 * Construct an array of all icon names in this iconset. |
| 15121 * |
| 15122 * @return {!Array} Array of icon names. |
| 15123 */ |
| 15124 getIconNames: function() { |
| 15125 this._icons = this._createIconMap(); |
| 15126 return Object.keys(this._icons).map(function(n) { |
| 15127 return this.name + ':' + n; |
| 15128 }, this); |
| 15129 }, |
| 15130 |
| 15131 /** |
| 15132 * Applies an icon to the given element. |
| 15133 * |
| 15134 * An svg icon is prepended to the element's shadowRoot if it exists, |
| 15135 * otherwise to the element itself. |
| 15136 * |
| 15137 * @method applyIcon |
| 15138 * @param {Element} element Element to which the icon is applied. |
| 15139 * @param {string} iconName Name of the icon to apply. |
| 15140 * @return {?Element} The svg element which renders the icon. |
| 15141 */ |
| 15142 applyIcon: function(element, iconName) { |
| 15143 // insert svg element into shadow root, if it exists |
| 15144 element = element.root || element; |
| 15145 // Remove old svg element |
| 15146 this.removeIcon(element); |
| 15147 // install new svg element |
| 15148 var svg = this._cloneIcon(iconName); |
| 15149 if (svg) { |
| 15150 var pde = Polymer.dom(element); |
| 15151 pde.insertBefore(svg, pde.childNodes[0]); |
| 15152 return element._svgIcon = svg; |
| 15153 } |
| 15154 return null; |
| 15155 }, |
| 15156 |
| 15157 /** |
| 15158 * Remove an icon from the given element by undoing the changes effected |
| 15159 * by `applyIcon`. |
| 15160 * |
| 15161 * @param {Element} element The element from which the icon is removed. |
| 15162 */ |
| 15163 removeIcon: function(element) { |
| 15164 // Remove old svg element |
| 15165 if (element._svgIcon) { |
| 15166 Polymer.dom(element).removeChild(element._svgIcon); |
| 15167 element._svgIcon = null; |
| 15168 } |
| 15169 }, |
| 15170 |
| 15171 /** |
| 15172 * |
| 15173 * When name is changed, register iconset metadata |
| 15174 * |
| 15175 */ |
| 15176 _nameChanged: function() { |
| 15177 new Polymer.IronMeta({type: 'iconset', key: this.name, value: this}); |
| 15178 this.async(function() { |
| 15179 this.fire('iron-iconset-added', this, {node: window}); |
| 15180 }); |
| 15181 }, |
| 15182 |
| 15183 /** |
| 15184 * Create a map of child SVG elements by id. |
| 15185 * |
| 15186 * @return {!Object} Map of id's to SVG elements. |
| 15187 */ |
| 15188 _createIconMap: function() { |
| 15189 // Objects chained to Object.prototype (`{}`) have members. Specifically, |
| 15190 // on FF there is a `watch` method that confuses the icon map, so we |
| 15191 // need to use a null-based object here. |
| 15192 var icons = Object.create(null); |
| 15193 Polymer.dom(this).querySelectorAll('[id]') |
| 15194 .forEach(function(icon) { |
| 15195 icons[icon.id] = icon; |
| 15196 }); |
| 15197 return icons; |
| 15198 }, |
| 15199 |
| 15200 /** |
| 15201 * Produce installable clone of the SVG element matching `id` in this |
| 15202 * iconset, or `undefined` if there is no matching element. |
| 15203 * |
| 15204 * @return {Element} Returns an installable clone of the SVG element |
| 15205 * matching `id`. |
| 15206 */ |
| 15207 _cloneIcon: function(id) { |
| 15208 // create the icon map on-demand, since the iconset itself has no discrete |
| 15209 // signal to know when it's children are fully parsed |
| 15210 this._icons = this._icons || this._createIconMap(); |
| 15211 return this._prepareSvgClone(this._icons[id], this.size); |
| 15212 }, |
| 15213 |
| 15214 /** |
| 15215 * @param {Element} sourceSvg |
| 15216 * @param {number} size |
| 15217 * @return {Element} |
| 15218 */ |
| 15219 _prepareSvgClone: function(sourceSvg, size) { |
| 15220 if (sourceSvg) { |
| 15221 var content = sourceSvg.cloneNode(true), |
| 15222 svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg'), |
| 15223 viewBox = content.getAttribute('viewBox') || '0 0 ' + size + ' ' + s
ize; |
| 15224 svg.setAttribute('viewBox', viewBox); |
| 15225 svg.setAttribute('preserveAspectRatio', 'xMidYMid meet'); |
| 15226 // TODO(dfreedm): `pointer-events: none` works around https://crbug.com/
370136 |
| 15227 // TODO(sjmiles): inline style may not be ideal, but avoids requiring a
shadow-root |
| 15228 svg.style.cssText = 'pointer-events: none; display: block; width: 100%;
height: 100%;'; |
| 15229 svg.appendChild(content).removeAttribute('id'); |
| 15230 return svg; |
| 15231 } |
| 15232 return null; |
| 15233 } |
| 15234 |
| 15235 }); |
| 15236 </script> |
| 15237 <iron-iconset-svg name="icons" size="24"> |
| 15238 <svg><defs> |
| 15239 <g id="3d-rotation"><path d="M7.52 21.48C4.25 19.94 1.91 16.76 1.55 13H.05C.56 1
9.16 5.71 24 12 24l.66-.03-3.81-3.81-1.33 1.32zm.89-6.52c-.19 0-.37-.03-.52-.08-
.16-.06-.29-.13-.4-.24-.11-.1-.2-.22-.26-.37-.06-.14-.09-.3-.09-.47h-1.3c0 .36.0
7.68.21.95.14.27.33.5.56.69.24.18.51.32.82.41.3.1.62.15.96.15.37 0 .72-.05 1.03-
.15.32-.1.6-.25.83-.44s.42-.43.55-.72c.13-.29.2-.61.2-.97 0-.19-.02-.38-.07-.56-
.05-.18-.12-.35-.23-.51-.1-.16-.24-.3-.4-.43-.17-.13-.37-.23-.61-.31.2-.09.37-.2
.52-.33.15-.13.27-.27.37-.42.1-.15.17-.3.22-.46.05-.16.07-.32.07-.48 0-.36-.06-.
68-.18-.96-.12-.28-.29-.51-.51-.69-.2-.19-.47-.33-.77-.43C9.1 8.05 8.76 8 8.39 8
c-.36 0-.69.05-1 .16-.3.11-.57.26-.79.45-.21.19-.38.41-.51.67-.12.26-.18.54-.18.
85h1.3c0-.17.03-.32.09-.45s.14-.25.25-.34c.11-.09.23-.17.38-.22.15-.05.3-.08.48-
.08.4 0 .7.1.89.31.19.2.29.49.29.86 0 .18-.03.34-.08.49-.05.15-.14.27-.25.37-.11
.1-.25.18-.41.24-.16.06-.36.09-.58.09H7.5v1.03h.77c.22 0 .42.02.6.07s.33.13.45.2
3c.12.11.22.24.29.4.07.16.1.35.1.57 0 .41-.12.72-.35.93-.23.23-.55.33-.95.33zm8.
55-5.92c-.32-.33-.7-.59-1.14-.77-.43-.18-.92-.27-1.46-.27H12v8h2.3c.55 0 1.06-.0
9 1.51-.27.45-.18.84-.43 1.16-.76.32-.33.57-.73.74-1.19.17-.47.26-.99.26-1.57v-.
4c0-.58-.09-1.1-.26-1.57-.18-.47-.43-.87-.75-1.2zm-.39 3.16c0 .42-.05.79-.14 1.1
3-.1.33-.24.62-.43.85-.19.23-.43.41-.71.53-.29.12-.62.18-.99.18h-.91V9.12h.97c.7
2 0 1.27.23 1.64.69.38.46.57 1.12.57 1.99v.4zM12 0l-.66.03 3.81 3.81 1.33-1.33c3
.27 1.55 5.61 4.72 5.96 8.48h1.5C23.44 4.84 18.29 0 12 0z"></path></g> |
| 15240 <g id="accessibility"><path d="M12 2c1.1 0 2 .9 2 2s-.9 2-2 2-2-.9-2-2 .9-2 2-2z
m9 7h-6v13h-2v-6h-2v6H9V9H3V7h18v2z"></path></g> |
| 15241 <g id="accessible"><circle cx="12" cy="4" r="2"></circle><path d="M19 13v-2c-1.5
4.02-3.09-.75-4.07-1.83l-1.29-1.43c-.17-.19-.38-.34-.61-.45-.01 0-.01-.01-.02-.0
1H13c-.35-.2-.75-.3-1.19-.26C10.76 7.11 10 8.04 10 9.09V15c0 1.1.9 2 2 2h5v5h2v-
5.5c0-1.1-.9-2-2-2h-3v-3.45c1.29 1.07 3.25 1.94 5 1.95zm-6.17 5c-.41 1.16-1.52 2
-2.83 2-1.66 0-3-1.34-3-3 0-1.31.84-2.41 2-2.83V12.1c-2.28.46-4 2.48-4 4.9 0 2.7
6 2.24 5 5 5 2.42 0 4.44-1.72 4.9-4h-2.07z"></path></g> |
| 15242 <g id="account-balance"><path d="M4 10v7h3v-7H4zm6 0v7h3v-7h-3zM2 22h19v-3H2v3zm
14-12v7h3v-7h-3zm-4.5-9L2 6v2h19V6l-9.5-5z"></path></g> |
| 15243 <g id="account-balance-wallet"><path d="M21 18v1c0 1.1-.9 2-2 2H5c-1.11 0-2-.9-2
-2V5c0-1.1.89-2 2-2h14c1.1 0 2 .9 2 2v1h-9c-1.11 0-2 .9-2 2v8c0 1.1.89 2 2 2h9zm
-9-2h10V8H12v8zm4-2.5c-.83 0-1.5-.67-1.5-1.5s.67-1.5 1.5-1.5 1.5.67 1.5 1.5-.67
1.5-1.5 1.5z"></path></g> |
| 15244 <g id="account-box"><path d="M3 5v14c0 1.1.89 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9
-2-2-2H5c-1.11 0-2 .9-2 2zm12 4c0 1.66-1.34 3-3 3s-3-1.34-3-3 1.34-3 3-3 3 1.34
3 3zm-9 8c0-2 4-3.1 6-3.1s6 1.1 6 3.1v1H6v-1z"></path></g> |
| 15245 <g id="account-circle"><path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 1
0-10S17.52 2 12 2zm0 3c1.66 0 3 1.34 3 3s-1.34 3-3 3-3-1.34-3-3 1.34-3 3-3zm0 14
.2c-2.5 0-4.71-1.28-6-3.22.03-1.99 4-3.08 6-3.08 1.99 0 5.97 1.09 6 3.08-1.29 1.
94-3.5 3.22-6 3.22z"></path></g> |
| 15246 <g id="add"><path d="M19 13h-6v6h-2v-6H5v-2h6V5h2v6h6v2z"></path></g> |
| 15247 <g id="add-alert"><path d="M10.01 21.01c0 1.1.89 1.99 1.99 1.99s1.99-.89 1.99-1.
99h-3.98zm8.87-4.19V11c0-3.25-2.25-5.97-5.29-6.69v-.72C13.59 2.71 12.88 2 12 2s-
1.59.71-1.59 1.59v.72C7.37 5.03 5.12 7.75 5.12 11v5.82L3 18.94V20h18v-1.06l-2.12
-2.12zM16 13.01h-3v3h-2v-3H8V11h3V8h2v3h3v2.01z"></path></g> |
| 15248 <g id="add-box"><path d="M19 3H5c-1.11 0-2 .9-2 2v14c0 1.1.89 2 2 2h14c1.1 0 2-.
9 2-2V5c0-1.1-.9-2-2-2zm-2 10h-4v4h-2v-4H7v-2h4V7h2v4h4v2z"></path></g> |
| 15249 <g id="add-circle"><path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10
S17.52 2 12 2zm5 11h-4v4h-2v-4H7v-2h4V7h2v4h4v2z"></path></g> |
| 15250 <g id="add-circle-outline"><path d="M13 7h-2v4H7v2h4v4h2v-4h4v-2h-4V7zm-1-5C6.48
2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm0 18c-4.41 0-8-3.59-8-8
s3.59-8 8-8 8 3.59 8 8-3.59 8-8 8z"></path></g> |
| 15251 <g id="add-shopping-cart"><path d="M11 9h2V6h3V4h-3V1h-2v3H8v2h3v3zm-4 9c-1.1 0-
1.99.9-1.99 2S5.9 22 7 22s2-.9 2-2-.9-2-2-2zm10 0c-1.1 0-1.99.9-1.99 2s.89 2 1.9
9 2 2-.9 2-2-.9-2-2-2zm-9.83-3.25l.03-.12.9-1.63h7.45c.75 0 1.41-.41 1.75-1.03l3
.86-7.01L19.42 4h-.01l-1.1 2-2.76 5H8.53l-.13-.27L6.16 6l-.95-2-.94-2H1v2h2l3.6
7.59-1.35 2.45c-.16.28-.25.61-.25.96 0 1.1.9 2 2 2h12v-2H7.42c-.13 0-.25-.11-.25
-.25z"></path></g> |
| 15252 <g id="alarm"><path d="M22 5.72l-4.6-3.86-1.29 1.53 4.6 3.86L22 5.72zM7.88 3.39L
6.6 1.86 2 5.71l1.29 1.53 4.59-3.85zM12.5 8H11v6l4.75 2.85.75-1.23-4-2.37V8zM12
4c-4.97 0-9 4.03-9 9s4.02 9 9 9c4.97 0 9-4.03 9-9s-4.03-9-9-9zm0 16c-3.87 0-7-3.
13-7-7s3.13-7 7-7 7 3.13 7 7-3.13 7-7 7z"></path></g> |
| 15253 <g id="alarm-add"><path d="M7.88 3.39L6.6 1.86 2 5.71l1.29 1.53 4.59-3.85zM22 5.
72l-4.6-3.86-1.29 1.53 4.6 3.86L22 5.72zM12 4c-4.97 0-9 4.03-9 9s4.02 9 9 9c4.97
0 9-4.03 9-9s-4.03-9-9-9zm0 16c-3.87 0-7-3.13-7-7s3.13-7 7-7 7 3.13 7 7-3.13 7-
7 7zm1-11h-2v3H8v2h3v3h2v-3h3v-2h-3V9z"></path></g> |
| 15254 <g id="alarm-off"><path d="M12 6c3.87 0 7 3.13 7 7 0 .84-.16 1.65-.43 2.4l1.52 1
.52c.58-1.19.91-2.51.91-3.92 0-4.97-4.03-9-9-9-1.41 0-2.73.33-3.92.91L9.6 6.43C1
0.35 6.16 11.16 6 12 6zm10-.28l-4.6-3.86-1.29 1.53 4.6 3.86L22 5.72zM2.92 2.29L1
.65 3.57 2.98 4.9l-1.11.93 1.42 1.42 1.11-.94.8.8C3.83 8.69 3 10.75 3 13c0 4.97
4.02 9 9 9 2.25 0 4.31-.83 5.89-2.2l2.2 2.2 1.27-1.27L3.89 3.27l-.97-.98zm13.55
16.1C15.26 19.39 13.7 20 12 20c-3.87 0-7-3.13-7-7 0-1.7.61-3.26 1.61-4.47l9.86 9
.86zM8.02 3.28L6.6 1.86l-.86.71 1.42 1.42.86-.71z"></path></g> |
| 15255 <g id="alarm-on"><path d="M22 5.72l-4.6-3.86-1.29 1.53 4.6 3.86L22 5.72zM7.88 3.
39L6.6 1.86 2 5.71l1.29 1.53 4.59-3.85zM12 4c-4.97 0-9 4.03-9 9s4.02 9 9 9c4.97
0 9-4.03 9-9s-4.03-9-9-9zm0 16c-3.87 0-7-3.13-7-7s3.13-7 7-7 7 3.13 7 7-3.13 7-7
7zm-1.46-5.47L8.41 12.4l-1.06 1.06 3.18 3.18 6-6-1.06-1.06-4.93 4.95z"></path><
/g> |
| 15256 <g id="all-out"><path d="M16.21 4.16l4 4v-4zm4 12l-4 4h4zm-12 4l-4-4v4zm-4-12l4-
4h-4zm12.95-.95c-2.73-2.73-7.17-2.73-9.9 0s-2.73 7.17 0 9.9 7.17 2.73 9.9 0 2.73
-7.16 0-9.9zm-1.1 8.8c-2.13 2.13-5.57 2.13-7.7 0s-2.13-5.57 0-7.7 5.57-2.13 7.7
0 2.13 5.57 0 7.7z"></path></g> |
| 15257 <g id="android"><path d="M6 18c0 .55.45 1 1 1h1v3.5c0 .83.67 1.5 1.5 1.5s1.5-.67
1.5-1.5V19h2v3.5c0 .83.67 1.5 1.5 1.5s1.5-.67 1.5-1.5V19h1c.55 0 1-.45 1-1V8H6v
10zM3.5 8C2.67 8 2 8.67 2 9.5v7c0 .83.67 1.5 1.5 1.5S5 17.33 5 16.5v-7C5 8.67 4.
33 8 3.5 8zm17 0c-.83 0-1.5.67-1.5 1.5v7c0 .83.67 1.5 1.5 1.5s1.5-.67 1.5-1.5v-7
c0-.83-.67-1.5-1.5-1.5zm-4.97-5.84l1.3-1.3c.2-.2.2-.51 0-.71-.2-.2-.51-.2-.71 0l
-1.48 1.48C13.85 1.23 12.95 1 12 1c-.96 0-1.86.23-2.66.63L7.85.15c-.2-.2-.51-.2-
.71 0-.2.2-.2.51 0 .71l1.31 1.31C6.97 3.26 6 5.01 6 7h12c0-1.99-.97-3.75-2.47-4.
84zM10 5H9V4h1v1zm5 0h-1V4h1v1z"></path></g> |
| 15258 <g id="announcement"><path d="M20 2H4c-1.1 0-1.99.9-1.99 2L2 22l4-4h14c1.1 0 2-.
9 2-2V4c0-1.1-.9-2-2-2zm-7 9h-2V5h2v6zm0 4h-2v-2h2v2z"></path></g> |
| 15259 <g id="apps"><path d="M4 8h4V4H4v4zm6 12h4v-4h-4v4zm-6 0h4v-4H4v4zm0-6h4v-4H4v4z
m6 0h4v-4h-4v4zm6-10v4h4V4h-4zm-6 4h4V4h-4v4zm6 6h4v-4h-4v4zm0 6h4v-4h-4v4z"></p
ath></g> |
| 15260 <g id="archive"><path d="M20.54 5.23l-1.39-1.68C18.88 3.21 18.47 3 18 3H6c-.47 0
-.88.21-1.16.55L3.46 5.23C3.17 5.57 3 6.02 3 6.5V19c0 1.1.9 2 2 2h14c1.1 0 2-.9
2-2V6.5c0-.48-.17-.93-.46-1.27zM12 17.5L6.5 12H10v-2h4v2h3.5L12 17.5zM5.12 5l.81
-1h12l.94 1H5.12z"></path></g> |
| 15261 <g id="arrow-back"><path d="M20 11H7.83l5.59-5.59L12 4l-8 8 8 8 1.41-1.41L7.83 1
3H20v-2z"></path></g> |
| 15262 <g id="arrow-downward"><path d="M20 12l-1.41-1.41L13 16.17V4h-2v12.17l-5.58-5.59
L4 12l8 8 8-8z"></path></g> |
| 15263 <g id="arrow-drop-down"><path d="M7 10l5 5 5-5z"></path></g> |
| 15264 <g id="arrow-drop-down-circle"><path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 1
0-4.48 10-10S17.52 2 12 2zm0 12l-4-4h8l-4 4z"></path></g> |
| 15265 <g id="arrow-drop-up"><path d="M7 14l5-5 5 5z"></path></g> |
| 15266 <g id="arrow-forward"><path d="M12 4l-1.41 1.41L16.17 11H4v2h12.17l-5.58 5.59L12
20l8-8z"></path></g> |
| 15267 <g id="arrow-upward"><path d="M4 12l1.41 1.41L11 7.83V20h2V7.83l5.58 5.59L20 12l
-8-8-8 8z"></path></g> |
| 15268 <g id="aspect-ratio"><path d="M19 12h-2v3h-3v2h5v-5zM7 9h3V7H5v5h2V9zm14-6H3c-1.
1 0-2 .9-2 2v14c0 1.1.9 2 2 2h18c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm0 16.01H3V4.99
h18v14.02z"></path></g> |
| 15269 <g id="assessment"><path d="M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-
.9 2-2V5c0-1.1-.9-2-2-2zM9 17H7v-7h2v7zm4 0h-2V7h2v10zm4 0h-2v-4h2v4z"></path></
g> |
| 15270 <g id="assignment"><path d="M19 3h-4.18C14.4 1.84 13.3 1 12 1c-1.3 0-2.4.84-2.82
2H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-7 0c.
55 0 1 .45 1 1s-.45 1-1 1-1-.45-1-1 .45-1 1-1zm2 14H7v-2h7v2zm3-4H7v-2h10v2zm0-4
H7V7h10v2z"></path></g> |
| 15271 <g id="assignment-ind"><path d="M19 3h-4.18C14.4 1.84 13.3 1 12 1c-1.3 0-2.4.84-
2.82 2H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-7
0c.55 0 1 .45 1 1s-.45 1-1 1-1-.45-1-1 .45-1 1-1zm0 4c1.66 0 3 1.34 3 3s-1.34 3
-3 3-3-1.34-3-3 1.34-3 3-3zm6 12H6v-1.4c0-2 4-3.1 6-3.1s6 1.1 6 3.1V19z"></path>
</g> |
| 15272 <g id="assignment-late"><path d="M19 3h-4.18C14.4 1.84 13.3 1 12 1c-1.3 0-2.4.84
-2.82 2H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-
6 15h-2v-2h2v2zm0-4h-2V8h2v6zm-1-9c-.55 0-1-.45-1-1s.45-1 1-1 1 .45 1 1-.45 1-1
1z"></path></g> |
| 15273 <g id="assignment-return"><path d="M19 3h-4.18C14.4 1.84 13.3 1 12 1c-1.3 0-2.4.
84-2.82 2H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2z
m-7 0c.55 0 1 .45 1 1s-.45 1-1 1-1-.45-1-1 .45-1 1-1zm4 12h-4v3l-5-5 5-5v3h4v4z"
></path></g> |
| 15274 <g id="assignment-returned"><path d="M19 3h-4.18C14.4 1.84 13.3 1 12 1c-1.3 0-2.
4.84-2.82 2H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-
2zm-7 0c.55 0 1 .45 1 1s-.45 1-1 1-1-.45-1-1 .45-1 1-1zm0 15l-5-5h3V9h4v4h3l-5 5
z"></path></g> |
| 15275 <g id="assignment-turned-in"><path d="M19 3h-4.18C14.4 1.84 13.3 1 12 1c-1.3 0-2
.4.84-2.82 2H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2
-2zm-7 0c.55 0 1 .45 1 1s-.45 1-1 1-1-.45-1-1 .45-1 1-1zm-2 14l-4-4 1.41-1.41L10
14.17l6.59-6.59L18 9l-8 8z"></path></g> |
| 15276 <g id="attachment"><path d="M2 12.5C2 9.46 4.46 7 7.5 7H18c2.21 0 4 1.79 4 4s-1.
79 4-4 4H9.5C8.12 15 7 13.88 7 12.5S8.12 10 9.5 10H17v2H9.41c-.55 0-.55 1 0 1H18
c1.1 0 2-.9 2-2s-.9-2-2-2H7.5C5.57 9 4 10.57 4 12.5S5.57 16 7.5 16H17v2H7.5C4.46
18 2 15.54 2 12.5z"></path></g> |
| 15277 <g id="autorenew"><path d="M12 6v3l4-4-4-4v3c-4.42 0-8 3.58-8 8 0 1.57.46 3.03 1
.24 4.26L6.7 14.8c-.45-.83-.7-1.79-.7-2.8 0-3.31 2.69-6 6-6zm6.76 1.74L17.3 9.2c
.44.84.7 1.79.7 2.8 0 3.31-2.69 6-6 6v-3l-4 4 4 4v-3c4.42 0 8-3.58 8-8 0-1.57-.4
6-3.03-1.24-4.26z"></path></g> |
| 15278 <g id="backspace"><path d="M22 3H7c-.69 0-1.23.35-1.59.88L0 12l5.41 8.11c.36.53.
9.89 1.59.89h15c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-3 12.59L17.59 17 14 13.41 10.4
1 17 9 15.59 12.59 12 9 8.41 10.41 7 14 10.59 17.59 7 19 8.41 15.41 12 19 15.59z
"></path></g> |
| 15279 <g id="backup"><path d="M19.35 10.04C18.67 6.59 15.64 4 12 4 9.11 4 6.6 5.64 5.3
5 8.04 2.34 8.36 0 10.91 0 14c0 3.31 2.69 6 6 6h13c2.76 0 5-2.24 5-5 0-2.64-2.05
-4.78-4.65-4.96zM14 13v4h-4v-4H7l5-5 5 5h-3z"></path></g> |
| 15280 <g id="block"><path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.5
2 2 12 2zM4 12c0-4.42 3.58-8 8-8 1.85 0 3.55.63 4.9 1.69L5.69 16.9C4.63 15.55 4
13.85 4 12zm8 8c-1.85 0-3.55-.63-4.9-1.69L18.31 7.1C19.37 8.45 20 10.15 20 12c0
4.42-3.58 8-8 8z"></path></g> |
| 15281 <g id="book"><path d="M18 2H6c-1.1 0-2 .9-2 2v16c0 1.1.9 2 2 2h12c1.1 0 2-.9 2-2
V4c0-1.1-.9-2-2-2zM6 4h5v8l-2.5-1.5L6 12V4z"></path></g> |
| 15282 <g id="bookmark"><path d="M17 3H7c-1.1 0-1.99.9-1.99 2L5 21l7-3 7 3V5c0-1.1-.9-2
-2-2z"></path></g> |
| 15283 <g id="bookmark-border"><path d="M17 3H7c-1.1 0-1.99.9-1.99 2L5 21l7-3 7 3V5c0-1
.1-.9-2-2-2zm0 15l-5-2.18L7 18V5h10v13z"></path></g> |
| 15284 <g id="bug-report"><path d="M20 8h-2.81c-.45-.78-1.07-1.45-1.82-1.96L17 4.41 15.
59 3l-2.17 2.17C12.96 5.06 12.49 5 12 5c-.49 0-.96.06-1.41.17L8.41 3 7 4.41l1.62
1.63C7.88 6.55 7.26 7.22 6.81 8H4v2h2.09c-.05.33-.09.66-.09 1v1H4v2h2v1c0 .34.0
4.67.09 1H4v2h2.81c1.04 1.79 2.97 3 5.19 3s4.15-1.21 5.19-3H20v-2h-2.09c.05-.33.
09-.66.09-1v-1h2v-2h-2v-1c0-.34-.04-.67-.09-1H20V8zm-6 8h-4v-2h4v2zm0-4h-4v-2h4v
2z"></path></g> |
| 15285 <g id="build"><path d="M22.7 19l-9.1-9.1c.9-2.3.4-5-1.5-6.9-2-2-5-2.4-7.4-1.3L9
6 6 9 1.6 4.7C.4 7.1.9 10.1 2.9 12.1c1.9 1.9 4.6 2.4 6.9 1.5l9.1 9.1c.4.4 1 .4 1
.4 0l2.3-2.3c.5-.4.5-1.1.1-1.4z"></path></g> |
| 15286 <g id="cached"><path d="M19 8l-4 4h3c0 3.31-2.69 6-6 6-1.01 0-1.97-.25-2.8-.7l-1
.46 1.46C8.97 19.54 10.43 20 12 20c4.42 0 8-3.58 8-8h3l-4-4zM6 12c0-3.31 2.69-6
6-6 1.01 0 1.97.25 2.8.7l1.46-1.46C15.03 4.46 13.57 4 12 4c-4.42 0-8 3.58-8 8H1l
4 4 4-4H6z"></path></g> |
| 15287 <g id="camera-enhance"><path d="M9 3L7.17 5H4c-1.1 0-2 .9-2 2v12c0 1.1.9 2 2 2h1
6c1.1 0 2-.9 2-2V7c0-1.1-.9-2-2-2h-3.17L15 3H9zm3 15c-2.76 0-5-2.24-5-5s2.24-5 5
-5 5 2.24 5 5-2.24 5-5 5zm0-1l1.25-2.75L16 13l-2.75-1.25L12 9l-1.25 2.75L8 13l2.
75 1.25z"></path></g> |
| 15288 <g id="cancel"><path d="M12 2C6.47 2 2 6.47 2 12s4.47 10 10 10 10-4.47 10-10S17.
53 2 12 2zm5 13.59L15.59 17 12 13.41 8.41 17 7 15.59 10.59 12 7 8.41 8.41 7 12 1
0.59 15.59 7 17 8.41 13.41 12 17 15.59z"></path></g> |
| 15289 <g id="card-giftcard"><path d="M20 6h-2.18c.11-.31.18-.65.18-1 0-1.66-1.34-3-3-3
-1.05 0-1.96.54-2.5 1.35l-.5.67-.5-.68C10.96 2.54 10.05 2 9 2 7.34 2 6 3.34 6 5c
0 .35.07.69.18 1H4c-1.11 0-1.99.89-1.99 2L2 19c0 1.11.89 2 2 2h16c1.11 0 2-.89 2
-2V8c0-1.11-.89-2-2-2zm-5-2c.55 0 1 .45 1 1s-.45 1-1 1-1-.45-1-1 .45-1 1-1zM9 4c
.55 0 1 .45 1 1s-.45 1-1 1-1-.45-1-1 .45-1 1-1zm11 15H4v-2h16v2zm0-5H4V8h5.08L7
10.83 8.62 12 11 8.76l1-1.36 1 1.36L15.38 12 17 10.83 14.92 8H20v6z"></path></g> |
| 15290 <g id="card-membership"><path d="M20 2H4c-1.11 0-2 .89-2 2v11c0 1.11.89 2 2 2h4v
5l4-2 4 2v-5h4c1.11 0 2-.89 2-2V4c0-1.11-.89-2-2-2zm0 13H4v-2h16v2zm0-5H4V4h16v6
z"></path></g> |
| 15291 <g id="card-travel"><path d="M20 6h-3V4c0-1.11-.89-2-2-2H9c-1.11 0-2 .89-2 2v2H4
c-1.11 0-2 .89-2 2v11c0 1.11.89 2 2 2h16c1.11 0 2-.89 2-2V8c0-1.11-.89-2-2-2zM9
4h6v2H9V4zm11 15H4v-2h16v2zm0-5H4V8h3v2h2V8h6v2h2V8h3v6z"></path></g> |
| 15292 <g id="change-history"><path d="M12 7.77L18.39 18H5.61L12 7.77M12 4L2 20h20L12 4
z"></path></g> |
| 15293 <g id="check"><path d="M9 16.17L4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41z"></path
></g> |
| 15294 <g id="check-box"><path d="M19 3H5c-1.11 0-2 .9-2 2v14c0 1.1.89 2 2 2h14c1.11 0
2-.9 2-2V5c0-1.1-.89-2-2-2zm-9 14l-5-5 1.41-1.41L10 14.17l7.59-7.59L19 8l-9 9z">
</path></g> |
| 15295 <g id="check-box-outline-blank"><path d="M19 5v14H5V5h14m0-2H5c-1.1 0-2 .9-2 2v1
4c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2z"></path></g> |
| 15296 <g id="check-circle"><path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-
10S17.52 2 12 2zm-2 15l-5-5 1.41-1.41L10 14.17l7.59-7.59L19 8l-9 9z"></path></g> |
| 15297 <g id="chevron-left"><path d="M15.41 7.41L14 6l-6 6 6 6 1.41-1.41L10.83 12z"></p
ath></g> |
| 15298 <g id="chevron-right"><path d="M10 6L8.59 7.41 13.17 12l-4.58 4.59L10 18l6-6z"><
/path></g> |
| 15299 <g id="chrome-reader-mode"><path d="M13 12h7v1.5h-7zm0-2.5h7V11h-7zm0 5h7V16h-7z
M21 4H3c-1.1 0-2 .9-2 2v13c0 1.1.9 2 2 2h18c1.1 0 2-.9 2-2V6c0-1.1-.9-2-2-2zm0 1
5h-9V6h9v13z"></path></g> |
| 15300 <g id="class"><path d="M18 2H6c-1.1 0-2 .9-2 2v16c0 1.1.9 2 2 2h12c1.1 0 2-.9 2-
2V4c0-1.1-.9-2-2-2zM6 4h5v8l-2.5-1.5L6 12V4z"></path></g> |
| 15301 <g id="clear"><path d="M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59
6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z"></path></g> |
| 15302 <g id="close"><path d="M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59
6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z"></path></g> |
| 15303 <g id="cloud"><path d="M19.35 10.04C18.67 6.59 15.64 4 12 4 9.11 4 6.6 5.64 5.35
8.04 2.34 8.36 0 10.91 0 14c0 3.31 2.69 6 6 6h13c2.76 0 5-2.24 5-5 0-2.64-2.05-
4.78-4.65-4.96z"></path></g> |
| 15304 <g id="cloud-circle"><path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-
10S17.52 2 12 2zm4.5 14H8c-1.66 0-3-1.34-3-3s1.34-3 3-3l.14.01C8.58 8.28 10.13 7
12 7c2.21 0 4 1.79 4 4h.5c1.38 0 2.5 1.12 2.5 2.5S17.88 16 16.5 16z"></path></g
> |
| 15305 <g id="cloud-done"><path d="M19.35 10.04C18.67 6.59 15.64 4 12 4 9.11 4 6.6 5.64
5.35 8.04 2.34 8.36 0 10.91 0 14c0 3.31 2.69 6 6 6h13c2.76 0 5-2.24 5-5 0-2.64-
2.05-4.78-4.65-4.96zM10 17l-3.5-3.5 1.41-1.41L10 14.17 15.18 9l1.41 1.41L10 17z"
></path></g> |
| 15306 <g id="cloud-download"><path d="M19.35 10.04C18.67 6.59 15.64 4 12 4 9.11 4 6.6
5.64 5.35 8.04 2.34 8.36 0 10.91 0 14c0 3.31 2.69 6 6 6h13c2.76 0 5-2.24 5-5 0-2
.64-2.05-4.78-4.65-4.96zM17 13l-5 5-5-5h3V9h4v4h3z"></path></g> |
| 15307 <g id="cloud-off"><path d="M19.35 10.04C18.67 6.59 15.64 4 12 4c-1.48 0-2.85.43-
4.01 1.17l1.46 1.46C10.21 6.23 11.08 6 12 6c3.04 0 5.5 2.46 5.5 5.5v.5H19c1.66 0
3 1.34 3 3 0 1.13-.64 2.11-1.56 2.62l1.45 1.45C23.16 18.16 24 16.68 24 15c0-2.6
4-2.05-4.78-4.65-4.96zM3 5.27l2.75 2.74C2.56 8.15 0 10.77 0 14c0 3.31 2.69 6 6 6
h11.73l2 2L21 20.73 4.27 4 3 5.27zM7.73 10l8 8H6c-2.21 0-4-1.79-4-4s1.79-4 4-4h1
.73z"></path></g> |
| 15308 <g id="cloud-queue"><path d="M19.35 10.04C18.67 6.59 15.64 4 12 4 9.11 4 6.6 5.6
4 5.35 8.04 2.34 8.36 0 10.91 0 14c0 3.31 2.69 6 6 6h13c2.76 0 5-2.24 5-5 0-2.64
-2.05-4.78-4.65-4.96zM19 18H6c-2.21 0-4-1.79-4-4s1.79-4 4-4h.71C7.37 7.69 9.48 6
12 6c3.04 0 5.5 2.46 5.5 5.5v.5H19c1.66 0 3 1.34 3 3s-1.34 3-3 3z"></path></g> |
| 15309 <g id="cloud-upload"><path d="M19.35 10.04C18.67 6.59 15.64 4 12 4 9.11 4 6.6 5.
64 5.35 8.04 2.34 8.36 0 10.91 0 14c0 3.31 2.69 6 6 6h13c2.76 0 5-2.24 5-5 0-2.6
4-2.05-4.78-4.65-4.96zM14 13v4h-4v-4H7l5-5 5 5h-3z"></path></g> |
| 15310 <g id="code"><path d="M9.4 16.6L4.8 12l4.6-4.6L8 6l-6 6 6 6 1.4-1.4zm5.2 0l4.6-4
.6-4.6-4.6L16 6l6 6-6 6-1.4-1.4z"></path></g> |
| 15311 <g id="compare-arrows"><path d="M9.01 14H2v2h7.01v3L13 15l-3.99-4v3zm5.98-1v-3H2
2V8h-7.01V5L11 9l3.99 4z"></path></g> |
| 15312 <g id="content-copy"><path d="M16 1H4c-1.1 0-2 .9-2 2v14h2V3h12V1zm3 4H8c-1.1 0-
2 .9-2 2v14c0 1.1.9 2 2 2h11c1.1 0 2-.9 2-2V7c0-1.1-.9-2-2-2zm0 16H8V7h11v14z"><
/path></g> |
| 15313 <g id="content-cut"><path d="M9.64 7.64c.23-.5.36-1.05.36-1.64 0-2.21-1.79-4-4-4
S2 3.79 2 6s1.79 4 4 4c.59 0 1.14-.13 1.64-.36L10 12l-2.36 2.36C7.14 14.13 6.59
14 6 14c-2.21 0-4 1.79-4 4s1.79 4 4 4 4-1.79 4-4c0-.59-.13-1.14-.36-1.64L12 14l7
7h3v-1L9.64 7.64zM6 8c-1.1 0-2-.89-2-2s.9-2 2-2 2 .89 2 2-.9 2-2 2zm0 12c-1.1 0
-2-.89-2-2s.9-2 2-2 2 .89 2 2-.9 2-2 2zm6-7.5c-.28 0-.5-.22-.5-.5s.22-.5.5-.5.5.
22.5.5-.22.5-.5.5zM19 3l-6 6 2 2 7-7V3z"></path></g> |
| 15314 <g id="content-paste"><path d="M19 2h-4.18C14.4.84 13.3 0 12 0c-1.3 0-2.4.84-2.8
2 2H5c-1.1 0-2 .9-2 2v16c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V4c0-1.1-.9-2-2-2zm-7 0c
.55 0 1 .45 1 1s-.45 1-1 1-1-.45-1-1 .45-1 1-1zm7 18H5V4h2v3h10V4h2v16z"></path>
</g> |
| 15315 <g id="copyright"><path d="M10.08 10.86c.05-.33.16-.62.3-.87s.34-.46.59-.62c.24-
.15.54-.22.91-.23.23.01.44.05.63.13.2.09.38.21.52.36s.25.33.34.53.13.42.14.64h1.
79c-.02-.47-.11-.9-.28-1.29s-.4-.73-.7-1.01-.66-.5-1.08-.66-.88-.23-1.39-.23c-.6
5 0-1.22.11-1.7.34s-.88.53-1.2.92-.56.84-.71 1.36S8 11.29 8 11.87v.27c0 .58.08 1
.12.23 1.64s.39.97.71 1.35.72.69 1.2.91 1.05.34 1.7.34c.47 0 .91-.08 1.32-.23s.7
7-.36 1.08-.63.56-.58.74-.94.29-.74.3-1.15h-1.79c-.01.21-.06.4-.15.58s-.21.33-.3
6.46-.32.23-.52.3c-.19.07-.39.09-.6.1-.36-.01-.66-.08-.89-.23-.25-.16-.45-.37-.5
9-.62s-.25-.55-.3-.88-.08-.67-.08-1v-.27c0-.35.03-.68.08-1.01zM12 2C6.48 2 2 6.4
8 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm0 18c-4.41 0-8-3.59-8-8s3.59-8
8-8 8 3.59 8 8-3.59 8-8 8z"></path></g> |
| 15316 <g id="create"><path d="M3 17.25V21h3.75L17.81 9.94l-3.75-3.75L3 17.25zM20.71 7.
04c.39-.39.39-1.02 0-1.41l-2.34-2.34c-.39-.39-1.02-.39-1.41 0l-1.83 1.83 3.75 3.
75 1.83-1.83z"></path></g> |
| 15317 <g id="create-new-folder"><path d="M20 6h-8l-2-2H4c-1.11 0-1.99.89-1.99 2L2 18c0
1.11.89 2 2 2h16c1.11 0 2-.89 2-2V8c0-1.11-.89-2-2-2zm-1 8h-3v3h-2v-3h-3v-2h3V9
h2v3h3v2z"></path></g> |
| 15318 <g id="credit-card"><path d="M20 4H4c-1.11 0-1.99.89-1.99 2L2 18c0 1.11.89 2 2 2
h16c1.11 0 2-.89 2-2V6c0-1.11-.89-2-2-2zm0 14H4v-6h16v6zm0-10H4V6h16v2z"></path>
</g> |
| 15319 <g id="dashboard"><path d="M3 13h8V3H3v10zm0 8h8v-6H3v6zm10 0h8V11h-8v10zm0-18v6
h8V3h-8z"></path></g> |
| 15320 <g id="date-range"><path d="M9 11H7v2h2v-2zm4 0h-2v2h2v-2zm4 0h-2v2h2v-2zm2-7h-1
V2h-2v2H8V2H6v2H5c-1.11 0-1.99.9-1.99 2L3 20c0 1.1.89 2 2 2h14c1.1 0 2-.9 2-2V6c
0-1.1-.9-2-2-2zm0 16H5V9h14v11z"></path></g> |
| 15321 <g id="delete"><path d="M6 19c0 1.1.9 2 2 2h8c1.1 0 2-.9 2-2V7H6v12zM19 4h-3.5l-
1-1h-5l-1 1H5v2h14V4z"></path></g> |
| 15322 <g id="description"><path d="M14 2H6c-1.1 0-1.99.9-1.99 2L4 20c0 1.1.89 2 1.99 2
H18c1.1 0 2-.9 2-2V8l-6-6zm2 16H8v-2h8v2zm0-4H8v-2h8v2zm-3-5V3.5L18.5 9H13z"></p
ath></g> |
| 15323 <g id="dns"><path d="M20 13H4c-.55 0-1 .45-1 1v6c0 .55.45 1 1 1h16c.55 0 1-.45 1
-1v-6c0-.55-.45-1-1-1zM7 19c-1.1 0-2-.9-2-2s.9-2 2-2 2 .9 2 2-.9 2-2 2zM20 3H4c-
.55 0-1 .45-1 1v6c0 .55.45 1 1 1h16c.55 0 1-.45 1-1V4c0-.55-.45-1-1-1zM7 9c-1.1
0-2-.9-2-2s.9-2 2-2 2 .9 2 2-.9 2-2 2z"></path></g> |
| 15324 <g id="done"><path d="M9 16.2L4.8 12l-1.4 1.4L9 19 21 7l-1.4-1.4L9 16.2z"></path
></g> |
| 15325 <g id="done-all"><path d="M18 7l-1.41-1.41-6.34 6.34 1.41 1.41L18 7zm4.24-1.41L1
1.66 16.17 7.48 12l-1.41 1.41L11.66 19l12-12-1.42-1.41zM.41 13.41L6 19l1.41-1.41
L1.83 12 .41 13.41z"></path></g> |
| 15326 <g id="donut-large"><path d="M11 5.08V2c-5 .5-9 4.81-9 10s4 9.5 9 10v-3.08c-3-.4
8-6-3.4-6-6.92s3-6.44 6-6.92zM18.97 11H22c-.47-5-4-8.53-9-9v3.08C16 5.51 18.54 8
18.97 11zM13 18.92V22c5-.47 8.53-4 9-9h-3.03c-.43 3-2.97 5.49-5.97 5.92z"></pat
h></g> |
| 15327 <g id="donut-small"><path d="M11 9.16V2c-5 .5-9 4.79-9 10s4 9.5 9 10v-7.16c-1-.4
1-2-1.52-2-2.84s1-2.43 2-2.84zM14.86 11H22c-.48-4.75-4-8.53-9-9v7.16c1 .3 1.52.9
8 1.86 1.84zM13 14.84V22c5-.47 8.52-4.25 9-9h-7.14c-.34.86-.86 1.54-1.86 1.84z">
</path></g> |
| 15328 <g id="drafts"><path d="M21.99 8c0-.72-.37-1.35-.94-1.7L12 1 2.95 6.3C2.38 6.65
2 7.28 2 8v10c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2l-.01-10zM12 13L3.74 7.84 12 3l8.26
4.84L12 13z"></path></g> |
| 15329 <g id="eject"><path d="M5 17h14v2H5zm7-12L5.33 15h13.34z"></path></g> |
| 15330 <g id="error"><path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.5
2 2 12 2zm1 15h-2v-2h2v2zm0-4h-2V7h2v6z"></path></g> |
| 15331 <g id="error-outline"><path d="M11 15h2v2h-2zm0-8h2v6h-2zm.99-5C6.47 2 2 6.48 2
12s4.47 10 9.99 10C17.52 22 22 17.52 22 12S17.52 2 11.99 2zM12 20c-4.42 0-8-3.58
-8-8s3.58-8 8-8 8 3.58 8 8-3.58 8-8 8z"></path></g> |
| 15332 <g id="event"><path d="M17 12h-5v5h5v-5zM16 1v2H8V1H6v2H5c-1.11 0-1.99.9-1.99 2L
3 19c0 1.1.89 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2h-1V1h-2zm3 18H5V8h14v11z"
></path></g> |
| 15333 <g id="event-seat"><path d="M4 18v3h3v-3h10v3h3v-6H4zm15-8h3v3h-3zM2 10h3v3H2zm1
5 3H7V5c0-1.1.9-2 2-2h6c1.1 0 2 .9 2 2v8z"></path></g> |
| 15334 <g id="exit-to-app"><path d="M10.09 15.59L11.5 17l5-5-5-5-1.41 1.41L12.67 11H3v2
h9.67l-2.58 2.59zM19 3H5c-1.11 0-2 .9-2 2v4h2V5h14v14H5v-4H3v4c0 1.1.89 2 2 2h14
c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2z"></path></g> |
| 15335 <g id="expand-less"><path d="M12 8l-6 6 1.41 1.41L12 10.83l4.59 4.58L18 14z"></p
ath></g> |
| 15336 <g id="expand-more"><path d="M16.59 8.59L12 13.17 7.41 8.59 6 10l6 6 6-6z"></pat
h></g> |
| 15337 <g id="explore"><path d="M12 10.9c-.61 0-1.1.49-1.1 1.1s.49 1.1 1.1 1.1c.61 0 1.
1-.49 1.1-1.1s-.49-1.1-1.1-1.1zM12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10
-10S17.52 2 12 2zm2.19 12.19L6 18l3.81-8.19L18 6l-3.81 8.19z"></path></g> |
| 15338 <g id="extension"><path d="M20.5 11H19V7c0-1.1-.9-2-2-2h-4V3.5C13 2.12 11.88 1 1
0.5 1S8 2.12 8 3.5V5H4c-1.1 0-1.99.9-1.99 2v3.8H3.5c1.49 0 2.7 1.21 2.7 2.7s-1.2
1 2.7-2.7 2.7H2V20c0 1.1.9 2 2 2h3.8v-1.5c0-1.49 1.21-2.7 2.7-2.7 1.49 0 2.7 1.2
1 2.7 2.7V22H17c1.1 0 2-.9 2-2v-4h1.5c1.38 0 2.5-1.12 2.5-2.5S21.88 11 20.5 11z"
></path></g> |
| 15339 <g id="face"><path d="M9 11.75c-.69 0-1.25.56-1.25 1.25s.56 1.25 1.25 1.25 1.25-
.56 1.25-1.25-.56-1.25-1.25-1.25zm6 0c-.69 0-1.25.56-1.25 1.25s.56 1.25 1.25 1.2
5 1.25-.56 1.25-1.25-.56-1.25-1.25-1.25zM12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 1
0-4.48 10-10S17.52 2 12 2zm0 18c-4.41 0-8-3.59-8-8 0-.29.02-.58.05-.86 2.36-1.05
4.23-2.98 5.21-5.37C11.07 8.33 14.05 10 17.42 10c.78 0 1.53-.09 2.25-.26.21.71.
33 1.47.33 2.26 0 4.41-3.59 8-8 8z"></path></g> |
| 15340 <g id="favorite"><path d="M12 21.35l-1.45-1.32C5.4 15.36 2 12.28 2 8.5 2 5.42 4.
42 3 7.5 3c1.74 0 3.41.81 4.5 2.09C13.09 3.81 14.76 3 16.5 3 19.58 3 22 5.42 22
8.5c0 3.78-3.4 6.86-8.55 11.54L12 21.35z"></path></g> |
| 15341 <g id="favorite-border"><path d="M16.5 3c-1.74 0-3.41.81-4.5 2.09C10.91 3.81 9.2
4 3 7.5 3 4.42 3 2 5.42 2 8.5c0 3.78 3.4 6.86 8.55 11.54L12 21.35l1.45-1.32C18.6
15.36 22 12.28 22 8.5 22 5.42 19.58 3 16.5 3zm-4.4 15.55l-.1.1-.1-.1C7.14 14.24
4 11.39 4 8.5 4 6.5 5.5 5 7.5 5c1.54 0 3.04.99 3.57 2.36h1.87C13.46 5.99 14.96
5 16.5 5c2 0 3.5 1.5 3.5 3.5 0 2.89-3.14 5.74-7.9 10.05z"></path></g> |
| 15342 <g id="feedback"><path d="M20 2H4c-1.1 0-1.99.9-1.99 2L2 22l4-4h14c1.1 0 2-.9 2-
2V4c0-1.1-.9-2-2-2zm-7 12h-2v-2h2v2zm0-4h-2V6h2v4z"></path></g> |
| 15343 <g id="file-download"><path d="M19 9h-4V3H9v6H5l7 7 7-7zM5 18v2h14v-2H5z"></path
></g> |
| 15344 <g id="file-upload"><path d="M9 16h6v-6h4l-7-7-7 7h4zm-4 2h14v2H5z"></path></g> |
| 15345 <g id="filter-list"><path d="M10 18h4v-2h-4v2zM3 6v2h18V6H3zm3 7h12v-2H6v2z"></p
ath></g> |
| 15346 <g id="find-in-page"><path d="M20 19.59V8l-6-6H6c-1.1 0-1.99.9-1.99 2L4 20c0 1.1
.89 2 1.99 2H18c.45 0 .85-.15 1.19-.4l-4.43-4.43c-.8.52-1.74.83-2.76.83-2.76 0-5
-2.24-5-5s2.24-5 5-5 5 2.24 5 5c0 1.02-.31 1.96-.83 2.75L20 19.59zM9 13c0 1.66 1
.34 3 3 3s3-1.34 3-3-1.34-3-3-3-3 1.34-3 3z"></path></g> |
| 15347 <g id="find-replace"><path d="M11 6c1.38 0 2.63.56 3.54 1.46L12 10h6V4l-2.05 2.0
5C14.68 4.78 12.93 4 11 4c-3.53 0-6.43 2.61-6.92 6H6.1c.46-2.28 2.48-4 4.9-4zm5.
64 9.14c.66-.9 1.12-1.97 1.28-3.14H15.9c-.46 2.28-2.48 4-4.9 4-1.38 0-2.63-.56-3
.54-1.46L10 12H4v6l2.05-2.05C7.32 17.22 9.07 18 11 18c1.55 0 2.98-.51 4.14-1.36L
20 21.49 21.49 20l-4.85-4.86z"></path></g> |
| 15348 <g id="fingerprint"><path d="M17.81 4.47c-.08 0-.16-.02-.23-.06C15.66 3.42 14 3
12.01 3c-1.98 0-3.86.47-5.57 1.41-.24.13-.54.04-.68-.2-.13-.24-.04-.55.2-.68C7.8
2 2.52 9.86 2 12.01 2c2.13 0 3.99.47 6.03 1.52.25.13.34.43.21.67-.09.18-.26.28-.
44.28zM3.5 9.72c-.1 0-.2-.03-.29-.09-.23-.16-.28-.47-.12-.7.99-1.4 2.25-2.5 3.75
-3.27C9.98 4.04 14 4.03 17.15 5.65c1.5.77 2.76 1.86 3.75 3.25.16.22.11.54-.12.7-
.23.16-.54.11-.7-.12-.9-1.26-2.04-2.25-3.39-2.94-2.87-1.47-6.54-1.47-9.4.01-1.36
.7-2.5 1.7-3.4 2.96-.08.14-.23.21-.39.21zm6.25 12.07c-.13 0-.26-.05-.35-.15-.87-
.87-1.34-1.43-2.01-2.64-.69-1.23-1.05-2.73-1.05-4.34 0-2.97 2.54-5.39 5.66-5.39s
5.66 2.42 5.66 5.39c0 .28-.22.5-.5.5s-.5-.22-.5-.5c0-2.42-2.09-4.39-4.66-4.39-2.
57 0-4.66 1.97-4.66 4.39 0 1.44.32 2.77.93 3.85.64 1.15 1.08 1.64 1.85 2.42.19.2
.19.51 0 .71-.11.1-.24.15-.37.15zm7.17-1.85c-1.19 0-2.24-.3-3.1-.89-1.49-1.01-2.
38-2.65-2.38-4.39 0-.28.22-.5.5-.5s.5.22.5.5c0 1.41.72 2.74 1.94 3.56.71.48 1.54
.71 2.54.71.24 0 .64-.03 1.04-.1.27-.05.53.13.58.41.05.27-.13.53-.41.58-.57.11-1
.07.12-1.21.12zM14.91 22c-.04 0-.09-.01-.13-.02-1.59-.44-2.63-1.03-3.72-2.1-1.4-
1.39-2.17-3.24-2.17-5.22 0-1.62 1.38-2.94 3.08-2.94 1.7 0 3.08 1.32 3.08 2.94 0
1.07.93 1.94 2.08 1.94s2.08-.87 2.08-1.94c0-3.77-3.25-6.83-7.25-6.83-2.84 0-5.44
1.58-6.61 4.03-.39.81-.59 1.76-.59 2.8 0 .78.07 2.01.67 3.61.1.26-.03.55-.29.64
-.26.1-.55-.04-.64-.29-.49-1.31-.73-2.61-.73-3.96 0-1.2.23-2.29.68-3.24 1.33-2.7
9 4.28-4.6 7.51-4.6 4.55 0 8.25 3.51 8.25 7.83 0 1.62-1.38 2.94-3.08 2.94s-3.08-
1.32-3.08-2.94c0-1.07-.93-1.94-2.08-1.94s-2.08.87-2.08 1.94c0 1.71.66 3.31 1.87
4.51.95.94 1.86 1.46 3.27 1.85.27.07.42.35.35.61-.05.23-.26.38-.47.38z"></path><
/g> |
| 15349 <g id="flag"><path d="M14.4 6L14 4H5v17h2v-7h5.6l.4 2h7V6z"></path></g> |
| 15350 <g id="flight-land"><path d="M2.5 19h19v2h-19zm7.18-5.73l4.35 1.16 5.31 1.42c.8.
21 1.62-.26 1.84-1.06.21-.8-.26-1.62-1.06-1.84l-5.31-1.42-2.76-9.02L10.12 2v8.28
L5.15 8.95l-.93-2.32-1.45-.39v5.17l1.6.43 5.31 1.43z"></path></g> |
| 15351 <g id="flight-takeoff"><path d="M2.5 19h19v2h-19zm19.57-9.36c-.21-.8-1.04-1.28-1
.84-1.06L14.92 10l-6.9-6.43-1.93.51 4.14 7.17-4.97 1.33-1.97-1.54-1.45.39 1.82 3
.16.77 1.33 1.6-.43 5.31-1.42 4.35-1.16L21 11.49c.81-.23 1.28-1.05 1.07-1.85z"><
/path></g> |
| 15352 <g id="flip-to-back"><path d="M9 7H7v2h2V7zm0 4H7v2h2v-2zm0-8c-1.11 0-2 .9-2 2h2
V3zm4 12h-2v2h2v-2zm6-12v2h2c0-1.1-.9-2-2-2zm-6 0h-2v2h2V3zM9 17v-2H7c0 1.1.89 2
2 2zm10-4h2v-2h-2v2zm0-4h2V7h-2v2zm0 8c1.1 0 2-.9 2-2h-2v2zM5 7H3v12c0 1.1.89 2
2 2h12v-2H5V7zm10-2h2V3h-2v2zm0 12h2v-2h-2v2z"></path></g> |
| 15353 <g id="flip-to-front"><path d="M3 13h2v-2H3v2zm0 4h2v-2H3v2zm2 4v-2H3c0 1.1.89 2
2 2zM3 9h2V7H3v2zm12 12h2v-2h-2v2zm4-18H9c-1.11 0-2 .9-2 2v10c0 1.1.89 2 2 2h10
c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm0 12H9V5h10v10zm-8 6h2v-2h-2v2zm-4 0h2v-2H7v2z
"></path></g> |
| 15354 <g id="folder"><path d="M10 4H4c-1.1 0-1.99.9-1.99 2L2 18c0 1.1.9 2 2 2h16c1.1 0
2-.9 2-2V8c0-1.1-.9-2-2-2h-8l-2-2z"></path></g> |
| 15355 <g id="folder-open"><path d="M20 6h-8l-2-2H4c-1.1 0-1.99.9-1.99 2L2 18c0 1.1.9 2
2 2h16c1.1 0 2-.9 2-2V8c0-1.1-.9-2-2-2zm0 12H4V8h16v10z"></path></g> |
| 15356 <g id="folder-shared"><path d="M20 6h-8l-2-2H4c-1.1 0-1.99.9-1.99 2L2 18c0 1.1.9
2 2 2h16c1.1 0 2-.9 2-2V8c0-1.1-.9-2-2-2zm-5 3c1.1 0 2 .9 2 2s-.9 2-2 2-2-.9-2-
2 .9-2 2-2zm4 8h-8v-1c0-1.33 2.67-2 4-2s4 .67 4 2v1z"></path></g> |
| 15357 <g id="font-download"><path d="M9.93 13.5h4.14L12 7.98zM20 2H4c-1.1 0-2 .9-2 2v1
6c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V4c0-1.1-.9-2-2-2zm-4.05 16.5l-1.14-3H9.17l-1.1
2 3H5.96l5.11-13h1.86l5.11 13h-2.09z"></path></g> |
| 15358 <g id="forward"><path d="M12 8V4l8 8-8 8v-4H4V8z"></path></g> |
| 15359 <g id="fullscreen"><path d="M7 14H5v5h5v-2H7v-3zm-2-4h2V7h3V5H5v5zm12 7h-3v2h5v-
5h-2v3zM14 5v2h3v3h2V5h-5z"></path></g> |
| 15360 <g id="fullscreen-exit"><path d="M5 16h3v3h2v-5H5v2zm3-8H5v2h5V5H8v3zm6 11h2v-3h
3v-2h-5v5zm2-11V5h-2v5h5V8h-3z"></path></g> |
| 15361 <g id="gavel"><path d="M1 21h12v2H1zM5.245 8.07l2.83-2.827 14.14 14.142-2.828 2.
828zM12.317 1l5.657 5.656-2.83 2.83-5.654-5.66zM3.825 9.485l5.657 5.657-2.828 2.
828-5.657-5.657z"></path></g> |
| 15362 <g id="gesture"><path d="M4.59 6.89c.7-.71 1.4-1.35 1.71-1.22.5.2 0 1.03-.3 1.52
-.25.42-2.86 3.89-2.86 6.31 0 1.28.48 2.34 1.34 2.98.75.56 1.74.73 2.64.46 1.07-
.31 1.95-1.4 3.06-2.77 1.21-1.49 2.83-3.44 4.08-3.44 1.63 0 1.65 1.01 1.76 1.79-
3.78.64-5.38 3.67-5.38 5.37 0 1.7 1.44 3.09 3.21 3.09 1.63 0 4.29-1.33 4.69-6.1H
21v-2.5h-2.47c-.15-1.65-1.09-4.2-4.03-4.2-2.25 0-4.18 1.91-4.94 2.84-.58.73-2.06
2.48-2.29 2.72-.25.3-.68.84-1.11.84-.45 0-.72-.83-.36-1.92.35-1.09 1.4-2.86 1.8
5-3.52.78-1.14 1.3-1.92 1.3-3.28C8.95 3.69 7.31 3 6.44 3 5.12 3 3.97 4 3.72 4.25
c-.36.36-.66.66-.88.93l1.75 1.71zm9.29 11.66c-.31 0-.74-.26-.74-.72 0-.6.73-2.2
2.87-2.76-.3 2.69-1.43 3.48-2.13 3.48z"></path></g> |
| 15363 <g id="get-app"><path d="M19 9h-4V3H9v6H5l7 7 7-7zM5 18v2h14v-2H5z"></path></g> |
| 15364 <g id="gif"><path d="M11.5 9H13v6h-1.5zM9 9H6c-.6 0-1 .5-1 1v4c0 .5.4 1 1 1h3c.6
0 1-.5 1-1v-2H8.5v1.5h-2v-3H10V10c0-.5-.4-1-1-1zm10 1.5V9h-4.5v6H16v-2h2v-1.5h-
2v-1z"></path></g> |
| 15365 <g id="grade"><path d="M12 17.27L18.18 21l-1.64-7.03L22 9.24l-7.19-.61L12 2 9.19
8.63 2 9.24l5.46 4.73L5.82 21z"></path></g> |
| 15366 <g id="group-work"><path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10
S17.52 2 12 2zM8 17.5c-1.38 0-2.5-1.12-2.5-2.5s1.12-2.5 2.5-2.5 2.5 1.12 2.5 2.5
-1.12 2.5-2.5 2.5zM9.5 8c0-1.38 1.12-2.5 2.5-2.5s2.5 1.12 2.5 2.5-1.12 2.5-2.5 2
.5S9.5 9.38 9.5 8zm6.5 9.5c-1.38 0-2.5-1.12-2.5-2.5s1.12-2.5 2.5-2.5 2.5 1.12 2.
5 2.5-1.12 2.5-2.5 2.5z"></path></g> |
| 15367 <g id="help"><path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52
2 12 2zm1 17h-2v-2h2v2zm2.07-7.75l-.9.92C13.45 12.9 13 13.5 13 15h-2v-.5c0-1.1.
45-2.1 1.17-2.83l1.24-1.26c.37-.36.59-.86.59-1.41 0-1.1-.9-2-2-2s-2 .9-2 2H8c0-2
.21 1.79-4 4-4s4 1.79 4 4c0 .88-.36 1.68-.93 2.25z"></path></g> |
| 15368 <g id="help-outline"><path d="M11 18h2v-2h-2v2zm1-16C6.48 2 2 6.48 2 12s4.48 10
10 10 10-4.48 10-10S17.52 2 12 2zm0 18c-4.41 0-8-3.59-8-8s3.59-8 8-8 8 3.59 8 8-
3.59 8-8 8zm0-14c-2.21 0-4 1.79-4 4h2c0-1.1.9-2 2-2s2 .9 2 2c0 2-3 1.75-3 5h2c0-
2.25 3-2.5 3-5 0-2.21-1.79-4-4-4z"></path></g> |
| 15369 <g id="highlight-off"><path d="M14.59 8L12 10.59 9.41 8 8 9.41 10.59 12 8 14.59
9.41 16 12 13.41 14.59 16 16 14.59 13.41 12 16 9.41 14.59 8zM12 2C6.47 2 2 6.47
2 12s4.47 10 10 10 10-4.47 10-10S17.53 2 12 2zm0 18c-4.41 0-8-3.59-8-8s3.59-8 8-
8 8 3.59 8 8-3.59 8-8 8z"></path></g> |
| 15370 <g id="history"><path d="M13 3c-4.97 0-9 4.03-9 9H1l3.89 3.89.07.14L9 12H6c0-3.8
7 3.13-7 7-7s7 3.13 7 7-3.13 7-7 7c-1.93 0-3.68-.79-4.94-2.06l-1.42 1.42C8.27 19
.99 10.51 21 13 21c4.97 0 9-4.03 9-9s-4.03-9-9-9zm-1 5v5l4.28 2.54.72-1.21-3.5-2
.08V8H12z"></path></g> |
| 15371 <g id="home"><path d="M10 20v-6h4v6h5v-8h3L12 3 2 12h3v8z"></path></g> |
| 15372 <g id="hourglass-empty"><path d="M6 2v6h.01L6 8.01 10 12l-4 4 .01.01H6V22h12v-5.
99h-.01L18 16l-4-4 4-3.99-.01-.01H18V2H6zm10 14.5V20H8v-3.5l4-4 4 4zm-4-5l-4-4V4
h8v3.5l-4 4z"></path></g> |
| 15373 <g id="hourglass-full"><path d="M6 2v6h.01L6 8.01 10 12l-4 4 .01.01H6V22h12v-5.9
9h-.01L18 16l-4-4 4-3.99-.01-.01H18V2H6z"></path></g> |
| 15374 <g id="http"><path d="M4.5 11h-2V9H1v6h1.5v-2.5h2V15H6V9H4.5v2zm2.5-.5h1.5V15H10
v-4.5h1.5V9H7v1.5zm5.5 0H14V15h1.5v-4.5H17V9h-4.5v1.5zm9-1.5H18v6h1.5v-2h2c.8 0
1.5-.7 1.5-1.5v-1c0-.8-.7-1.5-1.5-1.5zm0 2.5h-2v-1h2v1z"></path></g> |
| 15375 <g id="https"><path d="M18 8h-1V6c0-2.76-2.24-5-5-5S7 3.24 7 6v2H6c-1.1 0-2 .9-2
2v10c0 1.1.9 2 2 2h12c1.1 0 2-.9 2-2V10c0-1.1-.9-2-2-2zm-6 9c-1.1 0-2-.9-2-2s.9
-2 2-2 2 .9 2 2-.9 2-2 2zm3.1-9H8.9V6c0-1.71 1.39-3.1 3.1-3.1 1.71 0 3.1 1.39 3.
1 3.1v2z"></path></g> |
| 15376 <g id="important-devices"><path d="M23 11.01L18 11c-.55 0-1 .45-1 1v9c0 .55.45 1
1 1h5c.55 0 1-.45 1-1v-9c0-.55-.45-.99-1-.99zM23 20h-5v-7h5v7zM20 2H2C.89 2 0 2
.89 0 4v12c0 1.1.89 2 2 2h7v2H7v2h8v-2h-2v-2h2v-2H2V4h18v5h2V4c0-1.11-.9-2-2-2zm
-8.03 7L11 6l-.97 3H7l2.47 1.76-.94 2.91 2.47-1.8 2.47 1.8-.94-2.91L15 9h-3.03z"
></path></g> |
| 15377 <g id="inbox"><path d="M19 3H4.99c-1.11 0-1.98.89-1.98 2L3 19c0 1.1.88 2 1.99 2H
19c1.1 0 2-.9 2-2V5c0-1.11-.9-2-2-2zm0 12h-4c0 1.66-1.35 3-3 3s-3-1.34-3-3H4.99V
5H19v10z"></path></g> |
| 15378 <g id="indeterminate-check-box"><path d="M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2
2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-2 10H7v-2h10v2z"></path></g> |
| 15379 <g id="info"><path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52
2 12 2zm1 15h-2v-6h2v6zm0-8h-2V7h2v2z"></path></g> |
| 15380 <g id="info-outline"><path d="M11 17h2v-6h-2v6zm1-15C6.48 2 2 6.48 2 12s4.48 10
10 10 10-4.48 10-10S17.52 2 12 2zm0 18c-4.41 0-8-3.59-8-8s3.59-8 8-8 8 3.59 8 8-
3.59 8-8 8zM11 9h2V7h-2v2z"></path></g> |
| 15381 <g id="input"><path d="M21 3.01H3c-1.1 0-2 .9-2 2V9h2V4.99h18v14.03H3V15H1v4.01c
0 1.1.9 1.98 2 1.98h18c1.1 0 2-.88 2-1.98v-14c0-1.11-.9-2-2-2zM11 16l4-4-4-4v3H1
v2h10v3z"></path></g> |
| 15382 <g id="invert-colors"><path d="M17.66 7.93L12 2.27 6.34 7.93c-3.12 3.12-3.12 8.1
9 0 11.31C7.9 20.8 9.95 21.58 12 21.58c2.05 0 4.1-.78 5.66-2.34 3.12-3.12 3.12-8
.19 0-11.31zM12 19.59c-1.6 0-3.11-.62-4.24-1.76C6.62 16.69 6 15.19 6 13.59s.62-3
.11 1.76-4.24L12 5.1v14.49z"></path></g> |
| 15383 <g id="label"><path d="M17.63 5.84C17.27 5.33 16.67 5 16 5L5 5.01C3.9 5.01 3 5.9
3 7v10c0 1.1.9 1.99 2 1.99L16 19c.67 0 1.27-.33 1.63-.84L22 12l-4.37-6.16z"></p
ath></g> |
| 15384 <g id="label-outline"><path d="M17.63 5.84C17.27 5.33 16.67 5 16 5L5 5.01C3.9 5.
01 3 5.9 3 7v10c0 1.1.9 1.99 2 1.99L16 19c.67 0 1.27-.33 1.63-.84L22 12l-4.37-6.
16zM16 17H5V7h11l3.55 5L16 17z"></path></g> |
| 15385 <g id="language"><path d="M11.99 2C6.47 2 2 6.48 2 12s4.47 10 9.99 10C17.52 22 2
2 17.52 22 12S17.52 2 11.99 2zm6.93 6h-2.95c-.32-1.25-.78-2.45-1.38-3.56 1.84.63
3.37 1.91 4.33 3.56zM12 4.04c.83 1.2 1.48 2.53 1.91 3.96h-3.82c.43-1.43 1.08-2.
76 1.91-3.96zM4.26 14C4.1 13.36 4 12.69 4 12s.1-1.36.26-2h3.38c-.08.66-.14 1.32-
.14 2 0 .68.06 1.34.14 2H4.26zm.82 2h2.95c.32 1.25.78 2.45 1.38 3.56-1.84-.63-3.
37-1.9-4.33-3.56zm2.95-8H5.08c.96-1.66 2.49-2.93 4.33-3.56C8.81 5.55 8.35 6.75 8
.03 8zM12 19.96c-.83-1.2-1.48-2.53-1.91-3.96h3.82c-.43 1.43-1.08 2.76-1.91 3.96z
M14.34 14H9.66c-.09-.66-.16-1.32-.16-2 0-.68.07-1.35.16-2h4.68c.09.65.16 1.32.16
2 0 .68-.07 1.34-.16 2zm.25 5.56c.6-1.11 1.06-2.31 1.38-3.56h2.95c-.96 1.65-2.4
9 2.93-4.33 3.56zM16.36 14c.08-.66.14-1.32.14-2 0-.68-.06-1.34-.14-2h3.38c.16.64
.26 1.31.26 2s-.1 1.36-.26 2h-3.38z"></path></g> |
| 15386 <g id="launch"><path d="M19 19H5V5h7V3H5c-1.11 0-2 .9-2 2v14c0 1.1.89 2 2 2h14c1
.1 0 2-.9 2-2v-7h-2v7zM14 3v2h3.59l-9.83 9.83 1.41 1.41L19 6.41V10h2V3h-7z"></pa
th></g> |
| 15387 <g id="lightbulb-outline"><path d="M9 21c0 .55.45 1 1 1h4c.55 0 1-.45 1-1v-1H9v1
zm3-19C8.14 2 5 5.14 5 9c0 2.38 1.19 4.47 3 5.74V17c0 .55.45 1 1 1h6c.55 0 1-.45
1-1v-2.26c1.81-1.27 3-3.36 3-5.74 0-3.86-3.14-7-7-7zm2.85 11.1l-.85.6V16h-4v-2.
3l-.85-.6C7.8 12.16 7 10.63 7 9c0-2.76 2.24-5 5-5s5 2.24 5 5c0 1.63-.8 3.16-2.15
4.1z"></path></g> |
| 15388 <g id="line-style"><path d="M3 16h5v-2H3v2zm6.5 0h5v-2h-5v2zm6.5 0h5v-2h-5v2zM3
20h2v-2H3v2zm4 0h2v-2H7v2zm4 0h2v-2h-2v2zm4 0h2v-2h-2v2zm4 0h2v-2h-2v2zM3 12h8v-
2H3v2zm10 0h8v-2h-8v2zM3 4v4h18V4H3z"></path></g> |
| 15389 <g id="line-weight"><path d="M3 17h18v-2H3v2zm0 3h18v-1H3v1zm0-7h18v-3H3v3zm0-9v
4h18V4H3z"></path></g> |
| 15390 <g id="link"><path d="M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76 0-5 2.24-5 5s2
.24 5 5 5h4v-1.9H7c-1.71 0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71 0
3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76 0 5-2.24 5-5s-2.24-5-5-5z"></pat
h></g> |
| 15391 <g id="list"><path d="M3 13h2v-2H3v2zm0 4h2v-2H3v2zm0-8h2V7H3v2zm4 4h14v-2H7v2zm
0 4h14v-2H7v2zM7 7v2h14V7H7z"></path></g> |
| 15392 <g id="lock"><path d="M18 8h-1V6c0-2.76-2.24-5-5-5S7 3.24 7 6v2H6c-1.1 0-2 .9-2
2v10c0 1.1.9 2 2 2h12c1.1 0 2-.9 2-2V10c0-1.1-.9-2-2-2zm-6 9c-1.1 0-2-.9-2-2s.9-
2 2-2 2 .9 2 2-.9 2-2 2zm3.1-9H8.9V6c0-1.71 1.39-3.1 3.1-3.1 1.71 0 3.1 1.39 3.1
3.1v2z"></path></g> |
| 15393 <g id="lock-open"><path d="M12 17c1.1 0 2-.9 2-2s-.9-2-2-2-2 .9-2 2 .9 2 2 2zm6-
9h-1V6c0-2.76-2.24-5-5-5S7 3.24 7 6h1.9c0-1.71 1.39-3.1 3.1-3.1 1.71 0 3.1 1.39
3.1 3.1v2H6c-1.1 0-2 .9-2 2v10c0 1.1.9 2 2 2h12c1.1 0 2-.9 2-2V10c0-1.1-.9-2-2-2
zm0 12H6V10h12v10z"></path></g> |
| 15394 <g id="lock-outline"><path d="M12 17c1.1 0 2-.9 2-2s-.9-2-2-2-2 .9-2 2 .9 2 2 2z
m6-9h-1V6c0-2.76-2.24-5-5-5S7 3.24 7 6v2H6c-1.1 0-2 .9-2 2v10c0 1.1.9 2 2 2h12c1
.1 0 2-.9 2-2V10c0-1.1-.9-2-2-2zM8.9 6c0-1.71 1.39-3.1 3.1-3.1s3.1 1.39 3.1 3.1v
2H8.9V6zM18 20H6V10h12v10z"></path></g> |
| 15395 <g id="loyalty"><path d="M21.41 11.58l-9-9C12.05 2.22 11.55 2 11 2H4c-1.1 0-2 .9
-2 2v7c0 .55.22 1.05.59 1.42l9 9c.36.36.86.58 1.41.58.55 0 1.05-.22 1.41-.59l7-7
c.37-.36.59-.86.59-1.41 0-.55-.23-1.06-.59-1.42zM5.5 7C4.67 7 4 6.33 4 5.5S4.67
4 5.5 4 7 4.67 7 5.5 6.33 7 5.5 7zm11.77 8.27L13 19.54l-4.27-4.27C8.28 14.81 8 1
4.19 8 13.5c0-1.38 1.12-2.5 2.5-2.5.69 0 1.32.28 1.77.74l.73.72.73-.73c.45-.45 1
.08-.73 1.77-.73 1.38 0 2.5 1.12 2.5 2.5 0 .69-.28 1.32-.73 1.77z"></path></g> |
| 15396 <g id="mail"><path d="M20 4H4c-1.1 0-1.99.9-1.99 2L2 18c0 1.1.9 2 2 2h16c1.1 0 2
-.9 2-2V6c0-1.1-.9-2-2-2zm0 4l-8 5-8-5V6l8 5 8-5v2z"></path></g> |
| 15397 <g id="markunread"><path d="M20 4H4c-1.1 0-1.99.9-1.99 2L2 18c0 1.1.9 2 2 2h16c1
.1 0 2-.9 2-2V6c0-1.1-.9-2-2-2zm0 4l-8 5-8-5V6l8 5 8-5v2z"></path></g> |
| 15398 <g id="markunread-mailbox"><path d="M20 6H10v6H8V4h6V0H6v6H4c-1.1 0-2 .9-2 2v12c
0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V8c0-1.1-.9-2-2-2z"></path></g> |
| 15399 <g id="menu"><path d="M3 18h18v-2H3v2zm0-5h18v-2H3v2zm0-7v2h18V6H3z"></path></g> |
| 15400 <g id="more-horiz"><path d="M6 10c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2zm12
0c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2zm-6 0c-1.1 0-2 .9-2 2s.9 2 2 2 2-.
9 2-2-.9-2-2-2z"></path></g> |
| 15401 <g id="more-vert"><path d="M12 8c1.1 0 2-.9 2-2s-.9-2-2-2-2 .9-2 2 .9 2 2 2zm0 2
c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2zm0 6c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2
-2-.9-2-2-2z"></path></g> |
| 15402 <g id="motorcycle"><path d="M19.44 9.03L15.41 5H11v2h3.59l2 2H5c-2.8 0-5 2.2-5 5
s2.2 5 5 5c2.46 0 4.45-1.69 4.9-4h1.65l2.77-2.77c-.21.54-.32 1.14-.32 1.77 0 2.8
2.2 5 5 5s5-2.2 5-5c0-2.65-1.97-4.77-4.56-4.97zM7.82 15C7.4 16.15 6.28 17 5 17c
-1.63 0-3-1.37-3-3s1.37-3 3-3c1.28 0 2.4.85 2.82 2H5v2h2.82zM19 17c-1.66 0-3-1.3
4-3-3s1.34-3 3-3 3 1.34 3 3-1.34 3-3 3z"></path></g> |
| 15403 <g id="move-to-inbox"><path d="M19 3H4.99c-1.11 0-1.98.9-1.98 2L3 19c0 1.1.88 2
1.99 2H19c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm0 12h-4c0 1.66-1.35 3-3 3s-3-1.34-3-3
H4.99V5H19v10zm-3-5h-2V7h-4v3H8l4 4 4-4z"></path></g> |
| 15404 <g id="next-week"><path d="M20 7h-4V5c0-.55-.22-1.05-.59-1.41C15.05 3.22 14.55 3
14 3h-4c-1.1 0-2 .9-2 2v2H4c-1.1 0-2 .9-2 2v11c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V
9c0-1.1-.9-2-2-2zM10 5h4v2h-4V5zm1 13.5l-1-1 3-3-3-3 1-1 4 4-4 4z"></path></g> |
| 15405 <g id="note-add"><path d="M14 2H6c-1.1 0-1.99.9-1.99 2L4 20c0 1.1.89 2 1.99 2H18
c1.1 0 2-.9 2-2V8l-6-6zm2 14h-3v3h-2v-3H8v-2h3v-3h2v3h3v2zm-3-7V3.5L18.5 9H13z">
</path></g> |
| 15406 <g id="offline-pin"><path d="M12 2C6.5 2 2 6.5 2 12s4.5 10 10 10 10-4.5 10-10S17
.5 2 12 2zm5 16H7v-2h10v2zm-6.7-4L7 10.7l1.4-1.4 1.9 1.9 5.3-5.3L17 7.3 10.3 14z
"></path></g> |
| 15407 <g id="opacity"><path d="M17.66 8L12 2.35 6.34 8C4.78 9.56 4 11.64 4 13.64s.78 4
.11 2.34 5.67 3.61 2.35 5.66 2.35 4.1-.79 5.66-2.35S20 15.64 20 13.64 19.22 9.56
17.66 8zM6 14c.01-2 .62-3.27 1.76-4.4L12 5.27l4.24 4.38C17.38 10.77 17.99 12 18
14H6z"></path></g> |
| 15408 <g id="open-in-browser"><path d="M19 4H5c-1.11 0-2 .9-2 2v12c0 1.1.89 2 2 2h4v-2
H5V8h14v10h-4v2h4c1.1 0 2-.9 2-2V6c0-1.1-.89-2-2-2zm-7 6l-4 4h3v6h2v-6h3l-4-4z">
</path></g> |
| 15409 <g id="open-in-new"><path d="M19 19H5V5h7V3H5c-1.11 0-2 .9-2 2v14c0 1.1.89 2 2 2
h14c1.1 0 2-.9 2-2v-7h-2v7zM14 3v2h3.59l-9.83 9.83 1.41 1.41L19 6.41V10h2V3h-7z"
></path></g> |
| 15410 <g id="open-with"><path d="M10 9h4V6h3l-5-5-5 5h3v3zm-1 1H6V7l-5 5 5 5v-3h3v-4zm
14 2l-5-5v3h-3v4h3v3l5-5zm-9 3h-4v3H7l5 5 5-5h-3v-3z"></path></g> |
| 15411 <g id="pageview"><path d="M11.5 9C10.12 9 9 10.12 9 11.5s1.12 2.5 2.5 2.5 2.5-1.
12 2.5-2.5S12.88 9 11.5 9zM20 4H4c-1.1 0-2 .9-2 2v12c0 1.1.9 2 2 2h16c1.1 0 2-.9
2-2V6c0-1.1-.9-2-2-2zm-3.21 14.21l-2.91-2.91c-.69.44-1.51.7-2.39.7C9.01 16 7 13
.99 7 11.5S9.01 7 11.5 7 16 9.01 16 11.5c0 .88-.26 1.69-.7 2.39l2.91 2.9-1.42 1.
42z"></path></g> |
| 15412 <g id="pan-tool"><path d="M23 5.5V20c0 2.2-1.8 4-4 4h-7.3c-1.08 0-2.1-.43-2.85-1
.19L1 14.83s1.26-1.23 1.3-1.25c.22-.19.49-.29.79-.29.22 0 .42.06.6.16.04.01 4.31
2.46 4.31 2.46V4c0-.83.67-1.5 1.5-1.5S11 3.17 11 4v7h1V1.5c0-.83.67-1.5 1.5-1.5
S15 .67 15 1.5V11h1V2.5c0-.83.67-1.5 1.5-1.5s1.5.67 1.5 1.5V11h1V5.5c0-.83.67-1.
5 1.5-1.5s1.5.67 1.5 1.5z"></path></g> |
| 15413 <g id="payment"><path d="M20 4H4c-1.11 0-1.99.89-1.99 2L2 18c0 1.11.89 2 2 2h16c
1.11 0 2-.89 2-2V6c0-1.11-.89-2-2-2zm0 14H4v-6h16v6zm0-10H4V6h16v2z"></path></g> |
| 15414 <g id="perm-camera-mic"><path d="M20 5h-3.17L15 3H9L7.17 5H4c-1.1 0-2 .9-2 2v12c
0 1.1.9 2 2 2h7v-2.09c-2.83-.48-5-2.94-5-5.91h2c0 2.21 1.79 4 4 4s4-1.79 4-4h2c0
2.97-2.17 5.43-5 5.91V21h7c1.1 0 2-.9 2-2V7c0-1.1-.9-2-2-2zm-6 8c0 1.1-.9 2-2 2
s-2-.9-2-2V9c0-1.1.9-2 2-2s2 .9 2 2v4z"></path></g> |
| 15415 <g id="perm-contact-calendar"><path d="M19 3h-1V1h-2v2H8V1H6v2H5c-1.11 0-2 .9-2
2v14c0 1.1.89 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-7 3c1.66 0 3 1.34 3 3s-
1.34 3-3 3-3-1.34-3-3 1.34-3 3-3zm6 12H6v-1c0-2 4-3.1 6-3.1s6 1.1 6 3.1v1z"></pa
th></g> |
| 15416 <g id="perm-data-setting"><path d="M18.99 11.5c.34 0 .67.03 1 .07L20 0 0 20h11.5
6c-.04-.33-.07-.66-.07-1 0-4.14 3.36-7.5 7.5-7.5zm3.71 7.99c.02-.16.04-.32.04-.4
9 0-.17-.01-.33-.04-.49l1.06-.83c.09-.08.12-.21.06-.32l-1-1.73c-.06-.11-.19-.15-
.31-.11l-1.24.5c-.26-.2-.54-.37-.85-.49l-.19-1.32c-.01-.12-.12-.21-.24-.21h-2c-.
12 0-.23.09-.25.21l-.19 1.32c-.3.13-.59.29-.85.49l-1.24-.5c-.11-.04-.24 0-.31.11
l-1 1.73c-.06.11-.04.24.06.32l1.06.83c-.02.16-.03.32-.03.49 0 .17.01.33.03.49l-1
.06.83c-.09.08-.12.21-.06.32l1 1.73c.06.11.19.15.31.11l1.24-.5c.26.2.54.37.85.49
l.19 1.32c.02.12.12.21.25.21h2c.12 0 .23-.09.25-.21l.19-1.32c.3-.13.59-.29.84-.4
9l1.25.5c.11.04.24 0 .31-.11l1-1.73c.06-.11.03-.24-.06-.32l-1.07-.83zm-3.71 1.01
c-.83 0-1.5-.67-1.5-1.5s.67-1.5 1.5-1.5 1.5.67 1.5 1.5-.67 1.5-1.5 1.5z"></path>
</g> |
| 15417 <g id="perm-device-information"><path d="M13 7h-2v2h2V7zm0 4h-2v6h2v-6zm4-9.99L7
1c-1.1 0-2 .9-2 2v18c0 1.1.9 2 2 2h10c1.1 0 2-.9 2-2V3c0-1.1-.9-1.99-2-1.99zM17
19H7V5h10v14z"></path></g> |
| 15418 <g id="perm-identity"><path d="M12 5.9c1.16 0 2.1.94 2.1 2.1s-.94 2.1-2.1 2.1S9.
9 9.16 9.9 8s.94-2.1 2.1-2.1m0 9c2.97 0 6.1 1.46 6.1 2.1v1.1H5.9V17c0-.64 3.13-2
.1 6.1-2.1M12 4C9.79 4 8 5.79 8 8s1.79 4 4 4 4-1.79 4-4-1.79-4-4-4zm0 9c-2.67 0-
8 1.34-8 4v3h16v-3c0-2.66-5.33-4-8-4z"></path></g> |
| 15419 <g id="perm-media"><path d="M2 6H0v5h.01L0 20c0 1.1.9 2 2 2h18v-2H2V6zm20-2h-8l-
2-2H6c-1.1 0-1.99.9-1.99 2L4 16c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V6c0-1.1-.9-2-2-2
zM7 15l4.5-6 3.5 4.51 2.5-3.01L21 15H7z"></path></g> |
| 15420 <g id="perm-phone-msg"><path d="M20 15.5c-1.25 0-2.45-.2-3.57-.57-.35-.11-.74-.0
3-1.02.24l-2.2 2.2c-2.83-1.44-5.15-3.75-6.59-6.58l2.2-2.21c.28-.27.36-.66.25-1.0
1C8.7 6.45 8.5 5.25 8.5 4c0-.55-.45-1-1-1H4c-.55 0-1 .45-1 1 0 9.39 7.61 17 17 1
7 .55 0 1-.45 1-1v-3.5c0-.55-.45-1-1-1zM12 3v10l3-3h6V3h-9z"></path></g> |
| 15421 <g id="perm-scan-wifi"><path d="M12 3C6.95 3 3.15 4.85 0 7.23L12 22 24 7.25C20.8
5 4.87 17.05 3 12 3zm1 13h-2v-6h2v6zm-2-8V6h2v2h-2z"></path></g> |
| 15422 <g id="pets"><circle cx="4.5" cy="9.5" r="2.5"></circle><circle cx="9" cy="5.5"
r="2.5"></circle><circle cx="15" cy="5.5" r="2.5"></circle><circle cx="19.5" cy=
"9.5" r="2.5"></circle><path d="M17.34 14.86c-.87-1.02-1.6-1.89-2.48-2.91-.46-.5
4-1.05-1.08-1.75-1.32-.11-.04-.22-.07-.33-.09-.25-.04-.52-.04-.78-.04s-.53 0-.79
.05c-.11.02-.22.05-.33.09-.7.24-1.28.78-1.75 1.32-.87 1.02-1.6 1.89-2.48 2.91-1.
31 1.31-2.92 2.76-2.62 4.79.29 1.02 1.02 2.03 2.33 2.32.73.15 3.06-.44 5.54-.44h
.18c2.48 0 4.81.58 5.54.44 1.31-.29 2.04-1.31 2.33-2.32.31-2.04-1.3-3.49-2.61-4.
8z"></path></g> |
| 15423 <g id="picture-in-picture"><path d="M19 7h-8v6h8V7zm2-4H3c-1.1 0-2 .9-2 2v14c0 1
.1.9 1.98 2 1.98h18c1.1 0 2-.88 2-1.98V5c0-1.1-.9-2-2-2zm0 16.01H3V4.98h18v14.03
z"></path></g> |
| 15424 <g id="picture-in-picture-alt"><path d="M19 11h-8v6h8v-6zm4 8V4.98C23 3.88 22.1
3 21 3H3c-1.1 0-2 .88-2 1.98V19c0 1.1.9 2 2 2h18c1.1 0 2-.9 2-2zm-2 .02H3V4.97h1
8v14.05z"></path></g> |
| 15425 <g id="play-for-work"><path d="M11 5v5.59H7.5l4.5 4.5 4.5-4.5H13V5h-2zm-5 9c0 3.
31 2.69 6 6 6s6-2.69 6-6h-2c0 2.21-1.79 4-4 4s-4-1.79-4-4H6z"></path></g> |
| 15426 <g id="polymer"><path d="M19 4h-4L7.11 16.63 4.5 12 9 4H5L.5 12 5 20h4l7.89-12.6
3L19.5 12 15 20h4l4.5-8z"></path></g> |
| 15427 <g id="power-settings-new"><path d="M13 3h-2v10h2V3zm4.83 2.17l-1.42 1.42C17.99
7.86 19 9.81 19 12c0 3.87-3.13 7-7 7s-7-3.13-7-7c0-2.19 1.01-4.14 2.58-5.42L6.17
5.17C4.23 6.82 3 9.26 3 12c0 4.97 4.03 9 9 9s9-4.03 9-9c0-2.74-1.23-5.18-3.17-6
.83z"></path></g> |
| 15428 <g id="pregnant-woman"><path d="M9 4c0-1.11.89-2 2-2s2 .89 2 2-.89 2-2 2-2-.89-2
-2zm7 9c-.01-1.34-.83-2.51-2-3 0-1.66-1.34-3-3-3s-3 1.34-3 3v7h2v5h3v-5h3v-4z"><
/path></g> |
| 15429 <g id="print"><path d="M19 8H5c-1.66 0-3 1.34-3 3v6h4v4h12v-4h4v-6c0-1.66-1.34-3
-3-3zm-3 11H8v-5h8v5zm3-7c-.55 0-1-.45-1-1s.45-1 1-1 1 .45 1 1-.45 1-1 1zm-1-9H6
v4h12V3z"></path></g> |
| 15430 <g id="query-builder"><path d="M11.99 2C6.47 2 2 6.48 2 12s4.47 10 9.99 10C17.52
22 22 17.52 22 12S17.52 2 11.99 2zM12 20c-4.42 0-8-3.58-8-8s3.58-8 8-8 8 3.58 8
8-3.58 8-8 8zm.5-13H11v6l5.25 3.15.75-1.23-4.5-2.67z"></path></g> |
| 15431 <g id="question-answer"><path d="M21 6h-2v9H6v2c0 .55.45 1 1 1h11l4 4V7c0-.55-.4
5-1-1-1zm-4 6V3c0-.55-.45-1-1-1H3c-.55 0-1 .45-1 1v14l4-4h10c.55 0 1-.45 1-1z"><
/path></g> |
| 15432 <g id="radio-button-checked"><path d="M12 7c-2.76 0-5 2.24-5 5s2.24 5 5 5 5-2.24
5-5-2.24-5-5-5zm0-5C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2
zm0 18c-4.42 0-8-3.58-8-8s3.58-8 8-8 8 3.58 8 8-3.58 8-8 8z"></path></g> |
| 15433 <g id="radio-button-unchecked"><path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 1
0-4.48 10-10S17.52 2 12 2zm0 18c-4.42 0-8-3.58-8-8s3.58-8 8-8 8 3.58 8 8-3.58 8-
8 8z"></path></g> |
| 15434 <g id="receipt"><path d="M18 17H6v-2h12v2zm0-4H6v-2h12v2zm0-4H6V7h12v2zM3 22l1.5
-1.5L6 22l1.5-1.5L9 22l1.5-1.5L12 22l1.5-1.5L15 22l1.5-1.5L18 22l1.5-1.5L21 22V2
l-1.5 1.5L18 2l-1.5 1.5L15 2l-1.5 1.5L12 2l-1.5 1.5L9 2 7.5 3.5 6 2 4.5 3.5 3 2v
20z"></path></g> |
| 15435 <g id="record-voice-over"><circle cx="9" cy="9" r="4"></circle><path d="M9 15c-2
.67 0-8 1.34-8 4v2h16v-2c0-2.66-5.33-4-8-4zm7.76-9.64l-1.68 1.69c.84 1.18.84 2.7
1 0 3.89l1.68 1.69c2.02-2.02 2.02-5.07 0-7.27zM20.07 2l-1.63 1.63c2.77 3.02 2.77
7.56 0 10.74L20.07 16c3.9-3.89 3.91-9.95 0-14z"></path></g> |
| 15436 <g id="redeem"><path d="M20 6h-2.18c.11-.31.18-.65.18-1 0-1.66-1.34-3-3-3-1.05 0
-1.96.54-2.5 1.35l-.5.67-.5-.68C10.96 2.54 10.05 2 9 2 7.34 2 6 3.34 6 5c0 .35.0
7.69.18 1H4c-1.11 0-1.99.89-1.99 2L2 19c0 1.11.89 2 2 2h16c1.11 0 2-.89 2-2V8c0-
1.11-.89-2-2-2zm-5-2c.55 0 1 .45 1 1s-.45 1-1 1-1-.45-1-1 .45-1 1-1zM9 4c.55 0 1
.45 1 1s-.45 1-1 1-1-.45-1-1 .45-1 1-1zm11 15H4v-2h16v2zm0-5H4V8h5.08L7 10.83 8
.62 12 11 8.76l1-1.36 1 1.36L15.38 12 17 10.83 14.92 8H20v6z"></path></g> |
| 15437 <g id="redo"><path d="M18.4 10.6C16.55 8.99 14.15 8 11.5 8c-4.65 0-8.58 3.03-9.9
6 7.22L3.9 16c1.05-3.19 4.05-5.5 7.6-5.5 1.95 0 3.73.72 5.12 1.88L13 16h9V7l-3.6
3.6z"></path></g> |
| 15438 <g id="refresh"><path d="M17.65 6.35C16.2 4.9 14.21 4 12 4c-4.42 0-7.99 3.58-7.9
9 8s3.57 8 7.99 8c3.73 0 6.84-2.55 7.73-6h-2.08c-.82 2.33-3.04 4-5.65 4-3.31 0-6
-2.69-6-6s2.69-6 6-6c1.66 0 3.14.69 4.22 1.78L13 11h7V4l-2.35 2.35z"></path></g> |
| 15439 <g id="remove"><path d="M19 13H5v-2h14v2z"></path></g> |
| 15440 <g id="remove-circle"><path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10
-10S17.52 2 12 2zm5 11H7v-2h10v2z"></path></g> |
| 15441 <g id="remove-circle-outline"><path d="M7 11v2h10v-2H7zm5-9C6.48 2 2 6.48 2 12s4
.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm0 18c-4.41 0-8-3.59-8-8s3.59-8 8-8 8 3.
59 8 8-3.59 8-8 8z"></path></g> |
| 15442 <g id="reorder"><path d="M3 15h18v-2H3v2zm0 4h18v-2H3v2zm0-8h18V9H3v2zm0-6v2h18V
5H3z"></path></g> |
| 15443 <g id="reply"><path d="M10 9V5l-7 7 7 7v-4.1c5 0 8.5 1.6 11 5.1-1-5-4-10-11-11z"
></path></g> |
| 15444 <g id="reply-all"><path d="M7 8V5l-7 7 7 7v-3l-4-4 4-4zm6 1V5l-7 7 7 7v-4.1c5 0
8.5 1.6 11 5.1-1-5-4-10-11-11z"></path></g> |
| 15445 <g id="report"><path d="M15.73 3H8.27L3 8.27v7.46L8.27 21h7.46L21 15.73V8.27L15.
73 3zM12 17.3c-.72 0-1.3-.58-1.3-1.3 0-.72.58-1.3 1.3-1.3.72 0 1.3.58 1.3 1.3 0
.72-.58 1.3-1.3 1.3zm1-4.3h-2V7h2v6z"></path></g> |
| 15446 <g id="report-problem"><path d="M1 21h22L12 2 1 21zm12-3h-2v-2h2v2zm0-4h-2v-4h2v
4z"></path></g> |
| 15447 <g id="restore"><path d="M13 3c-4.97 0-9 4.03-9 9H1l3.89 3.89.07.14L9 12H6c0-3.8
7 3.13-7 7-7s7 3.13 7 7-3.13 7-7 7c-1.93 0-3.68-.79-4.94-2.06l-1.42 1.42C8.27 19
.99 10.51 21 13 21c4.97 0 9-4.03 9-9s-4.03-9-9-9zm-1 5v5l4.28 2.54.72-1.21-3.5-2
.08V8H12z"></path></g> |
| 15448 <g id="room"><path d="M12 2C8.13 2 5 5.13 5 9c0 5.25 7 13 7 13s7-7.75 7-13c0-3.8
7-3.13-7-7-7zm0 9.5c-1.38 0-2.5-1.12-2.5-2.5s1.12-2.5 2.5-2.5 2.5 1.12 2.5 2.5-1
.12 2.5-2.5 2.5z"></path></g> |
| 15449 <g id="rounded-corner"><path d="M19 19h2v2h-2v-2zm0-2h2v-2h-2v2zM3 13h2v-2H3v2zm
0 4h2v-2H3v2zm0-8h2V7H3v2zm0-4h2V3H3v2zm4 0h2V3H7v2zm8 16h2v-2h-2v2zm-4 0h2v-2h-
2v2zm4 0h2v-2h-2v2zm-8 0h2v-2H7v2zm-4 0h2v-2H3v2zM21 8c0-2.76-2.24-5-5-5h-5v2h5c
1.65 0 3 1.35 3 3v5h2V8z"></path></g> |
| 15450 <g id="rowing"><path d="M8.5 14.5L4 19l1.5 1.5L9 17h2l-2.5-2.5zM15 1c-1.1 0-2 .9
-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2zm6 20.01L18 24l-2.99-3.01V19.5l-7.1-7.09c-.31.05
-.61.07-.91.07v-2.16c1.66.03 3.61-.87 4.67-2.04l1.4-1.55c.19-.21.43-.38.69-.5.29
-.14.62-.23.96-.23h.03C15.99 6.01 17 7.02 17 8.26v5.75c0 .84-.35 1.61-.92 2.16l-
3.58-3.58v-2.27c-.63.52-1.43 1.02-2.29 1.39L16.5 18H18l3 3.01z"></path></g> |
| 15451 <g id="save"><path d="M17 3H5c-1.11 0-2 .9-2 2v14c0 1.1.89 2 2 2h14c1.1 0 2-.9 2
-2V7l-4-4zm-5 16c-1.66 0-3-1.34-3-3s1.34-3 3-3 3 1.34 3 3-1.34 3-3 3zm3-10H5V5h1
0v4z"></path></g> |
| 15452 <g id="schedule"><path d="M11.99 2C6.47 2 2 6.48 2 12s4.47 10 9.99 10C17.52 22 2
2 17.52 22 12S17.52 2 11.99 2zM12 20c-4.42 0-8-3.58-8-8s3.58-8 8-8 8 3.58 8 8-3.
58 8-8 8zm.5-13H11v6l5.25 3.15.75-1.23-4.5-2.67z"></path></g> |
| 15453 <g id="search"><path d="M15.5 14h-.79l-.28-.27C15.41 12.59 16 11.11 16 9.5 16 5.
91 13.09 3 9.5 3S3 5.91 3 9.5 5.91 16 9.5 16c1.61 0 3.09-.59 4.23-1.57l.27.28v.7
9l5 4.99L20.49 19l-4.99-5zm-6 0C7.01 14 5 11.99 5 9.5S7.01 5 9.5 5 14 7.01 14 9.
5 11.99 14 9.5 14z"></path></g> |
| 15454 <g id="select-all"><path d="M3 5h2V3c-1.1 0-2 .9-2 2zm0 8h2v-2H3v2zm4 8h2v-2H7v2
zM3 9h2V7H3v2zm10-6h-2v2h2V3zm6 0v2h2c0-1.1-.9-2-2-2zM5 21v-2H3c0 1.1.9 2 2 2zm-
2-4h2v-2H3v2zM9 3H7v2h2V3zm2 18h2v-2h-2v2zm8-8h2v-2h-2v2zm0 8c1.1 0 2-.9 2-2h-2v
2zm0-12h2V7h-2v2zm0 8h2v-2h-2v2zm-4 4h2v-2h-2v2zm0-16h2V3h-2v2zM7 17h10V7H7v10zm
2-8h6v6H9V9z"></path></g> |
| 15455 <g id="send"><path d="M2.01 21L23 12 2.01 3 2 10l15 2-15 2z"></path></g> |
| 15456 <g id="settings"><path d="M19.43 12.98c.04-.32.07-.64.07-.98s-.03-.66-.07-.98l2.
11-1.65c.19-.15.24-.42.12-.64l-2-3.46c-.12-.22-.39-.3-.61-.22l-2.49 1c-.52-.4-1.
08-.73-1.69-.98l-.38-2.65C14.46 2.18 14.25 2 14 2h-4c-.25 0-.46.18-.49.42l-.38 2
.65c-.61.25-1.17.59-1.69.98l-2.49-1c-.23-.09-.49 0-.61.22l-2 3.46c-.13.22-.07.49
.12.64l2.11 1.65c-.04.32-.07.65-.07.98s.03.66.07.98l-2.11 1.65c-.19.15-.24.42-.1
2.64l2 3.46c.12.22.39.3.61.22l2.49-1c.52.4 1.08.73 1.69.98l.38 2.65c.03.24.24.42
.49.42h4c.25 0 .46-.18.49-.42l.38-2.65c.61-.25 1.17-.59 1.69-.98l2.49 1c.23.09.4
9 0 .61-.22l2-3.46c.12-.22.07-.49-.12-.64l-2.11-1.65zM12 15.5c-1.93 0-3.5-1.57-3
.5-3.5s1.57-3.5 3.5-3.5 3.5 1.57 3.5 3.5-1.57 3.5-3.5 3.5z"></path></g> |
| 15457 <g id="settings-applications"><path d="M12 10c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-
.9-2-2-2zm7-7H5c-1.11 0-2 .9-2 2v14c0 1.1.89 2 2 2h14c1.11 0 2-.9 2-2V5c0-1.1-.8
9-2-2-2zm-1.75 9c0 .23-.02.46-.05.68l1.48 1.16c.13.11.17.3.08.45l-1.4 2.42c-.09.
15-.27.21-.43.15l-1.74-.7c-.36.28-.76.51-1.18.69l-.26 1.85c-.03.17-.18.3-.35.3h-
2.8c-.17 0-.32-.13-.35-.29l-.26-1.85c-.43-.18-.82-.41-1.18-.69l-1.74.7c-.16.06-.
34 0-.43-.15l-1.4-2.42c-.09-.15-.05-.34.08-.45l1.48-1.16c-.03-.23-.05-.46-.05-.6
9 0-.23.02-.46.05-.68l-1.48-1.16c-.13-.11-.17-.3-.08-.45l1.4-2.42c.09-.15.27-.21
.43-.15l1.74.7c.36-.28.76-.51 1.18-.69l.26-1.85c.03-.17.18-.3.35-.3h2.8c.17 0 .3
2.13.35.29l.26 1.85c.43.18.82.41 1.18.69l1.74-.7c.16-.06.34 0 .43.15l1.4 2.42c.0
9.15.05.34-.08.45l-1.48 1.16c.03.23.05.46.05.69z"></path></g> |
| 15458 <g id="settings-backup-restore"><path d="M14 12c0-1.1-.9-2-2-2s-2 .9-2 2 .9 2 2
2 2-.9 2-2zm-2-9c-4.97 0-9 4.03-9 9H0l4 4 4-4H5c0-3.87 3.13-7 7-7s7 3.13 7 7-3.1
3 7-7 7c-1.51 0-2.91-.49-4.06-1.3l-1.42 1.44C8.04 20.3 9.94 21 12 21c4.97 0 9-4.
03 9-9s-4.03-9-9-9z"></path></g> |
| 15459 <g id="settings-bluetooth"><path d="M11 24h2v-2h-2v2zm-4 0h2v-2H7v2zm8 0h2v-2h-2
v2zm2.71-18.29L12 0h-1v7.59L6.41 3 5 4.41 10.59 10 5 15.59 6.41 17 11 12.41V20h1
l5.71-5.71-4.3-4.29 4.3-4.29zM13 3.83l1.88 1.88L13 7.59V3.83zm1.88 10.46L13 16.1
7v-3.76l1.88 1.88z"></path></g> |
| 15460 <g id="settings-brightness"><path d="M21 3H3c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h18
c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm0 16.01H3V4.99h18v14.02zM8 16h2.5l1.5 1.5 1.5-
1.5H16v-2.5l1.5-1.5-1.5-1.5V8h-2.5L12 6.5 10.5 8H8v2.5L6.5 12 8 13.5V16zm4-7c1.6
6 0 3 1.34 3 3s-1.34 3-3 3V9z"></path></g> |
| 15461 <g id="settings-cell"><path d="M7 24h2v-2H7v2zm4 0h2v-2h-2v2zm4 0h2v-2h-2v2zM16
.01L8 0C6.9 0 6 .9 6 2v16c0 1.1.9 2 2 2h8c1.1 0 2-.9 2-2V2c0-1.1-.9-1.99-2-1.99z
M16 16H8V4h8v12z"></path></g> |
| 15462 <g id="settings-ethernet"><path d="M7.77 6.76L6.23 5.48.82 12l5.41 6.52 1.54-1.2
8L3.42 12l4.35-5.24zM7 13h2v-2H7v2zm10-2h-2v2h2v-2zm-6 2h2v-2h-2v2zm6.77-7.52l-1
.54 1.28L20.58 12l-4.35 5.24 1.54 1.28L23.18 12l-5.41-6.52z"></path></g> |
| 15463 <g id="settings-input-antenna"><path d="M12 5c-3.87 0-7 3.13-7 7h2c0-2.76 2.24-5
5-5s5 2.24 5 5h2c0-3.87-3.13-7-7-7zm1 9.29c.88-.39 1.5-1.26 1.5-2.29 0-1.38-1.1
2-2.5-2.5-2.5S9.5 10.62 9.5 12c0 1.02.62 1.9 1.5 2.29v3.3L7.59 21 9 22.41l3-3 3
3L16.41 21 13 17.59v-3.3zM12 1C5.93 1 1 5.93 1 12h2c0-4.97 4.03-9 9-9s9 4.03 9 9
h2c0-6.07-4.93-11-11-11z"></path></g> |
| 15464 <g id="settings-input-component"><path d="M5 2c0-.55-.45-1-1-1s-1 .45-1 1v4H1v6h
6V6H5V2zm4 14c0 1.3.84 2.4 2 2.82V23h2v-4.18c1.16-.41 2-1.51 2-2.82v-2H9v2zm-8 0
c0 1.3.84 2.4 2 2.82V23h2v-4.18C6.16 18.4 7 17.3 7 16v-2H1v2zM21 6V2c0-.55-.45-1
-1-1s-1 .45-1 1v4h-2v6h6V6h-2zm-8-4c0-.55-.45-1-1-1s-1 .45-1 1v4H9v6h6V6h-2V2zm4
14c0 1.3.84 2.4 2 2.82V23h2v-4.18c1.16-.41 2-1.51 2-2.82v-2h-6v2z"></path></g> |
| 15465 <g id="settings-input-composite"><path d="M5 2c0-.55-.45-1-1-1s-1 .45-1 1v4H1v6h
6V6H5V2zm4 14c0 1.3.84 2.4 2 2.82V23h2v-4.18c1.16-.41 2-1.51 2-2.82v-2H9v2zm-8 0
c0 1.3.84 2.4 2 2.82V23h2v-4.18C6.16 18.4 7 17.3 7 16v-2H1v2zM21 6V2c0-.55-.45-1
-1-1s-1 .45-1 1v4h-2v6h6V6h-2zm-8-4c0-.55-.45-1-1-1s-1 .45-1 1v4H9v6h6V6h-2V2zm4
14c0 1.3.84 2.4 2 2.82V23h2v-4.18c1.16-.41 2-1.51 2-2.82v-2h-6v2z"></path></g> |
| 15466 <g id="settings-input-hdmi"><path d="M18 7V4c0-1.1-.9-2-2-2H8c-1.1 0-2 .9-2 2v3H
5v6l3 6v3h8v-3l3-6V7h-1zM8 4h8v3h-2V5h-1v2h-2V5h-1v2H8V4z"></path></g> |
| 15467 <g id="settings-input-svideo"><path d="M8 11.5c0-.83-.67-1.5-1.5-1.5S5 10.67 5 1
1.5 5.67 13 6.5 13 8 12.33 8 11.5zm7-5c0-.83-.67-1.5-1.5-1.5h-3C9.67 5 9 5.67 9
6.5S9.67 8 10.5 8h3c.83 0 1.5-.67 1.5-1.5zM8.5 15c-.83 0-1.5.67-1.5 1.5S7.67 18
8.5 18s1.5-.67 1.5-1.5S9.33 15 8.5 15zM12 1C5.93 1 1 5.93 1 12s4.93 11 11 11 11-
4.93 11-11S18.07 1 12 1zm0 20c-4.96 0-9-4.04-9-9s4.04-9 9-9 9 4.04 9 9-4.04 9-9
9zm5.5-11c-.83 0-1.5.67-1.5 1.5s.67 1.5 1.5 1.5 1.5-.67 1.5-1.5-.67-1.5-1.5-1.5z
m-2 5c-.83 0-1.5.67-1.5 1.5s.67 1.5 1.5 1.5 1.5-.67 1.5-1.5-.67-1.5-1.5-1.5z"></
path></g> |
| 15468 <g id="settings-overscan"><path d="M12.01 5.5L10 8h4l-1.99-2.5zM18 10v4l2.5-1.99
L18 10zM6 10l-2.5 2.01L6 14v-4zm8 6h-4l2.01 2.5L14 16zm7-13H3c-1.1 0-2 .9-2 2v14
c0 1.1.9 2 2 2h18c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm0 16.01H3V4.99h18v14.02z"></p
ath></g> |
| 15469 <g id="settings-phone"><path d="M13 9h-2v2h2V9zm4 0h-2v2h2V9zm3 6.5c-1.25 0-2.45
-.2-3.57-.57-.35-.11-.74-.03-1.02.24l-2.2 2.2c-2.83-1.44-5.15-3.75-6.59-6.58l2.2
-2.21c.28-.27.36-.66.25-1.01C8.7 6.45 8.5 5.25 8.5 4c0-.55-.45-1-1-1H4c-.55 0-1
.45-1 1 0 9.39 7.61 17 17 17 .55 0 1-.45 1-1v-3.5c0-.55-.45-1-1-1zM19 9v2h2V9h-2
z"></path></g> |
| 15470 <g id="settings-power"><path d="M7 24h2v-2H7v2zm4 0h2v-2h-2v2zm2-22h-2v10h2V2zm3
.56 2.44l-1.45 1.45C16.84 6.94 18 8.83 18 11c0 3.31-2.69 6-6 6s-6-2.69-6-6c0-2.1
7 1.16-4.06 2.88-5.12L7.44 4.44C5.36 5.88 4 8.28 4 11c0 4.42 3.58 8 8 8s8-3.58 8
-8c0-2.72-1.36-5.12-3.44-6.56zM15 24h2v-2h-2v2z"></path></g> |
| 15471 <g id="settings-remote"><path d="M15 9H9c-.55 0-1 .45-1 1v12c0 .55.45 1 1 1h6c.5
5 0 1-.45 1-1V10c0-.55-.45-1-1-1zm-3 6c-1.1 0-2-.9-2-2s.9-2 2-2 2 .9 2 2-.9 2-2
2zM7.05 6.05l1.41 1.41C9.37 6.56 10.62 6 12 6s2.63.56 3.54 1.46l1.41-1.41C15.68
4.78 13.93 4 12 4s-3.68.78-4.95 2.05zM12 0C8.96 0 6.21 1.23 4.22 3.22l1.41 1.41C
7.26 3.01 9.51 2 12 2s4.74 1.01 6.36 2.64l1.41-1.41C17.79 1.23 15.04 0 12 0z"></
path></g> |
| 15472 <g id="settings-voice"><path d="M7 24h2v-2H7v2zm5-11c1.66 0 2.99-1.34 2.99-3L15
4c0-1.66-1.34-3-3-3S9 2.34 9 4v6c0 1.66 1.34 3 3 3zm-1 11h2v-2h-2v2zm4 0h2v-2h-2
v2zm4-14h-1.7c0 3-2.54 5.1-5.3 5.1S6.7 13 6.7 10H5c0 3.41 2.72 6.23 6 6.72V20h2v
-3.28c3.28-.49 6-3.31 6-6.72z"></path></g> |
| 15473 <g id="shop"><path d="M16 6V4c0-1.11-.89-2-2-2h-4c-1.11 0-2 .89-2 2v2H2v13c0 1.1
1.89 2 2 2h16c1.11 0 2-.89 2-2V6h-6zm-6-2h4v2h-4V4zM9 18V9l7.5 4L9 18z"></path><
/g> |
| 15474 <g id="shop-two"><path d="M3 9H1v11c0 1.11.89 2 2 2h14c1.11 0 2-.89 2-2H3V9zm15-
4V3c0-1.11-.89-2-2-2h-4c-1.11 0-2 .89-2 2v2H5v11c0 1.11.89 2 2 2h14c1.11 0 2-.89
2-2V5h-5zm-6-2h4v2h-4V3zm0 12V8l5.5 3-5.5 4z"></path></g> |
| 15475 <g id="shopping-basket"><path d="M17.21 9l-4.38-6.56c-.19-.28-.51-.42-.83-.42-.3
2 0-.64.14-.83.43L6.79 9H2c-.55 0-1 .45-1 1 0 .09.01.18.04.27l2.54 9.27c.23.84 1
1.46 1.92 1.46h13c.92 0 1.69-.62 1.93-1.46l2.54-9.27L23 10c0-.55-.45-1-1-1h-4.7
9zM9 9l3-4.4L15 9H9zm3 8c-1.1 0-2-.9-2-2s.9-2 2-2 2 .9 2 2-.9 2-2 2z"></path></g
> |
| 15476 <g id="shopping-cart"><path d="M7 18c-1.1 0-1.99.9-1.99 2S5.9 22 7 22s2-.9 2-2-.
9-2-2-2zM1 2v2h2l3.6 7.59-1.35 2.45c-.16.28-.25.61-.25.96 0 1.1.9 2 2 2h12v-2H7.
42c-.14 0-.25-.11-.25-.25l.03-.12.9-1.63h7.45c.75 0 1.41-.41 1.75-1.03l3.58-6.49
c.08-.14.12-.31.12-.48 0-.55-.45-1-1-1H5.21l-.94-2H1zm16 16c-1.1 0-1.99.9-1.99 2
s.89 2 1.99 2 2-.9 2-2-.9-2-2-2z"></path></g> |
| 15477 <g id="sort"><path d="M3 18h6v-2H3v2zM3 6v2h18V6H3zm0 7h12v-2H3v2z"></path></g> |
| 15478 <g id="speaker-notes"><path d="M20 2H4c-1.1 0-1.99.9-1.99 2L2 22l4-4h14c1.1 0 2-
.9 2-2V4c0-1.1-.9-2-2-2zM8 14H6v-2h2v2zm0-3H6V9h2v2zm0-3H6V6h2v2zm7 6h-5v-2h5v2z
m3-3h-8V9h8v2zm0-3h-8V6h8v2z"></path></g> |
| 15479 <g id="spellcheck"><path d="M12.45 16h2.09L9.43 3H7.57L2.46 16h2.09l1.12-3h5.64l
1.14 3zm-6.02-5L8.5 5.48 10.57 11H6.43zm15.16.59l-8.09 8.09L9.83 16l-1.41 1.41 5
.09 5.09L23 13l-1.41-1.41z"></path></g> |
| 15480 <g id="star"><path d="M12 17.27L18.18 21l-1.64-7.03L22 9.24l-7.19-.61L12 2 9.19
8.63 2 9.24l5.46 4.73L5.82 21z"></path></g> |
| 15481 <g id="star-border"><path d="M22 9.24l-7.19-.62L12 2 9.19 8.63 2 9.24l5.46 4.73L
5.82 21 12 17.27 18.18 21l-1.63-7.03L22 9.24zM12 15.4l-3.76 2.27 1-4.28-3.32-2.8
8 4.38-.38L12 6.1l1.71 4.04 4.38.38-3.32 2.88 1 4.28L12 15.4z"></path></g> |
| 15482 <g id="star-half"><path d="M22 9.24l-7.19-.62L12 2 9.19 8.63 2 9.24l5.46 4.73L5.
82 21 12 17.27 18.18 21l-1.63-7.03L22 9.24zM12 15.4V6.1l1.71 4.04 4.38.38-3.32 2
.88 1 4.28L12 15.4z"></path></g> |
| 15483 <g id="stars"><path d="M11.99 2C6.47 2 2 6.48 2 12s4.47 10 9.99 10C17.52 22 22 1
7.52 22 12S17.52 2 11.99 2zm4.24 16L12 15.45 7.77 18l1.12-4.81-3.73-3.23 4.92-.4
2L12 5l1.92 4.53 4.92.42-3.73 3.23L16.23 18z"></path></g> |
| 15484 <g id="store"><path d="M20 4H4v2h16V4zm1 10v-2l-1-5H4l-1 5v2h1v6h10v-6h4v6h2v-6h
1zm-9 4H6v-4h6v4z"></path></g> |
| 15485 <g id="subdirectory-arrow-left"><path d="M11 9l1.42 1.42L8.83 14H18V4h2v12H8.83l
3.59 3.58L11 21l-6-6 6-6z"></path></g> |
| 15486 <g id="subdirectory-arrow-right"><path d="M19 15l-6 6-1.42-1.42L15.17 16H4V4h2v1
0h9.17l-3.59-3.58L13 9l6 6z"></path></g> |
| 15487 <g id="subject"><path d="M14 17H4v2h10v-2zm6-8H4v2h16V9zM4 15h16v-2H4v2zM4 5v2h1
6V5H4z"></path></g> |
| 15488 <g id="supervisor-account"><path d="M16.5 12c1.38 0 2.49-1.12 2.49-2.5S17.88 7 1
6.5 7C15.12 7 14 8.12 14 9.5s1.12 2.5 2.5 2.5zM9 11c1.66 0 2.99-1.34 2.99-3S10.6
6 5 9 5C7.34 5 6 6.34 6 8s1.34 3 3 3zm7.5 3c-1.83 0-5.5.92-5.5 2.75V19h11v-2.25c
0-1.83-3.67-2.75-5.5-2.75zM9 13c-2.33 0-7 1.17-7 3.5V19h7v-2.25c0-.85.33-2.34 2.
37-3.47C10.5 13.1 9.66 13 9 13z"></path></g> |
| 15489 <g id="swap-horiz"><path d="M6.99 11L3 15l3.99 4v-3H14v-2H6.99v-3zM21 9l-3.99-4v
3H10v2h7.01v3L21 9z"></path></g> |
| 15490 <g id="swap-vert"><path d="M16 17.01V10h-2v7.01h-3L15 21l4-3.99h-3zM9 3L5 6.99h3
V14h2V6.99h3L9 3z"></path></g> |
| 15491 <g id="swap-vertical-circle"><path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-
4.48 10-10S17.52 2 12 2zM6.5 9L10 5.5 13.5 9H11v4H9V9H6.5zm11 6L14 18.5 10.5 15H
13v-4h2v4h2.5z"></path></g> |
| 15492 <g id="system-update-alt"><path d="M12 16.5l4-4h-3v-9h-2v9H8l4 4zm9-13h-6v1.99h6
v14.03H3V5.49h6V3.5H3c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h18c1.1 0 2-.9 2-2v-14c0-1
.1-.9-2-2-2z"></path></g> |
| 15493 <g id="tab"><path d="M21 3H3c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h18c1.1 0 2-.9 2-2V
5c0-1.1-.9-2-2-2zm0 16H3V5h10v4h8v10z"></path></g> |
| 15494 <g id="tab-unselected"><path d="M1 9h2V7H1v2zm0 4h2v-2H1v2zm0-8h2V3c-1.1 0-2 .9-
2 2zm8 16h2v-2H9v2zm-8-4h2v-2H1v2zm2 4v-2H1c0 1.1.9 2 2 2zM21 3h-8v6h10V5c0-1.1-
.9-2-2-2zm0 14h2v-2h-2v2zM9 5h2V3H9v2zM5 21h2v-2H5v2zM5 5h2V3H5v2zm16 16c1.1 0 2
-.9 2-2h-2v2zm0-8h2v-2h-2v2zm-8 8h2v-2h-2v2zm4 0h2v-2h-2v2z"></path></g> |
| 15495 <g id="text-format"><path d="M5 17v2h14v-2H5zm4.5-4.2h5l.9 2.2h2.1L12.75 4h-1.5L
6.5 15h2.1l.9-2.2zM12 5.98L13.87 11h-3.74L12 5.98z"></path></g> |
| 15496 <g id="theaters"><path d="M18 3v2h-2V3H8v2H6V3H4v18h2v-2h2v2h8v-2h2v2h2V3h-2zM8
17H6v-2h2v2zm0-4H6v-2h2v2zm0-4H6V7h2v2zm10 8h-2v-2h2v2zm0-4h-2v-2h2v2zm0-4h-2V7h
2v2z"></path></g> |
| 15497 <g id="thumb-down"><path d="M15 3H6c-.83 0-1.54.5-1.84 1.22l-3.02 7.05c-.09.23-.
14.47-.14.73v1.91l.01.01L1 14c0 1.1.9 2 2 2h6.31l-.95 4.57-.03.32c0 .41.17.79.44
1.06L9.83 23l6.59-6.59c.36-.36.58-.86.58-1.41V5c0-1.1-.9-2-2-2zm4 0v12h4V3h-4z"
></path></g> |
| 15498 <g id="thumb-up"><path d="M1 21h4V9H1v12zm22-11c0-1.1-.9-2-2-2h-6.31l.95-4.57.03
-.32c0-.41-.17-.79-.44-1.06L14.17 1 7.59 7.59C7.22 7.95 7 8.45 7 9v10c0 1.1.9 2
2 2h9c.83 0 1.54-.5 1.84-1.22l3.02-7.05c.09-.23.14-.47.14-.73v-1.91l-.01-.01L23
10z"></path></g> |
| 15499 <g id="thumbs-up-down"><path d="M12 6c0-.55-.45-1-1-1H5.82l.66-3.18.02-.23c0-.31
-.13-.59-.33-.8L5.38 0 .44 4.94C.17 5.21 0 5.59 0 6v6.5c0 .83.67 1.5 1.5 1.5h6.7
5c.62 0 1.15-.38 1.38-.91l2.26-5.29c.07-.17.11-.36.11-.55V6zm10.5 4h-6.75c-.62 0
-1.15.38-1.38.91l-2.26 5.29c-.07.17-.11.36-.11.55V18c0 .55.45 1 1 1h5.18l-.66 3.
18-.02.24c0 .31.13.59.33.8l.79.78 4.94-4.94c.27-.27.44-.65.44-1.06v-6.5c0-.83-.6
7-1.5-1.5-1.5z"></path></g> |
| 15500 <g id="timeline"><path d="M23 8c0 1.1-.9 2-2 2-.18 0-.35-.02-.51-.07l-3.56 3.55c
.05.16.07.34.07.52 0 1.1-.9 2-2 2s-2-.9-2-2c0-.18.02-.36.07-.52l-2.55-2.55c-.16.
05-.34.07-.52.07s-.36-.02-.52-.07l-4.55 4.56c.05.16.07.33.07.51 0 1.1-.9 2-2 2s-
2-.9-2-2 .9-2 2-2c.18 0 .35.02.51.07l4.56-4.55C8.02 9.36 8 9.18 8 9c0-1.1.9-2 2-
2s2 .9 2 2c0 .18-.02.36-.07.52l2.55 2.55c.16-.05.34-.07.52-.07s.36.02.52.07l3.55
-3.56C19.02 8.35 19 8.18 19 8c0-1.1.9-2 2-2s2 .9 2 2z"></path></g> |
| 15501 <g id="toc"><path d="M3 9h14V7H3v2zm0 4h14v-2H3v2zm0 4h14v-2H3v2zm16 0h2v-2h-2v2
zm0-10v2h2V7h-2zm0 6h2v-2h-2v2z"></path></g> |
| 15502 <g id="today"><path d="M19 3h-1V1h-2v2H8V1H6v2H5c-1.11 0-1.99.9-1.99 2L3 19c0 1.
1.89 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm0 16H5V8h14v11zM7 10h5v5H7z"></pa
th></g> |
| 15503 <g id="toll"><path d="M15 4c-4.42 0-8 3.58-8 8s3.58 8 8 8 8-3.58 8-8-3.58-8-8-8z
m0 14c-3.31 0-6-2.69-6-6s2.69-6 6-6 6 2.69 6 6-2.69 6-6 6zM3 12c0-2.61 1.67-4.83
4-5.65V4.26C3.55 5.15 1 8.27 1 12s2.55 6.85 6 7.74v-2.09c-2.33-.82-4-3.04-4-5.6
5z"></path></g> |
| 15504 <g id="touch-app"><path d="M9 11.24V7.5C9 6.12 10.12 5 11.5 5S14 6.12 14 7.5v3.7
4c1.21-.81 2-2.18 2-3.74C16 5.01 13.99 3 11.5 3S7 5.01 7 7.5c0 1.56.79 2.93 2 3.
74zm9.84 4.63l-4.54-2.26c-.17-.07-.35-.11-.54-.11H13v-6c0-.83-.67-1.5-1.5-1.5S10
6.67 10 7.5v10.74l-3.43-.72c-.08-.01-.15-.03-.24-.03-.31 0-.59.13-.79.33l-.79.8
4.94 4.94c.27.27.65.44 1.06.44h6.79c.75 0 1.33-.55 1.44-1.28l.75-5.27c.01-.07.0
2-.14.02-.2 0-.62-.38-1.16-.91-1.38z"></path></g> |
| 15505 <g id="track-changes"><path d="M19.07 4.93l-1.41 1.41C19.1 7.79 20 9.79 20 12c0
4.42-3.58 8-8 8s-8-3.58-8-8c0-4.08 3.05-7.44 7-7.93v2.02C8.16 6.57 6 9.03 6 12c0
3.31 2.69 6 6 6s6-2.69 6-6c0-1.66-.67-3.16-1.76-4.24l-1.41 1.41C15.55 9.9 16 10
.9 16 12c0 2.21-1.79 4-4 4s-4-1.79-4-4c0-1.86 1.28-3.41 3-3.86v2.14c-.6.35-1 .98
-1 1.72 0 1.1.9 2 2 2s2-.9 2-2c0-.74-.4-1.38-1-1.72V2h-1C6.48 2 2 6.48 2 12s4.48
10 10 10 10-4.48 10-10c0-2.76-1.12-5.26-2.93-7.07z"></path></g> |
| 15506 <g id="translate"><path d="M12.87 15.07l-2.54-2.51.03-.03c1.74-1.94 2.98-4.17 3.
71-6.53H17V4h-7V2H8v2H1v1.99h11.17C11.5 7.92 10.44 9.75 9 11.35 8.07 10.32 7.3 9
.19 6.69 8h-2c.73 1.63 1.73 3.17 2.98 4.56l-5.09 5.02L4 19l5-5 3.11 3.11.76-2.04
zM18.5 10h-2L12 22h2l1.12-3h4.75L21 22h2l-4.5-12zm-2.62 7l1.62-4.33L19.12 17h-3.
24z"></path></g> |
| 15507 <g id="trending-down"><path d="M16 18l2.29-2.29-4.88-4.88-4 4L2 7.41 3.41 6l6 6
4-4 6.3 6.29L22 12v6z"></path></g> |
| 15508 <g id="trending-flat"><path d="M22 12l-4-4v3H3v2h15v3z"></path></g> |
| 15509 <g id="trending-up"><path d="M16 6l2.29 2.29-4.88 4.88-4-4L2 16.59 3.41 18l6-6 4
4 6.3-6.29L22 12V6z"></path></g> |
| 15510 <g id="turned-in"><path d="M17 3H7c-1.1 0-1.99.9-1.99 2L5 21l7-3 7 3V5c0-1.1-.9-
2-2-2z"></path></g> |
| 15511 <g id="turned-in-not"><path d="M17 3H7c-1.1 0-1.99.9-1.99 2L5 21l7-3 7 3V5c0-1.1
-.9-2-2-2zm0 15l-5-2.18L7 18V5h10v13z"></path></g> |
| 15512 <g id="unarchive"><path d="M20.55 5.22l-1.39-1.68C18.88 3.21 18.47 3 18 3H6c-.47
0-.88.21-1.15.55L3.46 5.22C3.17 5.57 3 6.01 3 6.5V19c0 1.1.89 2 2 2h14c1.1 0 2-
.9 2-2V6.5c0-.49-.17-.93-.45-1.28zM12 9.5l5.5 5.5H14v2h-4v-2H6.5L12 9.5zM5.12 5l
.82-1h12l.93 1H5.12z"></path></g> |
| 15513 <g id="undo"><path d="M12.5 8c-2.65 0-5.05.99-6.9 2.6L2 7v9h9l-3.62-3.62c1.39-1.
16 3.16-1.88 5.12-1.88 3.54 0 6.55 2.31 7.6 5.5l2.37-.78C21.08 11.03 17.15 8 12.
5 8z"></path></g> |
| 15514 <g id="unfold-less"><path d="M7.41 18.59L8.83 20 12 16.83 15.17 20l1.41-1.41L12
14l-4.59 4.59zm9.18-13.18L15.17 4 12 7.17 8.83 4 7.41 5.41 12 10l4.59-4.59z"></p
ath></g> |
| 15515 <g id="unfold-more"><path d="M12 5.83L15.17 9l1.41-1.41L12 3 7.41 7.59 8.83 9 12
5.83zm0 12.34L8.83 15l-1.41 1.41L12 21l4.59-4.59L15.17 15 12 18.17z"></path></g
> |
| 15516 <g id="update"><path d="M21 10.12h-6.78l2.74-2.82c-2.73-2.7-7.15-2.8-9.88-.1-2.7
3 2.71-2.73 7.08 0 9.79 2.73 2.71 7.15 2.71 9.88 0C18.32 15.65 19 14.08 19 12.1h
2c0 1.98-.88 4.55-2.64 6.29-3.51 3.48-9.21 3.48-12.72 0-3.5-3.47-3.53-9.11-.02-1
2.58 3.51-3.47 9.14-3.47 12.65 0L21 3v7.12zM12.5 8v4.25l3.5 2.08-.72 1.21L11 13V
8h1.5z"></path></g> |
| 15517 <g id="verified-user"><path d="M12 1L3 5v6c0 5.55 3.84 10.74 9 12 5.16-1.26 9-6.
45 9-12V5l-9-4zm-2 16l-4-4 1.41-1.41L10 14.17l6.59-6.59L18 9l-8 8z"></path></g> |
| 15518 <g id="view-agenda"><path d="M20 13H3c-.55 0-1 .45-1 1v6c0 .55.45 1 1 1h17c.55 0
1-.45 1-1v-6c0-.55-.45-1-1-1zm0-10H3c-.55 0-1 .45-1 1v6c0 .55.45 1 1 1h17c.55 0
1-.45 1-1V4c0-.55-.45-1-1-1z"></path></g> |
| 15519 <g id="view-array"><path d="M4 18h3V5H4v13zM18 5v13h3V5h-3zM8 18h9V5H8v13z"></pa
th></g> |
| 15520 <g id="view-carousel"><path d="M7 19h10V4H7v15zm-5-2h4V6H2v11zM18 6v11h4V6h-4z">
</path></g> |
| 15521 <g id="view-column"><path d="M10 18h5V5h-5v13zm-6 0h5V5H4v13zM16 5v13h5V5h-5z"><
/path></g> |
| 15522 <g id="view-day"><path d="M2 21h19v-3H2v3zM20 8H3c-.55 0-1 .45-1 1v6c0 .55.45 1
1 1h17c.55 0 1-.45 1-1V9c0-.55-.45-1-1-1zM2 3v3h19V3H2z"></path></g> |
| 15523 <g id="view-headline"><path d="M4 15h16v-2H4v2zm0 4h16v-2H4v2zm0-8h16V9H4v2zm0-6
v2h16V5H4z"></path></g> |
| 15524 <g id="view-list"><path d="M4 14h4v-4H4v4zm0 5h4v-4H4v4zM4 9h4V5H4v4zm5 5h12v-4H
9v4zm0 5h12v-4H9v4zM9 5v4h12V5H9z"></path></g> |
| 15525 <g id="view-module"><path d="M4 11h5V5H4v6zm0 7h5v-6H4v6zm6 0h5v-6h-5v6zm6 0h5v-
6h-5v6zm-6-7h5V5h-5v6zm6-6v6h5V5h-5z"></path></g> |
| 15526 <g id="view-quilt"><path d="M10 18h5v-6h-5v6zm-6 0h5V5H4v13zm12 0h5v-6h-5v6zM10
5v6h11V5H10z"></path></g> |
| 15527 <g id="view-stream"><path d="M4 18h17v-6H4v6zM4 5v6h17V5H4z"></path></g> |
| 15528 <g id="view-week"><path d="M6 5H3c-.55 0-1 .45-1 1v12c0 .55.45 1 1 1h3c.55 0 1-.
45 1-1V6c0-.55-.45-1-1-1zm14 0h-3c-.55 0-1 .45-1 1v12c0 .55.45 1 1 1h3c.55 0 1-.
45 1-1V6c0-.55-.45-1-1-1zm-7 0h-3c-.55 0-1 .45-1 1v12c0 .55.45 1 1 1h3c.55 0 1-.
45 1-1V6c0-.55-.45-1-1-1z"></path></g> |
| 15529 <g id="visibility"><path d="M12 4.5C7 4.5 2.73 7.61 1 12c1.73 4.39 6 7.5 11 7.5s
9.27-3.11 11-7.5c-1.73-4.39-6-7.5-11-7.5zM12 17c-2.76 0-5-2.24-5-5s2.24-5 5-5 5
2.24 5 5-2.24 5-5 5zm0-8c-1.66 0-3 1.34-3 3s1.34 3 3 3 3-1.34 3-3-1.34-3-3-3z"><
/path></g> |
| 15530 <g id="visibility-off"><path d="M12 7c2.76 0 5 2.24 5 5 0 .65-.13 1.26-.36 1.83l
2.92 2.92c1.51-1.26 2.7-2.89 3.43-4.75-1.73-4.39-6-7.5-11-7.5-1.4 0-2.74.25-3.98
.7l2.16 2.16C10.74 7.13 11.35 7 12 7zM2 4.27l2.28 2.28.46.46C3.08 8.3 1.78 10.02
1 12c1.73 4.39 6 7.5 11 7.5 1.55 0 3.03-.3 4.38-.84l.42.42L19.73 22 21 20.73 3.
27 3 2 4.27zM7.53 9.8l1.55 1.55c-.05.21-.08.43-.08.65 0 1.66 1.34 3 3 3 .22 0 .4
4-.03.65-.08l1.55 1.55c-.67.33-1.41.53-2.2.53-2.76 0-5-2.24-5-5 0-.79.2-1.53.53-
2.2zm4.31-.78l3.15 3.15.02-.16c0-1.66-1.34-3-3-3l-.17.01z"></path></g> |
| 15531 <g id="warning"><path d="M1 21h22L12 2 1 21zm12-3h-2v-2h2v2zm0-4h-2v-4h2v4z"></p
ath></g> |
| 15532 <g id="watch-later"><path d="M12 2C6.5 2 2 6.5 2 12s4.5 10 10 10 10-4.5 10-10S17
.5 2 12 2zm4.2 14.2L11 13V7h1.5v5.2l4.5 2.7-.8 1.3z"></path></g> |
| 15533 <g id="weekend"><path d="M21 10c-1.1 0-2 .9-2 2v3H5v-3c0-1.1-.9-2-2-2s-2 .9-2 2v
5c0 1.1.9 2 2 2h18c1.1 0 2-.9 2-2v-5c0-1.1-.9-2-2-2zm-3-5H6c-1.1 0-2 .9-2 2v2.15
c1.16.41 2 1.51 2 2.82V14h12v-2.03c0-1.3.84-2.4 2-2.82V7c0-1.1-.9-2-2-2z"></path
></g> |
| 15534 <g id="work"><path d="M20 6h-4V4c0-1.11-.89-2-2-2h-4c-1.11 0-2 .89-2 2v2H4c-1.11
0-1.99.89-1.99 2L2 19c0 1.11.89 2 2 2h16c1.11 0 2-.89 2-2V8c0-1.11-.89-2-2-2zm-
6 0h-4V4h4v2z"></path></g> |
| 15535 <g id="youtube-searched-for"><path d="M17.01 14h-.8l-.27-.27c.98-1.14 1.57-2.61
1.57-4.23 0-3.59-2.91-6.5-6.5-6.5s-6.5 3-6.5 6.5H2l3.84 4 4.16-4H6.51C6.51 7 8.5
3 5 11.01 5s4.5 2.01 4.5 4.5c0 2.48-2.02 4.5-4.5 4.5-.65 0-1.26-.14-1.82-.38L7.7
1 15.1c.97.57 2.09.9 3.3.9 1.61 0 3.08-.59 4.22-1.57l.27.27v.79l5.01 4.99L22 19l
-4.99-5z"></path></g> |
| 15536 <g id="zoom-in"><path d="M15.5 14h-.79l-.28-.27C15.41 12.59 16 11.11 16 9.5 16 5
.91 13.09 3 9.5 3S3 5.91 3 9.5 5.91 16 9.5 16c1.61 0 3.09-.59 4.23-1.57l.27.28v.
79l5 4.99L20.49 19l-4.99-5zm-6 0C7.01 14 5 11.99 5 9.5S7.01 5 9.5 5 14 7.01 14 9
.5 11.99 14 9.5 14zm2.5-4h-2v2H9v-2H7V9h2V7h1v2h2v1z"></path></g> |
| 15537 <g id="zoom-out"><path d="M15.5 14h-.79l-.28-.27C15.41 12.59 16 11.11 16 9.5 16
5.91 13.09 3 9.5 3S3 5.91 3 9.5 5.91 16 9.5 16c1.61 0 3.09-.59 4.23-1.57l.27.28v
.79l5 4.99L20.49 19l-4.99-5zm-6 0C7.01 14 5 11.99 5 9.5S7.01 5 9.5 5 14 7.01 14
9.5 11.99 14 9.5 14zM7 9h5v1H7z"></path></g> |
| 15538 </defs></svg> |
| 15539 </iron-iconset-svg> |
| 15540 <dom-module id="sort-toggle" assetpath="/res/imp/common/"> |
| 15541 <template> |
| 15542 <style> |
| 15543 :host { |
| 15544 display: inline-block; |
| 15545 position: relative; |
| 15546 min-width:20px; |
| 15547 min-height:16px; |
| 15548 vertical-align: middle; |
| 15549 } |
| 15550 iron-icon { |
| 15551 position: absolute; |
| 15552 left: 0; |
| 15553 cursor: pointer; |
| 15554 } |
| 15555 .hidden { |
| 15556 visibility: hidden; |
| 15557 } |
| 15558 </style> |
| 15559 |
| 15560 <span on-click="toggle"> |
| 15561 <iron-icon style="top:0" class$="[[_hidden(sort,'1')]]" icon="icons:arrow-
drop-down"> |
| 15562 </iron-icon> |
| 15563 <iron-icon style="bottom:0" class$="[[_hidden(sort,'-1')]]" icon="icons:ar
row-drop-up"> |
| 15564 </iron-icon> |
| 15565 </span> |
| 15566 |
| 15567 </template> |
| 15568 <script> |
| 15569 Polymer({ |
| 15570 is: "sort-toggle", |
| 15571 properties: { |
| 15572 name: { |
| 15573 type: String, |
| 15574 observer: "_resetSort", |
| 15575 }, |
| 15576 sort: { |
| 15577 type: Number, |
| 15578 value: 0, |
| 15579 notify: true, |
| 15580 }, |
| 15581 }, |
| 15582 toggle: function() { |
| 15583 if (this.sort === -1) { |
| 15584 this.set("sort", 0); |
| 15585 } else if (this.sort === 1) { |
| 15586 this.set("sort", -1); |
| 15587 } else { |
| 15588 this.set("sort", 1); |
| 15589 } |
| 15590 this.fire("sort_change", {sort: this.sort, name: this.name}); |
| 15591 }, |
| 15592 _hidden: function(num, compare) { |
| 15593 // double equals intentionally used here because compare is a string |
| 15594 // and num is an int. |
| 15595 if (num == compare) { |
| 15596 return "hidden"; |
| 15597 } |
| 15598 return ""; |
| 15599 }, |
| 15600 _resetSort: function(newV, old) { |
| 15601 // Because of how Polymer inserts and moves elements around, we need to |
| 15602 // reset the sort value if the name changes so the ascending sort by |
| 15603 // "os" doesn't become the ascending sort by "gpu" if a column gets |
| 15604 // added. |
| 15605 this.set("sort", 0); |
| 15606 this.fire("sort_change", {sort: 0, name: newV}); |
| 15607 }, |
| 15608 }); |
| 15609 </script> |
| 15610 </dom-module><script> |
| 15611 |
| 15612 window.SwarmingBehaviors = window.SwarmingBehaviors || {}; |
| 15613 (function(){ |
| 15614 var ANDROID_ALIASES = { |
| 15615 "bullhead": "Nexus 5X", |
| 15616 "flo": "Nexus 7", |
| 15617 "hammerhead": "Nexus 5", |
| 15618 "mako": "Nexus 4", |
| 15619 "shamu": "Nexus 6", |
| 15620 }; |
| 15621 // Taken from http://developer.android.com/reference/android/os/BatteryManag
er.html |
| 15622 var BATTERY_HEALTH_UNKNOWN = 1; |
| 15623 var BATTERY_HEALTH_GOOD = 2; |
| 15624 var BATTERY_STATUS_CHARGING = 2; |
| 15625 |
| 15626 var UNAUTHENTICATED = "unauthenticated"; |
| 15627 var AVAILABLE = "available"; |
| 15628 |
| 15629 var GPU_ALIASES = { |
| 15630 "1002": "AMD", |
| 15631 "1002:6779": "AMD Radeon HD 6450/7450/8450", |
| 15632 "1002:6821": "AMD Radeon HD 8870M", |
| 15633 "102b": "Matrox", |
| 15634 "102b:0522": "Matrox MGA G200e", |
| 15635 "102b:0532": "Matrox MGA G200eW", |
| 15636 "102b:0534": "Matrox G200eR2", |
| 15637 "10de": "NVIDIA", |
| 15638 "10de:08aa": "NVIDIA GeForce 320M", |
| 15639 "10de:0fe9": "NVIDIA GeForce GT 750M Mac Edition", |
| 15640 "10de:104a": "NVIDIA GeForce GT 610", |
| 15641 "10de:11c0": "NVIDIA GeForce GTX 660", |
| 15642 "10de:1244": "NVIDIA GeForce GTX 550 Ti", |
| 15643 "10de:1401": "NVIDIA GeForce GTX 960", |
| 15644 "8086": "Intel", |
| 15645 "8086:041a": "Intel Xeon Integrated", |
| 15646 "8086:0a2e": "Intel Haswell Integrated", |
| 15647 "8086:0d26": "Intel Crystal Well Integrated", |
| 15648 } |
| 15649 |
| 15650 // matches a string like "ALIAS (ORIG)", with ORIG as group 1 |
| 15651 var ALIAS_REGEXP = /.+ \((.*)\)/; |
| 15652 |
| 15653 // This behavior wraps up all the shared bot-list functionality. |
| 15654 SwarmingBehaviors.BotListBehavior = { |
| 15655 |
| 15656 _androidAlias: function(device) { |
| 15657 if (device.notReady) { |
| 15658 return UNAUTHENTICATED.toUpperCase(); |
| 15659 } |
| 15660 var t = this._deviceType(device); |
| 15661 var a = ANDROID_ALIASES[t]; |
| 15662 if (!a) { |
| 15663 return "UNKNOWN"; |
| 15664 } |
| 15665 return a; |
| 15666 }, |
| 15667 |
| 15668 _applyAlias: function(orig, alias) { |
| 15669 return alias +" ("+orig+")"; |
| 15670 }, |
| 15671 |
| 15672 _cores: function(bot) { |
| 15673 // For whatever reason, sometimes cores are in dimensions and sometimes
they are in state, but never both. |
| 15674 var c = (bot && bot.state && bot.state.cores); |
| 15675 if (c && c.length > 0) { |
| 15676 return c; |
| 15677 } |
| 15678 c = this._dimension(bot, "cores") || ["Unknown"]; |
| 15679 return c; |
| 15680 }, |
| 15681 |
| 15682 _devices: function(bot) { |
| 15683 var devices = []; |
| 15684 var d = (bot && bot.state && bot.state.devices) || {}; |
| 15685 // state.devices is like {Serial:Object}, so we need to keep the serial |
| 15686 for (key in d) { |
| 15687 var o = d[key]; |
| 15688 o.serial = key; |
| 15689 o.okay = (o.state === AVAILABLE); |
| 15690 devices.push(o); |
| 15691 } |
| 15692 return devices; |
| 15693 }, |
| 15694 |
| 15695 _deviceType: function(device) { |
| 15696 if (!device || !device.build) { |
| 15697 return "unknown"; |
| 15698 } |
| 15699 var t = device.build["build.product"] || device.build["product.board"] |
| |
| 15700 device.build["product.device"] || "unknown"; |
| 15701 return t.toLowerCase(); |
| 15702 }, |
| 15703 |
| 15704 _dimension: function(data, dim) { |
| 15705 if (!data || !data.dimensions || !dim) { |
| 15706 return undefined; |
| 15707 } |
| 15708 for (var i = 0; i<data.dimensions.length; i++) { |
| 15709 if (data.dimensions[i].key === dim) { |
| 15710 return data.dimensions[i].value; |
| 15711 } |
| 15712 } |
| 15713 return undefined; |
| 15714 }, |
| 15715 |
| 15716 _gpuAlias: function(gpu) { |
| 15717 var a = GPU_ALIASES[gpu]; |
| 15718 if (!a) { |
| 15719 return "UNKNOWN"; |
| 15720 } |
| 15721 return a; |
| 15722 }, |
| 15723 |
| 15724 _unalias: function(str) { |
| 15725 var match = ALIAS_REGEXP.exec(str); |
| 15726 if (match) { |
| 15727 return match[1]; |
| 15728 } |
| 15729 return str; |
| 15730 }, |
| 15731 } |
| 15732 })() |
| 15733 </script> |
| 15734 <dom-module id="bot-list-data" assetpath="/res/imp/botlist/"> |
| 15735 <template> |
| 15736 <iron-ajax id="request" url="/_ah/api/swarming/v1/bots/list" headers="[[auth
_headers]]" handle-as="json" last-response="{{_data}}" loading="{{busy}}"> |
| 15737 </iron-ajax> |
| 15738 </template> |
| 15739 <script> |
| 15740 (function(){ |
| 15741 var DIMENSIONS = ["cores", "cpu", "id", "os", "pool"]; |
| 15742 // "gpu" and "devices" are added separately because we need to |
| 15743 // deal with aliases. |
| 15744 var BOT_PROPERTIES = ["gpu", "devices", "task", "status"]; |
| 15745 Polymer({ |
| 15746 is: 'bot-list-data', |
| 15747 properties: { |
| 15748 auth_headers: { |
| 15749 type: Object, |
| 15750 observer: "signIn", |
| 15751 }, |
| 15752 |
| 15753 bots: { |
| 15754 type: Array, |
| 15755 computed: "_bots(_data)", |
| 15756 notify: true, |
| 15757 }, |
| 15758 busy: { |
| 15759 type: Boolean, |
| 15760 notify: true, |
| 15761 }, |
| 15762 primary_map: { |
| 15763 type:Object, |
| 15764 computed: "_primaryMap(bots)", |
| 15765 notify: true, |
| 15766 }, |
| 15767 primary_arr: { |
| 15768 type:Array, |
| 15769 value: function() { |
| 15770 return DIMENSIONS.concat(BOT_PROPERTIES); |
| 15771 }, |
| 15772 notify: true, |
| 15773 }, |
| 15774 |
| 15775 _data: { |
| 15776 type: Object, |
| 15777 }, |
| 15778 }, |
| 15779 behaviors: [SwarmingBehaviors.BotListBehavior], |
| 15780 |
| 15781 signIn: function(){ |
| 15782 this.$.request.generateRequest(); |
| 15783 }, |
| 15784 |
| 15785 _bots: function(){ |
| 15786 if (!this._data || !this._data.items) { |
| 15787 return []; |
| 15788 } |
| 15789 this._data.items.forEach(function(o){ |
| 15790 o.state = JSON.parse(o.state); |
| 15791 }); |
| 15792 return this._data.items; |
| 15793 }, |
| 15794 |
| 15795 _primaryMap: function(bots){ |
| 15796 var map = {}; |
| 15797 DIMENSIONS.forEach(function(p){ |
| 15798 map[p] = {}; |
| 15799 }); |
| 15800 map["devices"] = {}; |
| 15801 map["gpu"] = {}; |
| 15802 bots.forEach(function(b){ |
| 15803 DIMENSIONS.forEach(function(d){ |
| 15804 var dims = this._dimension(b, d) || []; |
| 15805 dims.forEach(function(e){ |
| 15806 map[d][e] = true; |
| 15807 }); |
| 15808 }.bind(this)); |
| 15809 |
| 15810 // Add Android devices and their aliases |
| 15811 this._devices(b).forEach(function(d){ |
| 15812 var dt = this._deviceType(d); |
| 15813 var alias = this._androidAlias(d); |
| 15814 if (dt !== "unknown") { |
| 15815 dt = this._applyAlias(dt,alias); |
| 15816 } |
| 15817 map["devices"][dt] = true; |
| 15818 }.bind(this)); |
| 15819 map["devices"]["none"] = true; |
| 15820 |
| 15821 // Add GPU aliases |
| 15822 var gpus = this._dimension(b, "gpu") || []; |
| 15823 gpus.forEach(function(g){ |
| 15824 var alias = this._gpuAlias(g); |
| 15825 if (alias !== "UNKNOWN") { |
| 15826 map["gpu"][this._applyAlias(g, alias)] = true; |
| 15827 } else { |
| 15828 map["gpu"][g] = true; |
| 15829 } |
| 15830 |
| 15831 }.bind(this)); |
| 15832 }.bind(this)); |
| 15833 |
| 15834 var pMap = {}; |
| 15835 for (key in map){ |
| 15836 pMap[key] = Object.keys(map[key]).sort(function(a,b){ |
| 15837 // Try numeric, aka "natural" sort first. |
| 15838 var ns = a - b; |
| 15839 if (ns) { |
| 15840 return ns; |
| 15841 } |
| 15842 return a.localeCompare(b); |
| 15843 }); |
| 15844 } |
| 15845 |
| 15846 // Create custom filter options |
| 15847 pMap["task"] = ["busy", "idle"]; |
| 15848 pMap["status"] = ["available", "dead", "quarantined"]; |
| 15849 return pMap; |
| 15850 }, |
| 15851 |
| 15852 }); |
| 15853 })(); |
| 15854 </script> |
| 15855 </dom-module><script> |
| 15856 |
| 15857 /** |
| 15858 * @param {!Function} selectCallback |
| 15859 * @constructor |
| 15860 */ |
| 15861 Polymer.IronSelection = function(selectCallback) { |
| 15862 this.selection = []; |
| 15863 this.selectCallback = selectCallback; |
| 15864 }; |
| 15865 |
| 15866 Polymer.IronSelection.prototype = { |
| 15867 |
| 15868 /** |
| 15869 * Retrieves the selected item(s). |
| 15870 * |
| 15871 * @method get |
| 15872 * @returns Returns the selected item(s). If the multi property is true, |
| 15873 * `get` will return an array, otherwise it will return |
| 15874 * the selected item or undefined if there is no selection. |
| 15875 */ |
| 15876 get: function() { |
| 15877 return this.multi ? this.selection.slice() : this.selection[0]; |
| 15878 }, |
| 15879 |
| 15880 /** |
| 15881 * Clears all the selection except the ones indicated. |
| 15882 * |
| 15883 * @method clear |
| 15884 * @param {Array} excludes items to be excluded. |
| 15885 */ |
| 15886 clear: function(excludes) { |
| 15887 this.selection.slice().forEach(function(item) { |
| 15888 if (!excludes || excludes.indexOf(item) < 0) { |
| 15889 this.setItemSelected(item, false); |
| 15890 } |
| 15891 }, this); |
| 15892 }, |
| 15893 |
| 15894 /** |
| 15895 * Indicates if a given item is selected. |
| 15896 * |
| 15897 * @method isSelected |
| 15898 * @param {*} item The item whose selection state should be checked. |
| 15899 * @returns Returns true if `item` is selected. |
| 15900 */ |
| 15901 isSelected: function(item) { |
| 15902 return this.selection.indexOf(item) >= 0; |
| 15903 }, |
| 15904 |
| 15905 /** |
| 15906 * Sets the selection state for a given item to either selected or deselecte
d. |
| 15907 * |
| 15908 * @method setItemSelected |
| 15909 * @param {*} item The item to select. |
| 15910 * @param {boolean} isSelected True for selected, false for deselected. |
| 15911 */ |
| 15912 setItemSelected: function(item, isSelected) { |
| 15913 if (item != null) { |
| 15914 if (isSelected !== this.isSelected(item)) { |
| 15915 // proceed to update selection only if requested state differs from cu
rrent |
| 15916 if (isSelected) { |
| 15917 this.selection.push(item); |
| 15918 } else { |
| 15919 var i = this.selection.indexOf(item); |
| 15920 if (i >= 0) { |
| 15921 this.selection.splice(i, 1); |
| 15922 } |
| 15923 } |
| 15924 if (this.selectCallback) { |
| 15925 this.selectCallback(item, isSelected); |
| 15926 } |
| 15927 } |
| 15928 } |
| 15929 }, |
| 15930 |
| 15931 /** |
| 15932 * Sets the selection state for a given item. If the `multi` property |
| 15933 * is true, then the selected state of `item` will be toggled; otherwise |
| 15934 * the `item` will be selected. |
| 15935 * |
| 15936 * @method select |
| 15937 * @param {*} item The item to select. |
| 15938 */ |
| 15939 select: function(item) { |
| 15940 if (this.multi) { |
| 15941 this.toggle(item); |
| 15942 } else if (this.get() !== item) { |
| 15943 this.setItemSelected(this.get(), false); |
| 15944 this.setItemSelected(item, true); |
| 15945 } |
| 15946 }, |
| 15947 |
| 15948 /** |
| 15949 * Toggles the selection state for `item`. |
| 15950 * |
| 15951 * @method toggle |
| 15952 * @param {*} item The item to toggle. |
| 15953 */ |
| 15954 toggle: function(item) { |
| 15955 this.setItemSelected(item, !this.isSelected(item)); |
| 15956 } |
| 15957 |
| 15958 }; |
| 15959 |
| 15960 </script> |
| 15961 <script> |
| 15962 |
| 15963 /** @polymerBehavior */ |
| 15964 Polymer.IronSelectableBehavior = { |
| 15965 |
| 15966 /** |
| 15967 * Fired when iron-selector is activated (selected or deselected). |
| 15968 * It is fired before the selected items are changed. |
| 15969 * Cancel the event to abort selection. |
| 15970 * |
| 15971 * @event iron-activate |
| 15972 */ |
| 15973 |
| 15974 /** |
| 15975 * Fired when an item is selected |
| 15976 * |
| 15977 * @event iron-select |
| 15978 */ |
| 15979 |
| 15980 /** |
| 15981 * Fired when an item is deselected |
| 15982 * |
| 15983 * @event iron-deselect |
| 15984 */ |
| 15985 |
| 15986 /** |
| 15987 * Fired when the list of selectable items changes (e.g., items are |
| 15988 * added or removed). The detail of the event is a mutation record that |
| 15989 * describes what changed. |
| 15990 * |
| 15991 * @event iron-items-changed |
| 15992 */ |
| 15993 |
| 15994 properties: { |
| 15995 |
| 15996 /** |
| 15997 * If you want to use an attribute value or property of an element for |
| 15998 * `selected` instead of the index, set this to the name of the attribute |
| 15999 * or property. Hyphenated values are converted to camel case when used to |
| 16000 * look up the property of a selectable element. Camel cased values are |
| 16001 * *not* converted to hyphenated values for attribute lookup. It's |
| 16002 * recommended that you provide the hyphenated form of the name so that |
| 16003 * selection works in both cases. (Use `attr-or-property-name` instead of |
| 16004 * `attrOrPropertyName`.) |
| 16005 */ |
| 16006 attrForSelected: { |
| 16007 type: String, |
| 16008 value: null |
| 16009 }, |
| 16010 |
| 16011 /** |
| 16012 * Gets or sets the selected element. The default is to use the index of t
he item. |
| 16013 * @type {string|number} |
| 16014 */ |
| 16015 selected: { |
| 16016 type: String, |
| 16017 notify: true |
| 16018 }, |
| 16019 |
| 16020 /** |
| 16021 * Returns the currently selected item. |
| 16022 * |
| 16023 * @type {?Object} |
| 16024 */ |
| 16025 selectedItem: { |
| 16026 type: Object, |
| 16027 readOnly: true, |
| 16028 notify: true |
| 16029 }, |
| 16030 |
| 16031 /** |
| 16032 * The event that fires from items when they are selected. Selectable |
| 16033 * will listen for this event from items and update the selection state. |
| 16034 * Set to empty string to listen to no events. |
| 16035 */ |
| 16036 activateEvent: { |
| 16037 type: String, |
| 16038 value: 'tap', |
| 16039 observer: '_activateEventChanged' |
| 16040 }, |
| 16041 |
| 16042 /** |
| 16043 * This is a CSS selector string. If this is set, only items that match t
he CSS selector |
| 16044 * are selectable. |
| 16045 */ |
| 16046 selectable: String, |
| 16047 |
| 16048 /** |
| 16049 * The class to set on elements when selected. |
| 16050 */ |
| 16051 selectedClass: { |
| 16052 type: String, |
| 16053 value: 'iron-selected' |
| 16054 }, |
| 16055 |
| 16056 /** |
| 16057 * The attribute to set on elements when selected. |
| 16058 */ |
| 16059 selectedAttribute: { |
| 16060 type: String, |
| 16061 value: null |
| 16062 }, |
| 16063 |
| 16064 /** |
| 16065 * Default fallback if the selection based on selected with `attrForSelect
ed` |
| 16066 * is not found. |
| 16067 */ |
| 16068 fallbackSelection: { |
| 16069 type: String, |
| 16070 value: null |
| 16071 }, |
| 16072 |
| 16073 /** |
| 16074 * The list of items from which a selection can be made. |
| 16075 */ |
| 16076 items: { |
| 16077 type: Array, |
| 16078 readOnly: true, |
| 16079 notify: true, |
| 16080 value: function() { |
| 16081 return []; |
| 16082 } |
| 16083 }, |
| 16084 |
| 16085 /** |
| 16086 * The set of excluded elements where the key is the `localName` |
| 16087 * of the element that will be ignored from the item list. |
| 16088 * |
| 16089 * @default {template: 1} |
| 16090 */ |
| 16091 _excludedLocalNames: { |
| 16092 type: Object, |
| 16093 value: function() { |
| 16094 return { |
| 16095 'template': 1 |
| 16096 }; |
| 16097 } |
| 16098 } |
| 16099 }, |
| 16100 |
| 16101 observers: [ |
| 16102 '_updateAttrForSelected(attrForSelected)', |
| 16103 '_updateSelected(selected)', |
| 16104 '_checkFallback(fallbackSelection)' |
| 16105 ], |
| 16106 |
| 16107 created: function() { |
| 16108 this._bindFilterItem = this._filterItem.bind(this); |
| 16109 this._selection = new Polymer.IronSelection(this._applySelection.bind(this
)); |
| 16110 }, |
| 16111 |
| 16112 attached: function() { |
| 16113 this._observer = this._observeItems(this); |
| 16114 this._updateItems(); |
| 16115 if (!this._shouldUpdateSelection) { |
| 16116 this._updateSelected(); |
| 16117 } |
| 16118 this._addListener(this.activateEvent); |
| 16119 }, |
| 16120 |
| 16121 detached: function() { |
| 16122 if (this._observer) { |
| 16123 Polymer.dom(this).unobserveNodes(this._observer); |
| 16124 } |
| 16125 this._removeListener(this.activateEvent); |
| 16126 }, |
| 16127 |
| 16128 /** |
| 16129 * Returns the index of the given item. |
| 16130 * |
| 16131 * @method indexOf |
| 16132 * @param {Object} item |
| 16133 * @returns Returns the index of the item |
| 16134 */ |
| 16135 indexOf: function(item) { |
| 16136 return this.items.indexOf(item); |
| 16137 }, |
| 16138 |
| 16139 /** |
| 16140 * Selects the given value. |
| 16141 * |
| 16142 * @method select |
| 16143 * @param {string|number} value the value to select. |
| 16144 */ |
| 16145 select: function(value) { |
| 16146 this.selected = value; |
| 16147 }, |
| 16148 |
| 16149 /** |
| 16150 * Selects the previous item. |
| 16151 * |
| 16152 * @method selectPrevious |
| 16153 */ |
| 16154 selectPrevious: function() { |
| 16155 var length = this.items.length; |
| 16156 var index = (Number(this._valueToIndex(this.selected)) - 1 + length) % len
gth; |
| 16157 this.selected = this._indexToValue(index); |
| 16158 }, |
| 16159 |
| 16160 /** |
| 16161 * Selects the next item. |
| 16162 * |
| 16163 * @method selectNext |
| 16164 */ |
| 16165 selectNext: function() { |
| 16166 var index = (Number(this._valueToIndex(this.selected)) + 1) % this.items.l
ength; |
| 16167 this.selected = this._indexToValue(index); |
| 16168 }, |
| 16169 |
| 16170 /** |
| 16171 * Selects the item at the given index. |
| 16172 * |
| 16173 * @method selectIndex |
| 16174 */ |
| 16175 selectIndex: function(index) { |
| 16176 this.select(this._indexToValue(index)); |
| 16177 }, |
| 16178 |
| 16179 /** |
| 16180 * Force a synchronous update of the `items` property. |
| 16181 * |
| 16182 * NOTE: Consider listening for the `iron-items-changed` event to respond to |
| 16183 * updates to the set of selectable items after updates to the DOM list and |
| 16184 * selection state have been made. |
| 16185 * |
| 16186 * WARNING: If you are using this method, you should probably consider an |
| 16187 * alternate approach. Synchronously querying for items is potentially |
| 16188 * slow for many use cases. The `items` property will update asynchronously |
| 16189 * on its own to reflect selectable items in the DOM. |
| 16190 */ |
| 16191 forceSynchronousItemUpdate: function() { |
| 16192 this._updateItems(); |
| 16193 }, |
| 16194 |
| 16195 get _shouldUpdateSelection() { |
| 16196 return this.selected != null; |
| 16197 }, |
| 16198 |
| 16199 _checkFallback: function() { |
| 16200 if (this._shouldUpdateSelection) { |
| 16201 this._updateSelected(); |
| 16202 } |
| 16203 }, |
| 16204 |
| 16205 _addListener: function(eventName) { |
| 16206 this.listen(this, eventName, '_activateHandler'); |
| 16207 }, |
| 16208 |
| 16209 _removeListener: function(eventName) { |
| 16210 this.unlisten(this, eventName, '_activateHandler'); |
| 16211 }, |
| 16212 |
| 16213 _activateEventChanged: function(eventName, old) { |
| 16214 this._removeListener(old); |
| 16215 this._addListener(eventName); |
| 16216 }, |
| 16217 |
| 16218 _updateItems: function() { |
| 16219 var nodes = Polymer.dom(this).queryDistributedElements(this.selectable ||
'*'); |
| 16220 nodes = Array.prototype.filter.call(nodes, this._bindFilterItem); |
| 16221 this._setItems(nodes); |
| 16222 }, |
| 16223 |
| 16224 _updateAttrForSelected: function() { |
| 16225 if (this._shouldUpdateSelection) { |
| 16226 this.selected = this._indexToValue(this.indexOf(this.selectedItem)); |
| 16227 } |
| 16228 }, |
| 16229 |
| 16230 _updateSelected: function() { |
| 16231 this._selectSelected(this.selected); |
| 16232 }, |
| 16233 |
| 16234 _selectSelected: function(selected) { |
| 16235 this._selection.select(this._valueToItem(this.selected)); |
| 16236 // Check for items, since this array is populated only when attached |
| 16237 // Since Number(0) is falsy, explicitly check for undefined |
| 16238 if (this.fallbackSelection && this.items.length && (this._selection.get()
=== undefined)) { |
| 16239 this.selected = this.fallbackSelection; |
| 16240 } |
| 16241 }, |
| 16242 |
| 16243 _filterItem: function(node) { |
| 16244 return !this._excludedLocalNames[node.localName]; |
| 16245 }, |
| 16246 |
| 16247 _valueToItem: function(value) { |
| 16248 return (value == null) ? null : this.items[this._valueToIndex(value)]; |
| 16249 }, |
| 16250 |
| 16251 _valueToIndex: function(value) { |
| 16252 if (this.attrForSelected) { |
| 16253 for (var i = 0, item; item = this.items[i]; i++) { |
| 16254 if (this._valueForItem(item) == value) { |
| 16255 return i; |
| 16256 } |
| 16257 } |
| 16258 } else { |
| 16259 return Number(value); |
| 16260 } |
| 16261 }, |
| 16262 |
| 16263 _indexToValue: function(index) { |
| 16264 if (this.attrForSelected) { |
| 16265 var item = this.items[index]; |
| 16266 if (item) { |
| 16267 return this._valueForItem(item); |
| 16268 } |
| 16269 } else { |
| 16270 return index; |
| 16271 } |
| 16272 }, |
| 16273 |
| 16274 _valueForItem: function(item) { |
| 16275 var propValue = item[Polymer.CaseMap.dashToCamelCase(this.attrForSelected)
]; |
| 16276 return propValue != undefined ? propValue : item.getAttribute(this.attrFor
Selected); |
| 16277 }, |
| 16278 |
| 16279 _applySelection: function(item, isSelected) { |
| 16280 if (this.selectedClass) { |
| 16281 this.toggleClass(this.selectedClass, isSelected, item); |
| 16282 } |
| 16283 if (this.selectedAttribute) { |
| 16284 this.toggleAttribute(this.selectedAttribute, isSelected, item); |
| 16285 } |
| 16286 this._selectionChange(); |
| 16287 this.fire('iron-' + (isSelected ? 'select' : 'deselect'), {item: item}); |
| 16288 }, |
| 16289 |
| 16290 _selectionChange: function() { |
| 16291 this._setSelectedItem(this._selection.get()); |
| 16292 }, |
| 16293 |
| 16294 // observe items change under the given node. |
| 16295 _observeItems: function(node) { |
| 16296 return Polymer.dom(node).observeNodes(function(mutation) { |
| 16297 this._updateItems(); |
| 16298 |
| 16299 if (this._shouldUpdateSelection) { |
| 16300 this._updateSelected(); |
| 16301 } |
| 16302 |
| 16303 // Let other interested parties know about the change so that |
| 16304 // we don't have to recreate mutation observers everywhere. |
| 16305 this.fire('iron-items-changed', mutation, { |
| 16306 bubbles: false, |
| 16307 cancelable: false |
| 16308 }); |
| 16309 }); |
| 16310 }, |
| 16311 |
| 16312 _activateHandler: function(e) { |
| 16313 var t = e.target; |
| 16314 var items = this.items; |
| 16315 while (t && t != this) { |
| 16316 var i = items.indexOf(t); |
| 16317 if (i >= 0) { |
| 16318 var value = this._indexToValue(i); |
| 16319 this._itemActivate(value, t); |
| 16320 return; |
| 16321 } |
| 16322 t = t.parentNode; |
| 16323 } |
| 16324 }, |
| 16325 |
| 16326 _itemActivate: function(value, item) { |
| 16327 if (!this.fire('iron-activate', |
| 16328 {selected: value, item: item}, {cancelable: true}).defaultPrevented) { |
| 16329 this.select(value); |
| 16330 } |
| 16331 } |
| 16332 |
| 16333 }; |
| 16334 |
| 16335 </script> |
| 16336 <script> |
| 16337 /** @polymerBehavior Polymer.IronMultiSelectableBehavior */ |
| 16338 Polymer.IronMultiSelectableBehaviorImpl = { |
| 16339 properties: { |
| 16340 |
| 16341 /** |
| 16342 * If true, multiple selections are allowed. |
| 16343 */ |
| 16344 multi: { |
| 16345 type: Boolean, |
| 16346 value: false, |
| 16347 observer: 'multiChanged' |
| 16348 }, |
| 16349 |
| 16350 /** |
| 16351 * Gets or sets the selected elements. This is used instead of `selected`
when `multi` |
| 16352 * is true. |
| 16353 */ |
| 16354 selectedValues: { |
| 16355 type: Array, |
| 16356 notify: true |
| 16357 }, |
| 16358 |
| 16359 /** |
| 16360 * Returns an array of currently selected items. |
| 16361 */ |
| 16362 selectedItems: { |
| 16363 type: Array, |
| 16364 readOnly: true, |
| 16365 notify: true |
| 16366 }, |
| 16367 |
| 16368 }, |
| 16369 |
| 16370 observers: [ |
| 16371 '_updateSelected(selectedValues.splices)' |
| 16372 ], |
| 16373 |
| 16374 /** |
| 16375 * Selects the given value. If the `multi` property is true, then the select
ed state of the |
| 16376 * `value` will be toggled; otherwise the `value` will be selected. |
| 16377 * |
| 16378 * @method select |
| 16379 * @param {string|number} value the value to select. |
| 16380 */ |
| 16381 select: function(value) { |
| 16382 if (this.multi) { |
| 16383 if (this.selectedValues) { |
| 16384 this._toggleSelected(value); |
| 16385 } else { |
| 16386 this.selectedValues = [value]; |
| 16387 } |
| 16388 } else { |
| 16389 this.selected = value; |
| 16390 } |
| 16391 }, |
| 16392 |
| 16393 multiChanged: function(multi) { |
| 16394 this._selection.multi = multi; |
| 16395 }, |
| 16396 |
| 16397 get _shouldUpdateSelection() { |
| 16398 return this.selected != null || |
| 16399 (this.selectedValues != null && this.selectedValues.length); |
| 16400 }, |
| 16401 |
| 16402 _updateAttrForSelected: function() { |
| 16403 if (!this.multi) { |
| 16404 Polymer.IronSelectableBehavior._updateAttrForSelected.apply(this); |
| 16405 } else if (this._shouldUpdateSelection) { |
| 16406 this.selectedValues = this.selectedItems.map(function(selectedItem) { |
| 16407 return this._indexToValue(this.indexOf(selectedItem)); |
| 16408 }, this).filter(function(unfilteredValue) { |
| 16409 return unfilteredValue != null; |
| 16410 }, this); |
| 16411 } |
| 16412 }, |
| 16413 |
| 16414 _updateSelected: function() { |
| 16415 if (this.multi) { |
| 16416 this._selectMulti(this.selectedValues); |
| 16417 } else { |
| 16418 this._selectSelected(this.selected); |
| 16419 } |
| 16420 }, |
| 16421 |
| 16422 _selectMulti: function(values) { |
| 16423 if (values) { |
| 16424 var selectedItems = this._valuesToItems(values); |
| 16425 // clear all but the current selected items |
| 16426 this._selection.clear(selectedItems); |
| 16427 // select only those not selected yet |
| 16428 for (var i = 0; i < selectedItems.length; i++) { |
| 16429 this._selection.setItemSelected(selectedItems[i], true); |
| 16430 } |
| 16431 // Check for items, since this array is populated only when attached |
| 16432 if (this.fallbackSelection && this.items.length && !this._selection.get(
).length) { |
| 16433 var fallback = this._valueToItem(this.fallbackSelection); |
| 16434 if (fallback) { |
| 16435 this.selectedValues = [this.fallbackSelection]; |
| 16436 } |
| 16437 } |
| 16438 } else { |
| 16439 this._selection.clear(); |
| 16440 } |
| 16441 }, |
| 16442 |
| 16443 _selectionChange: function() { |
| 16444 var s = this._selection.get(); |
| 16445 if (this.multi) { |
| 16446 this._setSelectedItems(s); |
| 16447 } else { |
| 16448 this._setSelectedItems([s]); |
| 16449 this._setSelectedItem(s); |
| 16450 } |
| 16451 }, |
| 16452 |
| 16453 _toggleSelected: function(value) { |
| 16454 var i = this.selectedValues.indexOf(value); |
| 16455 var unselected = i < 0; |
| 16456 if (unselected) { |
| 16457 this.push('selectedValues',value); |
| 16458 } else { |
| 16459 this.splice('selectedValues',i,1); |
| 16460 } |
| 16461 }, |
| 16462 |
| 16463 _valuesToItems: function(values) { |
| 16464 return (values == null) ? null : values.map(function(value) { |
| 16465 return this._valueToItem(value); |
| 16466 }, this); |
| 16467 } |
| 16468 }; |
| 16469 |
| 16470 /** @polymerBehavior */ |
| 16471 Polymer.IronMultiSelectableBehavior = [ |
| 16472 Polymer.IronSelectableBehavior, |
| 16473 Polymer.IronMultiSelectableBehaviorImpl |
| 16474 ]; |
| 16475 |
| 16476 </script> |
| 16477 <script> |
| 16478 /** |
| 16479 `iron-selector` is an element which can be used to manage a list of elements |
| 16480 that can be selected. Tapping on the item will make the item selected. The `
selected` indicates |
| 16481 which item is being selected. The default is to use the index of the item. |
| 16482 |
| 16483 Example: |
| 16484 |
| 16485 <iron-selector selected="0"> |
| 16486 <div>Item 1</div> |
| 16487 <div>Item 2</div> |
| 16488 <div>Item 3</div> |
| 16489 </iron-selector> |
| 16490 |
| 16491 If you want to use the attribute value of an element for `selected` instead of
the index, |
| 16492 set `attrForSelected` to the name of the attribute. For example, if you want
to select item by |
| 16493 `name`, set `attrForSelected` to `name`. |
| 16494 |
| 16495 Example: |
| 16496 |
| 16497 <iron-selector attr-for-selected="name" selected="foo"> |
| 16498 <div name="foo">Foo</div> |
| 16499 <div name="bar">Bar</div> |
| 16500 <div name="zot">Zot</div> |
| 16501 </iron-selector> |
| 16502 |
| 16503 You can specify a default fallback with `fallbackSelection` in case the `selec
ted` attribute does |
| 16504 not match the `attrForSelected` attribute of any elements. |
| 16505 |
| 16506 Example: |
| 16507 |
| 16508 <iron-selector attr-for-selected="name" selected="non-existing" |
| 16509 fallback-selection="default"> |
| 16510 <div name="foo">Foo</div> |
| 16511 <div name="bar">Bar</div> |
| 16512 <div name="default">Default</div> |
| 16513 </iron-selector> |
| 16514 |
| 16515 Note: When the selector is multi, the selection will set to `fallbackSelection
` iff |
| 16516 the number of matching elements is zero. |
| 16517 |
| 16518 `iron-selector` is not styled. Use the `iron-selected` CSS class to style the
selected element. |
| 16519 |
| 16520 Example: |
| 16521 |
| 16522 <style> |
| 16523 .iron-selected { |
| 16524 background: #eee; |
| 16525 } |
| 16526 </style> |
| 16527 |
| 16528 ... |
| 16529 |
| 16530 <iron-selector selected="0"> |
| 16531 <div>Item 1</div> |
| 16532 <div>Item 2</div> |
| 16533 <div>Item 3</div> |
| 16534 </iron-selector> |
| 16535 |
| 16536 @demo demo/index.html |
| 16537 */ |
| 16538 |
| 16539 Polymer({ |
| 16540 |
| 16541 is: 'iron-selector', |
| 16542 |
| 16543 behaviors: [ |
| 16544 Polymer.IronMultiSelectableBehavior |
| 16545 ] |
| 16546 |
| 16547 }); |
| 16548 |
| 16549 </script> |
| 16550 |
| 16551 |
| 16552 <style is="custom-style"> |
| 16553 |
| 16554 :root { |
| 16555 /* |
| 16556 * You can use these generic variables in your elements for easy theming. |
| 16557 * For example, if all your elements use `--primary-text-color` as its main |
| 16558 * color, then switching from a light to a dark theme is just a matter of |
| 16559 * changing the value of `--primary-text-color` in your application. |
| 16560 */ |
| 16561 --primary-text-color: var(--light-theme-text-color); |
| 16562 --primary-background-color: var(--light-theme-background-color); |
| 16563 --secondary-text-color: var(--light-theme-secondary-color); |
| 16564 --disabled-text-color: var(--light-theme-disabled-color); |
| 16565 --divider-color: var(--light-theme-divider-color); |
| 16566 --error-color: var(--paper-deep-orange-a700); |
| 16567 |
| 16568 /* |
| 16569 * Primary and accent colors. Also see color.html for more colors. |
| 16570 */ |
| 16571 --primary-color: var(--paper-indigo-500); |
| 16572 --light-primary-color: var(--paper-indigo-100); |
| 16573 --dark-primary-color: var(--paper-indigo-700); |
| 16574 |
| 16575 --accent-color: var(--paper-pink-a200); |
| 16576 --light-accent-color: var(--paper-pink-a100); |
| 16577 --dark-accent-color: var(--paper-pink-a400); |
| 16578 |
| 16579 |
| 16580 /* |
| 16581 * Material Design Light background theme |
| 16582 */ |
| 16583 --light-theme-background-color: #ffffff; |
| 16584 --light-theme-base-color: #000000; |
| 16585 --light-theme-text-color: var(--paper-grey-900); |
| 16586 --light-theme-secondary-color: #737373; /* for secondary text and icons */ |
| 16587 --light-theme-disabled-color: #9b9b9b; /* disabled/hint text */ |
| 16588 --light-theme-divider-color: #dbdbdb; |
| 16589 |
| 16590 /* |
| 16591 * Material Design Dark background theme |
| 16592 */ |
| 16593 --dark-theme-background-color: var(--paper-grey-900); |
| 16594 --dark-theme-base-color: #ffffff; |
| 16595 --dark-theme-text-color: #ffffff; |
| 16596 --dark-theme-secondary-color: #bcbcbc; /* for secondary text and icons */ |
| 16597 --dark-theme-disabled-color: #646464; /* disabled/hint text */ |
| 16598 --dark-theme-divider-color: #3c3c3c; |
| 16599 |
| 16600 /* |
| 16601 * Deprecated values because of their confusing names. |
| 16602 */ |
| 16603 --text-primary-color: var(--dark-theme-text-color); |
| 16604 --default-primary-color: var(--primary-color); |
| 16605 |
| 16606 } |
| 16607 |
| 16608 </style> |
| 16609 <script> |
| 16610 /** |
| 16611 * Singleton IronMeta instance. |
| 16612 */ |
| 16613 Polymer.IronValidatableBehaviorMeta = null; |
| 16614 |
| 16615 /** |
| 16616 * `Use Polymer.IronValidatableBehavior` to implement an element that validate
s user input. |
| 16617 * Use the related `Polymer.IronValidatorBehavior` to add custom validation lo
gic to an iron-input. |
| 16618 * |
| 16619 * By default, an `<iron-form>` element validates its fields when the user pre
sses the submit button. |
| 16620 * To validate a form imperatively, call the form's `validate()` method, which
in turn will |
| 16621 * call `validate()` on all its children. By using `Polymer.IronValidatableBeh
avior`, your |
| 16622 * custom element will get a public `validate()`, which |
| 16623 * will return the validity of the element, and a corresponding `invalid` attr
ibute, |
| 16624 * which can be used for styling. |
| 16625 * |
| 16626 * To implement the custom validation logic of your element, you must override |
| 16627 * the protected `_getValidity()` method of this behaviour, rather than `valid
ate()`. |
| 16628 * See [this](https://github.com/PolymerElements/iron-form/blob/master/demo/si
mple-element.html) |
| 16629 * for an example. |
| 16630 * |
| 16631 * ### Accessibility |
| 16632 * |
| 16633 * Changing the `invalid` property, either manually or by calling `validate()`
will update the |
| 16634 * `aria-invalid` attribute. |
| 16635 * |
| 16636 * @demo demo/index.html |
| 16637 * @polymerBehavior |
| 16638 */ |
| 16639 Polymer.IronValidatableBehavior = { |
| 16640 |
| 16641 properties: { |
| 16642 |
| 16643 /** |
| 16644 * Name of the validator to use. |
| 16645 */ |
| 16646 validator: { |
| 16647 type: String |
| 16648 }, |
| 16649 |
| 16650 /** |
| 16651 * True if the last call to `validate` is invalid. |
| 16652 */ |
| 16653 invalid: { |
| 16654 notify: true, |
| 16655 reflectToAttribute: true, |
| 16656 type: Boolean, |
| 16657 value: false |
| 16658 }, |
| 16659 |
| 16660 /** |
| 16661 * This property is deprecated and should not be used. Use the global |
| 16662 * validator meta singleton, `Polymer.IronValidatableBehaviorMeta` instead
. |
| 16663 */ |
| 16664 _validatorMeta: { |
| 16665 type: Object |
| 16666 }, |
| 16667 |
| 16668 /** |
| 16669 * Namespace for this validator. This property is deprecated and should |
| 16670 * not be used. For all intents and purposes, please consider it a |
| 16671 * read-only, config-time property. |
| 16672 */ |
| 16673 validatorType: { |
| 16674 type: String, |
| 16675 value: 'validator' |
| 16676 }, |
| 16677 |
| 16678 _validator: { |
| 16679 type: Object, |
| 16680 computed: '__computeValidator(validator)' |
| 16681 } |
| 16682 }, |
| 16683 |
| 16684 observers: [ |
| 16685 '_invalidChanged(invalid)' |
| 16686 ], |
| 16687 |
| 16688 registered: function() { |
| 16689 Polymer.IronValidatableBehaviorMeta = new Polymer.IronMeta({type: 'validat
or'}); |
| 16690 }, |
| 16691 |
| 16692 _invalidChanged: function() { |
| 16693 if (this.invalid) { |
| 16694 this.setAttribute('aria-invalid', 'true'); |
| 16695 } else { |
| 16696 this.removeAttribute('aria-invalid'); |
| 16697 } |
| 16698 }, |
| 16699 |
| 16700 /** |
| 16701 * @return {boolean} True if the validator `validator` exists. |
| 16702 */ |
| 16703 hasValidator: function() { |
| 16704 return this._validator != null; |
| 16705 }, |
| 16706 |
| 16707 /** |
| 16708 * Returns true if the `value` is valid, and updates `invalid`. If you want |
| 16709 * your element to have custom validation logic, do not override this method
; |
| 16710 * override `_getValidity(value)` instead. |
| 16711 |
| 16712 * @param {Object} value The value to be validated. By default, it is passed |
| 16713 * to the validator's `validate()` function, if a validator is set. |
| 16714 * @return {boolean} True if `value` is valid. |
| 16715 */ |
| 16716 validate: function(value) { |
| 16717 this.invalid = !this._getValidity(value); |
| 16718 return !this.invalid; |
| 16719 }, |
| 16720 |
| 16721 /** |
| 16722 * Returns true if `value` is valid. By default, it is passed |
| 16723 * to the validator's `validate()` function, if a validator is set. You |
| 16724 * should override this method if you want to implement custom validity |
| 16725 * logic for your element. |
| 16726 * |
| 16727 * @param {Object} value The value to be validated. |
| 16728 * @return {boolean} True if `value` is valid. |
| 16729 */ |
| 16730 |
| 16731 _getValidity: function(value) { |
| 16732 if (this.hasValidator()) { |
| 16733 return this._validator.validate(value); |
| 16734 } |
| 16735 return true; |
| 16736 }, |
| 16737 |
| 16738 __computeValidator: function() { |
| 16739 return Polymer.IronValidatableBehaviorMeta && |
| 16740 Polymer.IronValidatableBehaviorMeta.byKey(this.validator); |
| 16741 } |
| 16742 }; |
| 16743 |
| 16744 </script> |
| 16745 <script> |
| 16746 /** |
| 16747 Polymer.IronFormElementBehavior enables a custom element to be included |
| 16748 in an `iron-form`. |
| 16749 |
| 16750 @demo demo/index.html |
| 16751 @polymerBehavior |
| 16752 */ |
| 16753 Polymer.IronFormElementBehavior = { |
| 16754 |
| 16755 properties: { |
| 16756 /** |
| 16757 * Fired when the element is added to an `iron-form`. |
| 16758 * |
| 16759 * @event iron-form-element-register |
| 16760 */ |
| 16761 |
| 16762 /** |
| 16763 * Fired when the element is removed from an `iron-form`. |
| 16764 * |
| 16765 * @event iron-form-element-unregister |
| 16766 */ |
| 16767 |
| 16768 /** |
| 16769 * The name of this element. |
| 16770 */ |
| 16771 name: { |
| 16772 type: String |
| 16773 }, |
| 16774 |
| 16775 /** |
| 16776 * The value for this element. |
| 16777 */ |
| 16778 value: { |
| 16779 notify: true, |
| 16780 type: String |
| 16781 }, |
| 16782 |
| 16783 /** |
| 16784 * Set to true to mark the input as required. If used in a form, a |
| 16785 * custom element that uses this behavior should also use |
| 16786 * Polymer.IronValidatableBehavior and define a custom validation method. |
| 16787 * Otherwise, a `required` element will always be considered valid. |
| 16788 * It's also strongly recommended to provide a visual style for the elemen
t |
| 16789 * when its value is invalid. |
| 16790 */ |
| 16791 required: { |
| 16792 type: Boolean, |
| 16793 value: false |
| 16794 }, |
| 16795 |
| 16796 /** |
| 16797 * The form that the element is registered to. |
| 16798 */ |
| 16799 _parentForm: { |
| 16800 type: Object |
| 16801 } |
| 16802 }, |
| 16803 |
| 16804 attached: function() { |
| 16805 // Note: the iron-form that this element belongs to will set this |
| 16806 // element's _parentForm property when handling this event. |
| 16807 this.fire('iron-form-element-register'); |
| 16808 }, |
| 16809 |
| 16810 detached: function() { |
| 16811 if (this._parentForm) { |
| 16812 this._parentForm.fire('iron-form-element-unregister', {target: this}); |
| 16813 } |
| 16814 } |
| 16815 |
| 16816 }; |
| 16817 |
| 16818 </script> |
| 16819 <script> |
| 16820 |
| 16821 /** |
| 16822 * Use `Polymer.IronCheckedElementBehavior` to implement a custom element |
| 16823 * that has a `checked` property, which can be used for validation if the |
| 16824 * element is also `required`. Element instances implementing this behavior |
| 16825 * will also be registered for use in an `iron-form` element. |
| 16826 * |
| 16827 * @demo demo/index.html |
| 16828 * @polymerBehavior Polymer.IronCheckedElementBehavior |
| 16829 */ |
| 16830 Polymer.IronCheckedElementBehaviorImpl = { |
| 16831 |
| 16832 properties: { |
| 16833 /** |
| 16834 * Fired when the checked state changes. |
| 16835 * |
| 16836 * @event iron-change |
| 16837 */ |
| 16838 |
| 16839 /** |
| 16840 * Gets or sets the state, `true` is checked and `false` is unchecked. |
| 16841 */ |
| 16842 checked: { |
| 16843 type: Boolean, |
| 16844 value: false, |
| 16845 reflectToAttribute: true, |
| 16846 notify: true, |
| 16847 observer: '_checkedChanged' |
| 16848 }, |
| 16849 |
| 16850 /** |
| 16851 * If true, the button toggles the active state with each tap or press |
| 16852 * of the spacebar. |
| 16853 */ |
| 16854 toggles: { |
| 16855 type: Boolean, |
| 16856 value: true, |
| 16857 reflectToAttribute: true |
| 16858 }, |
| 16859 |
| 16860 /* Overriden from Polymer.IronFormElementBehavior */ |
| 16861 value: { |
| 16862 type: String, |
| 16863 value: 'on', |
| 16864 observer: '_valueChanged' |
| 16865 } |
| 16866 }, |
| 16867 |
| 16868 observers: [ |
| 16869 '_requiredChanged(required)' |
| 16870 ], |
| 16871 |
| 16872 created: function() { |
| 16873 // Used by `iron-form` to handle the case that an element with this behavi
or |
| 16874 // doesn't have a role of 'checkbox' or 'radio', but should still only be |
| 16875 // included when the form is serialized if `this.checked === true`. |
| 16876 this._hasIronCheckedElementBehavior = true; |
| 16877 }, |
| 16878 |
| 16879 /** |
| 16880 * Returns false if the element is required and not checked, and true otherw
ise. |
| 16881 * @param {*=} _value Ignored. |
| 16882 * @return {boolean} true if `required` is false or if `checked` is true. |
| 16883 */ |
| 16884 _getValidity: function(_value) { |
| 16885 return this.disabled || !this.required || this.checked; |
| 16886 }, |
| 16887 |
| 16888 /** |
| 16889 * Update the aria-required label when `required` is changed. |
| 16890 */ |
| 16891 _requiredChanged: function() { |
| 16892 if (this.required) { |
| 16893 this.setAttribute('aria-required', 'true'); |
| 16894 } else { |
| 16895 this.removeAttribute('aria-required'); |
| 16896 } |
| 16897 }, |
| 16898 |
| 16899 /** |
| 16900 * Fire `iron-changed` when the checked state changes. |
| 16901 */ |
| 16902 _checkedChanged: function() { |
| 16903 this.active = this.checked; |
| 16904 this.fire('iron-change'); |
| 16905 }, |
| 16906 |
| 16907 /** |
| 16908 * Reset value to 'on' if it is set to `undefined`. |
| 16909 */ |
| 16910 _valueChanged: function() { |
| 16911 if (this.value === undefined || this.value === null) { |
| 16912 this.value = 'on'; |
| 16913 } |
| 16914 } |
| 16915 }; |
| 16916 |
| 16917 /** @polymerBehavior Polymer.IronCheckedElementBehavior */ |
| 16918 Polymer.IronCheckedElementBehavior = [ |
| 16919 Polymer.IronFormElementBehavior, |
| 16920 Polymer.IronValidatableBehavior, |
| 16921 Polymer.IronCheckedElementBehaviorImpl |
| 16922 ]; |
| 16923 |
| 16924 </script> |
| 16925 <script> |
| 16926 (function() { |
| 16927 'use strict'; |
| 16928 |
| 16929 /** |
| 16930 * Chrome uses an older version of DOM Level 3 Keyboard Events |
| 16931 * |
| 16932 * Most keys are labeled as text, but some are Unicode codepoints. |
| 16933 * Values taken from: http://www.w3.org/TR/2007/WD-DOM-Level-3-Events-200712
21/keyset.html#KeySet-Set |
| 16934 */ |
| 16935 var KEY_IDENTIFIER = { |
| 16936 'U+0008': 'backspace', |
| 16937 'U+0009': 'tab', |
| 16938 'U+001B': 'esc', |
| 16939 'U+0020': 'space', |
| 16940 'U+007F': 'del' |
| 16941 }; |
| 16942 |
| 16943 /** |
| 16944 * Special table for KeyboardEvent.keyCode. |
| 16945 * KeyboardEvent.keyIdentifier is better, and KeyBoardEvent.key is even bett
er |
| 16946 * than that. |
| 16947 * |
| 16948 * Values from: https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEve
nt.keyCode#Value_of_keyCode |
| 16949 */ |
| 16950 var KEY_CODE = { |
| 16951 8: 'backspace', |
| 16952 9: 'tab', |
| 16953 13: 'enter', |
| 16954 27: 'esc', |
| 16955 33: 'pageup', |
| 16956 34: 'pagedown', |
| 16957 35: 'end', |
| 16958 36: 'home', |
| 16959 32: 'space', |
| 16960 37: 'left', |
| 16961 38: 'up', |
| 16962 39: 'right', |
| 16963 40: 'down', |
| 16964 46: 'del', |
| 16965 106: '*' |
| 16966 }; |
| 16967 |
| 16968 /** |
| 16969 * MODIFIER_KEYS maps the short name for modifier keys used in a key |
| 16970 * combo string to the property name that references those same keys |
| 16971 * in a KeyboardEvent instance. |
| 16972 */ |
| 16973 var MODIFIER_KEYS = { |
| 16974 'shift': 'shiftKey', |
| 16975 'ctrl': 'ctrlKey', |
| 16976 'alt': 'altKey', |
| 16977 'meta': 'metaKey' |
| 16978 }; |
| 16979 |
| 16980 /** |
| 16981 * KeyboardEvent.key is mostly represented by printable character made by |
| 16982 * the keyboard, with unprintable keys labeled nicely. |
| 16983 * |
| 16984 * However, on OS X, Alt+char can make a Unicode character that follows an |
| 16985 * Apple-specific mapping. In this case, we fall back to .keyCode. |
| 16986 */ |
| 16987 var KEY_CHAR = /[a-z0-9*]/; |
| 16988 |
| 16989 /** |
| 16990 * Matches a keyIdentifier string. |
| 16991 */ |
| 16992 var IDENT_CHAR = /U\+/; |
| 16993 |
| 16994 /** |
| 16995 * Matches arrow keys in Gecko 27.0+ |
| 16996 */ |
| 16997 var ARROW_KEY = /^arrow/; |
| 16998 |
| 16999 /** |
| 17000 * Matches space keys everywhere (notably including IE10's exceptional name |
| 17001 * `spacebar`). |
| 17002 */ |
| 17003 var SPACE_KEY = /^space(bar)?/; |
| 17004 |
| 17005 /** |
| 17006 * Matches ESC key. |
| 17007 * |
| 17008 * Value from: http://w3c.github.io/uievents-key/#key-Escape |
| 17009 */ |
| 17010 var ESC_KEY = /^escape$/; |
| 17011 |
| 17012 /** |
| 17013 * Transforms the key. |
| 17014 * @param {string} key The KeyBoardEvent.key |
| 17015 * @param {Boolean} [noSpecialChars] Limits the transformation to |
| 17016 * alpha-numeric characters. |
| 17017 */ |
| 17018 function transformKey(key, noSpecialChars) { |
| 17019 var validKey = ''; |
| 17020 if (key) { |
| 17021 var lKey = key.toLowerCase(); |
| 17022 if (lKey === ' ' || SPACE_KEY.test(lKey)) { |
| 17023 validKey = 'space'; |
| 17024 } else if (ESC_KEY.test(lKey)) { |
| 17025 validKey = 'esc'; |
| 17026 } else if (lKey.length == 1) { |
| 17027 if (!noSpecialChars || KEY_CHAR.test(lKey)) { |
| 17028 validKey = lKey; |
| 17029 } |
| 17030 } else if (ARROW_KEY.test(lKey)) { |
| 17031 validKey = lKey.replace('arrow', ''); |
| 17032 } else if (lKey == 'multiply') { |
| 17033 // numpad '*' can map to Multiply on IE/Windows |
| 17034 validKey = '*'; |
| 17035 } else { |
| 17036 validKey = lKey; |
| 17037 } |
| 17038 } |
| 17039 return validKey; |
| 17040 } |
| 17041 |
| 17042 function transformKeyIdentifier(keyIdent) { |
| 17043 var validKey = ''; |
| 17044 if (keyIdent) { |
| 17045 if (keyIdent in KEY_IDENTIFIER) { |
| 17046 validKey = KEY_IDENTIFIER[keyIdent]; |
| 17047 } else if (IDENT_CHAR.test(keyIdent)) { |
| 17048 keyIdent = parseInt(keyIdent.replace('U+', '0x'), 16); |
| 17049 validKey = String.fromCharCode(keyIdent).toLowerCase(); |
| 17050 } else { |
| 17051 validKey = keyIdent.toLowerCase(); |
| 17052 } |
| 17053 } |
| 17054 return validKey; |
| 17055 } |
| 17056 |
| 17057 function transformKeyCode(keyCode) { |
| 17058 var validKey = ''; |
| 17059 if (Number(keyCode)) { |
| 17060 if (keyCode >= 65 && keyCode <= 90) { |
| 17061 // ascii a-z |
| 17062 // lowercase is 32 offset from uppercase |
| 17063 validKey = String.fromCharCode(32 + keyCode); |
| 17064 } else if (keyCode >= 112 && keyCode <= 123) { |
| 17065 // function keys f1-f12 |
| 17066 validKey = 'f' + (keyCode - 112); |
| 17067 } else if (keyCode >= 48 && keyCode <= 57) { |
| 17068 // top 0-9 keys |
| 17069 validKey = String(keyCode - 48); |
| 17070 } else if (keyCode >= 96 && keyCode <= 105) { |
| 17071 // num pad 0-9 |
| 17072 validKey = String(keyCode - 96); |
| 17073 } else { |
| 17074 validKey = KEY_CODE[keyCode]; |
| 17075 } |
| 17076 } |
| 17077 return validKey; |
| 17078 } |
| 17079 |
| 17080 /** |
| 17081 * Calculates the normalized key for a KeyboardEvent. |
| 17082 * @param {KeyboardEvent} keyEvent |
| 17083 * @param {Boolean} [noSpecialChars] Set to true to limit keyEvent.key |
| 17084 * transformation to alpha-numeric chars. This is useful with key |
| 17085 * combinations like shift + 2, which on FF for MacOS produces |
| 17086 * keyEvent.key = @ |
| 17087 * To get 2 returned, set noSpecialChars = true |
| 17088 * To get @ returned, set noSpecialChars = false |
| 17089 */ |
| 17090 function normalizedKeyForEvent(keyEvent, noSpecialChars) { |
| 17091 // Fall back from .key, to .keyIdentifier, to .keyCode, and then to |
| 17092 // .detail.key to support artificial keyboard events. |
| 17093 return transformKey(keyEvent.key, noSpecialChars) || |
| 17094 transformKeyIdentifier(keyEvent.keyIdentifier) || |
| 17095 transformKeyCode(keyEvent.keyCode) || |
| 17096 transformKey(keyEvent.detail ? keyEvent.detail.key : keyEvent.detail, no
SpecialChars) || ''; |
| 17097 } |
| 17098 |
| 17099 function keyComboMatchesEvent(keyCombo, event) { |
| 17100 // For combos with modifiers we support only alpha-numeric keys |
| 17101 var keyEvent = normalizedKeyForEvent(event, keyCombo.hasModifiers); |
| 17102 return keyEvent === keyCombo.key && |
| 17103 (!keyCombo.hasModifiers || ( |
| 17104 !!event.shiftKey === !!keyCombo.shiftKey && |
| 17105 !!event.ctrlKey === !!keyCombo.ctrlKey && |
| 17106 !!event.altKey === !!keyCombo.altKey && |
| 17107 !!event.metaKey === !!keyCombo.metaKey) |
| 17108 ); |
| 17109 } |
| 17110 |
| 17111 function parseKeyComboString(keyComboString) { |
| 17112 if (keyComboString.length === 1) { |
| 17113 return { |
| 17114 combo: keyComboString, |
| 17115 key: keyComboString, |
| 17116 event: 'keydown' |
| 17117 }; |
| 17118 } |
| 17119 return keyComboString.split('+').reduce(function(parsedKeyCombo, keyComboP
art) { |
| 17120 var eventParts = keyComboPart.split(':'); |
| 17121 var keyName = eventParts[0]; |
| 17122 var event = eventParts[1]; |
| 17123 |
| 17124 if (keyName in MODIFIER_KEYS) { |
| 17125 parsedKeyCombo[MODIFIER_KEYS[keyName]] = true; |
| 17126 parsedKeyCombo.hasModifiers = true; |
| 17127 } else { |
| 17128 parsedKeyCombo.key = keyName; |
| 17129 parsedKeyCombo.event = event || 'keydown'; |
| 17130 } |
| 17131 |
| 17132 return parsedKeyCombo; |
| 17133 }, { |
| 17134 combo: keyComboString.split(':').shift() |
| 17135 }); |
| 17136 } |
| 17137 |
| 17138 function parseEventString(eventString) { |
| 17139 return eventString.trim().split(' ').map(function(keyComboString) { |
| 17140 return parseKeyComboString(keyComboString); |
| 17141 }); |
| 17142 } |
| 17143 |
| 17144 /** |
| 17145 * `Polymer.IronA11yKeysBehavior` provides a normalized interface for proces
sing |
| 17146 * keyboard commands that pertain to [WAI-ARIA best practices](http://www.w3
.org/TR/wai-aria-practices/#kbd_general_binding). |
| 17147 * The element takes care of browser differences with respect to Keyboard ev
ents |
| 17148 * and uses an expressive syntax to filter key presses. |
| 17149 * |
| 17150 * Use the `keyBindings` prototype property to express what combination of k
eys |
| 17151 * will trigger the callback. A key binding has the format |
| 17152 * `"KEY+MODIFIER:EVENT": "callback"` (`"KEY": "callback"` or |
| 17153 * `"KEY:EVENT": "callback"` are valid as well). Some examples: |
| 17154 * |
| 17155 * keyBindings: { |
| 17156 * 'space': '_onKeydown', // same as 'space:keydown' |
| 17157 * 'shift+tab': '_onKeydown', |
| 17158 * 'enter:keypress': '_onKeypress', |
| 17159 * 'esc:keyup': '_onKeyup' |
| 17160 * } |
| 17161 * |
| 17162 * The callback will receive with an event containing the following informat
ion in `event.detail`: |
| 17163 * |
| 17164 * _onKeydown: function(event) { |
| 17165 * console.log(event.detail.combo); // KEY+MODIFIER, e.g. "shift+tab" |
| 17166 * console.log(event.detail.key); // KEY only, e.g. "tab" |
| 17167 * console.log(event.detail.event); // EVENT, e.g. "keydown" |
| 17168 * console.log(event.detail.keyboardEvent); // the original KeyboardE
vent |
| 17169 * } |
| 17170 * |
| 17171 * Use the `keyEventTarget` attribute to set up event handlers on a specific |
| 17172 * node. |
| 17173 * |
| 17174 * See the [demo source code](https://github.com/PolymerElements/iron-a11y-k
eys-behavior/blob/master/demo/x-key-aware.html) |
| 17175 * for an example. |
| 17176 * |
| 17177 * @demo demo/index.html |
| 17178 * @polymerBehavior |
| 17179 */ |
| 17180 Polymer.IronA11yKeysBehavior = { |
| 17181 properties: { |
| 17182 /** |
| 17183 * The EventTarget that will be firing relevant KeyboardEvents. Set it t
o |
| 17184 * `null` to disable the listeners. |
| 17185 * @type {?EventTarget} |
| 17186 */ |
| 17187 keyEventTarget: { |
| 17188 type: Object, |
| 17189 value: function() { |
| 17190 return this; |
| 17191 } |
| 17192 }, |
| 17193 |
| 17194 /** |
| 17195 * If true, this property will cause the implementing element to |
| 17196 * automatically stop propagation on any handled KeyboardEvents. |
| 17197 */ |
| 17198 stopKeyboardEventPropagation: { |
| 17199 type: Boolean, |
| 17200 value: false |
| 17201 }, |
| 17202 |
| 17203 _boundKeyHandlers: { |
| 17204 type: Array, |
| 17205 value: function() { |
| 17206 return []; |
| 17207 } |
| 17208 }, |
| 17209 |
| 17210 // We use this due to a limitation in IE10 where instances will have |
| 17211 // own properties of everything on the "prototype". |
| 17212 _imperativeKeyBindings: { |
| 17213 type: Object, |
| 17214 value: function() { |
| 17215 return {}; |
| 17216 } |
| 17217 } |
| 17218 }, |
| 17219 |
| 17220 observers: [ |
| 17221 '_resetKeyEventListeners(keyEventTarget, _boundKeyHandlers)' |
| 17222 ], |
| 17223 |
| 17224 |
| 17225 /** |
| 17226 * To be used to express what combination of keys will trigger the relati
ve |
| 17227 * callback. e.g. `keyBindings: { 'esc': '_onEscPressed'}` |
| 17228 * @type {Object} |
| 17229 */ |
| 17230 keyBindings: {}, |
| 17231 |
| 17232 registered: function() { |
| 17233 this._prepKeyBindings(); |
| 17234 }, |
| 17235 |
| 17236 attached: function() { |
| 17237 this._listenKeyEventListeners(); |
| 17238 }, |
| 17239 |
| 17240 detached: function() { |
| 17241 this._unlistenKeyEventListeners(); |
| 17242 }, |
| 17243 |
| 17244 /** |
| 17245 * Can be used to imperatively add a key binding to the implementing |
| 17246 * element. This is the imperative equivalent of declaring a keybinding |
| 17247 * in the `keyBindings` prototype property. |
| 17248 */ |
| 17249 addOwnKeyBinding: function(eventString, handlerName) { |
| 17250 this._imperativeKeyBindings[eventString] = handlerName; |
| 17251 this._prepKeyBindings(); |
| 17252 this._resetKeyEventListeners(); |
| 17253 }, |
| 17254 |
| 17255 /** |
| 17256 * When called, will remove all imperatively-added key bindings. |
| 17257 */ |
| 17258 removeOwnKeyBindings: function() { |
| 17259 this._imperativeKeyBindings = {}; |
| 17260 this._prepKeyBindings(); |
| 17261 this._resetKeyEventListeners(); |
| 17262 }, |
| 17263 |
| 17264 /** |
| 17265 * Returns true if a keyboard event matches `eventString`. |
| 17266 * |
| 17267 * @param {KeyboardEvent} event |
| 17268 * @param {string} eventString |
| 17269 * @return {boolean} |
| 17270 */ |
| 17271 keyboardEventMatchesKeys: function(event, eventString) { |
| 17272 var keyCombos = parseEventString(eventString); |
| 17273 for (var i = 0; i < keyCombos.length; ++i) { |
| 17274 if (keyComboMatchesEvent(keyCombos[i], event)) { |
| 17275 return true; |
| 17276 } |
| 17277 } |
| 17278 return false; |
| 17279 }, |
| 17280 |
| 17281 _collectKeyBindings: function() { |
| 17282 var keyBindings = this.behaviors.map(function(behavior) { |
| 17283 return behavior.keyBindings; |
| 17284 }); |
| 17285 |
| 17286 if (keyBindings.indexOf(this.keyBindings) === -1) { |
| 17287 keyBindings.push(this.keyBindings); |
| 17288 } |
| 17289 |
| 17290 return keyBindings; |
| 17291 }, |
| 17292 |
| 17293 _prepKeyBindings: function() { |
| 17294 this._keyBindings = {}; |
| 17295 |
| 17296 this._collectKeyBindings().forEach(function(keyBindings) { |
| 17297 for (var eventString in keyBindings) { |
| 17298 this._addKeyBinding(eventString, keyBindings[eventString]); |
| 17299 } |
| 17300 }, this); |
| 17301 |
| 17302 for (var eventString in this._imperativeKeyBindings) { |
| 17303 this._addKeyBinding(eventString, this._imperativeKeyBindings[eventStri
ng]); |
| 17304 } |
| 17305 |
| 17306 // Give precedence to combos with modifiers to be checked first. |
| 17307 for (var eventName in this._keyBindings) { |
| 17308 this._keyBindings[eventName].sort(function (kb1, kb2) { |
| 17309 var b1 = kb1[0].hasModifiers; |
| 17310 var b2 = kb2[0].hasModifiers; |
| 17311 return (b1 === b2) ? 0 : b1 ? -1 : 1; |
| 17312 }) |
| 17313 } |
| 17314 }, |
| 17315 |
| 17316 _addKeyBinding: function(eventString, handlerName) { |
| 17317 parseEventString(eventString).forEach(function(keyCombo) { |
| 17318 this._keyBindings[keyCombo.event] = |
| 17319 this._keyBindings[keyCombo.event] || []; |
| 17320 |
| 17321 this._keyBindings[keyCombo.event].push([ |
| 17322 keyCombo, |
| 17323 handlerName |
| 17324 ]); |
| 17325 }, this); |
| 17326 }, |
| 17327 |
| 17328 _resetKeyEventListeners: function() { |
| 17329 this._unlistenKeyEventListeners(); |
| 17330 |
| 17331 if (this.isAttached) { |
| 17332 this._listenKeyEventListeners(); |
| 17333 } |
| 17334 }, |
| 17335 |
| 17336 _listenKeyEventListeners: function() { |
| 17337 if (!this.keyEventTarget) { |
| 17338 return; |
| 17339 } |
| 17340 Object.keys(this._keyBindings).forEach(function(eventName) { |
| 17341 var keyBindings = this._keyBindings[eventName]; |
| 17342 var boundKeyHandler = this._onKeyBindingEvent.bind(this, keyBindings); |
| 17343 |
| 17344 this._boundKeyHandlers.push([this.keyEventTarget, eventName, boundKeyH
andler]); |
| 17345 |
| 17346 this.keyEventTarget.addEventListener(eventName, boundKeyHandler); |
| 17347 }, this); |
| 17348 }, |
| 17349 |
| 17350 _unlistenKeyEventListeners: function() { |
| 17351 var keyHandlerTuple; |
| 17352 var keyEventTarget; |
| 17353 var eventName; |
| 17354 var boundKeyHandler; |
| 17355 |
| 17356 while (this._boundKeyHandlers.length) { |
| 17357 // My kingdom for block-scope binding and destructuring assignment.. |
| 17358 keyHandlerTuple = this._boundKeyHandlers.pop(); |
| 17359 keyEventTarget = keyHandlerTuple[0]; |
| 17360 eventName = keyHandlerTuple[1]; |
| 17361 boundKeyHandler = keyHandlerTuple[2]; |
| 17362 |
| 17363 keyEventTarget.removeEventListener(eventName, boundKeyHandler); |
| 17364 } |
| 17365 }, |
| 17366 |
| 17367 _onKeyBindingEvent: function(keyBindings, event) { |
| 17368 if (this.stopKeyboardEventPropagation) { |
| 17369 event.stopPropagation(); |
| 17370 } |
| 17371 |
| 17372 // if event has been already prevented, don't do anything |
| 17373 if (event.defaultPrevented) { |
| 17374 return; |
| 17375 } |
| 17376 |
| 17377 for (var i = 0; i < keyBindings.length; i++) { |
| 17378 var keyCombo = keyBindings[i][0]; |
| 17379 var handlerName = keyBindings[i][1]; |
| 17380 if (keyComboMatchesEvent(keyCombo, event)) { |
| 17381 this._triggerKeyHandler(keyCombo, handlerName, event); |
| 17382 // exit the loop if eventDefault was prevented |
| 17383 if (event.defaultPrevented) { |
| 17384 return; |
| 17385 } |
| 17386 } |
| 17387 } |
| 17388 }, |
| 17389 |
| 17390 _triggerKeyHandler: function(keyCombo, handlerName, keyboardEvent) { |
| 17391 var detail = Object.create(keyCombo); |
| 17392 detail.keyboardEvent = keyboardEvent; |
| 17393 var event = new CustomEvent(keyCombo.event, { |
| 17394 detail: detail, |
| 17395 cancelable: true |
| 17396 }); |
| 17397 this[handlerName].call(this, event); |
| 17398 if (event.defaultPrevented) { |
| 17399 keyboardEvent.preventDefault(); |
| 17400 } |
| 17401 } |
| 17402 }; |
| 17403 })(); |
| 17404 </script> |
| 17405 <script> |
| 17406 |
| 17407 /** |
| 17408 * @demo demo/index.html |
| 17409 * @polymerBehavior |
| 17410 */ |
| 17411 Polymer.IronControlState = { |
| 17412 |
| 17413 properties: { |
| 17414 |
| 17415 /** |
| 17416 * If true, the element currently has focus. |
| 17417 */ |
| 17418 focused: { |
| 17419 type: Boolean, |
| 17420 value: false, |
| 17421 notify: true, |
| 17422 readOnly: true, |
| 17423 reflectToAttribute: true |
| 17424 }, |
| 17425 |
| 17426 /** |
| 17427 * If true, the user cannot interact with this element. |
| 17428 */ |
| 17429 disabled: { |
| 17430 type: Boolean, |
| 17431 value: false, |
| 17432 notify: true, |
| 17433 observer: '_disabledChanged', |
| 17434 reflectToAttribute: true |
| 17435 }, |
| 17436 |
| 17437 _oldTabIndex: { |
| 17438 type: Number |
| 17439 }, |
| 17440 |
| 17441 _boundFocusBlurHandler: { |
| 17442 type: Function, |
| 17443 value: function() { |
| 17444 return this._focusBlurHandler.bind(this); |
| 17445 } |
| 17446 } |
| 17447 |
| 17448 }, |
| 17449 |
| 17450 observers: [ |
| 17451 '_changedControlState(focused, disabled)' |
| 17452 ], |
| 17453 |
| 17454 ready: function() { |
| 17455 this.addEventListener('focus', this._boundFocusBlurHandler, true); |
| 17456 this.addEventListener('blur', this._boundFocusBlurHandler, true); |
| 17457 }, |
| 17458 |
| 17459 _focusBlurHandler: function(event) { |
| 17460 // NOTE(cdata): if we are in ShadowDOM land, `event.target` will |
| 17461 // eventually become `this` due to retargeting; if we are not in |
| 17462 // ShadowDOM land, `event.target` will eventually become `this` due |
| 17463 // to the second conditional which fires a synthetic event (that is also |
| 17464 // handled). In either case, we can disregard `event.path`. |
| 17465 |
| 17466 if (event.target === this) { |
| 17467 this._setFocused(event.type === 'focus'); |
| 17468 } else if (!this.shadowRoot) { |
| 17469 var target = /** @type {Node} */(Polymer.dom(event).localTarget); |
| 17470 if (!this.isLightDescendant(target)) { |
| 17471 this.fire(event.type, {sourceEvent: event}, { |
| 17472 node: this, |
| 17473 bubbles: event.bubbles, |
| 17474 cancelable: event.cancelable |
| 17475 }); |
| 17476 } |
| 17477 } |
| 17478 }, |
| 17479 |
| 17480 _disabledChanged: function(disabled, old) { |
| 17481 this.setAttribute('aria-disabled', disabled ? 'true' : 'false'); |
| 17482 this.style.pointerEvents = disabled ? 'none' : ''; |
| 17483 if (disabled) { |
| 17484 this._oldTabIndex = this.tabIndex; |
| 17485 this._setFocused(false); |
| 17486 this.tabIndex = -1; |
| 17487 this.blur(); |
| 17488 } else if (this._oldTabIndex !== undefined) { |
| 17489 this.tabIndex = this._oldTabIndex; |
| 17490 } |
| 17491 }, |
| 17492 |
| 17493 _changedControlState: function() { |
| 17494 // _controlStateChanged is abstract, follow-on behaviors may implement it |
| 17495 if (this._controlStateChanged) { |
| 17496 this._controlStateChanged(); |
| 17497 } |
| 17498 } |
| 17499 |
| 17500 }; |
| 17501 |
| 17502 </script> |
| 17503 <script> |
| 17504 |
| 17505 /** |
| 17506 * @demo demo/index.html |
| 17507 * @polymerBehavior Polymer.IronButtonState |
| 17508 */ |
| 17509 Polymer.IronButtonStateImpl = { |
| 17510 |
| 17511 properties: { |
| 17512 |
| 17513 /** |
| 17514 * If true, the user is currently holding down the button. |
| 17515 */ |
| 17516 pressed: { |
| 17517 type: Boolean, |
| 17518 readOnly: true, |
| 17519 value: false, |
| 17520 reflectToAttribute: true, |
| 17521 observer: '_pressedChanged' |
| 17522 }, |
| 17523 |
| 17524 /** |
| 17525 * If true, the button toggles the active state with each tap or press |
| 17526 * of the spacebar. |
| 17527 */ |
| 17528 toggles: { |
| 17529 type: Boolean, |
| 17530 value: false, |
| 17531 reflectToAttribute: true |
| 17532 }, |
| 17533 |
| 17534 /** |
| 17535 * If true, the button is a toggle and is currently in the active state. |
| 17536 */ |
| 17537 active: { |
| 17538 type: Boolean, |
| 17539 value: false, |
| 17540 notify: true, |
| 17541 reflectToAttribute: true |
| 17542 }, |
| 17543 |
| 17544 /** |
| 17545 * True if the element is currently being pressed by a "pointer," which |
| 17546 * is loosely defined as mouse or touch input (but specifically excluding |
| 17547 * keyboard input). |
| 17548 */ |
| 17549 pointerDown: { |
| 17550 type: Boolean, |
| 17551 readOnly: true, |
| 17552 value: false |
| 17553 }, |
| 17554 |
| 17555 /** |
| 17556 * True if the input device that caused the element to receive focus |
| 17557 * was a keyboard. |
| 17558 */ |
| 17559 receivedFocusFromKeyboard: { |
| 17560 type: Boolean, |
| 17561 readOnly: true |
| 17562 }, |
| 17563 |
| 17564 /** |
| 17565 * The aria attribute to be set if the button is a toggle and in the |
| 17566 * active state. |
| 17567 */ |
| 17568 ariaActiveAttribute: { |
| 17569 type: String, |
| 17570 value: 'aria-pressed', |
| 17571 observer: '_ariaActiveAttributeChanged' |
| 17572 } |
| 17573 }, |
| 17574 |
| 17575 listeners: { |
| 17576 down: '_downHandler', |
| 17577 up: '_upHandler', |
| 17578 tap: '_tapHandler' |
| 17579 }, |
| 17580 |
| 17581 observers: [ |
| 17582 '_detectKeyboardFocus(focused)', |
| 17583 '_activeChanged(active, ariaActiveAttribute)' |
| 17584 ], |
| 17585 |
| 17586 keyBindings: { |
| 17587 'enter:keydown': '_asyncClick', |
| 17588 'space:keydown': '_spaceKeyDownHandler', |
| 17589 'space:keyup': '_spaceKeyUpHandler', |
| 17590 }, |
| 17591 |
| 17592 _mouseEventRe: /^mouse/, |
| 17593 |
| 17594 _tapHandler: function() { |
| 17595 if (this.toggles) { |
| 17596 // a tap is needed to toggle the active state |
| 17597 this._userActivate(!this.active); |
| 17598 } else { |
| 17599 this.active = false; |
| 17600 } |
| 17601 }, |
| 17602 |
| 17603 _detectKeyboardFocus: function(focused) { |
| 17604 this._setReceivedFocusFromKeyboard(!this.pointerDown && focused); |
| 17605 }, |
| 17606 |
| 17607 // to emulate native checkbox, (de-)activations from a user interaction fire |
| 17608 // 'change' events |
| 17609 _userActivate: function(active) { |
| 17610 if (this.active !== active) { |
| 17611 this.active = active; |
| 17612 this.fire('change'); |
| 17613 } |
| 17614 }, |
| 17615 |
| 17616 _downHandler: function(event) { |
| 17617 this._setPointerDown(true); |
| 17618 this._setPressed(true); |
| 17619 this._setReceivedFocusFromKeyboard(false); |
| 17620 }, |
| 17621 |
| 17622 _upHandler: function() { |
| 17623 this._setPointerDown(false); |
| 17624 this._setPressed(false); |
| 17625 }, |
| 17626 |
| 17627 /** |
| 17628 * @param {!KeyboardEvent} event . |
| 17629 */ |
| 17630 _spaceKeyDownHandler: function(event) { |
| 17631 var keyboardEvent = event.detail.keyboardEvent; |
| 17632 var target = Polymer.dom(keyboardEvent).localTarget; |
| 17633 |
| 17634 // Ignore the event if this is coming from a focused light child, since th
at |
| 17635 // element will deal with it. |
| 17636 if (this.isLightDescendant(/** @type {Node} */(target))) |
| 17637 return; |
| 17638 |
| 17639 keyboardEvent.preventDefault(); |
| 17640 keyboardEvent.stopImmediatePropagation(); |
| 17641 this._setPressed(true); |
| 17642 }, |
| 17643 |
| 17644 /** |
| 17645 * @param {!KeyboardEvent} event . |
| 17646 */ |
| 17647 _spaceKeyUpHandler: function(event) { |
| 17648 var keyboardEvent = event.detail.keyboardEvent; |
| 17649 var target = Polymer.dom(keyboardEvent).localTarget; |
| 17650 |
| 17651 // Ignore the event if this is coming from a focused light child, since th
at |
| 17652 // element will deal with it. |
| 17653 if (this.isLightDescendant(/** @type {Node} */(target))) |
| 17654 return; |
| 17655 |
| 17656 if (this.pressed) { |
| 17657 this._asyncClick(); |
| 17658 } |
| 17659 this._setPressed(false); |
| 17660 }, |
| 17661 |
| 17662 // trigger click asynchronously, the asynchrony is useful to allow one |
| 17663 // event handler to unwind before triggering another event |
| 17664 _asyncClick: function() { |
| 17665 this.async(function() { |
| 17666 this.click(); |
| 17667 }, 1); |
| 17668 }, |
| 17669 |
| 17670 // any of these changes are considered a change to button state |
| 17671 |
| 17672 _pressedChanged: function(pressed) { |
| 17673 this._changedButtonState(); |
| 17674 }, |
| 17675 |
| 17676 _ariaActiveAttributeChanged: function(value, oldValue) { |
| 17677 if (oldValue && oldValue != value && this.hasAttribute(oldValue)) { |
| 17678 this.removeAttribute(oldValue); |
| 17679 } |
| 17680 }, |
| 17681 |
| 17682 _activeChanged: function(active, ariaActiveAttribute) { |
| 17683 if (this.toggles) { |
| 17684 this.setAttribute(this.ariaActiveAttribute, |
| 17685 active ? 'true' : 'false'); |
| 17686 } else { |
| 17687 this.removeAttribute(this.ariaActiveAttribute); |
| 17688 } |
| 17689 this._changedButtonState(); |
| 17690 }, |
| 17691 |
| 17692 _controlStateChanged: function() { |
| 17693 if (this.disabled) { |
| 17694 this._setPressed(false); |
| 17695 } else { |
| 17696 this._changedButtonState(); |
| 17697 } |
| 17698 }, |
| 17699 |
| 17700 // provide hook for follow-on behaviors to react to button-state |
| 17701 |
| 17702 _changedButtonState: function() { |
| 17703 if (this._buttonStateChanged) { |
| 17704 this._buttonStateChanged(); // abstract |
| 17705 } |
| 17706 } |
| 17707 |
| 17708 }; |
| 17709 |
| 17710 /** @polymerBehavior */ |
| 17711 Polymer.IronButtonState = [ |
| 17712 Polymer.IronA11yKeysBehavior, |
| 17713 Polymer.IronButtonStateImpl |
| 17714 ]; |
| 17715 |
| 17716 </script> |
| 17717 |
| 17718 |
| 17719 <dom-module id="paper-ripple" assetpath="/res/imp/bower_components/paper-ripple/
"> |
| 17720 |
| 17721 <template> |
| 17722 <style> |
| 17723 :host { |
| 17724 display: block; |
| 17725 position: absolute; |
| 17726 border-radius: inherit; |
| 17727 overflow: hidden; |
| 17728 top: 0; |
| 17729 left: 0; |
| 17730 right: 0; |
| 17731 bottom: 0; |
| 17732 |
| 17733 /* See PolymerElements/paper-behaviors/issues/34. On non-Chrome browsers
, |
| 17734 * creating a node (with a position:absolute) in the middle of an event |
| 17735 * handler "interrupts" that event handler (which happens when the |
| 17736 * ripple is created on demand) */ |
| 17737 pointer-events: none; |
| 17738 } |
| 17739 |
| 17740 :host([animating]) { |
| 17741 /* This resolves a rendering issue in Chrome (as of 40) where the |
| 17742 ripple is not properly clipped by its parent (which may have |
| 17743 rounded corners). See: http://jsbin.com/temexa/4 |
| 17744 |
| 17745 Note: We only apply this style conditionally. Otherwise, the browser |
| 17746 will create a new compositing layer for every ripple element on the |
| 17747 page, and that would be bad. */ |
| 17748 -webkit-transform: translate(0, 0); |
| 17749 transform: translate3d(0, 0, 0); |
| 17750 } |
| 17751 |
| 17752 #background, |
| 17753 #waves, |
| 17754 .wave-container, |
| 17755 .wave { |
| 17756 pointer-events: none; |
| 17757 position: absolute; |
| 17758 top: 0; |
| 17759 left: 0; |
| 17760 width: 100%; |
| 17761 height: 100%; |
| 17762 } |
| 17763 |
| 17764 #background, |
| 17765 .wave { |
| 17766 opacity: 0; |
| 17767 } |
| 17768 |
| 17769 #waves, |
| 17770 .wave { |
| 17771 overflow: hidden; |
| 17772 } |
| 17773 |
| 17774 .wave-container, |
| 17775 .wave { |
| 17776 border-radius: 50%; |
| 17777 } |
| 17778 |
| 17779 :host(.circle) #background, |
| 17780 :host(.circle) #waves { |
| 17781 border-radius: 50%; |
| 17782 } |
| 17783 |
| 17784 :host(.circle) .wave-container { |
| 17785 overflow: hidden; |
| 17786 } |
| 17787 </style> |
| 17788 |
| 17789 <div id="background"></div> |
| 17790 <div id="waves"></div> |
| 17791 </template> |
| 17792 </dom-module> |
| 17793 <script> |
| 17794 (function() { |
| 17795 var Utility = { |
| 17796 distance: function(x1, y1, x2, y2) { |
| 17797 var xDelta = (x1 - x2); |
| 17798 var yDelta = (y1 - y2); |
| 17799 |
| 17800 return Math.sqrt(xDelta * xDelta + yDelta * yDelta); |
| 17801 }, |
| 17802 |
| 17803 now: window.performance && window.performance.now ? |
| 17804 window.performance.now.bind(window.performance) : Date.now |
| 17805 }; |
| 17806 |
| 17807 /** |
| 17808 * @param {HTMLElement} element |
| 17809 * @constructor |
| 17810 */ |
| 17811 function ElementMetrics(element) { |
| 17812 this.element = element; |
| 17813 this.width = this.boundingRect.width; |
| 17814 this.height = this.boundingRect.height; |
| 17815 |
| 17816 this.size = Math.max(this.width, this.height); |
| 17817 } |
| 17818 |
| 17819 ElementMetrics.prototype = { |
| 17820 get boundingRect () { |
| 17821 return this.element.getBoundingClientRect(); |
| 17822 }, |
| 17823 |
| 17824 furthestCornerDistanceFrom: function(x, y) { |
| 17825 var topLeft = Utility.distance(x, y, 0, 0); |
| 17826 var topRight = Utility.distance(x, y, this.width, 0); |
| 17827 var bottomLeft = Utility.distance(x, y, 0, this.height); |
| 17828 var bottomRight = Utility.distance(x, y, this.width, this.height); |
| 17829 |
| 17830 return Math.max(topLeft, topRight, bottomLeft, bottomRight); |
| 17831 } |
| 17832 }; |
| 17833 |
| 17834 /** |
| 17835 * @param {HTMLElement} element |
| 17836 * @constructor |
| 17837 */ |
| 17838 function Ripple(element) { |
| 17839 this.element = element; |
| 17840 this.color = window.getComputedStyle(element).color; |
| 17841 |
| 17842 this.wave = document.createElement('div'); |
| 17843 this.waveContainer = document.createElement('div'); |
| 17844 this.wave.style.backgroundColor = this.color; |
| 17845 this.wave.classList.add('wave'); |
| 17846 this.waveContainer.classList.add('wave-container'); |
| 17847 Polymer.dom(this.waveContainer).appendChild(this.wave); |
| 17848 |
| 17849 this.resetInteractionState(); |
| 17850 } |
| 17851 |
| 17852 Ripple.MAX_RADIUS = 300; |
| 17853 |
| 17854 Ripple.prototype = { |
| 17855 get recenters() { |
| 17856 return this.element.recenters; |
| 17857 }, |
| 17858 |
| 17859 get center() { |
| 17860 return this.element.center; |
| 17861 }, |
| 17862 |
| 17863 get mouseDownElapsed() { |
| 17864 var elapsed; |
| 17865 |
| 17866 if (!this.mouseDownStart) { |
| 17867 return 0; |
| 17868 } |
| 17869 |
| 17870 elapsed = Utility.now() - this.mouseDownStart; |
| 17871 |
| 17872 if (this.mouseUpStart) { |
| 17873 elapsed -= this.mouseUpElapsed; |
| 17874 } |
| 17875 |
| 17876 return elapsed; |
| 17877 }, |
| 17878 |
| 17879 get mouseUpElapsed() { |
| 17880 return this.mouseUpStart ? |
| 17881 Utility.now () - this.mouseUpStart : 0; |
| 17882 }, |
| 17883 |
| 17884 get mouseDownElapsedSeconds() { |
| 17885 return this.mouseDownElapsed / 1000; |
| 17886 }, |
| 17887 |
| 17888 get mouseUpElapsedSeconds() { |
| 17889 return this.mouseUpElapsed / 1000; |
| 17890 }, |
| 17891 |
| 17892 get mouseInteractionSeconds() { |
| 17893 return this.mouseDownElapsedSeconds + this.mouseUpElapsedSeconds; |
| 17894 }, |
| 17895 |
| 17896 get initialOpacity() { |
| 17897 return this.element.initialOpacity; |
| 17898 }, |
| 17899 |
| 17900 get opacityDecayVelocity() { |
| 17901 return this.element.opacityDecayVelocity; |
| 17902 }, |
| 17903 |
| 17904 get radius() { |
| 17905 var width2 = this.containerMetrics.width * this.containerMetrics.width; |
| 17906 var height2 = this.containerMetrics.height * this.containerMetrics.heigh
t; |
| 17907 var waveRadius = Math.min( |
| 17908 Math.sqrt(width2 + height2), |
| 17909 Ripple.MAX_RADIUS |
| 17910 ) * 1.1 + 5; |
| 17911 |
| 17912 var duration = 1.1 - 0.2 * (waveRadius / Ripple.MAX_RADIUS); |
| 17913 var timeNow = this.mouseInteractionSeconds / duration; |
| 17914 var size = waveRadius * (1 - Math.pow(80, -timeNow)); |
| 17915 |
| 17916 return Math.abs(size); |
| 17917 }, |
| 17918 |
| 17919 get opacity() { |
| 17920 if (!this.mouseUpStart) { |
| 17921 return this.initialOpacity; |
| 17922 } |
| 17923 |
| 17924 return Math.max( |
| 17925 0, |
| 17926 this.initialOpacity - this.mouseUpElapsedSeconds * this.opacityDecayVe
locity |
| 17927 ); |
| 17928 }, |
| 17929 |
| 17930 get outerOpacity() { |
| 17931 // Linear increase in background opacity, capped at the opacity |
| 17932 // of the wavefront (waveOpacity). |
| 17933 var outerOpacity = this.mouseUpElapsedSeconds * 0.3; |
| 17934 var waveOpacity = this.opacity; |
| 17935 |
| 17936 return Math.max( |
| 17937 0, |
| 17938 Math.min(outerOpacity, waveOpacity) |
| 17939 ); |
| 17940 }, |
| 17941 |
| 17942 get isOpacityFullyDecayed() { |
| 17943 return this.opacity < 0.01 && |
| 17944 this.radius >= Math.min(this.maxRadius, Ripple.MAX_RADIUS); |
| 17945 }, |
| 17946 |
| 17947 get isRestingAtMaxRadius() { |
| 17948 return this.opacity >= this.initialOpacity && |
| 17949 this.radius >= Math.min(this.maxRadius, Ripple.MAX_RADIUS); |
| 17950 }, |
| 17951 |
| 17952 get isAnimationComplete() { |
| 17953 return this.mouseUpStart ? |
| 17954 this.isOpacityFullyDecayed : this.isRestingAtMaxRadius; |
| 17955 }, |
| 17956 |
| 17957 get translationFraction() { |
| 17958 return Math.min( |
| 17959 1, |
| 17960 this.radius / this.containerMetrics.size * 2 / Math.sqrt(2) |
| 17961 ); |
| 17962 }, |
| 17963 |
| 17964 get xNow() { |
| 17965 if (this.xEnd) { |
| 17966 return this.xStart + this.translationFraction * (this.xEnd - this.xSta
rt); |
| 17967 } |
| 17968 |
| 17969 return this.xStart; |
| 17970 }, |
| 17971 |
| 17972 get yNow() { |
| 17973 if (this.yEnd) { |
| 17974 return this.yStart + this.translationFraction * (this.yEnd - this.ySta
rt); |
| 17975 } |
| 17976 |
| 17977 return this.yStart; |
| 17978 }, |
| 17979 |
| 17980 get isMouseDown() { |
| 17981 return this.mouseDownStart && !this.mouseUpStart; |
| 17982 }, |
| 17983 |
| 17984 resetInteractionState: function() { |
| 17985 this.maxRadius = 0; |
| 17986 this.mouseDownStart = 0; |
| 17987 this.mouseUpStart = 0; |
| 17988 |
| 17989 this.xStart = 0; |
| 17990 this.yStart = 0; |
| 17991 this.xEnd = 0; |
| 17992 this.yEnd = 0; |
| 17993 this.slideDistance = 0; |
| 17994 |
| 17995 this.containerMetrics = new ElementMetrics(this.element); |
| 17996 }, |
| 17997 |
| 17998 draw: function() { |
| 17999 var scale; |
| 18000 var translateString; |
| 18001 var dx; |
| 18002 var dy; |
| 18003 |
| 18004 this.wave.style.opacity = this.opacity; |
| 18005 |
| 18006 scale = this.radius / (this.containerMetrics.size / 2); |
| 18007 dx = this.xNow - (this.containerMetrics.width / 2); |
| 18008 dy = this.yNow - (this.containerMetrics.height / 2); |
| 18009 |
| 18010 |
| 18011 // 2d transform for safari because of border-radius and overflow:hidden
clipping bug. |
| 18012 // https://bugs.webkit.org/show_bug.cgi?id=98538 |
| 18013 this.waveContainer.style.webkitTransform = 'translate(' + dx + 'px, ' +
dy + 'px)'; |
| 18014 this.waveContainer.style.transform = 'translate3d(' + dx + 'px, ' + dy +
'px, 0)'; |
| 18015 this.wave.style.webkitTransform = 'scale(' + scale + ',' + scale + ')'; |
| 18016 this.wave.style.transform = 'scale3d(' + scale + ',' + scale + ',1)'; |
| 18017 }, |
| 18018 |
| 18019 /** @param {Event=} event */ |
| 18020 downAction: function(event) { |
| 18021 var xCenter = this.containerMetrics.width / 2; |
| 18022 var yCenter = this.containerMetrics.height / 2; |
| 18023 |
| 18024 this.resetInteractionState(); |
| 18025 this.mouseDownStart = Utility.now(); |
| 18026 |
| 18027 if (this.center) { |
| 18028 this.xStart = xCenter; |
| 18029 this.yStart = yCenter; |
| 18030 this.slideDistance = Utility.distance( |
| 18031 this.xStart, this.yStart, this.xEnd, this.yEnd |
| 18032 ); |
| 18033 } else { |
| 18034 this.xStart = event ? |
| 18035 event.detail.x - this.containerMetrics.boundingRect.left : |
| 18036 this.containerMetrics.width / 2; |
| 18037 this.yStart = event ? |
| 18038 event.detail.y - this.containerMetrics.boundingRect.top : |
| 18039 this.containerMetrics.height / 2; |
| 18040 } |
| 18041 |
| 18042 if (this.recenters) { |
| 18043 this.xEnd = xCenter; |
| 18044 this.yEnd = yCenter; |
| 18045 this.slideDistance = Utility.distance( |
| 18046 this.xStart, this.yStart, this.xEnd, this.yEnd |
| 18047 ); |
| 18048 } |
| 18049 |
| 18050 this.maxRadius = this.containerMetrics.furthestCornerDistanceFrom( |
| 18051 this.xStart, |
| 18052 this.yStart |
| 18053 ); |
| 18054 |
| 18055 this.waveContainer.style.top = |
| 18056 (this.containerMetrics.height - this.containerMetrics.size) / 2 + 'px'
; |
| 18057 this.waveContainer.style.left = |
| 18058 (this.containerMetrics.width - this.containerMetrics.size) / 2 + 'px'; |
| 18059 |
| 18060 this.waveContainer.style.width = this.containerMetrics.size + 'px'; |
| 18061 this.waveContainer.style.height = this.containerMetrics.size + 'px'; |
| 18062 }, |
| 18063 |
| 18064 /** @param {Event=} event */ |
| 18065 upAction: function(event) { |
| 18066 if (!this.isMouseDown) { |
| 18067 return; |
| 18068 } |
| 18069 |
| 18070 this.mouseUpStart = Utility.now(); |
| 18071 }, |
| 18072 |
| 18073 remove: function() { |
| 18074 Polymer.dom(this.waveContainer.parentNode).removeChild( |
| 18075 this.waveContainer |
| 18076 ); |
| 18077 } |
| 18078 }; |
| 18079 |
| 18080 Polymer({ |
| 18081 is: 'paper-ripple', |
| 18082 |
| 18083 behaviors: [ |
| 18084 Polymer.IronA11yKeysBehavior |
| 18085 ], |
| 18086 |
| 18087 properties: { |
| 18088 /** |
| 18089 * The initial opacity set on the wave. |
| 18090 * |
| 18091 * @attribute initialOpacity |
| 18092 * @type number |
| 18093 * @default 0.25 |
| 18094 */ |
| 18095 initialOpacity: { |
| 18096 type: Number, |
| 18097 value: 0.25 |
| 18098 }, |
| 18099 |
| 18100 /** |
| 18101 * How fast (opacity per second) the wave fades out. |
| 18102 * |
| 18103 * @attribute opacityDecayVelocity |
| 18104 * @type number |
| 18105 * @default 0.8 |
| 18106 */ |
| 18107 opacityDecayVelocity: { |
| 18108 type: Number, |
| 18109 value: 0.8 |
| 18110 }, |
| 18111 |
| 18112 /** |
| 18113 * If true, ripples will exhibit a gravitational pull towards |
| 18114 * the center of their container as they fade away. |
| 18115 * |
| 18116 * @attribute recenters |
| 18117 * @type boolean |
| 18118 * @default false |
| 18119 */ |
| 18120 recenters: { |
| 18121 type: Boolean, |
| 18122 value: false |
| 18123 }, |
| 18124 |
| 18125 /** |
| 18126 * If true, ripples will center inside its container |
| 18127 * |
| 18128 * @attribute recenters |
| 18129 * @type boolean |
| 18130 * @default false |
| 18131 */ |
| 18132 center: { |
| 18133 type: Boolean, |
| 18134 value: false |
| 18135 }, |
| 18136 |
| 18137 /** |
| 18138 * A list of the visual ripples. |
| 18139 * |
| 18140 * @attribute ripples |
| 18141 * @type Array |
| 18142 * @default [] |
| 18143 */ |
| 18144 ripples: { |
| 18145 type: Array, |
| 18146 value: function() { |
| 18147 return []; |
| 18148 } |
| 18149 }, |
| 18150 |
| 18151 /** |
| 18152 * True when there are visible ripples animating within the |
| 18153 * element. |
| 18154 */ |
| 18155 animating: { |
| 18156 type: Boolean, |
| 18157 readOnly: true, |
| 18158 reflectToAttribute: true, |
| 18159 value: false |
| 18160 }, |
| 18161 |
| 18162 /** |
| 18163 * If true, the ripple will remain in the "down" state until `holdDown` |
| 18164 * is set to false again. |
| 18165 */ |
| 18166 holdDown: { |
| 18167 type: Boolean, |
| 18168 value: false, |
| 18169 observer: '_holdDownChanged' |
| 18170 }, |
| 18171 |
| 18172 /** |
| 18173 * If true, the ripple will not generate a ripple effect |
| 18174 * via pointer interaction. |
| 18175 * Calling ripple's imperative api like `simulatedRipple` will |
| 18176 * still generate the ripple effect. |
| 18177 */ |
| 18178 noink: { |
| 18179 type: Boolean, |
| 18180 value: false |
| 18181 }, |
| 18182 |
| 18183 _animating: { |
| 18184 type: Boolean |
| 18185 }, |
| 18186 |
| 18187 _boundAnimate: { |
| 18188 type: Function, |
| 18189 value: function() { |
| 18190 return this.animate.bind(this); |
| 18191 } |
| 18192 } |
| 18193 }, |
| 18194 |
| 18195 get target () { |
| 18196 return this.keyEventTarget; |
| 18197 }, |
| 18198 |
| 18199 keyBindings: { |
| 18200 'enter:keydown': '_onEnterKeydown', |
| 18201 'space:keydown': '_onSpaceKeydown', |
| 18202 'space:keyup': '_onSpaceKeyup' |
| 18203 }, |
| 18204 |
| 18205 attached: function() { |
| 18206 // Set up a11yKeysBehavior to listen to key events on the target, |
| 18207 // so that space and enter activate the ripple even if the target doesn'
t |
| 18208 // handle key events. The key handlers deal with `noink` themselves. |
| 18209 if (this.parentNode.nodeType == 11) { // DOCUMENT_FRAGMENT_NODE |
| 18210 this.keyEventTarget = Polymer.dom(this).getOwnerRoot().host; |
| 18211 } else { |
| 18212 this.keyEventTarget = this.parentNode; |
| 18213 } |
| 18214 var keyEventTarget = /** @type {!EventTarget} */ (this.keyEventTarget); |
| 18215 this.listen(keyEventTarget, 'up', 'uiUpAction'); |
| 18216 this.listen(keyEventTarget, 'down', 'uiDownAction'); |
| 18217 }, |
| 18218 |
| 18219 detached: function() { |
| 18220 this.unlisten(this.keyEventTarget, 'up', 'uiUpAction'); |
| 18221 this.unlisten(this.keyEventTarget, 'down', 'uiDownAction'); |
| 18222 this.keyEventTarget = null; |
| 18223 }, |
| 18224 |
| 18225 get shouldKeepAnimating () { |
| 18226 for (var index = 0; index < this.ripples.length; ++index) { |
| 18227 if (!this.ripples[index].isAnimationComplete) { |
| 18228 return true; |
| 18229 } |
| 18230 } |
| 18231 |
| 18232 return false; |
| 18233 }, |
| 18234 |
| 18235 simulatedRipple: function() { |
| 18236 this.downAction(null); |
| 18237 |
| 18238 // Please see polymer/polymer#1305 |
| 18239 this.async(function() { |
| 18240 this.upAction(); |
| 18241 }, 1); |
| 18242 }, |
| 18243 |
| 18244 /** |
| 18245 * Provokes a ripple down effect via a UI event, |
| 18246 * respecting the `noink` property. |
| 18247 * @param {Event=} event |
| 18248 */ |
| 18249 uiDownAction: function(event) { |
| 18250 if (!this.noink) { |
| 18251 this.downAction(event); |
| 18252 } |
| 18253 }, |
| 18254 |
| 18255 /** |
| 18256 * Provokes a ripple down effect via a UI event, |
| 18257 * *not* respecting the `noink` property. |
| 18258 * @param {Event=} event |
| 18259 */ |
| 18260 downAction: function(event) { |
| 18261 if (this.holdDown && this.ripples.length > 0) { |
| 18262 return; |
| 18263 } |
| 18264 |
| 18265 var ripple = this.addRipple(); |
| 18266 |
| 18267 ripple.downAction(event); |
| 18268 |
| 18269 if (!this._animating) { |
| 18270 this._animating = true; |
| 18271 this.animate(); |
| 18272 } |
| 18273 }, |
| 18274 |
| 18275 /** |
| 18276 * Provokes a ripple up effect via a UI event, |
| 18277 * respecting the `noink` property. |
| 18278 * @param {Event=} event |
| 18279 */ |
| 18280 uiUpAction: function(event) { |
| 18281 if (!this.noink) { |
| 18282 this.upAction(event); |
| 18283 } |
| 18284 }, |
| 18285 |
| 18286 /** |
| 18287 * Provokes a ripple up effect via a UI event, |
| 18288 * *not* respecting the `noink` property. |
| 18289 * @param {Event=} event |
| 18290 */ |
| 18291 upAction: function(event) { |
| 18292 if (this.holdDown) { |
| 18293 return; |
| 18294 } |
| 18295 |
| 18296 this.ripples.forEach(function(ripple) { |
| 18297 ripple.upAction(event); |
| 18298 }); |
| 18299 |
| 18300 this._animating = true; |
| 18301 this.animate(); |
| 18302 }, |
| 18303 |
| 18304 onAnimationComplete: function() { |
| 18305 this._animating = false; |
| 18306 this.$.background.style.backgroundColor = null; |
| 18307 this.fire('transitionend'); |
| 18308 }, |
| 18309 |
| 18310 addRipple: function() { |
| 18311 var ripple = new Ripple(this); |
| 18312 |
| 18313 Polymer.dom(this.$.waves).appendChild(ripple.waveContainer); |
| 18314 this.$.background.style.backgroundColor = ripple.color; |
| 18315 this.ripples.push(ripple); |
| 18316 |
| 18317 this._setAnimating(true); |
| 18318 |
| 18319 return ripple; |
| 18320 }, |
| 18321 |
| 18322 removeRipple: function(ripple) { |
| 18323 var rippleIndex = this.ripples.indexOf(ripple); |
| 18324 |
| 18325 if (rippleIndex < 0) { |
| 18326 return; |
| 18327 } |
| 18328 |
| 18329 this.ripples.splice(rippleIndex, 1); |
| 18330 |
| 18331 ripple.remove(); |
| 18332 |
| 18333 if (!this.ripples.length) { |
| 18334 this._setAnimating(false); |
| 18335 } |
| 18336 }, |
| 18337 |
| 18338 animate: function() { |
| 18339 if (!this._animating) { |
| 18340 return; |
| 18341 } |
| 18342 var index; |
| 18343 var ripple; |
| 18344 |
| 18345 for (index = 0; index < this.ripples.length; ++index) { |
| 18346 ripple = this.ripples[index]; |
| 18347 |
| 18348 ripple.draw(); |
| 18349 |
| 18350 this.$.background.style.opacity = ripple.outerOpacity; |
| 18351 |
| 18352 if (ripple.isOpacityFullyDecayed && !ripple.isRestingAtMaxRadius) { |
| 18353 this.removeRipple(ripple); |
| 18354 } |
| 18355 } |
| 18356 |
| 18357 if (!this.shouldKeepAnimating && this.ripples.length === 0) { |
| 18358 this.onAnimationComplete(); |
| 18359 } else { |
| 18360 window.requestAnimationFrame(this._boundAnimate); |
| 18361 } |
| 18362 }, |
| 18363 |
| 18364 _onEnterKeydown: function() { |
| 18365 this.uiDownAction(); |
| 18366 this.async(this.uiUpAction, 1); |
| 18367 }, |
| 18368 |
| 18369 _onSpaceKeydown: function() { |
| 18370 this.uiDownAction(); |
| 18371 }, |
| 18372 |
| 18373 _onSpaceKeyup: function() { |
| 18374 this.uiUpAction(); |
| 18375 }, |
| 18376 |
| 18377 // note: holdDown does not respect noink since it can be a focus based |
| 18378 // effect. |
| 18379 _holdDownChanged: function(newVal, oldVal) { |
| 18380 if (oldVal === undefined) { |
| 18381 return; |
| 18382 } |
| 18383 if (newVal) { |
| 18384 this.downAction(); |
| 18385 } else { |
| 18386 this.upAction(); |
| 18387 } |
| 18388 } |
| 18389 |
| 18390 /** |
| 18391 Fired when the animation finishes. |
| 18392 This is useful if you want to wait until |
| 18393 the ripple animation finishes to perform some action. |
| 18394 |
| 18395 @event transitionend |
| 18396 @param {{node: Object}} detail Contains the animated node. |
| 18397 */ |
| 18398 }); |
| 18399 })(); |
| 18400 </script> |
| 18401 <script> |
| 18402 /** |
| 18403 * `Polymer.PaperRippleBehavior` dynamically implements a ripple |
| 18404 * when the element has focus via pointer or keyboard. |
| 18405 * |
| 18406 * NOTE: This behavior is intended to be used in conjunction with and after |
| 18407 * `Polymer.IronButtonState` and `Polymer.IronControlState`. |
| 18408 * |
| 18409 * @polymerBehavior Polymer.PaperRippleBehavior |
| 18410 */ |
| 18411 Polymer.PaperRippleBehavior = { |
| 18412 properties: { |
| 18413 /** |
| 18414 * If true, the element will not produce a ripple effect when interacted |
| 18415 * with via the pointer. |
| 18416 */ |
| 18417 noink: { |
| 18418 type: Boolean, |
| 18419 observer: '_noinkChanged' |
| 18420 }, |
| 18421 |
| 18422 /** |
| 18423 * @type {Element|undefined} |
| 18424 */ |
| 18425 _rippleContainer: { |
| 18426 type: Object, |
| 18427 } |
| 18428 }, |
| 18429 |
| 18430 /** |
| 18431 * Ensures a `<paper-ripple>` element is available when the element is |
| 18432 * focused. |
| 18433 */ |
| 18434 _buttonStateChanged: function() { |
| 18435 if (this.focused) { |
| 18436 this.ensureRipple(); |
| 18437 } |
| 18438 }, |
| 18439 |
| 18440 /** |
| 18441 * In addition to the functionality provided in `IronButtonState`, ensures |
| 18442 * a ripple effect is created when the element is in a `pressed` state. |
| 18443 */ |
| 18444 _downHandler: function(event) { |
| 18445 Polymer.IronButtonStateImpl._downHandler.call(this, event); |
| 18446 if (this.pressed) { |
| 18447 this.ensureRipple(event); |
| 18448 } |
| 18449 }, |
| 18450 |
| 18451 /** |
| 18452 * Ensures this element contains a ripple effect. For startup efficiency |
| 18453 * the ripple effect is dynamically on demand when needed. |
| 18454 * @param {!Event=} optTriggeringEvent (optional) event that triggered the |
| 18455 * ripple. |
| 18456 */ |
| 18457 ensureRipple: function(optTriggeringEvent) { |
| 18458 if (!this.hasRipple()) { |
| 18459 this._ripple = this._createRipple(); |
| 18460 this._ripple.noink = this.noink; |
| 18461 var rippleContainer = this._rippleContainer || this.root; |
| 18462 if (rippleContainer) { |
| 18463 Polymer.dom(rippleContainer).appendChild(this._ripple); |
| 18464 } |
| 18465 if (optTriggeringEvent) { |
| 18466 // Check if the event happened inside of the ripple container |
| 18467 // Fall back to host instead of the root because distributed text |
| 18468 // nodes are not valid event targets |
| 18469 var domContainer = Polymer.dom(this._rippleContainer || this); |
| 18470 var target = Polymer.dom(optTriggeringEvent).rootTarget; |
| 18471 if (domContainer.deepContains( /** @type {Node} */(target))) { |
| 18472 this._ripple.uiDownAction(optTriggeringEvent); |
| 18473 } |
| 18474 } |
| 18475 } |
| 18476 }, |
| 18477 |
| 18478 /** |
| 18479 * Returns the `<paper-ripple>` element used by this element to create |
| 18480 * ripple effects. The element's ripple is created on demand, when |
| 18481 * necessary, and calling this method will force the |
| 18482 * ripple to be created. |
| 18483 */ |
| 18484 getRipple: function() { |
| 18485 this.ensureRipple(); |
| 18486 return this._ripple; |
| 18487 }, |
| 18488 |
| 18489 /** |
| 18490 * Returns true if this element currently contains a ripple effect. |
| 18491 * @return {boolean} |
| 18492 */ |
| 18493 hasRipple: function() { |
| 18494 return Boolean(this._ripple); |
| 18495 }, |
| 18496 |
| 18497 /** |
| 18498 * Create the element's ripple effect via creating a `<paper-ripple>`. |
| 18499 * Override this method to customize the ripple element. |
| 18500 * @return {!PaperRippleElement} Returns a `<paper-ripple>` element. |
| 18501 */ |
| 18502 _createRipple: function() { |
| 18503 return /** @type {!PaperRippleElement} */ ( |
| 18504 document.createElement('paper-ripple')); |
| 18505 }, |
| 18506 |
| 18507 _noinkChanged: function(noink) { |
| 18508 if (this.hasRipple()) { |
| 18509 this._ripple.noink = noink; |
| 18510 } |
| 18511 } |
| 18512 }; |
| 18513 </script> |
| 18514 <script> |
| 18515 /** |
| 18516 * `Polymer.PaperInkyFocusBehavior` implements a ripple when the element has k
eyboard focus. |
| 18517 * |
| 18518 * @polymerBehavior Polymer.PaperInkyFocusBehavior |
| 18519 */ |
| 18520 Polymer.PaperInkyFocusBehaviorImpl = { |
| 18521 observers: [ |
| 18522 '_focusedChanged(receivedFocusFromKeyboard)' |
| 18523 ], |
| 18524 |
| 18525 _focusedChanged: function(receivedFocusFromKeyboard) { |
| 18526 if (receivedFocusFromKeyboard) { |
| 18527 this.ensureRipple(); |
| 18528 } |
| 18529 if (this.hasRipple()) { |
| 18530 this._ripple.holdDown = receivedFocusFromKeyboard; |
| 18531 } |
| 18532 }, |
| 18533 |
| 18534 _createRipple: function() { |
| 18535 var ripple = Polymer.PaperRippleBehavior._createRipple(); |
| 18536 ripple.id = 'ink'; |
| 18537 ripple.setAttribute('center', ''); |
| 18538 ripple.classList.add('circle'); |
| 18539 return ripple; |
| 18540 } |
| 18541 }; |
| 18542 |
| 18543 /** @polymerBehavior Polymer.PaperInkyFocusBehavior */ |
| 18544 Polymer.PaperInkyFocusBehavior = [ |
| 18545 Polymer.IronButtonState, |
| 18546 Polymer.IronControlState, |
| 18547 Polymer.PaperRippleBehavior, |
| 18548 Polymer.PaperInkyFocusBehaviorImpl |
| 18549 ]; |
| 18550 </script> |
| 18551 <script> |
| 18552 /** |
| 18553 * Use `Polymer.PaperCheckedElementBehavior` to implement a custom element |
| 18554 * that has a `checked` property similar to `Polymer.IronCheckedElementBehavio
r` |
| 18555 * and is compatible with having a ripple effect. |
| 18556 * @polymerBehavior Polymer.PaperCheckedElementBehavior |
| 18557 */ |
| 18558 Polymer.PaperCheckedElementBehaviorImpl = { |
| 18559 /** |
| 18560 * Synchronizes the element's checked state with its ripple effect. |
| 18561 */ |
| 18562 _checkedChanged: function() { |
| 18563 Polymer.IronCheckedElementBehaviorImpl._checkedChanged.call(this); |
| 18564 if (this.hasRipple()) { |
| 18565 if (this.checked) { |
| 18566 this._ripple.setAttribute('checked', ''); |
| 18567 } else { |
| 18568 this._ripple.removeAttribute('checked'); |
| 18569 } |
| 18570 } |
| 18571 }, |
| 18572 |
| 18573 /** |
| 18574 * Synchronizes the element's `active` and `checked` state. |
| 18575 */ |
| 18576 _buttonStateChanged: function() { |
| 18577 Polymer.PaperRippleBehavior._buttonStateChanged.call(this); |
| 18578 if (this.disabled) { |
| 18579 return; |
| 18580 } |
| 18581 if (this.isAttached) { |
| 18582 this.checked = this.active; |
| 18583 } |
| 18584 } |
| 18585 }; |
| 18586 |
| 18587 /** @polymerBehavior Polymer.PaperCheckedElementBehavior */ |
| 18588 Polymer.PaperCheckedElementBehavior = [ |
| 18589 Polymer.PaperInkyFocusBehavior, |
| 18590 Polymer.IronCheckedElementBehavior, |
| 18591 Polymer.PaperCheckedElementBehaviorImpl |
| 18592 ]; |
| 18593 </script> |
| 18594 |
| 18595 |
| 18596 <dom-module id="paper-checkbox" assetpath="/res/imp/bower_components/paper-check
box/"> |
| 18597 <template strip-whitespace=""> |
| 18598 <style> |
| 18599 :host { |
| 18600 display: inline-block; |
| 18601 white-space: nowrap; |
| 18602 cursor: pointer; |
| 18603 --calculated-paper-checkbox-size: var(--paper-checkbox-size, 18px); |
| 18604 @apply(--paper-font-common-base); |
| 18605 line-height: 0; |
| 18606 -webkit-tap-highlight-color: transparent; |
| 18607 } |
| 18608 |
| 18609 :host([hidden]) { |
| 18610 display: none !important; |
| 18611 } |
| 18612 |
| 18613 :host(:focus) { |
| 18614 outline: none; |
| 18615 } |
| 18616 |
| 18617 .hidden { |
| 18618 display: none; |
| 18619 } |
| 18620 |
| 18621 #checkboxContainer { |
| 18622 display: inline-block; |
| 18623 position: relative; |
| 18624 width: var(--calculated-paper-checkbox-size); |
| 18625 height: var(--calculated-paper-checkbox-size); |
| 18626 min-width: var(--calculated-paper-checkbox-size); |
| 18627 margin: var(--paper-checkbox-margin, initial); |
| 18628 vertical-align: var(--paper-checkbox-vertical-align, middle); |
| 18629 background-color: var(--paper-checkbox-unchecked-background-color, trans
parent); |
| 18630 } |
| 18631 |
| 18632 #ink { |
| 18633 position: absolute; |
| 18634 |
| 18635 /* Center the ripple in the checkbox by negative offsetting it by |
| 18636 * (inkWidth - rippleWidth) / 2 */ |
| 18637 top: calc(0px - (2.66 * var(--calculated-paper-checkbox-size) - var(--ca
lculated-paper-checkbox-size)) / 2); |
| 18638 left: calc(0px - (2.66 * var(--calculated-paper-checkbox-size) - var(--c
alculated-paper-checkbox-size)) / 2); |
| 18639 width: calc(2.66 * var(--calculated-paper-checkbox-size)); |
| 18640 height: calc(2.66 * var(--calculated-paper-checkbox-size)); |
| 18641 color: var(--paper-checkbox-unchecked-ink-color, --primary-text-color); |
| 18642 opacity: 0.6; |
| 18643 pointer-events: none; |
| 18644 } |
| 18645 |
| 18646 :host-context([dir="rtl"]) #ink { |
| 18647 right: calc(0px - (2.66 * var(--calculated-paper-checkbox-size) - var(--
calculated-paper-checkbox-size)) / 2); |
| 18648 left: auto; |
| 18649 } |
| 18650 |
| 18651 #ink[checked] { |
| 18652 color: var(--paper-checkbox-checked-ink-color, --primary-color); |
| 18653 } |
| 18654 |
| 18655 #checkbox { |
| 18656 position: relative; |
| 18657 box-sizing: border-box; |
| 18658 height: 100%; |
| 18659 border: solid 2px; |
| 18660 border-color: var(--paper-checkbox-unchecked-color, --primary-text-color
); |
| 18661 border-radius: 2px; |
| 18662 pointer-events: none; |
| 18663 -webkit-transition: background-color 140ms, border-color 140ms; |
| 18664 transition: background-color 140ms, border-color 140ms; |
| 18665 } |
| 18666 |
| 18667 /* checkbox checked animations */ |
| 18668 #checkbox.checked #checkmark { |
| 18669 -webkit-animation: checkmark-expand 140ms ease-out forwards; |
| 18670 animation: checkmark-expand 140ms ease-out forwards; |
| 18671 } |
| 18672 |
| 18673 @-webkit-keyframes checkmark-expand { |
| 18674 0% { |
| 18675 -webkit-transform: scale(0, 0) rotate(45deg); |
| 18676 } |
| 18677 100% { |
| 18678 -webkit-transform: scale(1, 1) rotate(45deg); |
| 18679 } |
| 18680 } |
| 18681 |
| 18682 @keyframes checkmark-expand { |
| 18683 0% { |
| 18684 transform: scale(0, 0) rotate(45deg); |
| 18685 } |
| 18686 100% { |
| 18687 transform: scale(1, 1) rotate(45deg); |
| 18688 } |
| 18689 } |
| 18690 |
| 18691 #checkbox.checked { |
| 18692 background-color: var(--paper-checkbox-checked-color, --primary-color); |
| 18693 border-color: var(--paper-checkbox-checked-color, --primary-color); |
| 18694 } |
| 18695 |
| 18696 #checkmark { |
| 18697 position: absolute; |
| 18698 width: 36%; |
| 18699 height: 70%; |
| 18700 border-style: solid; |
| 18701 border-top: none; |
| 18702 border-left: none; |
| 18703 border-right-width: calc(2/15 * var(--calculated-paper-checkbox-size)); |
| 18704 border-bottom-width: calc(2/15 * var(--calculated-paper-checkbox-size)); |
| 18705 border-color: var(--paper-checkbox-checkmark-color, white); |
| 18706 -webkit-transform-origin: 97% 86%; |
| 18707 transform-origin: 97% 86%; |
| 18708 box-sizing: content-box; /* protect against page-level box-sizing */ |
| 18709 } |
| 18710 |
| 18711 :host-context([dir="rtl"]) #checkmark { |
| 18712 -webkit-transform-origin: 50% 14%; |
| 18713 transform-origin: 50% 14%; |
| 18714 } |
| 18715 |
| 18716 /* label */ |
| 18717 #checkboxLabel { |
| 18718 position: relative; |
| 18719 display: inline-block; |
| 18720 vertical-align: middle; |
| 18721 padding-left: var(--paper-checkbox-label-spacing, 8px); |
| 18722 white-space: normal; |
| 18723 line-height: normal; |
| 18724 color: var(--paper-checkbox-label-color, --primary-text-color); |
| 18725 @apply(--paper-checkbox-label); |
| 18726 } |
| 18727 |
| 18728 :host([checked]) #checkboxLabel { |
| 18729 color: var(--paper-checkbox-label-checked-color, --paper-checkbox-label-
color); |
| 18730 @apply(--paper-checkbox-label-checked); |
| 18731 } |
| 18732 |
| 18733 :host-context([dir="rtl"]) #checkboxLabel { |
| 18734 padding-right: var(--paper-checkbox-label-spacing, 8px); |
| 18735 padding-left: 0; |
| 18736 } |
| 18737 |
| 18738 #checkboxLabel[hidden] { |
| 18739 display: none; |
| 18740 } |
| 18741 |
| 18742 /* disabled state */ |
| 18743 |
| 18744 :host([disabled]) #checkbox { |
| 18745 opacity: 0.5; |
| 18746 border-color: var(--paper-checkbox-unchecked-color, --primary-text-color
); |
| 18747 } |
| 18748 |
| 18749 :host([disabled][checked]) #checkbox { |
| 18750 background-color: var(--paper-checkbox-unchecked-color, --primary-text-c
olor); |
| 18751 opacity: 0.5; |
| 18752 } |
| 18753 |
| 18754 :host([disabled]) #checkboxLabel { |
| 18755 opacity: 0.65; |
| 18756 } |
| 18757 |
| 18758 /* invalid state */ |
| 18759 #checkbox.invalid:not(.checked) { |
| 18760 border-color: var(--paper-checkbox-error-color, --error-color); |
| 18761 } |
| 18762 </style> |
| 18763 |
| 18764 <div id="checkboxContainer"> |
| 18765 <div id="checkbox" class$="[[_computeCheckboxClass(checked, invalid)]]"> |
| 18766 <div id="checkmark" class$="[[_computeCheckmarkClass(checked)]]"></div> |
| 18767 </div> |
| 18768 </div> |
| 18769 |
| 18770 <div id="checkboxLabel"><content></content></div> |
| 18771 </template> |
| 18772 |
| 18773 <script> |
| 18774 Polymer({ |
| 18775 is: 'paper-checkbox', |
| 18776 |
| 18777 behaviors: [ |
| 18778 Polymer.PaperCheckedElementBehavior |
| 18779 ], |
| 18780 |
| 18781 hostAttributes: { |
| 18782 role: 'checkbox', |
| 18783 'aria-checked': false, |
| 18784 tabindex: 0 |
| 18785 }, |
| 18786 |
| 18787 properties: { |
| 18788 /** |
| 18789 * Fired when the checked state changes due to user interaction. |
| 18790 * |
| 18791 * @event change |
| 18792 */ |
| 18793 |
| 18794 /** |
| 18795 * Fired when the checked state changes. |
| 18796 * |
| 18797 * @event iron-change |
| 18798 */ |
| 18799 ariaActiveAttribute: { |
| 18800 type: String, |
| 18801 value: 'aria-checked' |
| 18802 } |
| 18803 }, |
| 18804 |
| 18805 _computeCheckboxClass: function(checked, invalid) { |
| 18806 var className = ''; |
| 18807 if (checked) { |
| 18808 className += 'checked '; |
| 18809 } |
| 18810 if (invalid) { |
| 18811 className += 'invalid'; |
| 18812 } |
| 18813 return className; |
| 18814 }, |
| 18815 |
| 18816 _computeCheckmarkClass: function(checked) { |
| 18817 return checked ? '' : 'hidden'; |
| 18818 }, |
| 18819 |
| 18820 // create ripple inside the checkboxContainer |
| 18821 _createRipple: function() { |
| 18822 this._rippleContainer = this.$.checkboxContainer; |
| 18823 return Polymer.PaperInkyFocusBehaviorImpl._createRipple.call(this); |
| 18824 } |
| 18825 |
| 18826 }); |
| 18827 </script> |
| 18828 </dom-module> |
| 18829 |
| 18830 |
| 18831 <dom-module id="paper-icon-button" assetpath="/res/imp/bower_components/paper-ic
on-button/"> |
| 18832 <template strip-whitespace=""> |
| 18833 <style> |
| 18834 :host { |
| 18835 display: inline-block; |
| 18836 position: relative; |
| 18837 padding: 8px; |
| 18838 outline: none; |
| 18839 -webkit-user-select: none; |
| 18840 -moz-user-select: none; |
| 18841 -ms-user-select: none; |
| 18842 user-select: none; |
| 18843 cursor: pointer; |
| 18844 z-index: 0; |
| 18845 line-height: 1; |
| 18846 |
| 18847 width: 40px; |
| 18848 height: 40px; |
| 18849 |
| 18850 /* NOTE: Both values are needed, since some phones require the value to
be `transparent`. */ |
| 18851 -webkit-tap-highlight-color: rgba(0, 0, 0, 0); |
| 18852 -webkit-tap-highlight-color: transparent; |
| 18853 |
| 18854 /* Because of polymer/2558, this style has lower specificity than * */ |
| 18855 box-sizing: border-box !important; |
| 18856 |
| 18857 @apply(--paper-icon-button); |
| 18858 } |
| 18859 |
| 18860 :host #ink { |
| 18861 color: var(--paper-icon-button-ink-color, --primary-text-color); |
| 18862 opacity: 0.6; |
| 18863 } |
| 18864 |
| 18865 :host([disabled]) { |
| 18866 color: var(--paper-icon-button-disabled-text, --disabled-text-color); |
| 18867 pointer-events: none; |
| 18868 cursor: auto; |
| 18869 |
| 18870 @apply(--paper-icon-button-disabled); |
| 18871 } |
| 18872 |
| 18873 :host(:hover) { |
| 18874 @apply(--paper-icon-button-hover); |
| 18875 } |
| 18876 |
| 18877 iron-icon { |
| 18878 --iron-icon-width: 100%; |
| 18879 --iron-icon-height: 100%; |
| 18880 } |
| 18881 </style> |
| 18882 |
| 18883 <iron-icon id="icon" src="[[src]]" icon="[[icon]]" alt$="[[alt]]"></iron-ico
n> |
| 18884 </template> |
| 18885 |
| 18886 <script> |
| 18887 Polymer({ |
| 18888 is: 'paper-icon-button', |
| 18889 |
| 18890 hostAttributes: { |
| 18891 role: 'button', |
| 18892 tabindex: '0' |
| 18893 }, |
| 18894 |
| 18895 behaviors: [ |
| 18896 Polymer.PaperInkyFocusBehavior |
| 18897 ], |
| 18898 |
| 18899 properties: { |
| 18900 /** |
| 18901 * The URL of an image for the icon. If the src property is specified, |
| 18902 * the icon property should not be. |
| 18903 */ |
| 18904 src: { |
| 18905 type: String |
| 18906 }, |
| 18907 |
| 18908 /** |
| 18909 * Specifies the icon name or index in the set of icons available in |
| 18910 * the icon's icon set. If the icon property is specified, |
| 18911 * the src property should not be. |
| 18912 */ |
| 18913 icon: { |
| 18914 type: String |
| 18915 }, |
| 18916 |
| 18917 /** |
| 18918 * Specifies the alternate text for the button, for accessibility. |
| 18919 */ |
| 18920 alt: { |
| 18921 type: String, |
| 18922 observer: "_altChanged" |
| 18923 } |
| 18924 }, |
| 18925 |
| 18926 _altChanged: function(newValue, oldValue) { |
| 18927 var label = this.getAttribute('aria-label'); |
| 18928 |
| 18929 // Don't stomp over a user-set aria-label. |
| 18930 if (!label || oldValue == label) { |
| 18931 this.setAttribute('aria-label', newValue); |
| 18932 } |
| 18933 } |
| 18934 }); |
| 18935 </script> |
| 18936 </dom-module> |
| 18937 |
| 18938 |
| 18939 <dom-module id="iron-a11y-announcer" assetpath="/res/imp/bower_components/iron-a
11y-announcer/"> |
| 18940 <template> |
| 18941 <style> |
| 18942 :host { |
| 18943 display: inline-block; |
| 18944 position: fixed; |
| 18945 clip: rect(0px,0px,0px,0px); |
| 18946 } |
| 18947 </style> |
| 18948 <div aria-live$="[[mode]]">[[_text]]</div> |
| 18949 </template> |
| 18950 |
| 18951 <script> |
| 18952 |
| 18953 (function() { |
| 18954 'use strict'; |
| 18955 |
| 18956 Polymer.IronA11yAnnouncer = Polymer({ |
| 18957 is: 'iron-a11y-announcer', |
| 18958 |
| 18959 properties: { |
| 18960 |
| 18961 /** |
| 18962 * The value of mode is used to set the `aria-live` attribute |
| 18963 * for the element that will be announced. Valid values are: `off`, |
| 18964 * `polite` and `assertive`. |
| 18965 */ |
| 18966 mode: { |
| 18967 type: String, |
| 18968 value: 'polite' |
| 18969 }, |
| 18970 |
| 18971 _text: { |
| 18972 type: String, |
| 18973 value: '' |
| 18974 } |
| 18975 }, |
| 18976 |
| 18977 created: function() { |
| 18978 if (!Polymer.IronA11yAnnouncer.instance) { |
| 18979 Polymer.IronA11yAnnouncer.instance = this; |
| 18980 } |
| 18981 |
| 18982 document.body.addEventListener('iron-announce', this._onIronAnnounce.b
ind(this)); |
| 18983 }, |
| 18984 |
| 18985 /** |
| 18986 * Cause a text string to be announced by screen readers. |
| 18987 * |
| 18988 * @param {string} text The text that should be announced. |
| 18989 */ |
| 18990 announce: function(text) { |
| 18991 this._text = ''; |
| 18992 this.async(function() { |
| 18993 this._text = text; |
| 18994 }, 100); |
| 18995 }, |
| 18996 |
| 18997 _onIronAnnounce: function(event) { |
| 18998 if (event.detail && event.detail.text) { |
| 18999 this.announce(event.detail.text); |
| 19000 } |
| 19001 } |
| 19002 }); |
| 19003 |
| 19004 Polymer.IronA11yAnnouncer.instance = null; |
| 19005 |
| 19006 Polymer.IronA11yAnnouncer.requestAvailability = function() { |
| 19007 if (!Polymer.IronA11yAnnouncer.instance) { |
| 19008 Polymer.IronA11yAnnouncer.instance = document.createElement('iron-a11y
-announcer'); |
| 19009 } |
| 19010 |
| 19011 document.body.appendChild(Polymer.IronA11yAnnouncer.instance); |
| 19012 }; |
| 19013 })(); |
| 19014 |
| 19015 </script> |
| 19016 </dom-module> |
| 19017 <script> |
| 19018 |
| 19019 /* |
| 19020 `<iron-input>` adds two-way binding and custom validators using `Polymer.IronVal
idatorBehavior` |
| 19021 to `<input>`. |
| 19022 |
| 19023 ### Two-way binding |
| 19024 |
| 19025 By default you can only get notified of changes to an `input`'s `value` due to u
ser input: |
| 19026 |
| 19027 <input value="{{myValue::input}}"> |
| 19028 |
| 19029 `iron-input` adds the `bind-value` property that mirrors the `value` property, a
nd can be used |
| 19030 for two-way data binding. `bind-value` will notify if it is changed either by us
er input or by script. |
| 19031 |
| 19032 <input is="iron-input" bind-value="{{myValue}}"> |
| 19033 |
| 19034 ### Custom validators |
| 19035 |
| 19036 You can use custom validators that implement `Polymer.IronValidatorBehavior` wit
h `<iron-input>`. |
| 19037 |
| 19038 <input is="iron-input" validator="my-custom-validator"> |
| 19039 |
| 19040 ### Stopping invalid input |
| 19041 |
| 19042 It may be desirable to only allow users to enter certain characters. You can use
the |
| 19043 `prevent-invalid-input` and `allowed-pattern` attributes together to accomplish
this. This feature |
| 19044 is separate from validation, and `allowed-pattern` does not affect how the input
is validated. |
| 19045 |
| 19046 <!-- only allow characters that match [0-9] --> |
| 19047 <input is="iron-input" prevent-invalid-input allowed-pattern="[0-9]"> |
| 19048 |
| 19049 @hero hero.svg |
| 19050 @demo demo/index.html |
| 19051 */ |
| 19052 |
| 19053 Polymer({ |
| 19054 |
| 19055 is: 'iron-input', |
| 19056 |
| 19057 extends: 'input', |
| 19058 |
| 19059 behaviors: [ |
| 19060 Polymer.IronValidatableBehavior |
| 19061 ], |
| 19062 |
| 19063 properties: { |
| 19064 |
| 19065 /** |
| 19066 * Use this property instead of `value` for two-way data binding. |
| 19067 */ |
| 19068 bindValue: { |
| 19069 observer: '_bindValueChanged', |
| 19070 type: String |
| 19071 }, |
| 19072 |
| 19073 /** |
| 19074 * Set to true to prevent the user from entering invalid input. If `allowe
dPattern` is set, |
| 19075 * any character typed by the user will be matched against that pattern, a
nd rejected if it's not a match. |
| 19076 * Pasted input will have each character checked individually; if any char
acter |
| 19077 * doesn't match `allowedPattern`, the entire pasted string will be reject
ed. |
| 19078 * If `allowedPattern` is not set, it will use the `type` attribute (only
supported for `type=number`). |
| 19079 */ |
| 19080 preventInvalidInput: { |
| 19081 type: Boolean |
| 19082 }, |
| 19083 |
| 19084 /** |
| 19085 * Regular expression that list the characters allowed as input. |
| 19086 * This pattern represents the allowed characters for the field; as the us
er inputs text, |
| 19087 * each individual character will be checked against the pattern (rather t
han checking |
| 19088 * the entire value as a whole). The recommended format should be a list o
f allowed characters; |
| 19089 * for example, `[a-zA-Z0-9.+-!;:]` |
| 19090 */ |
| 19091 allowedPattern: { |
| 19092 type: String, |
| 19093 observer: "_allowedPatternChanged" |
| 19094 }, |
| 19095 |
| 19096 _previousValidInput: { |
| 19097 type: String, |
| 19098 value: '' |
| 19099 }, |
| 19100 |
| 19101 _patternAlreadyChecked: { |
| 19102 type: Boolean, |
| 19103 value: false |
| 19104 } |
| 19105 |
| 19106 }, |
| 19107 |
| 19108 listeners: { |
| 19109 'input': '_onInput', |
| 19110 'keypress': '_onKeypress' |
| 19111 }, |
| 19112 |
| 19113 /** @suppress {checkTypes} */ |
| 19114 registered: function() { |
| 19115 // Feature detect whether we need to patch dispatchEvent (i.e. on FF and I
E). |
| 19116 if (!this._canDispatchEventOnDisabled()) { |
| 19117 this._origDispatchEvent = this.dispatchEvent; |
| 19118 this.dispatchEvent = this._dispatchEventFirefoxIE; |
| 19119 } |
| 19120 }, |
| 19121 |
| 19122 created: function() { |
| 19123 Polymer.IronA11yAnnouncer.requestAvailability(); |
| 19124 }, |
| 19125 |
| 19126 _canDispatchEventOnDisabled: function() { |
| 19127 var input = document.createElement('input'); |
| 19128 var canDispatch = false; |
| 19129 input.disabled = true; |
| 19130 |
| 19131 input.addEventListener('feature-check-dispatch-event', function() { |
| 19132 canDispatch = true; |
| 19133 }); |
| 19134 |
| 19135 try { |
| 19136 input.dispatchEvent(new Event('feature-check-dispatch-event')); |
| 19137 } catch(e) {} |
| 19138 |
| 19139 return canDispatch; |
| 19140 }, |
| 19141 |
| 19142 _dispatchEventFirefoxIE: function() { |
| 19143 // Due to Firefox bug, events fired on disabled form controls can throw |
| 19144 // errors; furthermore, neither IE nor Firefox will actually dispatch |
| 19145 // events from disabled form controls; as such, we toggle disable around |
| 19146 // the dispatch to allow notifying properties to notify |
| 19147 // See issue #47 for details |
| 19148 var disabled = this.disabled; |
| 19149 this.disabled = false; |
| 19150 this._origDispatchEvent.apply(this, arguments); |
| 19151 this.disabled = disabled; |
| 19152 }, |
| 19153 |
| 19154 get _patternRegExp() { |
| 19155 var pattern; |
| 19156 if (this.allowedPattern) { |
| 19157 pattern = new RegExp(this.allowedPattern); |
| 19158 } else { |
| 19159 switch (this.type) { |
| 19160 case 'number': |
| 19161 pattern = /[0-9.,e-]/; |
| 19162 break; |
| 19163 } |
| 19164 } |
| 19165 return pattern; |
| 19166 }, |
| 19167 |
| 19168 ready: function() { |
| 19169 this.bindValue = this.value; |
| 19170 }, |
| 19171 |
| 19172 /** |
| 19173 * @suppress {checkTypes} |
| 19174 */ |
| 19175 _bindValueChanged: function() { |
| 19176 if (this.value !== this.bindValue) { |
| 19177 this.value = !(this.bindValue || this.bindValue === 0 || this.bindValue
=== false) ? '' : this.bindValue; |
| 19178 } |
| 19179 // manually notify because we don't want to notify until after setting val
ue |
| 19180 this.fire('bind-value-changed', {value: this.bindValue}); |
| 19181 }, |
| 19182 |
| 19183 _allowedPatternChanged: function() { |
| 19184 // Force to prevent invalid input when an `allowed-pattern` is set |
| 19185 this.preventInvalidInput = this.allowedPattern ? true : false; |
| 19186 }, |
| 19187 |
| 19188 _onInput: function() { |
| 19189 // Need to validate each of the characters pasted if they haven't |
| 19190 // been validated inside `_onKeypress` already. |
| 19191 if (this.preventInvalidInput && !this._patternAlreadyChecked) { |
| 19192 var valid = this._checkPatternValidity(); |
| 19193 if (!valid) { |
| 19194 this._announceInvalidCharacter('Invalid string of characters not enter
ed.'); |
| 19195 this.value = this._previousValidInput; |
| 19196 } |
| 19197 } |
| 19198 |
| 19199 this.bindValue = this.value; |
| 19200 this._previousValidInput = this.value; |
| 19201 this._patternAlreadyChecked = false; |
| 19202 }, |
| 19203 |
| 19204 _isPrintable: function(event) { |
| 19205 // What a control/printable character is varies wildly based on the browse
r. |
| 19206 // - most control characters (arrows, backspace) do not send a `keypress`
event |
| 19207 // in Chrome, but the *do* on Firefox |
| 19208 // - in Firefox, when they do send a `keypress` event, control chars have |
| 19209 // a charCode = 0, keyCode = xx (for ex. 40 for down arrow) |
| 19210 // - printable characters always send a keypress event. |
| 19211 // - in Firefox, printable chars always have a keyCode = 0. In Chrome, the
keyCode |
| 19212 // always matches the charCode. |
| 19213 // None of this makes any sense. |
| 19214 |
| 19215 // For these keys, ASCII code == browser keycode. |
| 19216 var anyNonPrintable = |
| 19217 (event.keyCode == 8) || // backspace |
| 19218 (event.keyCode == 9) || // tab |
| 19219 (event.keyCode == 13) || // enter |
| 19220 (event.keyCode == 27); // escape |
| 19221 |
| 19222 // For these keys, make sure it's a browser keycode and not an ASCII code. |
| 19223 var mozNonPrintable = |
| 19224 (event.keyCode == 19) || // pause |
| 19225 (event.keyCode == 20) || // caps lock |
| 19226 (event.keyCode == 45) || // insert |
| 19227 (event.keyCode == 46) || // delete |
| 19228 (event.keyCode == 144) || // num lock |
| 19229 (event.keyCode == 145) || // scroll lock |
| 19230 (event.keyCode > 32 && event.keyCode < 41) || // page up/down, end, ho
me, arrows |
| 19231 (event.keyCode > 111 && event.keyCode < 124); // fn keys |
| 19232 |
| 19233 return !anyNonPrintable && !(event.charCode == 0 && mozNonPrintable); |
| 19234 }, |
| 19235 |
| 19236 _onKeypress: function(event) { |
| 19237 if (!this.preventInvalidInput && this.type !== 'number') { |
| 19238 return; |
| 19239 } |
| 19240 var regexp = this._patternRegExp; |
| 19241 if (!regexp) { |
| 19242 return; |
| 19243 } |
| 19244 |
| 19245 // Handle special keys and backspace |
| 19246 if (event.metaKey || event.ctrlKey || event.altKey) |
| 19247 return; |
| 19248 |
| 19249 // Check the pattern either here or in `_onInput`, but not in both. |
| 19250 this._patternAlreadyChecked = true; |
| 19251 |
| 19252 var thisChar = String.fromCharCode(event.charCode); |
| 19253 if (this._isPrintable(event) && !regexp.test(thisChar)) { |
| 19254 event.preventDefault(); |
| 19255 this._announceInvalidCharacter('Invalid character ' + thisChar + ' not e
ntered.'); |
| 19256 } |
| 19257 }, |
| 19258 |
| 19259 _checkPatternValidity: function() { |
| 19260 var regexp = this._patternRegExp; |
| 19261 if (!regexp) { |
| 19262 return true; |
| 19263 } |
| 19264 for (var i = 0; i < this.value.length; i++) { |
| 19265 if (!regexp.test(this.value[i])) { |
| 19266 return false; |
| 19267 } |
| 19268 } |
| 19269 return true; |
| 19270 }, |
| 19271 |
| 19272 /** |
| 19273 * Returns true if `value` is valid. The validator provided in `validator` w
ill be used first, |
| 19274 * then any constraints. |
| 19275 * @return {boolean} True if the value is valid. |
| 19276 */ |
| 19277 validate: function() { |
| 19278 // First, check what the browser thinks. Some inputs (like type=number) |
| 19279 // behave weirdly and will set the value to "" if something invalid is |
| 19280 // entered, but will set the validity correctly. |
| 19281 var valid = this.checkValidity(); |
| 19282 |
| 19283 // Only do extra checking if the browser thought this was valid. |
| 19284 if (valid) { |
| 19285 // Empty, required input is invalid |
| 19286 if (this.required && this.value === '') { |
| 19287 valid = false; |
| 19288 } else if (this.hasValidator()) { |
| 19289 valid = Polymer.IronValidatableBehavior.validate.call(this, this.value
); |
| 19290 } |
| 19291 } |
| 19292 |
| 19293 this.invalid = !valid; |
| 19294 this.fire('iron-input-validate'); |
| 19295 return valid; |
| 19296 }, |
| 19297 |
| 19298 _announceInvalidCharacter: function(message) { |
| 19299 this.fire('iron-announce', { text: message }); |
| 19300 } |
| 19301 }); |
| 19302 |
| 19303 /* |
| 19304 The `iron-input-validate` event is fired whenever `validate()` is called. |
| 19305 @event iron-input-validate |
| 19306 */ |
| 19307 |
| 19308 </script> |
| 19309 <script> |
| 19310 |
| 19311 // Generate unique, monotonically increasing IDs for labels (needed by |
| 19312 // aria-labelledby) and add-ons. |
| 19313 Polymer.PaperInputHelper = {}; |
| 19314 Polymer.PaperInputHelper.NextLabelID = 1; |
| 19315 Polymer.PaperInputHelper.NextAddonID = 1; |
| 19316 |
| 19317 /** |
| 19318 * Use `Polymer.PaperInputBehavior` to implement inputs with `<paper-input-con
tainer>`. This |
| 19319 * behavior is implemented by `<paper-input>`. It exposes a number of properti
es from |
| 19320 * `<paper-input-container>` and `<input is="iron-input">` and they should be
bound in your |
| 19321 * template. |
| 19322 * |
| 19323 * The input element can be accessed by the `inputElement` property if you nee
d to access |
| 19324 * properties or methods that are not exposed. |
| 19325 * @polymerBehavior Polymer.PaperInputBehavior |
| 19326 */ |
| 19327 Polymer.PaperInputBehaviorImpl = { |
| 19328 |
| 19329 properties: { |
| 19330 /** |
| 19331 * Fired when the input changes due to user interaction. |
| 19332 * |
| 19333 * @event change |
| 19334 */ |
| 19335 |
| 19336 /** |
| 19337 * The label for this input. If you're using PaperInputBehavior to |
| 19338 * implement your own paper-input-like element, bind this to |
| 19339 * `<label>`'s content and `hidden` property, e.g. |
| 19340 * `<label hidden$="[[!label]]">[[label]]</label>` in your `template` |
| 19341 */ |
| 19342 label: { |
| 19343 type: String |
| 19344 }, |
| 19345 |
| 19346 /** |
| 19347 * The value for this input. If you're using PaperInputBehavior to |
| 19348 * implement your own paper-input-like element, bind this to |
| 19349 * the `<input is="iron-input">`'s `bindValue` |
| 19350 * property, or the value property of your input that is `notify:true`. |
| 19351 */ |
| 19352 value: { |
| 19353 notify: true, |
| 19354 type: String |
| 19355 }, |
| 19356 |
| 19357 /** |
| 19358 * Set to true to disable this input. If you're using PaperInputBehavior t
o |
| 19359 * implement your own paper-input-like element, bind this to |
| 19360 * both the `<paper-input-container>`'s and the input's `disabled` propert
y. |
| 19361 */ |
| 19362 disabled: { |
| 19363 type: Boolean, |
| 19364 value: false |
| 19365 }, |
| 19366 |
| 19367 /** |
| 19368 * Returns true if the value is invalid. If you're using PaperInputBehavio
r to |
| 19369 * implement your own paper-input-like element, bind this to both the |
| 19370 * `<paper-input-container>`'s and the input's `invalid` property. |
| 19371 * |
| 19372 * If `autoValidate` is true, the `invalid` attribute is managed automatic
ally, |
| 19373 * which can clobber attempts to manage it manually. |
| 19374 */ |
| 19375 invalid: { |
| 19376 type: Boolean, |
| 19377 value: false, |
| 19378 notify: true |
| 19379 }, |
| 19380 |
| 19381 /** |
| 19382 * Set to true to prevent the user from entering invalid input. If you're |
| 19383 * using PaperInputBehavior to implement your own paper-input-like elemen
t, |
| 19384 * bind this to `<input is="iron-input">`'s `preventInvalidInput` property
. |
| 19385 */ |
| 19386 preventInvalidInput: { |
| 19387 type: Boolean |
| 19388 }, |
| 19389 |
| 19390 /** |
| 19391 * Set this to specify the pattern allowed by `preventInvalidInput`. If |
| 19392 * you're using PaperInputBehavior to implement your own paper-input-like |
| 19393 * element, bind this to the `<input is="iron-input">`'s `allowedPattern` |
| 19394 * property. |
| 19395 */ |
| 19396 allowedPattern: { |
| 19397 type: String |
| 19398 }, |
| 19399 |
| 19400 /** |
| 19401 * The type of the input. The supported types are `text`, `number` and `pa
ssword`. |
| 19402 * If you're using PaperInputBehavior to implement your own paper-input-li
ke element, |
| 19403 * bind this to the `<input is="iron-input">`'s `type` property. |
| 19404 */ |
| 19405 type: { |
| 19406 type: String |
| 19407 }, |
| 19408 |
| 19409 /** |
| 19410 * The datalist of the input (if any). This should match the id of an exis
ting `<datalist>`. |
| 19411 * If you're using PaperInputBehavior to implement your own paper-input-li
ke |
| 19412 * element, bind this to the `<input is="iron-input">`'s `list` property. |
| 19413 */ |
| 19414 list: { |
| 19415 type: String |
| 19416 }, |
| 19417 |
| 19418 /** |
| 19419 * A pattern to validate the `input` with. If you're using PaperInputBehav
ior to |
| 19420 * implement your own paper-input-like element, bind this to |
| 19421 * the `<input is="iron-input">`'s `pattern` property. |
| 19422 */ |
| 19423 pattern: { |
| 19424 type: String |
| 19425 }, |
| 19426 |
| 19427 /** |
| 19428 * Set to true to mark the input as required. If you're using PaperInputBe
havior to |
| 19429 * implement your own paper-input-like element, bind this to |
| 19430 * the `<input is="iron-input">`'s `required` property. |
| 19431 */ |
| 19432 required: { |
| 19433 type: Boolean, |
| 19434 value: false |
| 19435 }, |
| 19436 |
| 19437 /** |
| 19438 * The error message to display when the input is invalid. If you're using |
| 19439 * PaperInputBehavior to implement your own paper-input-like element, |
| 19440 * bind this to the `<paper-input-error>`'s content, if using. |
| 19441 */ |
| 19442 errorMessage: { |
| 19443 type: String |
| 19444 }, |
| 19445 |
| 19446 /** |
| 19447 * Set to true to show a character counter. |
| 19448 */ |
| 19449 charCounter: { |
| 19450 type: Boolean, |
| 19451 value: false |
| 19452 }, |
| 19453 |
| 19454 /** |
| 19455 * Set to true to disable the floating label. If you're using PaperInputBe
havior to |
| 19456 * implement your own paper-input-like element, bind this to |
| 19457 * the `<paper-input-container>`'s `noLabelFloat` property. |
| 19458 */ |
| 19459 noLabelFloat: { |
| 19460 type: Boolean, |
| 19461 value: false |
| 19462 }, |
| 19463 |
| 19464 /** |
| 19465 * Set to true to always float the label. If you're using PaperInputBehavi
or to |
| 19466 * implement your own paper-input-like element, bind this to |
| 19467 * the `<paper-input-container>`'s `alwaysFloatLabel` property. |
| 19468 */ |
| 19469 alwaysFloatLabel: { |
| 19470 type: Boolean, |
| 19471 value: false |
| 19472 }, |
| 19473 |
| 19474 /** |
| 19475 * Set to true to auto-validate the input value. If you're using PaperInpu
tBehavior to |
| 19476 * implement your own paper-input-like element, bind this to |
| 19477 * the `<paper-input-container>`'s `autoValidate` property. |
| 19478 */ |
| 19479 autoValidate: { |
| 19480 type: Boolean, |
| 19481 value: false |
| 19482 }, |
| 19483 |
| 19484 /** |
| 19485 * Name of the validator to use. If you're using PaperInputBehavior to |
| 19486 * implement your own paper-input-like element, bind this to |
| 19487 * the `<input is="iron-input">`'s `validator` property. |
| 19488 */ |
| 19489 validator: { |
| 19490 type: String |
| 19491 }, |
| 19492 |
| 19493 // HTMLInputElement attributes for binding if needed |
| 19494 |
| 19495 /** |
| 19496 * If you're using PaperInputBehavior to implement your own paper-input-li
ke |
| 19497 * element, bind this to the `<input is="iron-input">`'s `autocomplete` pr
operty. |
| 19498 */ |
| 19499 autocomplete: { |
| 19500 type: String, |
| 19501 value: 'off' |
| 19502 }, |
| 19503 |
| 19504 /** |
| 19505 * If you're using PaperInputBehavior to implement your own paper-input-li
ke |
| 19506 * element, bind this to the `<input is="iron-input">`'s `autofocus` prope
rty. |
| 19507 */ |
| 19508 autofocus: { |
| 19509 type: Boolean, |
| 19510 observer: '_autofocusChanged' |
| 19511 }, |
| 19512 |
| 19513 /** |
| 19514 * If you're using PaperInputBehavior to implement your own paper-input-li
ke |
| 19515 * element, bind this to the `<input is="iron-input">`'s `inputmode` prope
rty. |
| 19516 */ |
| 19517 inputmode: { |
| 19518 type: String |
| 19519 }, |
| 19520 |
| 19521 /** |
| 19522 * The minimum length of the input value. |
| 19523 * If you're using PaperInputBehavior to implement your own paper-input-li
ke |
| 19524 * element, bind this to the `<input is="iron-input">`'s `minlength` prope
rty. |
| 19525 */ |
| 19526 minlength: { |
| 19527 type: Number |
| 19528 }, |
| 19529 |
| 19530 /** |
| 19531 * The maximum length of the input value. |
| 19532 * If you're using PaperInputBehavior to implement your own paper-input-li
ke |
| 19533 * element, bind this to the `<input is="iron-input">`'s `maxlength` prope
rty. |
| 19534 */ |
| 19535 maxlength: { |
| 19536 type: Number |
| 19537 }, |
| 19538 |
| 19539 /** |
| 19540 * The minimum (numeric or date-time) input value. |
| 19541 * If you're using PaperInputBehavior to implement your own paper-input-li
ke |
| 19542 * element, bind this to the `<input is="iron-input">`'s `min` property. |
| 19543 */ |
| 19544 min: { |
| 19545 type: String |
| 19546 }, |
| 19547 |
| 19548 /** |
| 19549 * The maximum (numeric or date-time) input value. |
| 19550 * Can be a String (e.g. `"2000-1-1"`) or a Number (e.g. `2`). |
| 19551 * If you're using PaperInputBehavior to implement your own paper-input-li
ke |
| 19552 * element, bind this to the `<input is="iron-input">`'s `max` property. |
| 19553 */ |
| 19554 max: { |
| 19555 type: String |
| 19556 }, |
| 19557 |
| 19558 /** |
| 19559 * Limits the numeric or date-time increments. |
| 19560 * If you're using PaperInputBehavior to implement your own paper-input-li
ke |
| 19561 * element, bind this to the `<input is="iron-input">`'s `step` property. |
| 19562 */ |
| 19563 step: { |
| 19564 type: String |
| 19565 }, |
| 19566 |
| 19567 /** |
| 19568 * If you're using PaperInputBehavior to implement your own paper-input-li
ke |
| 19569 * element, bind this to the `<input is="iron-input">`'s `name` property. |
| 19570 */ |
| 19571 name: { |
| 19572 type: String |
| 19573 }, |
| 19574 |
| 19575 /** |
| 19576 * A placeholder string in addition to the label. If this is set, the labe
l will always float. |
| 19577 */ |
| 19578 placeholder: { |
| 19579 type: String, |
| 19580 // need to set a default so _computeAlwaysFloatLabel is run |
| 19581 value: '' |
| 19582 }, |
| 19583 |
| 19584 /** |
| 19585 * If you're using PaperInputBehavior to implement your own paper-input-li
ke |
| 19586 * element, bind this to the `<input is="iron-input">`'s `readonly` proper
ty. |
| 19587 */ |
| 19588 readonly: { |
| 19589 type: Boolean, |
| 19590 value: false |
| 19591 }, |
| 19592 |
| 19593 /** |
| 19594 * If you're using PaperInputBehavior to implement your own paper-input-li
ke |
| 19595 * element, bind this to the `<input is="iron-input">`'s `size` property. |
| 19596 */ |
| 19597 size: { |
| 19598 type: Number |
| 19599 }, |
| 19600 |
| 19601 // Nonstandard attributes for binding if needed |
| 19602 |
| 19603 /** |
| 19604 * If you're using PaperInputBehavior to implement your own paper-input-li
ke |
| 19605 * element, bind this to the `<input is="iron-input">`'s `autocapitalize`
property. |
| 19606 */ |
| 19607 autocapitalize: { |
| 19608 type: String, |
| 19609 value: 'none' |
| 19610 }, |
| 19611 |
| 19612 /** |
| 19613 * If you're using PaperInputBehavior to implement your own paper-input-li
ke |
| 19614 * element, bind this to the `<input is="iron-input">`'s `autocorrect` pro
perty. |
| 19615 */ |
| 19616 autocorrect: { |
| 19617 type: String, |
| 19618 value: 'off' |
| 19619 }, |
| 19620 |
| 19621 /** |
| 19622 * If you're using PaperInputBehavior to implement your own paper-input-li
ke |
| 19623 * element, bind this to the `<input is="iron-input">`'s `autosave` proper
ty, |
| 19624 * used with type=search. |
| 19625 */ |
| 19626 autosave: { |
| 19627 type: String |
| 19628 }, |
| 19629 |
| 19630 /** |
| 19631 * If you're using PaperInputBehavior to implement your own paper-input-li
ke |
| 19632 * element, bind this to the `<input is="iron-input">`'s `results` propert
y, |
| 19633 * used with type=search. |
| 19634 */ |
| 19635 results: { |
| 19636 type: Number |
| 19637 }, |
| 19638 |
| 19639 /** |
| 19640 * If you're using PaperInputBehavior to implement your own paper-input-li
ke |
| 19641 * element, bind this to the `<input is="iron-input">`'s `accept` property
, |
| 19642 * used with type=file. |
| 19643 */ |
| 19644 accept: { |
| 19645 type: String |
| 19646 }, |
| 19647 |
| 19648 /** |
| 19649 * If you're using PaperInputBehavior to implement your own paper-input-li
ke |
| 19650 * element, bind this to the`<input is="iron-input">`'s `multiple` propert
y, |
| 19651 * used with type=file. |
| 19652 */ |
| 19653 multiple: { |
| 19654 type: Boolean |
| 19655 }, |
| 19656 |
| 19657 _ariaDescribedBy: { |
| 19658 type: String, |
| 19659 value: '' |
| 19660 }, |
| 19661 |
| 19662 _ariaLabelledBy: { |
| 19663 type: String, |
| 19664 value: '' |
| 19665 } |
| 19666 |
| 19667 }, |
| 19668 |
| 19669 listeners: { |
| 19670 'addon-attached': '_onAddonAttached', |
| 19671 }, |
| 19672 |
| 19673 keyBindings: { |
| 19674 'shift+tab:keydown': '_onShiftTabDown' |
| 19675 }, |
| 19676 |
| 19677 hostAttributes: { |
| 19678 tabindex: 0 |
| 19679 }, |
| 19680 |
| 19681 /** |
| 19682 * Returns a reference to the input element. |
| 19683 */ |
| 19684 get inputElement() { |
| 19685 return this.$.input; |
| 19686 }, |
| 19687 |
| 19688 /** |
| 19689 * Returns a reference to the focusable element. |
| 19690 */ |
| 19691 get _focusableElement() { |
| 19692 return this.inputElement; |
| 19693 }, |
| 19694 |
| 19695 registered: function() { |
| 19696 // These types have some default placeholder text; overlapping |
| 19697 // the label on top of it looks terrible. Auto-float the label in this cas
e. |
| 19698 this._typesThatHaveText = ["date", "datetime", "datetime-local", "month", |
| 19699 "time", "week", "file"]; |
| 19700 }, |
| 19701 |
| 19702 attached: function() { |
| 19703 this._updateAriaLabelledBy(); |
| 19704 |
| 19705 if (this.inputElement && |
| 19706 this._typesThatHaveText.indexOf(this.inputElement.type) !== -1) { |
| 19707 this.alwaysFloatLabel = true; |
| 19708 } |
| 19709 }, |
| 19710 |
| 19711 _appendStringWithSpace: function(str, more) { |
| 19712 if (str) { |
| 19713 str = str + ' ' + more; |
| 19714 } else { |
| 19715 str = more; |
| 19716 } |
| 19717 return str; |
| 19718 }, |
| 19719 |
| 19720 _onAddonAttached: function(event) { |
| 19721 var target = event.path ? event.path[0] : event.target; |
| 19722 if (target.id) { |
| 19723 this._ariaDescribedBy = this._appendStringWithSpace(this._ariaDescribedB
y, target.id); |
| 19724 } else { |
| 19725 var id = 'paper-input-add-on-' + Polymer.PaperInputHelper.NextAddonID++; |
| 19726 target.id = id; |
| 19727 this._ariaDescribedBy = this._appendStringWithSpace(this._ariaDescribedB
y, id); |
| 19728 } |
| 19729 }, |
| 19730 |
| 19731 /** |
| 19732 * Validates the input element and sets an error style if needed. |
| 19733 * |
| 19734 * @return {boolean} |
| 19735 */ |
| 19736 validate: function() { |
| 19737 return this.inputElement.validate(); |
| 19738 }, |
| 19739 |
| 19740 /** |
| 19741 * Forward focus to inputElement. Overriden from IronControlState. |
| 19742 */ |
| 19743 _focusBlurHandler: function(event) { |
| 19744 Polymer.IronControlState._focusBlurHandler.call(this, event); |
| 19745 |
| 19746 // Forward the focus to the nested input. |
| 19747 if (this.focused && !this._shiftTabPressed) |
| 19748 this._focusableElement.focus(); |
| 19749 }, |
| 19750 |
| 19751 /** |
| 19752 * Handler that is called when a shift+tab keypress is detected by the menu. |
| 19753 * |
| 19754 * @param {CustomEvent} event A key combination event. |
| 19755 */ |
| 19756 _onShiftTabDown: function(event) { |
| 19757 var oldTabIndex = this.getAttribute('tabindex'); |
| 19758 this._shiftTabPressed = true; |
| 19759 this.setAttribute('tabindex', '-1'); |
| 19760 this.async(function() { |
| 19761 this.setAttribute('tabindex', oldTabIndex); |
| 19762 this._shiftTabPressed = false; |
| 19763 }, 1); |
| 19764 }, |
| 19765 |
| 19766 /** |
| 19767 * If `autoValidate` is true, then validates the element. |
| 19768 */ |
| 19769 _handleAutoValidate: function() { |
| 19770 if (this.autoValidate) |
| 19771 this.validate(); |
| 19772 }, |
| 19773 |
| 19774 /** |
| 19775 * Restores the cursor to its original position after updating the value. |
| 19776 * @param {string} newValue The value that should be saved. |
| 19777 */ |
| 19778 updateValueAndPreserveCaret: function(newValue) { |
| 19779 // Not all elements might have selection, and even if they have the |
| 19780 // right properties, accessing them might throw an exception (like for |
| 19781 // <input type=number>) |
| 19782 try { |
| 19783 var start = this.inputElement.selectionStart; |
| 19784 this.value = newValue; |
| 19785 |
| 19786 // The cursor automatically jumps to the end after re-setting the value, |
| 19787 // so restore it to its original position. |
| 19788 this.inputElement.selectionStart = start; |
| 19789 this.inputElement.selectionEnd = start; |
| 19790 } catch (e) { |
| 19791 // Just set the value and give up on the caret. |
| 19792 this.value = newValue; |
| 19793 } |
| 19794 }, |
| 19795 |
| 19796 _computeAlwaysFloatLabel: function(alwaysFloatLabel, placeholder) { |
| 19797 return placeholder || alwaysFloatLabel; |
| 19798 }, |
| 19799 |
| 19800 _updateAriaLabelledBy: function() { |
| 19801 var label = Polymer.dom(this.root).querySelector('label'); |
| 19802 if (!label) { |
| 19803 this._ariaLabelledBy = ''; |
| 19804 return; |
| 19805 } |
| 19806 var labelledBy; |
| 19807 if (label.id) { |
| 19808 labelledBy = label.id; |
| 19809 } else { |
| 19810 labelledBy = 'paper-input-label-' + Polymer.PaperInputHelper.NextLabelID
++; |
| 19811 label.id = labelledBy; |
| 19812 } |
| 19813 this._ariaLabelledBy = labelledBy; |
| 19814 }, |
| 19815 |
| 19816 _onChange:function(event) { |
| 19817 // In the Shadow DOM, the `change` event is not leaked into the |
| 19818 // ancestor tree, so we must do this manually. |
| 19819 // See https://w3c.github.io/webcomponents/spec/shadow/#events-that-are-no
t-leaked-into-ancestor-trees. |
| 19820 if (this.shadowRoot) { |
| 19821 this.fire(event.type, {sourceEvent: event}, { |
| 19822 node: this, |
| 19823 bubbles: event.bubbles, |
| 19824 cancelable: event.cancelable |
| 19825 }); |
| 19826 } |
| 19827 }, |
| 19828 |
| 19829 _autofocusChanged: function() { |
| 19830 // Firefox doesn't respect the autofocus attribute if it's applied after |
| 19831 // the page is loaded (Chrome/WebKit do respect it), preventing an |
| 19832 // autofocus attribute specified in markup from taking effect when the |
| 19833 // element is upgraded. As a workaround, if the autofocus property is set, |
| 19834 // and the focus hasn't already been moved elsewhere, we take focus. |
| 19835 if (this.autofocus && this._focusableElement) { |
| 19836 |
| 19837 // In IE 11, the default document.activeElement can be the page's |
| 19838 // outermost html element, but there are also cases (under the |
| 19839 // polyfill?) in which the activeElement is not a real HTMLElement, but |
| 19840 // just a plain object. We identify the latter case as having no valid |
| 19841 // activeElement. |
| 19842 var activeElement = document.activeElement; |
| 19843 var isActiveElementValid = activeElement instanceof HTMLElement; |
| 19844 |
| 19845 // Has some other element has already taken the focus? |
| 19846 var isSomeElementActive = isActiveElementValid && |
| 19847 activeElement !== document.body && |
| 19848 activeElement !== document.documentElement; /* IE 11 */ |
| 19849 if (!isSomeElementActive) { |
| 19850 // No specific element has taken the focus yet, so we can take it. |
| 19851 this._focusableElement.focus(); |
| 19852 } |
| 19853 } |
| 19854 } |
| 19855 } |
| 19856 |
| 19857 /** @polymerBehavior */ |
| 19858 Polymer.PaperInputBehavior = [ |
| 19859 Polymer.IronControlState, |
| 19860 Polymer.IronA11yKeysBehavior, |
| 19861 Polymer.PaperInputBehaviorImpl |
| 19862 ]; |
| 19863 </script> |
| 19864 <link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:400,
300,300italic,400italic,500,500italic,700,700italic"> |
| 19865 <link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto+Mono
:400,700"> |
| 19866 <style is="custom-style"> |
| 19867 |
| 19868 :root { |
| 19869 |
| 19870 /* Shared Styles */ |
| 19871 --paper-font-common-base: { |
| 19872 font-family: 'Roboto', 'Noto', sans-serif; |
| 19873 -webkit-font-smoothing: antialiased; |
| 19874 }; |
| 19875 |
| 19876 --paper-font-common-code: { |
| 19877 font-family: 'Roboto Mono', 'Consolas', 'Menlo', monospace; |
| 19878 -webkit-font-smoothing: antialiased; |
| 19879 }; |
| 19880 |
| 19881 --paper-font-common-expensive-kerning: { |
| 19882 text-rendering: optimizeLegibility; |
| 19883 }; |
| 19884 |
| 19885 --paper-font-common-nowrap: { |
| 19886 white-space: nowrap; |
| 19887 overflow: hidden; |
| 19888 text-overflow: ellipsis; |
| 19889 }; |
| 19890 |
| 19891 /* Material Font Styles */ |
| 19892 |
| 19893 --paper-font-display4: { |
| 19894 @apply(--paper-font-common-base); |
| 19895 @apply(--paper-font-common-nowrap); |
| 19896 |
| 19897 font-size: 112px; |
| 19898 font-weight: 300; |
| 19899 letter-spacing: -.044em; |
| 19900 line-height: 120px; |
| 19901 }; |
| 19902 |
| 19903 --paper-font-display3: { |
| 19904 @apply(--paper-font-common-base); |
| 19905 @apply(--paper-font-common-nowrap); |
| 19906 |
| 19907 font-size: 56px; |
| 19908 font-weight: 400; |
| 19909 letter-spacing: -.026em; |
| 19910 line-height: 60px; |
| 19911 }; |
| 19912 |
| 19913 --paper-font-display2: { |
| 19914 @apply(--paper-font-common-base); |
| 19915 |
| 19916 font-size: 45px; |
| 19917 font-weight: 400; |
| 19918 letter-spacing: -.018em; |
| 19919 line-height: 48px; |
| 19920 }; |
| 19921 |
| 19922 --paper-font-display1: { |
| 19923 @apply(--paper-font-common-base); |
| 19924 |
| 19925 font-size: 34px; |
| 19926 font-weight: 400; |
| 19927 letter-spacing: -.01em; |
| 19928 line-height: 40px; |
| 19929 }; |
| 19930 |
| 19931 --paper-font-headline: { |
| 19932 @apply(--paper-font-common-base); |
| 19933 |
| 19934 font-size: 24px; |
| 19935 font-weight: 400; |
| 19936 letter-spacing: -.012em; |
| 19937 line-height: 32px; |
| 19938 }; |
| 19939 |
| 19940 --paper-font-title: { |
| 19941 @apply(--paper-font-common-base); |
| 19942 @apply(--paper-font-common-nowrap); |
| 19943 |
| 19944 font-size: 20px; |
| 19945 font-weight: 500; |
| 19946 line-height: 28px; |
| 19947 }; |
| 19948 |
| 19949 --paper-font-subhead: { |
| 19950 @apply(--paper-font-common-base); |
| 19951 |
| 19952 font-size: 16px; |
| 19953 font-weight: 400; |
| 19954 line-height: 24px; |
| 19955 }; |
| 19956 |
| 19957 --paper-font-body2: { |
| 19958 @apply(--paper-font-common-base); |
| 19959 |
| 19960 font-size: 14px; |
| 19961 font-weight: 500; |
| 19962 line-height: 24px; |
| 19963 }; |
| 19964 |
| 19965 --paper-font-body1: { |
| 19966 @apply(--paper-font-common-base); |
| 19967 |
| 19968 font-size: 14px; |
| 19969 font-weight: 400; |
| 19970 line-height: 20px; |
| 19971 }; |
| 19972 |
| 19973 --paper-font-caption: { |
| 19974 @apply(--paper-font-common-base); |
| 19975 @apply(--paper-font-common-nowrap); |
| 19976 |
| 19977 font-size: 12px; |
| 19978 font-weight: 400; |
| 19979 letter-spacing: 0.011em; |
| 19980 line-height: 20px; |
| 19981 }; |
| 19982 |
| 19983 --paper-font-menu: { |
| 19984 @apply(--paper-font-common-base); |
| 19985 @apply(--paper-font-common-nowrap); |
| 19986 |
| 19987 font-size: 13px; |
| 19988 font-weight: 500; |
| 19989 line-height: 24px; |
| 19990 }; |
| 19991 |
| 19992 --paper-font-button: { |
| 19993 @apply(--paper-font-common-base); |
| 19994 @apply(--paper-font-common-nowrap); |
| 19995 |
| 19996 font-size: 14px; |
| 19997 font-weight: 500; |
| 19998 letter-spacing: 0.018em; |
| 19999 line-height: 24px; |
| 20000 text-transform: uppercase; |
| 20001 }; |
| 20002 |
| 20003 --paper-font-code2: { |
| 20004 @apply(--paper-font-common-code); |
| 20005 |
| 20006 font-size: 14px; |
| 20007 font-weight: 700; |
| 20008 line-height: 20px; |
| 20009 }; |
| 20010 |
| 20011 --paper-font-code1: { |
| 20012 @apply(--paper-font-common-code); |
| 20013 |
| 20014 font-size: 14px; |
| 20015 font-weight: 500; |
| 20016 line-height: 20px; |
| 20017 }; |
| 20018 |
| 20019 } |
| 20020 |
| 20021 </style> |
| 20022 <script> |
| 20023 |
| 20024 /** |
| 20025 * Use `Polymer.PaperInputAddonBehavior` to implement an add-on for `<paper-in
put-container>`. A |
| 20026 * add-on appears below the input, and may display information based on the in
put value and |
| 20027 * validity such as a character counter or an error message. |
| 20028 * @polymerBehavior |
| 20029 */ |
| 20030 Polymer.PaperInputAddonBehavior = { |
| 20031 |
| 20032 hostAttributes: { |
| 20033 'add-on': '' |
| 20034 }, |
| 20035 |
| 20036 attached: function() { |
| 20037 this.fire('addon-attached'); |
| 20038 }, |
| 20039 |
| 20040 /** |
| 20041 * The function called by `<paper-input-container>` when the input value or
validity changes. |
| 20042 * @param {{ |
| 20043 * inputElement: (Element|undefined), |
| 20044 * value: (string|undefined), |
| 20045 * invalid: boolean |
| 20046 * }} state - |
| 20047 * inputElement: The input element. |
| 20048 * value: The input value. |
| 20049 * invalid: True if the input value is invalid. |
| 20050 */ |
| 20051 update: function(state) { |
| 20052 } |
| 20053 |
| 20054 }; |
| 20055 |
| 20056 </script> |
| 20057 |
| 20058 |
| 20059 <dom-module id="paper-input-char-counter" assetpath="/res/imp/bower_components/p
aper-input/"> |
| 20060 <template> |
| 20061 <style> |
| 20062 :host { |
| 20063 display: inline-block; |
| 20064 float: right; |
| 20065 |
| 20066 @apply(--paper-font-caption); |
| 20067 @apply(--paper-input-char-counter); |
| 20068 } |
| 20069 |
| 20070 :host([hidden]) { |
| 20071 display: none !important; |
| 20072 } |
| 20073 |
| 20074 :host-context([dir="rtl"]) { |
| 20075 float: left; |
| 20076 } |
| 20077 </style> |
| 20078 |
| 20079 <span>[[_charCounterStr]]</span> |
| 20080 </template> |
| 20081 </dom-module> |
| 20082 |
| 20083 <script> |
| 20084 Polymer({ |
| 20085 is: 'paper-input-char-counter', |
| 20086 |
| 20087 behaviors: [ |
| 20088 Polymer.PaperInputAddonBehavior |
| 20089 ], |
| 20090 |
| 20091 properties: { |
| 20092 _charCounterStr: { |
| 20093 type: String, |
| 20094 value: '0' |
| 20095 } |
| 20096 }, |
| 20097 |
| 20098 /** |
| 20099 * This overrides the update function in PaperInputAddonBehavior. |
| 20100 * @param {{ |
| 20101 * inputElement: (Element|undefined), |
| 20102 * value: (string|undefined), |
| 20103 * invalid: boolean |
| 20104 * }} state - |
| 20105 * inputElement: The input element. |
| 20106 * value: The input value. |
| 20107 * invalid: True if the input value is invalid. |
| 20108 */ |
| 20109 update: function(state) { |
| 20110 if (!state.inputElement) { |
| 20111 return; |
| 20112 } |
| 20113 |
| 20114 state.value = state.value || ''; |
| 20115 |
| 20116 var counter = state.value.toString().length.toString(); |
| 20117 |
| 20118 if (state.inputElement.hasAttribute('maxlength')) { |
| 20119 counter += '/' + state.inputElement.getAttribute('maxlength'); |
| 20120 } |
| 20121 |
| 20122 this._charCounterStr = counter; |
| 20123 } |
| 20124 }); |
| 20125 </script> |
| 20126 |
| 20127 |
| 20128 <dom-module id="paper-input-container" assetpath="/res/imp/bower_components/pape
r-input/"> |
| 20129 <template> |
| 20130 <style> |
| 20131 :host { |
| 20132 display: block; |
| 20133 padding: 8px 0; |
| 20134 |
| 20135 @apply(--paper-input-container); |
| 20136 } |
| 20137 |
| 20138 :host([inline]) { |
| 20139 display: inline-block; |
| 20140 } |
| 20141 |
| 20142 :host([disabled]) { |
| 20143 pointer-events: none; |
| 20144 opacity: 0.33; |
| 20145 |
| 20146 @apply(--paper-input-container-disabled); |
| 20147 } |
| 20148 |
| 20149 :host([hidden]) { |
| 20150 display: none !important; |
| 20151 } |
| 20152 |
| 20153 .floated-label-placeholder { |
| 20154 @apply(--paper-font-caption); |
| 20155 } |
| 20156 |
| 20157 .underline { |
| 20158 position: relative; |
| 20159 } |
| 20160 |
| 20161 .focused-line { |
| 20162 @apply(--layout-fit); |
| 20163 |
| 20164 background: var(--paper-input-container-focus-color, --primary-color); |
| 20165 height: 2px; |
| 20166 |
| 20167 -webkit-transform-origin: center center; |
| 20168 transform-origin: center center; |
| 20169 -webkit-transform: scale3d(0,1,1); |
| 20170 transform: scale3d(0,1,1); |
| 20171 |
| 20172 @apply(--paper-input-container-underline-focus); |
| 20173 } |
| 20174 |
| 20175 .underline.is-highlighted .focused-line { |
| 20176 -webkit-transform: none; |
| 20177 transform: none; |
| 20178 -webkit-transition: -webkit-transform 0.25s; |
| 20179 transition: transform 0.25s; |
| 20180 |
| 20181 @apply(--paper-transition-easing); |
| 20182 } |
| 20183 |
| 20184 .underline.is-invalid .focused-line { |
| 20185 background: var(--paper-input-container-invalid-color, --error-color); |
| 20186 -webkit-transform: none; |
| 20187 transform: none; |
| 20188 -webkit-transition: -webkit-transform 0.25s; |
| 20189 transition: transform 0.25s; |
| 20190 |
| 20191 @apply(--paper-transition-easing); |
| 20192 } |
| 20193 |
| 20194 .unfocused-line { |
| 20195 @apply(--layout-fit); |
| 20196 |
| 20197 background: var(--paper-input-container-color, --secondary-text-color); |
| 20198 height: 1px; |
| 20199 |
| 20200 @apply(--paper-input-container-underline); |
| 20201 } |
| 20202 |
| 20203 :host([disabled]) .unfocused-line { |
| 20204 border-bottom: 1px dashed; |
| 20205 border-color: var(--paper-input-container-color, --secondary-text-color)
; |
| 20206 background: transparent; |
| 20207 |
| 20208 @apply(--paper-input-container-underline-disabled); |
| 20209 } |
| 20210 |
| 20211 .label-and-input-container { |
| 20212 @apply(--layout-flex-auto); |
| 20213 @apply(--layout-relative); |
| 20214 |
| 20215 width: 100%; |
| 20216 max-width: 100%; |
| 20217 } |
| 20218 |
| 20219 .input-content { |
| 20220 @apply(--layout-horizontal); |
| 20221 @apply(--layout-center); |
| 20222 |
| 20223 position: relative; |
| 20224 } |
| 20225 |
| 20226 .input-content ::content label, |
| 20227 .input-content ::content .paper-input-label { |
| 20228 position: absolute; |
| 20229 top: 0; |
| 20230 right: 0; |
| 20231 left: 0; |
| 20232 width: 100%; |
| 20233 font: inherit; |
| 20234 color: var(--paper-input-container-color, --secondary-text-color); |
| 20235 -webkit-transition: -webkit-transform 0.25s, width 0.25s; |
| 20236 transition: transform 0.25s, width 0.25s; |
| 20237 -webkit-transform-origin: left top; |
| 20238 transform-origin: left top; |
| 20239 |
| 20240 @apply(--paper-font-common-nowrap); |
| 20241 @apply(--paper-font-subhead); |
| 20242 @apply(--paper-input-container-label); |
| 20243 @apply(--paper-transition-easing); |
| 20244 } |
| 20245 |
| 20246 .input-content.label-is-floating ::content label, |
| 20247 .input-content.label-is-floating ::content .paper-input-label { |
| 20248 -webkit-transform: translateY(-75%) scale(0.75); |
| 20249 transform: translateY(-75%) scale(0.75); |
| 20250 |
| 20251 /* Since we scale to 75/100 of the size, we actually have 100/75 of the |
| 20252 original space now available */ |
| 20253 width: 133%; |
| 20254 |
| 20255 @apply(--paper-input-container-label-floating); |
| 20256 } |
| 20257 |
| 20258 :host-context([dir="rtl"]) .input-content.label-is-floating ::content labe
l, |
| 20259 :host-context([dir="rtl"]) .input-content.label-is-floating ::content .pap
er-input-label { |
| 20260 /* TODO(noms): Figure out why leaving the width at 133% before the anima
tion |
| 20261 * actually makes |
| 20262 * it wider on the right side, not left side, as you would expect in RTL
*/ |
| 20263 width: 100%; |
| 20264 -webkit-transform-origin: right top; |
| 20265 transform-origin: right top; |
| 20266 } |
| 20267 |
| 20268 .input-content.label-is-highlighted ::content label, |
| 20269 .input-content.label-is-highlighted ::content .paper-input-label { |
| 20270 color: var(--paper-input-container-focus-color, --primary-color); |
| 20271 |
| 20272 @apply(--paper-input-container-label-focus); |
| 20273 } |
| 20274 |
| 20275 .input-content.is-invalid ::content label, |
| 20276 .input-content.is-invalid ::content .paper-input-label { |
| 20277 color: var(--paper-input-container-invalid-color, --error-color); |
| 20278 } |
| 20279 |
| 20280 .input-content.label-is-hidden ::content label, |
| 20281 .input-content.label-is-hidden ::content .paper-input-label { |
| 20282 visibility: hidden; |
| 20283 } |
| 20284 |
| 20285 .input-content ::content input, |
| 20286 .input-content ::content textarea, |
| 20287 .input-content ::content iron-autogrow-textarea, |
| 20288 .input-content ::content .paper-input-input { |
| 20289 position: relative; /* to make a stacking context */ |
| 20290 outline: none; |
| 20291 box-shadow: none; |
| 20292 padding: 0; |
| 20293 width: 100%; |
| 20294 max-width: 100%; |
| 20295 background: transparent; |
| 20296 border: none; |
| 20297 color: var(--paper-input-container-input-color, --primary-text-color); |
| 20298 -webkit-appearance: none; |
| 20299 text-align: inherit; |
| 20300 |
| 20301 @apply(--paper-font-subhead); |
| 20302 @apply(--paper-input-container-input); |
| 20303 } |
| 20304 |
| 20305 ::content [prefix] { |
| 20306 @apply(--paper-font-subhead); |
| 20307 |
| 20308 @apply(--paper-input-prefix); |
| 20309 @apply(--layout-flex-none); |
| 20310 } |
| 20311 |
| 20312 ::content [suffix] { |
| 20313 @apply(--paper-font-subhead); |
| 20314 |
| 20315 @apply(--paper-input-suffix); |
| 20316 @apply(--layout-flex-none); |
| 20317 } |
| 20318 |
| 20319 /* Firefox sets a min-width on the input, which can cause layout issues */ |
| 20320 .input-content ::content input { |
| 20321 min-width: 0; |
| 20322 } |
| 20323 |
| 20324 .input-content ::content textarea { |
| 20325 resize: none; |
| 20326 } |
| 20327 |
| 20328 .add-on-content { |
| 20329 position: relative; |
| 20330 } |
| 20331 |
| 20332 .add-on-content.is-invalid ::content * { |
| 20333 color: var(--paper-input-container-invalid-color, --error-color); |
| 20334 } |
| 20335 |
| 20336 .add-on-content.is-highlighted ::content * { |
| 20337 color: var(--paper-input-container-focus-color, --primary-color); |
| 20338 } |
| 20339 </style> |
| 20340 |
| 20341 <template is="dom-if" if="[[!noLabelFloat]]"> |
| 20342 <div class="floated-label-placeholder" aria-hidden="true"> </div> |
| 20343 </template> |
| 20344 |
| 20345 <div class$="[[_computeInputContentClass(noLabelFloat,alwaysFloatLabel,focus
ed,invalid,_inputHasContent)]]"> |
| 20346 <content select="[prefix]" id="prefix"></content> |
| 20347 |
| 20348 <div class="label-and-input-container" id="labelAndInputContainer"> |
| 20349 <content select=":not([add-on]):not([prefix]):not([suffix])"></content> |
| 20350 </div> |
| 20351 |
| 20352 <content select="[suffix]"></content> |
| 20353 </div> |
| 20354 |
| 20355 <div class$="[[_computeUnderlineClass(focused,invalid)]]"> |
| 20356 <div class="unfocused-line"></div> |
| 20357 <div class="focused-line"></div> |
| 20358 </div> |
| 20359 |
| 20360 <div class$="[[_computeAddOnContentClass(focused,invalid)]]"> |
| 20361 <content id="addOnContent" select="[add-on]"></content> |
| 20362 </div> |
| 20363 </template> |
| 20364 </dom-module> |
| 20365 |
| 20366 <script> |
| 20367 Polymer({ |
| 20368 is: 'paper-input-container', |
| 20369 |
| 20370 properties: { |
| 20371 /** |
| 20372 * Set to true to disable the floating label. The label disappears when th
e input value is |
| 20373 * not null. |
| 20374 */ |
| 20375 noLabelFloat: { |
| 20376 type: Boolean, |
| 20377 value: false |
| 20378 }, |
| 20379 |
| 20380 /** |
| 20381 * Set to true to always float the floating label. |
| 20382 */ |
| 20383 alwaysFloatLabel: { |
| 20384 type: Boolean, |
| 20385 value: false |
| 20386 }, |
| 20387 |
| 20388 /** |
| 20389 * The attribute to listen for value changes on. |
| 20390 */ |
| 20391 attrForValue: { |
| 20392 type: String, |
| 20393 value: 'bind-value' |
| 20394 }, |
| 20395 |
| 20396 /** |
| 20397 * Set to true to auto-validate the input value when it changes. |
| 20398 */ |
| 20399 autoValidate: { |
| 20400 type: Boolean, |
| 20401 value: false |
| 20402 }, |
| 20403 |
| 20404 /** |
| 20405 * True if the input is invalid. This property is set automatically when t
he input value |
| 20406 * changes if auto-validating, or when the `iron-input-validate` event is
heard from a child. |
| 20407 */ |
| 20408 invalid: { |
| 20409 observer: '_invalidChanged', |
| 20410 type: Boolean, |
| 20411 value: false |
| 20412 }, |
| 20413 |
| 20414 /** |
| 20415 * True if the input has focus. |
| 20416 */ |
| 20417 focused: { |
| 20418 readOnly: true, |
| 20419 type: Boolean, |
| 20420 value: false, |
| 20421 notify: true |
| 20422 }, |
| 20423 |
| 20424 _addons: { |
| 20425 type: Array |
| 20426 // do not set a default value here intentionally - it will be initialize
d lazily when a |
| 20427 // distributed child is attached, which may occur before configuration f
or this element |
| 20428 // in polyfill. |
| 20429 }, |
| 20430 |
| 20431 _inputHasContent: { |
| 20432 type: Boolean, |
| 20433 value: false |
| 20434 }, |
| 20435 |
| 20436 _inputSelector: { |
| 20437 type: String, |
| 20438 value: 'input,textarea,.paper-input-input' |
| 20439 }, |
| 20440 |
| 20441 _boundOnFocus: { |
| 20442 type: Function, |
| 20443 value: function() { |
| 20444 return this._onFocus.bind(this); |
| 20445 } |
| 20446 }, |
| 20447 |
| 20448 _boundOnBlur: { |
| 20449 type: Function, |
| 20450 value: function() { |
| 20451 return this._onBlur.bind(this); |
| 20452 } |
| 20453 }, |
| 20454 |
| 20455 _boundOnInput: { |
| 20456 type: Function, |
| 20457 value: function() { |
| 20458 return this._onInput.bind(this); |
| 20459 } |
| 20460 }, |
| 20461 |
| 20462 _boundValueChanged: { |
| 20463 type: Function, |
| 20464 value: function() { |
| 20465 return this._onValueChanged.bind(this); |
| 20466 } |
| 20467 } |
| 20468 }, |
| 20469 |
| 20470 listeners: { |
| 20471 'addon-attached': '_onAddonAttached', |
| 20472 'iron-input-validate': '_onIronInputValidate' |
| 20473 }, |
| 20474 |
| 20475 get _valueChangedEvent() { |
| 20476 return this.attrForValue + '-changed'; |
| 20477 }, |
| 20478 |
| 20479 get _propertyForValue() { |
| 20480 return Polymer.CaseMap.dashToCamelCase(this.attrForValue); |
| 20481 }, |
| 20482 |
| 20483 get _inputElement() { |
| 20484 return Polymer.dom(this).querySelector(this._inputSelector); |
| 20485 }, |
| 20486 |
| 20487 get _inputElementValue() { |
| 20488 return this._inputElement[this._propertyForValue] || this._inputElement.va
lue; |
| 20489 }, |
| 20490 |
| 20491 ready: function() { |
| 20492 if (!this._addons) { |
| 20493 this._addons = []; |
| 20494 } |
| 20495 this.addEventListener('focus', this._boundOnFocus, true); |
| 20496 this.addEventListener('blur', this._boundOnBlur, true); |
| 20497 }, |
| 20498 |
| 20499 attached: function() { |
| 20500 if (this.attrForValue) { |
| 20501 this._inputElement.addEventListener(this._valueChangedEvent, this._bound
ValueChanged); |
| 20502 } else { |
| 20503 this.addEventListener('input', this._onInput); |
| 20504 } |
| 20505 |
| 20506 // Only validate when attached if the input already has a value. |
| 20507 if (this._inputElementValue != '') { |
| 20508 this._handleValueAndAutoValidate(this._inputElement); |
| 20509 } else { |
| 20510 this._handleValue(this._inputElement); |
| 20511 } |
| 20512 }, |
| 20513 |
| 20514 _onAddonAttached: function(event) { |
| 20515 if (!this._addons) { |
| 20516 this._addons = []; |
| 20517 } |
| 20518 var target = event.target; |
| 20519 if (this._addons.indexOf(target) === -1) { |
| 20520 this._addons.push(target); |
| 20521 if (this.isAttached) { |
| 20522 this._handleValue(this._inputElement); |
| 20523 } |
| 20524 } |
| 20525 }, |
| 20526 |
| 20527 _onFocus: function() { |
| 20528 this._setFocused(true); |
| 20529 }, |
| 20530 |
| 20531 _onBlur: function() { |
| 20532 this._setFocused(false); |
| 20533 this._handleValueAndAutoValidate(this._inputElement); |
| 20534 }, |
| 20535 |
| 20536 _onInput: function(event) { |
| 20537 this._handleValueAndAutoValidate(event.target); |
| 20538 }, |
| 20539 |
| 20540 _onValueChanged: function(event) { |
| 20541 this._handleValueAndAutoValidate(event.target); |
| 20542 }, |
| 20543 |
| 20544 _handleValue: function(inputElement) { |
| 20545 var value = this._inputElementValue; |
| 20546 |
| 20547 // type="number" hack needed because this.value is empty until it's valid |
| 20548 if (value || value === 0 || (inputElement.type === 'number' && !inputEleme
nt.checkValidity())) { |
| 20549 this._inputHasContent = true; |
| 20550 } else { |
| 20551 this._inputHasContent = false; |
| 20552 } |
| 20553 |
| 20554 this.updateAddons({ |
| 20555 inputElement: inputElement, |
| 20556 value: value, |
| 20557 invalid: this.invalid |
| 20558 }); |
| 20559 }, |
| 20560 |
| 20561 _handleValueAndAutoValidate: function(inputElement) { |
| 20562 if (this.autoValidate) { |
| 20563 var valid; |
| 20564 if (inputElement.validate) { |
| 20565 valid = inputElement.validate(this._inputElementValue); |
| 20566 } else { |
| 20567 valid = inputElement.checkValidity(); |
| 20568 } |
| 20569 this.invalid = !valid; |
| 20570 } |
| 20571 |
| 20572 // Call this last to notify the add-ons. |
| 20573 this._handleValue(inputElement); |
| 20574 }, |
| 20575 |
| 20576 _onIronInputValidate: function(event) { |
| 20577 this.invalid = this._inputElement.invalid; |
| 20578 }, |
| 20579 |
| 20580 _invalidChanged: function() { |
| 20581 if (this._addons) { |
| 20582 this.updateAddons({invalid: this.invalid}); |
| 20583 } |
| 20584 }, |
| 20585 |
| 20586 /** |
| 20587 * Call this to update the state of add-ons. |
| 20588 * @param {Object} state Add-on state. |
| 20589 */ |
| 20590 updateAddons: function(state) { |
| 20591 for (var addon, index = 0; addon = this._addons[index]; index++) { |
| 20592 addon.update(state); |
| 20593 } |
| 20594 }, |
| 20595 |
| 20596 _computeInputContentClass: function(noLabelFloat, alwaysFloatLabel, focused,
invalid, _inputHasContent) { |
| 20597 var cls = 'input-content'; |
| 20598 if (!noLabelFloat) { |
| 20599 var label = this.querySelector('label'); |
| 20600 |
| 20601 if (alwaysFloatLabel || _inputHasContent) { |
| 20602 cls += ' label-is-floating'; |
| 20603 // If the label is floating, ignore any offsets that may have been |
| 20604 // applied from a prefix element. |
| 20605 this.$.labelAndInputContainer.style.position = 'static'; |
| 20606 |
| 20607 if (invalid) { |
| 20608 cls += ' is-invalid'; |
| 20609 } else if (focused) { |
| 20610 cls += " label-is-highlighted"; |
| 20611 } |
| 20612 } else { |
| 20613 // When the label is not floating, it should overlap the input element
. |
| 20614 if (label) { |
| 20615 this.$.labelAndInputContainer.style.position = 'relative'; |
| 20616 } |
| 20617 } |
| 20618 } else { |
| 20619 if (_inputHasContent) { |
| 20620 cls += ' label-is-hidden'; |
| 20621 } |
| 20622 } |
| 20623 return cls; |
| 20624 }, |
| 20625 |
| 20626 _computeUnderlineClass: function(focused, invalid) { |
| 20627 var cls = 'underline'; |
| 20628 if (invalid) { |
| 20629 cls += ' is-invalid'; |
| 20630 } else if (focused) { |
| 20631 cls += ' is-highlighted' |
| 20632 } |
| 20633 return cls; |
| 20634 }, |
| 20635 |
| 20636 _computeAddOnContentClass: function(focused, invalid) { |
| 20637 var cls = 'add-on-content'; |
| 20638 if (invalid) { |
| 20639 cls += ' is-invalid'; |
| 20640 } else if (focused) { |
| 20641 cls += ' is-highlighted' |
| 20642 } |
| 20643 return cls; |
| 20644 } |
| 20645 }); |
| 20646 </script> |
| 20647 |
| 20648 |
| 20649 <dom-module id="paper-input-error" assetpath="/res/imp/bower_components/paper-in
put/"> |
| 20650 <template> |
| 20651 <style> |
| 20652 :host { |
| 20653 display: inline-block; |
| 20654 visibility: hidden; |
| 20655 |
| 20656 color: var(--paper-input-container-invalid-color, --error-color); |
| 20657 |
| 20658 @apply(--paper-font-caption); |
| 20659 @apply(--paper-input-error); |
| 20660 position: absolute; |
| 20661 left:0; |
| 20662 right:0; |
| 20663 } |
| 20664 |
| 20665 :host([invalid]) { |
| 20666 visibility: visible; |
| 20667 }; |
| 20668 </style> |
| 20669 |
| 20670 <content></content> |
| 20671 </template> |
| 20672 </dom-module> |
| 20673 |
| 20674 <script> |
| 20675 Polymer({ |
| 20676 is: 'paper-input-error', |
| 20677 |
| 20678 behaviors: [ |
| 20679 Polymer.PaperInputAddonBehavior |
| 20680 ], |
| 20681 |
| 20682 properties: { |
| 20683 /** |
| 20684 * True if the error is showing. |
| 20685 */ |
| 20686 invalid: { |
| 20687 readOnly: true, |
| 20688 reflectToAttribute: true, |
| 20689 type: Boolean |
| 20690 } |
| 20691 }, |
| 20692 |
| 20693 /** |
| 20694 * This overrides the update function in PaperInputAddonBehavior. |
| 20695 * @param {{ |
| 20696 * inputElement: (Element|undefined), |
| 20697 * value: (string|undefined), |
| 20698 * invalid: boolean |
| 20699 * }} state - |
| 20700 * inputElement: The input element. |
| 20701 * value: The input value. |
| 20702 * invalid: True if the input value is invalid. |
| 20703 */ |
| 20704 update: function(state) { |
| 20705 this._setInvalid(state.invalid); |
| 20706 } |
| 20707 }); |
| 20708 </script> |
| 20709 |
| 20710 |
| 20711 <dom-module id="paper-input" assetpath="/res/imp/bower_components/paper-input/"> |
| 20712 <template> |
| 20713 <style> |
| 20714 :host { |
| 20715 display: block; |
| 20716 } |
| 20717 |
| 20718 :host([hidden]) { |
| 20719 display: none !important; |
| 20720 } |
| 20721 |
| 20722 input::-webkit-input-placeholder { |
| 20723 color: var(--paper-input-container-color, --secondary-text-color); |
| 20724 } |
| 20725 |
| 20726 input:-moz-placeholder { |
| 20727 color: var(--paper-input-container-color, --secondary-text-color); |
| 20728 } |
| 20729 |
| 20730 input::-moz-placeholder { |
| 20731 color: var(--paper-input-container-color, --secondary-text-color); |
| 20732 } |
| 20733 |
| 20734 input:-ms-input-placeholder { |
| 20735 color: var(--paper-input-container-color, --secondary-text-color); |
| 20736 } |
| 20737 </style> |
| 20738 |
| 20739 <paper-input-container no-label-float="[[noLabelFloat]]" always-float-label=
"[[_computeAlwaysFloatLabel(alwaysFloatLabel,placeholder)]]" auto-validate$="[[a
utoValidate]]" disabled$="[[disabled]]" invalid="[[invalid]]"> |
| 20740 |
| 20741 <content select="[prefix]"></content> |
| 20742 |
| 20743 <label hidden$="[[!label]]" aria-hidden="true" for="input">[[label]]</labe
l> |
| 20744 |
| 20745 <input is="iron-input" id="input" aria-labelledby$="[[_ariaLabelledBy]]" a
ria-describedby$="[[_ariaDescribedBy]]" disabled$="[[disabled]]" title$="[[title
]]" bind-value="{{value}}" invalid="{{invalid}}" prevent-invalid-input="[[preven
tInvalidInput]]" allowed-pattern="[[allowedPattern]]" validator="[[validator]]"
type$="[[type]]" pattern$="[[pattern]]" required$="[[required]]" autocomplete$="
[[autocomplete]]" autofocus$="[[autofocus]]" inputmode$="[[inputmode]]" minlengt
h$="[[minlength]]" maxlength$="[[maxlength]]" min$="[[min]]" max$="[[max]]" step
$="[[step]]" name$="[[name]]" placeholder$="[[placeholder]]" readonly$="[[readon
ly]]" list$="[[list]]" size$="[[size]]" autocapitalize$="[[autocapitalize]]" aut
ocorrect$="[[autocorrect]]" on-change="_onChange" tabindex$="[[tabindex]]" autos
ave$="[[autosave]]" results$="[[results]]" accept$="[[accept]]" multiple$="[[mul
tiple]]"> |
| 20746 |
| 20747 <content select="[suffix]"></content> |
| 20748 |
| 20749 <template is="dom-if" if="[[errorMessage]]"> |
| 20750 <paper-input-error aria-live="assertive">[[errorMessage]]</paper-input-e
rror> |
| 20751 </template> |
| 20752 |
| 20753 <template is="dom-if" if="[[charCounter]]"> |
| 20754 <paper-input-char-counter></paper-input-char-counter> |
| 20755 </template> |
| 20756 |
| 20757 </paper-input-container> |
| 20758 </template> |
| 20759 </dom-module> |
| 20760 |
| 20761 <script> |
| 20762 Polymer({ |
| 20763 is: 'paper-input', |
| 20764 |
| 20765 behaviors: [ |
| 20766 Polymer.IronFormElementBehavior, |
| 20767 Polymer.PaperInputBehavior |
| 20768 ] |
| 20769 }); |
| 20770 </script> |
| 20771 <dom-module id="bot-filters" assetpath="/res/imp/botlist/"> |
| 20772 <template> |
| 20773 <style include="iron-flex iron-flex-alignment iron-positioning"> |
| 20774 :host { |
| 20775 display: block; |
| 20776 font-family: sans-serif; |
| 20777 } |
| 20778 .container { |
| 20779 min-height: 120px; |
| 20780 width: 100%; |
| 20781 } |
| 20782 |
| 20783 .item { |
| 20784 border-bottom: 1px solid #EEE; |
| 20785 max-width: 250px; |
| 20786 min-height: 1.0em; |
| 20787 min-width: 100px; |
| 20788 padding: 0.1em 0.2em; |
| 20789 line-height: 1.5em; |
| 20790 } |
| 20791 |
| 20792 .iron-selected { |
| 20793 background-color: #4285f4; |
| 20794 color: white; |
| 20795 } |
| 20796 |
| 20797 .header { |
| 20798 height: 2em; |
| 20799 padding: .25em; |
| 20800 line-height: 2em; |
| 20801 } |
| 20802 |
| 20803 .selector { |
| 20804 border: 1px solid black; |
| 20805 margin: 0 5px; |
| 20806 max-height: 200px; |
| 20807 min-height: 130px; |
| 20808 min-width: 200px; |
| 20809 overflow: auto; |
| 20810 } |
| 20811 |
| 20812 .icons { |
| 20813 cursor:pointer; |
| 20814 height:20px; |
| 20815 margin:2px; |
| 20816 width:20px; |
| 20817 flex-shrink: 0; |
| 20818 } |
| 20819 |
| 20820 .side-by-side { |
| 20821 display: inline-block; |
| 20822 vertical-align: top; |
| 20823 } |
| 20824 |
| 20825 paper-checkbox { |
| 20826 max-height: 2em; |
| 20827 } |
| 20828 </style> |
| 20829 |
| 20830 <div class="container horizontal layout"> |
| 20831 |
| 20832 <div> |
| 20833 <div class="header">Columns:</div> |
| 20834 <div class="selector"> |
| 20835 <template is="dom-repeat" items="[[columns]]" as="col"> |
| 20836 <div class="item horizontal layout" label="[[col]]"> |
| 20837 <span>[[col]]</span> |
| 20838 <span class="flex"></span> |
| 20839 <iron-icon class="icons" icon="icons:remove-circle-outline" hidd
en="{{_cantRemoveColumn(col,columns.*)}}" on-tap="removeColumn"> |
| 20840 </iron-icon> |
| 20841 </div> |
| 20842 </template> |
| 20843 </div> |
| 20844 </div> |
| 20845 |
| 20846 <div class="narrow-down-selector"> |
| 20847 <div> |
| 20848 <paper-input id="filter" label="Narrow options" no-label-float="true"
value="{{query}}"></paper-input> |
| 20849 </div> |
| 20850 |
| 20851 <div class="selector side-by-side"> |
| 20852 <iron-selector attr-for-selected="label" selected="{{primary_selected}
}"> |
| 20853 <template is="dom-repeat" items="[[primary_items]]" as="item"> |
| 20854 <div class="item horizontal layout" label="[[item]]"> |
| 20855 <iron-icon style="margin:0 -6px;" icon="icons:more-vert"> |
| 20856 </iron-icon> |
| 20857 <span>[[item]]</span> |
| 20858 <span class="flex"></span> |
| 20859 <iron-icon class="icons" icon="icons:arrow-back" hidden="{{_cant
AddColumn(item,columns.*)}}" on-tap="addColumn"> |
| 20860 </iron-icon> |
| 20861 </div> |
| 20862 </template> |
| 20863 </iron-selector> |
| 20864 </div> |
| 20865 |
| 20866 <div class="selector side-by-side"> |
| 20867 <template is="dom-repeat" items="[[secondary_items]]" as="item"> |
| 20868 <div class="item horizontal layout" label="[[item]]"> |
| 20869 <span>[[item]]</span> |
| 20870 <span class="flex"></span> |
| 20871 <iron-icon class="icons" icon="icons:arrow-forward" hidden="{{_can
tAddFilter(primary_selected,item,filters.*)}}" on-tap="addFilter"> |
| 20872 </iron-icon> |
| 20873 </div> |
| 20874 </template> |
| 20875 </div> |
| 20876 </div> |
| 20877 |
| 20878 <div> |
| 20879 <div class="header">Filters: </div> |
| 20880 <div class="selector"> |
| 20881 <template is="dom-repeat" items="[[filters]]" as="fil"> |
| 20882 <div class="item horizontal layout" label="[[fil]]"> |
| 20883 <span>[[fil]]</span> |
| 20884 <span class="flex"></span> |
| 20885 <iron-icon class="icons" icon="icons:remove-circle-outline" hidden
="{{_cantRemoveFilter(fil,filters.*)}}" on-tap="removeFilter"> |
| 20886 </iron-icon> |
| 20887 </div> |
| 20888 </template> |
| 20889 </div> |
| 20890 </div> |
| 20891 |
| 20892 <paper-checkbox checked="{{verbose}}">Verbose Entries</paper-checkbox> |
| 20893 |
| 20894 </div> |
| 20895 |
| 20896 </template> |
| 20897 <script> |
| 20898 (function(){ |
| 20899 var FILTER_SEP = " | "; |
| 20900 // filterMap is a map of primary -> function. The function returns a boolea
n |
| 20901 // "does the bot (first arg) match the second argument". These functions wi
ll |
| 20902 // have "this" be the botlist, and will have |
| 20903 var filterMap = { |
| 20904 cores: function(bot, cores){ |
| 20905 var o = this._cores(bot); |
| 20906 return o.indexOf(cores) !== -1; |
| 20907 }, |
| 20908 cpu: function(bot, cpu){ |
| 20909 var o = this._dimension(bot, "cpu") || ["none"]; |
| 20910 return o.indexOf(cpu) !== -1; |
| 20911 }, |
| 20912 devices: function(bot, device){ |
| 20913 if (device === "none") { |
| 20914 return this._devices(bot).length === 0; |
| 20915 } |
| 20916 // extract the deviceType, if it is not "unknown". |
| 20917 device = this._unalias(device); |
| 20918 var found = false; |
| 20919 this._devices(bot).forEach(function(d) { |
| 20920 if (this._deviceType(d) === device) { |
| 20921 found = true; |
| 20922 } |
| 20923 }.bind(this)); |
| 20924 return found; |
| 20925 }, |
| 20926 gpu: function(bot, gpu){ |
| 20927 var o = this._dimension(bot, "gpu") || ["none"]; |
| 20928 return o.indexOf(this._unalias(gpu)) !== -1; |
| 20929 }, |
| 20930 id: function(bot, id) { |
| 20931 return bot.bot_id === id; |
| 20932 }, |
| 20933 os: function(bot, os){ |
| 20934 var o = this._dimension(bot, "os") || ["Unknown"]; |
| 20935 return o.indexOf(os) !== -1; |
| 20936 }, |
| 20937 pool: function(bot, pool){ |
| 20938 var o = this._dimension(bot, "pool") || ["Unknown"]; |
| 20939 return o.indexOf(pool) !== -1; |
| 20940 }, |
| 20941 status: function(bot, status){ |
| 20942 if (status === "quarantined") { |
| 20943 return bot.quarantined; |
| 20944 } else if (status === "dead") { |
| 20945 return bot.is_dead; |
| 20946 } else { |
| 20947 // Status must be available. |
| 20948 return !bot.quarantined && !bot.is_dead; |
| 20949 } |
| 20950 }, |
| 20951 task: function(bot, task) { |
| 20952 if (task === "idle") { |
| 20953 return this._taskId(bot) === "idle"; |
| 20954 } |
| 20955 // task === "busy" |
| 20956 return this._taskId(bot) !== "idle"; |
| 20957 } |
| 20958 }; |
| 20959 |
| 20960 // returns true if string b is in string a, case notwithstanding. |
| 20961 var containsCaseInsensitive = function(a, b) { |
| 20962 return a.toLocaleLowerCase().indexOf(b.toLocaleLowerCase()) !== -1; |
| 20963 }; |
| 20964 |
| 20965 Polymer({ |
| 20966 is: "bot-filters", |
| 20967 properties: { |
| 20968 // input |
| 20969 primary_map: { |
| 20970 type: Object, |
| 20971 }, |
| 20972 primary_arr: { |
| 20973 type: Array, |
| 20974 }, |
| 20975 |
| 20976 // output |
| 20977 columns: { |
| 20978 type: Array, |
| 20979 value: function() { |
| 20980 return ["id","os","task","status"]; |
| 20981 }, |
| 20982 notify: true, |
| 20983 }, |
| 20984 filter: { |
| 20985 type: Object, |
| 20986 computed: "_makeFilter(filters.*)", |
| 20987 notify: true, |
| 20988 }, |
| 20989 verbose: { |
| 20990 type: Boolean, |
| 20991 value: false, |
| 20992 notify: true, |
| 20993 }, |
| 20994 |
| 20995 // private |
| 20996 filters:{ |
| 20997 type:Array, |
| 20998 value: function() { |
| 20999 return []; |
| 21000 } |
| 21001 }, |
| 21002 filter_selected: { |
| 21003 type: String, |
| 21004 value:"", |
| 21005 }, |
| 21006 primary_items: { |
| 21007 type: Array, |
| 21008 computed: "_primary(query, primary_map, primary_arr, columns)", |
| 21009 }, |
| 21010 primary_selected: { |
| 21011 type: String, |
| 21012 value: "", |
| 21013 }, |
| 21014 query: { |
| 21015 type:String, |
| 21016 }, |
| 21017 secondary_items: { |
| 21018 type: Array, |
| 21019 computed: "_secondary(primary_selected, query, primary_map)", |
| 21020 }, |
| 21021 |
| 21022 }, |
| 21023 |
| 21024 addColumn: function(e) { |
| 21025 var col = e.model.item; |
| 21026 e.preventDefault(); |
| 21027 e.stopPropagation(); |
| 21028 if (this._cantAddColumn(col)) { |
| 21029 return; |
| 21030 } |
| 21031 this.push("columns", col); |
| 21032 }, |
| 21033 |
| 21034 addFilter: function(e) { |
| 21035 var filterItem = e.model.item; |
| 21036 if (this._cantAddFilter(this.primary_selected, filterItem)) { |
| 21037 return; |
| 21038 } |
| 21039 var filter = this.primary_selected + FILTER_SEP + filterItem; |
| 21040 this.push("filters", filter); |
| 21041 }, |
| 21042 |
| 21043 removeColumn: function(e){ |
| 21044 var col = e.model.col; |
| 21045 if (this._cantRemoveColumn(col, this.columns)){ |
| 21046 return; |
| 21047 } |
| 21048 var idx = this.columns.indexOf(col); |
| 21049 if (idx !== -1) { |
| 21050 this.splice("columns", idx, 1); |
| 21051 } |
| 21052 this.set("column_selected",""); |
| 21053 }, |
| 21054 |
| 21055 removeFilter: function(e){ |
| 21056 var filter = e.model.fil; |
| 21057 if (this._cantRemoveFilter(filter)){ |
| 21058 return; |
| 21059 } |
| 21060 var idx = this.filters.indexOf(filter); |
| 21061 if (idx !== -1) { |
| 21062 this.splice("filters", idx, 1); |
| 21063 } |
| 21064 this.set("filter_selected",""); |
| 21065 }, |
| 21066 |
| 21067 _cantAddColumn: function(col) { |
| 21068 if (!col) { |
| 21069 return true; |
| 21070 } |
| 21071 return this.columns.indexOf(col) !== -1; |
| 21072 }, |
| 21073 |
| 21074 _cantAddFilter: function(primary_selected, filterItem) { |
| 21075 if (!primary_selected || !filterItem) { |
| 21076 return true; |
| 21077 } |
| 21078 var filter = primary_selected + FILTER_SEP + filterItem; |
| 21079 return this.filters.indexOf(filter) !== -1; |
| 21080 }, |
| 21081 |
| 21082 _cantRemoveColumn: function(col) { |
| 21083 return !col || col === "id" || this.columns.indexOf(col) === -1; |
| 21084 }, |
| 21085 |
| 21086 _cantRemoveFilter: function(filter_selected) { |
| 21087 return !filter_selected || this.filters.indexOf(filter_selected) === -1; |
| 21088 }, |
| 21089 |
| 21090 _makeFilter: function() { |
| 21091 // The filters belonging to the same primary key will be or'd together.
Those groups will be and'd together. |
| 21092 var filterGroups = {}; |
| 21093 this.filters.forEach(function(filterString){ |
| 21094 var idx = filterString.indexOf(FILTER_SEP); |
| 21095 var primary = filterString.slice(0, idx); |
| 21096 var param = filterString.slice(idx + FILTER_SEP.length); |
| 21097 var arr = filterGroups[primary] || []; |
| 21098 arr.push(param); |
| 21099 filterGroups[primary] = arr; |
| 21100 }); |
| 21101 return { |
| 21102 filter: function(bot){ |
| 21103 var retVal = true; |
| 21104 for (primary in filterGroups){ |
| 21105 var params = filterGroups[primary]; |
| 21106 var filter = filterMap[primary]; |
| 21107 var groupResult = false; |
| 21108 if (filter) { |
| 21109 params.forEach(function(param){ |
| 21110 groupResult = groupResult || filter.bind(this)(bot,param); |
| 21111 }.bind(this)); |
| 21112 } |
| 21113 retVal = retVal && groupResult; |
| 21114 } |
| 21115 return retVal; |
| 21116 } |
| 21117 } |
| 21118 }, |
| 21119 |
| 21120 _primary: function(query, primary_map, primary_arr) { |
| 21121 var arr = this.primary_arr.filter(function(s){ |
| 21122 if (containsCaseInsensitive(s, query)) { |
| 21123 return true; |
| 21124 } |
| 21125 var opts = primary_map[s]; |
| 21126 for (var i = 0; i < opts.length; i++) { |
| 21127 if (containsCaseInsensitive(opts[i], query)) { |
| 21128 return true; |
| 21129 } |
| 21130 } |
| 21131 return false; |
| 21132 }); |
| 21133 // Update the selected to be the current one (if it is still with being |
| 21134 // shown) or the first match. |
| 21135 if (this.query && arr.length > 0 && |
| 21136 arr.indexOf(this.primary_selected) === -1) { |
| 21137 this.set("primary_selected", arr[0]); |
| 21138 } |
| 21139 return arr; |
| 21140 }, |
| 21141 _secondary: function(primary_selected, query, primary_map) { |
| 21142 if (!primary_selected) { |
| 21143 return []; |
| 21144 } |
| 21145 var opts = primary_map[primary_selected].filter(function(s){ |
| 21146 return containsCaseInsensitive(s, query); |
| 21147 }); |
| 21148 |
| 21149 return opts; |
| 21150 }, |
| 21151 |
| 21152 }); |
| 21153 })(); |
| 21154 </script> |
| 21155 </dom-module><dom-module id="bot-list" assetpath="/res/imp/botlist/"> |
| 21156 <template> |
| 21157 <style include="iron-flex iron-flex-alignment iron-positioning"> |
| 21158 bot-filters { |
| 21159 margin-bottom:2px; |
| 21160 } |
| 21161 .bot { |
| 21162 margin:5px; |
| 21163 max-width:400px; |
| 21164 min-height:100px; |
| 21165 min-width:300px; |
| 21166 } |
| 21167 table { |
| 21168 border-collapse: collapse; |
| 21169 border: 1px solid black; |
| 21170 } |
| 21171 td, th { |
| 21172 border: 1px solid black; |
| 21173 padding: 5px; |
| 21174 } |
| 21175 |
| 21176 .bot-list th > span { |
| 21177 display:inline-block; |
| 21178 } |
| 21179 |
| 21180 .quarantined, .bad-device { |
| 21181 background-color: #ffdddd; |
| 21182 border: 2px solid black; |
| 21183 } |
| 21184 .dead { |
| 21185 background-color: #cccccc; |
| 21186 border: 2px solid black; |
| 21187 } |
| 21188 </style> |
| 21189 |
| 21190 <swarming-app auth_headers="{{auth_headers}}" busy="[[busy]]" name="Swarming
Bot List"> |
| 21191 |
| 21192 <bot-filters primary_map="[[primary_map]]" primary_arr="[[primary_arr]]" c
olumns="{{columns}}" filter="{{filter}}" verbose="{{verbose}}"> |
| 21193 </bot-filters> |
| 21194 |
| 21195 <bot-list-data auth_headers="[[auth_headers]]" bots="{{bots}}" busy="{{bus
y}}" primary_map="{{primary_map}}" primary_arr="{{primary_arr}}"> |
| 21196 </bot-list-data> |
| 21197 |
| 21198 <table class="bot-list"> |
| 21199 <thead on-sort_change="sortChange"> |
| 21200 |
| 21201 <tr><th> |
| 21202 <span>Bot Id</span> |
| 21203 <sort-toggle name="id"></sort-toggle> |
| 21204 </th> |
| 21205 |
| 21206 <th hidden$="[[_hide('task', columns.*)]]"> |
| 21207 <span>Current Task</span> |
| 21208 <sort-toggle name="task"></sort-toggle> |
| 21209 </th> |
| 21210 |
| 21211 <template is="dom-repeat" items="[[plain_columns]]" as="c"> |
| 21212 <th hidden$="[[_hide(c)]]"> |
| 21213 <span>[[_header(c)]]</span> |
| 21214 <sort-toggle name="[[c]]"></sort-toggle> |
| 21215 </th> |
| 21216 </template> |
| 21217 </tr></thead> |
| 21218 <tbody> |
| 21219 <template id="bot_table" is="dom-repeat" items="[[bots]]" as="bot" ini
tial-count="50" sort="_sortBotTable" filter="_filterBotTable"> |
| 21220 |
| 21221 <tr class$="[[_botClass(bot)]]"> |
| 21222 <td><a class="center" href$="[[_botLink(bot.bot_id)]]" target="_bl
ank">[[bot.bot_id]]</a></td> |
| 21223 <td hidden$="[[_hide('task', columns.*)]]"> |
| 21224 Current Task: |
| 21225 <a href$="[[_taskLink(bot)]]">[[_taskId(bot)]]</a> |
| 21226 </td> |
| 21227 |
| 21228 <template is="dom-repeat" items="[[plain_columns]]" as="c"> |
| 21229 <td hidden$="[[_hide(c)]]">[[_column(c, bot, verbose)]]</td> |
| 21230 </template> |
| 21231 |
| 21232 </tr> |
| 21233 <template is="dom-repeat" items="[[_devices(bot)]]" as="device"> |
| 21234 <tr hidden$="[[_hide('devices', columns.*)]]" class$="[[_deviceCla
ss(device)]]"> |
| 21235 <td></td> |
| 21236 <td hidden$="[[_hide('task', columns.*)]]"></td> |
| 21237 <template is="dom-repeat" items="[[plain_columns]]" as="c"> |
| 21238 <td hidden$="[[_hide(c)]]">[[_deviceColumn(c, device, verbose)
]]</td> |
| 21239 </template> |
| 21240 </tr> |
| 21241 </template> |
| 21242 </template> |
| 21243 </tbody> |
| 21244 </table> |
| 21245 |
| 21246 </swarming-app> |
| 21247 |
| 21248 </template> |
| 21249 <script> |
| 21250 (function(){ |
| 21251 var special_columns = ["id", "task"]; |
| 21252 |
| 21253 var headerMap = { |
| 21254 // "id" and "task" are special, so they don't go here and are just |
| 21255 // hard-coded below. |
| 21256 "cores": "Cores", |
| 21257 "cpu": "CPU", |
| 21258 "devices": "Devices", |
| 21259 "gpu": "GPU", |
| 21260 "os": "OS", |
| 21261 "pool": "Pool", |
| 21262 "status": "Status", |
| 21263 }; |
| 21264 |
| 21265 // This maps column name to a function that will return the content. |
| 21266 var columnMap = { |
| 21267 cores: function(bot){ |
| 21268 var cores = this._cores(bot); |
| 21269 if (this.verbose){ |
| 21270 return cores.join(" | "); |
| 21271 } |
| 21272 return cores[0]; |
| 21273 }, |
| 21274 cpu: function(bot){ |
| 21275 var cpus = this._dimension(bot, 'cpu') || ['Unknown']; |
| 21276 if (this.verbose){ |
| 21277 return cpus.join(" | "); |
| 21278 } |
| 21279 return cpus[0]; |
| 21280 }, |
| 21281 devices: function(bot){ |
| 21282 return this._devices(bot).length + " devices attached"; |
| 21283 }, |
| 21284 gpu: function(bot){ |
| 21285 var gpus = this._dimension(bot, 'gpu') |
| 21286 if (!gpus) { |
| 21287 return "none"; |
| 21288 } |
| 21289 var verbose = [] |
| 21290 var named = []; |
| 21291 // non-verbose mode has only the top level GPU info "e.g. NVidia" |
| 21292 // which is found by looking for gpu ids w/o a colon. |
| 21293 gpus.forEach(function(g){ |
| 21294 var alias = this._gpuAlias(g); |
| 21295 if (alias === "UNKNOWN") { |
| 21296 verbose.push(g); |
| 21297 if (g.indexOf(":") === -1){ |
| 21298 named.push(g); |
| 21299 } |
| 21300 return; |
| 21301 } |
| 21302 verbose.push(this._applyAlias(g,alias)); |
| 21303 if (g.indexOf(":") === -1){ |
| 21304 named.push(this._applyAlias(g,alias)); |
| 21305 } |
| 21306 }.bind(this)) |
| 21307 if (this.verbose){ |
| 21308 return verbose.join(" | "); |
| 21309 } |
| 21310 return named.join(" | "); |
| 21311 }, |
| 21312 id: function(bot) { |
| 21313 return bot.bot_id; |
| 21314 }, |
| 21315 os: function(bot){ |
| 21316 var os = this._dimension(bot, 'os') || ['Unknown']; |
| 21317 if (this.verbose){ |
| 21318 return os.join(" | "); |
| 21319 } |
| 21320 return os[0]; |
| 21321 }, |
| 21322 pool: function(bot) { |
| 21323 var pool = this._dimension(bot, 'pool') || ['Unknown']; |
| 21324 return pool.join(" | "); |
| 21325 }, |
| 21326 status: function(bot){ |
| 21327 if (bot.quarantined) { |
| 21328 return "Quarantined: " + bot.quarantined; |
| 21329 } |
| 21330 if (bot.is_dead) { |
| 21331 return "Dead: " + bot.is_dead; |
| 21332 } |
| 21333 return "Alive"; |
| 21334 }, |
| 21335 task: function(bot){ |
| 21336 return this._taskId(bot); |
| 21337 } |
| 21338 |
| 21339 }; |
| 21340 |
| 21341 Polymer({ |
| 21342 is: 'bot-list', |
| 21343 behaviors: [SwarmingBehaviors.BotListBehavior], |
| 21344 |
| 21345 properties: { |
| 21346 |
| 21347 columns: { |
| 21348 type: Array, |
| 21349 }, |
| 21350 // Should have a property "filter" which is a function. |
| 21351 filter: { |
| 21352 type: Object, |
| 21353 }, |
| 21354 |
| 21355 plain_columns: { |
| 21356 type: Array, |
| 21357 computed: "_stripSpecial(columns.*)", |
| 21358 }, |
| 21359 |
| 21360 sorts: { |
| 21361 type: Array, |
| 21362 }, |
| 21363 |
| 21364 verbose: { |
| 21365 type: Boolean, |
| 21366 } |
| 21367 }, |
| 21368 |
| 21369 observers: ['_reRender(filter.*)', '_checkSorts(columns.*)'], |
| 21370 |
| 21371 _botClass: function(bot) { |
| 21372 if (bot.quarantined) { |
| 21373 return "quarantined"; |
| 21374 } |
| 21375 if (bot.is_dead) { |
| 21376 return "dead"; |
| 21377 } |
| 21378 return ""; |
| 21379 }, |
| 21380 |
| 21381 _botLink: function(id) { |
| 21382 return "/restricted/bot/"+id; |
| 21383 }, |
| 21384 |
| 21385 _checkSorts: function() { |
| 21386 if (!this.sorts) { |
| 21387 return; |
| 21388 } |
| 21389 this.sorts = this.sorts.filter(function(s){ |
| 21390 return this.columns.indexOf(s) !== -1; |
| 21391 }.bind(this)); |
| 21392 this._reRender(); |
| 21393 }, |
| 21394 |
| 21395 _column: function(col, bot){ |
| 21396 return columnMap[col].bind(this)(bot); |
| 21397 }, |
| 21398 |
| 21399 _deviceColumn: function(col, device){ |
| 21400 if (col === "devices") { |
| 21401 var str = this._androidAlias(device); |
| 21402 if (device.okay) { |
| 21403 str = this._applyAlias(this._deviceType(device), str); |
| 21404 } |
| 21405 str += " S/N:"; |
| 21406 str += device.serial; |
| 21407 return str; |
| 21408 } |
| 21409 if (col === "status") { |
| 21410 return device.state; |
| 21411 } |
| 21412 return ""; |
| 21413 }, |
| 21414 |
| 21415 _deviceClass: function(device) { |
| 21416 if (!device.okay) { |
| 21417 return "bad-device"; |
| 21418 } |
| 21419 return ""; |
| 21420 }, |
| 21421 |
| 21422 _filterBotTable: function(bot) { |
| 21423 if (!this.filter || !this.filter.filter) { |
| 21424 return true; |
| 21425 } |
| 21426 return this.filter.filter.bind(this)(bot); |
| 21427 }, |
| 21428 |
| 21429 _header: function(col){ |
| 21430 return headerMap[col]; |
| 21431 }, |
| 21432 |
| 21433 _hide: function(col) { |
| 21434 return this.columns.indexOf(col) === -1; |
| 21435 }, |
| 21436 |
| 21437 _reRender: function(filter, sort) { |
| 21438 this.$.bot_table.render(); |
| 21439 }, |
| 21440 |
| 21441 _sortBotTable: function(botA, botB) { |
| 21442 if (!this.sorts) { |
| 21443 return 0; |
| 21444 } |
| 21445 for (var i = 0; i< this.sorts.length; i++) { |
| 21446 var s = this.sorts[i]; |
| 21447 var botACol = this._column(s.name, botA); |
| 21448 var botBCol = this._column(s.name, botB); |
| 21449 // s.sort is either -1 or 1 (if it is 0, it should have been removed f
rom this list). |
| 21450 var sort = s.sort * botACol.localeCompare(botBCol); |
| 21451 // Try numeric, aka "natural" sort and use it if ns is not NaN. |
| 21452 var ns = botACol - botBCol; |
| 21453 if (ns) { |
| 21454 sort = s.sort * ns; |
| 21455 } |
| 21456 |
| 21457 if (sort) { // If there is a difference with this sort column, use |
| 21458 return sort; |
| 21459 } |
| 21460 } |
| 21461 return 0; |
| 21462 }, |
| 21463 |
| 21464 sortChange: function(e) { |
| 21465 if (!(e && e.detail && e.detail.name)) { |
| 21466 return; |
| 21467 } |
| 21468 var sorts = this.sorts || []; |
| 21469 var found = false; |
| 21470 for (var i = 0; i<sorts.length; i++) { |
| 21471 if (sorts[i].name === e.detail.name) { |
| 21472 sorts[i].sort = e.detail.sort; |
| 21473 found = true; |
| 21474 break; |
| 21475 } |
| 21476 } |
| 21477 if (!found) { |
| 21478 sorts.push(e.detail); |
| 21479 } |
| 21480 |
| 21481 this.sorts=sorts; |
| 21482 this._reRender(); |
| 21483 }, |
| 21484 |
| 21485 _stripSpecial: function(){ |
| 21486 return this.columns.filter(function(c){ |
| 21487 return special_columns.indexOf(c) === -1; |
| 21488 }).sort(); |
| 21489 }, |
| 21490 |
| 21491 _taskId: function(data) { |
| 21492 if (data && data.task_id) { |
| 21493 return data.task_id; |
| 21494 } |
| 21495 return "idle"; |
| 21496 }, |
| 21497 |
| 21498 _taskLink: function(data) { |
| 21499 if (data && data.task_id) { |
| 21500 return "/user/task/" + data.task_id; |
| 21501 } |
| 21502 return undefined; |
| 21503 } |
| 21504 |
| 21505 }); |
| 21506 })(); |
| 21507 </script> |
| 14650 </dom-module></div></body></html> | 21508 </dom-module></div></body></html> |
| OLD | NEW |