From 82b2b9cb9425b9ed306405452a4edc787c0513ec Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen <Paulus@PaulusSchoutsen.nl> Date: Thu, 30 Oct 2014 22:24:28 -0700 Subject: [PATCH] Squashed bugs in frontend --- homeassistant/components/http/frontend.py | 2 +- .../components/http/www_static/frontend.html | 23339 ++++++++-------- .../polymer/home-assistant-api.html | 139 +- .../polymer/home-assistant-main.html | 8 +- .../http/www_static/polymer/splash-login.html | 64 +- .../http/www_static/polymer/state-card.html | 52 +- .../http/www_static/polymer/states-cards.html | 4 +- 7 files changed, 11855 insertions(+), 11753 deletions(-) diff --git a/homeassistant/components/http/frontend.py b/homeassistant/components/http/frontend.py index 43045d35be5..49170a1fb2a 100644 --- a/homeassistant/components/http/frontend.py +++ b/homeassistant/components/http/frontend.py @@ -1,2 +1,2 @@ """ DO NOT MODIFY. Auto-generated by build_polymer script """ -VERSION = "57f41262ccbd90c2e988e5be0a5dab59" +VERSION = "b476e6588846c1ce0e194dfec06da78e" diff --git a/homeassistant/components/http/www_static/frontend.html b/homeassistant/components/http/www_static/frontend.html index 5d59404ce18..eca4ad79b3e 100644 --- a/homeassistant/components/http/www_static/frontend.html +++ b/homeassistant/components/http/www_static/frontend.html @@ -18,62 +18,51 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN --> <!-- -`core-header-panel` contains a header section and a content panel section. - -__Important:__ The `core-header-panel` will not display if its parent does not have a height. - -Using [layout attributes](http://www.polymer-project.org/docs/polymer/layout-attrs.html), you can easily make the `core-header-panel` fill the screen +@group Paper Elements - <body fullbleed layout vertical> - <core-header-panel flex> - <core-toolbar> - <div>Hello World!</div> - </core-toolbar> - </core-header-panel> - </body> +Material Design: <a href="http://www.google.com/design/spec/components/buttons.html">Buttons</a> -or, if you would prefer to do it in CSS, just give `html`, `body`, and `core-header-panel` a height of 100%: +`paper-button` is a button. When the user touches the button, a ripple effect emanates +from the point of contact. It may be flat or raised. A raised button is styled with a +shadow. - html, body { - height: 100%; - margin: 0; - } - core-header-panel { - height: 100%; - } +Example: -Special support is provided for scrolling modes when one uses a core-toolbar or equivalent -for the header section. + <paper-button>flat button</paper-button> + <paper-button raised>raised button</paper-button> -Example: +You may use custom DOM in the button body to create a variety of buttons. For example, to +create a button with an icon and some text: - <core-header-panel> - <core-toolbar>Header</core-toolbar> - <div>Content goes here...</div> - </core-header-panel> + <paper-button> + <core-icon icon="favorite"> + custom button content + </paper-button> -If you want to use other than `core-toolbar` for the header, add -`core-header` class to that element. +Styling +------- -Example: +Style the button with CSS as you would a normal DOM element. - <core-header-panel> - <div class="core-header">Header</div> - <div>Content goes here...</div> - </core-header-panel> + /* make #my-button green with yellow text */ + #my-button { + background: green; + color: yellow; + } -To have the content fits to the main area, use `fit` attribute. +By default, the ripple is the same color as the foreground at 25% opacity. You may +customize the color using this selector: - <core-header-panel> - <div class="core-header">standard</div> - <div class="content" fit>content fits 100% below the header</div> - </core-header-panel> + /* make #my-button use a blue ripple instead of foreground color */ + #my-button::shadow #ripple { + color: blue; + } -Use `mode` to control the header and scrolling behavior. +The opacity of the ripple is not customizable via CSS. -@group Polymer Core Elements -@element core-header-panel -@homepage github.io +@element paper-button +@extends paper-button-base +@status unstable --> <!-- @@ -388,6350 +377,1410 @@ var b=z(a,a.delegate_&&a.delegate_.prepareBinding);w(a,b,a.model_)}),a.setModelF return c[b]},styleCacheForScope:function(a){if(d){var b=a.host?a.host.localName:a.localName;return h[b]||(h[b]={})}return a._scopeStyles=a._scopeStyles||{}}},h={};a.api.instance.styles=g}(Polymer),function(a){function b(a,b){if("string"!=typeof a){var c=b||document._currentScript;if(b=a,a=c&&c.parentNode&&c.parentNode.getAttribute?c.parentNode.getAttribute("name"):"",!a)throw"Element name could not be inferred."}if(f(a))throw"Already registered (Polymer) prototype for element "+a;e(a,b),d(a)}function c(a,b){i[a]=b}function d(a){i[a]&&(i[a].registerWhenReady(),delete i[a])}function e(a,b){return j[a]=b||{}}function f(a){return j[a]}function g(a,b){if("string"!=typeof b)return!1;var c=HTMLElement.getPrototypeForTag(b),d=c&&c.constructor;return d?CustomElements.instanceof?CustomElements.instanceof(a,d):a instanceof d:!1}var h=a.extend,i=(a.api,{}),j={};a.getRegisteredPrototype=f,a.waitingForPrototype=c,a.instanceOfType=g,window.Polymer=b,h(Polymer,a),Platform.consumeDeclarations&&Platform.consumeDeclarations(function(a){if(a)for(var c,d=0,e=a.length;e>d&&(c=a[d]);d++)b.apply(null,c)})}(Polymer),function(a){var b={resolveElementPaths:function(a){Polymer.urlResolver.resolveDom(a)},addResolvePathApi:function(){var a=this.getAttribute("assetpath")||"",b=new URL(a,this.ownerDocument.baseURI);this.prototype.resolvePath=function(a,c){var d=new URL(a,c||b);return d.href}}};a.api.declaration.path=b}(Polymer),function(a){function b(a,b){var c=new URL(a.getAttribute("href"),b).href;return"@import '"+c+"';"}function c(a,b){if(a){b===document&&(b=document.head),i&&(b=document.head);var c=d(a.textContent),e=a.getAttribute(h);e&&c.setAttribute(h,e);var f=b.firstElementChild;if(b===document.head){var g="style["+h+"]",j=document.head.querySelectorAll(g);j.length&&(f=j[j.length-1].nextElementSibling)}b.insertBefore(c,f)}}function d(a,b){b=b||document,b=b.createElement?b:b.ownerDocument;var c=b.createElement("style");return c.textContent=a,c}function e(a){return a&&a.__resource||""}function f(a,b){return q?q.call(a,b):void 0}var g=(window.logFlags||{},a.api.instance.styles),h=g.STYLE_SCOPE_ATTRIBUTE,i=window.ShadowDOMPolyfill,j="style",k="@import",l="link[rel=stylesheet]",m="global",n="polymer-scope",o={loadStyles:function(a){var b=this.fetchTemplate(),c=b&&this.templateContent();if(c){this.convertSheetsToStyles(c);var d=this.findLoadableStyles(c);if(d.length){var e=b.ownerDocument.baseURI;return Polymer.styleResolver.loadStyles(d,e,a)}}a&&a()},convertSheetsToStyles:function(a){for(var c,e,f=a.querySelectorAll(l),g=0,h=f.length;h>g&&(c=f[g]);g++)e=d(b(c,this.ownerDocument.baseURI),this.ownerDocument),this.copySheetAttributes(e,c),c.parentNode.replaceChild(e,c)},copySheetAttributes:function(a,b){for(var c,d=0,e=b.attributes,f=e.length;(c=e[d])&&f>d;d++)"rel"!==c.name&&"href"!==c.name&&a.setAttribute(c.name,c.value)},findLoadableStyles:function(a){var b=[];if(a)for(var c,d=a.querySelectorAll(j),e=0,f=d.length;f>e&&(c=d[e]);e++)c.textContent.match(k)&&b.push(c);return b},installSheets:function(){this.cacheSheets(),this.cacheStyles(),this.installLocalSheets(),this.installGlobalStyles()},cacheSheets:function(){this.sheets=this.findNodes(l),this.sheets.forEach(function(a){a.parentNode&&a.parentNode.removeChild(a)})},cacheStyles:function(){this.styles=this.findNodes(j+"["+n+"]"),this.styles.forEach(function(a){a.parentNode&&a.parentNode.removeChild(a)})},installLocalSheets:function(){var a=this.sheets.filter(function(a){return!a.hasAttribute(n)}),b=this.templateContent();if(b){var c="";if(a.forEach(function(a){c+=e(a)+"\n"}),c){var f=d(c,this.ownerDocument);b.insertBefore(f,b.firstChild)}}},findNodes:function(a,b){var c=this.querySelectorAll(a).array(),d=this.templateContent();if(d){var e=d.querySelectorAll(a).array();c=c.concat(e)}return b?c.filter(b):c},installGlobalStyles:function(){var a=this.styleForScope(m);c(a,document.head)},cssTextForScope:function(a){var b="",c="["+n+"="+a+"]",d=function(a){return f(a,c)},g=this.sheets.filter(d);g.forEach(function(a){b+=e(a)+"\n\n"});var h=this.styles.filter(d);return h.forEach(function(a){b+=a.textContent+"\n\n"}),b},styleForScope:function(a){var b=this.cssTextForScope(a);return this.cssTextToScopeStyle(b,a)},cssTextToScopeStyle:function(a,b){if(a){var c=d(a);return c.setAttribute(h,this.getAttribute("name")+"-"+b),c}}},p=HTMLElement.prototype,q=p.matches||p.matchesSelector||p.webkitMatchesSelector||p.mozMatchesSelector;a.api.declaration.styles=o,a.applyStyleToScope=c}(Polymer),function(a){var b=(window.logFlags||{},a.api.instance.events),c=b.EVENT_PREFIX,d={};["webkitAnimationStart","webkitAnimationEnd","webkitTransitionEnd","DOMFocusOut","DOMFocusIn","DOMMouseScroll"].forEach(function(a){d[a.toLowerCase()]=a});var e={parseHostEvents:function(){var a=this.prototype.eventDelegates;this.addAttributeDelegates(a)},addAttributeDelegates:function(a){for(var b,c=0;b=this.attributes[c];c++)this.hasEventPrefix(b.name)&&(a[this.removeEventPrefix(b.name)]=b.value.replace("{{","").replace("}}","").trim())},hasEventPrefix:function(a){return a&&"o"===a[0]&&"n"===a[1]&&"-"===a[2]},removeEventPrefix:function(a){return a.slice(f)},findController:function(a){for(;a.parentNode;){if(a.eventController)return a.eventController;a=a.parentNode}return a.host},getEventHandler:function(a,b,c){var d=this;return function(e){a&&a.PolymerBase||(a=d.findController(b));var f=[e,e.detail,e.currentTarget];a.dispatchMethod(a,c,f)}},prepareEventBinding:function(a,b){if(this.hasEventPrefix(b)){var c=this.removeEventPrefix(b);c=d[c]||c;var e=this;return function(b,d,f){function g(){return"{{ "+a+" }}"}var h=e.getEventHandler(void 0,d,a);return PolymerGestures.addEventListener(d,c,h),f?void 0:{open:g,discardChanges:g,close:function(){PolymerGestures.removeEventListener(d,c,h)}}}}}},f=c.length;a.api.declaration.events=e}(Polymer),function(a){var b={inferObservers:function(a){var b,c=a.observe;for(var d in a)"Changed"===d.slice(-7)&&(c||(c=a.observe={}),b=d.slice(0,-7),c[b]=c[b]||d)},explodeObservers:function(a){var b=a.observe;if(b){var c={};for(var d in b)for(var e,f=d.split(" "),g=0;e=f[g];g++)c[e]=b[d];a.observe=c}},optimizePropertyMaps:function(a){if(a.observe){var b=a._observeNames=[];for(var c in a.observe)for(var d,e=c.split(" "),f=0;d=e[f];f++)b.push(d)}if(a.publish){var b=a._publishNames=[];for(var c in a.publish)b.push(c)}if(a.computed){var b=a._computedNames=[];for(var c in a.computed)b.push(c)}},publishProperties:function(a,b){var c=a.publish;c&&(this.requireProperties(c,a,b),a._publishLC=this.lowerCaseMap(c))},requireProperties:function(a,b){b.reflect=b.reflect||{};for(var c in a){var d=a[c];d&&void 0!==d.reflect&&(b.reflect[c]=Boolean(d.reflect),d=d.value),void 0!==d&&(b[c]=d)}},lowerCaseMap:function(a){var b={};for(var c in a)b[c.toLowerCase()]=c;return b},createPropertyAccessor:function(a,b){var c=this.prototype,d=a+"_",e=a+"Observable_";c[d]=c[a],Object.defineProperty(c,a,{get:function(){var a=this[e];return a&&a.deliver(),this[d]},set:function(c){if(b)return this[d];var f=this[e];if(f)return void f.setValue(c);var g=this[d];return this[d]=c,this.emitPropertyChangeRecord(a,c,g),c},configurable:!0})},createPropertyAccessors:function(a){var b=a._computedNames;if(b&&b.length)for(var c,d=0,e=b.length;e>d&&(c=b[d]);d++)this.createPropertyAccessor(c,!0);var b=a._publishNames;if(b&&b.length)for(var c,d=0,e=b.length;e>d&&(c=b[d]);d++)a.computed&&a.computed[c]||this.createPropertyAccessor(c)}};a.api.declaration.properties=b}(Polymer),function(a){var b="attributes",c=/\s|,/,d={inheritAttributesObjects:function(a){this.inheritObject(a,"publishLC"),this.inheritObject(a,"_instanceAttributes")},publishAttributes:function(a){var d=this.getAttribute(b);if(d)for(var e,f=a.publish||(a.publish={}),g=d.split(c),h=0,i=g.length;i>h;h++)e=g[h].trim(),e&&void 0===f[e]&&(f[e]=void 0)},accumulateInstanceAttributes:function(){for(var a,b=this.prototype._instanceAttributes,c=this.attributes,d=0,e=c.length;e>d&&(a=c[d]);d++)this.isInstanceAttribute(a.name)&&(b[a.name]=a.value)},isInstanceAttribute:function(a){return!this.blackList[a]&&"on-"!==a.slice(0,3)},blackList:{name:1,"extends":1,constructor:1,noscript:1,assetpath:1,"cache-csstext":1}};d.blackList[b]=1,a.api.declaration.attributes=d}(Polymer),function(a){var b=a.api.declaration.events,c=new PolymerExpressions,d=c.prepareBinding;c.prepareBinding=function(a,e,f){return b.prepareEventBinding(a,e,f)||d.call(c,a,e,f)};var e={syntax:c,fetchTemplate:function(){return this.querySelector("template")},templateContent:function(){var a=this.fetchTemplate();return a&&a.content},installBindingDelegate:function(a){a&&(a.bindingDelegate=this.syntax)}};a.api.declaration.mdv=e}(Polymer),function(a){function b(a){if(!Object.__proto__){var b=Object.getPrototypeOf(a);a.__proto__=b,d(b)&&(b.__proto__=Object.getPrototypeOf(b))}}var c=a.api,d=a.isBase,e=a.extend,f=window.ShadowDOMPolyfill,g={register:function(a,b){this.buildPrototype(a,b),this.registerPrototype(a,b),this.publishConstructor()},buildPrototype:function(b,c){var d=a.getRegisteredPrototype(b),e=this.generateBasePrototype(c);this.desugarBeforeChaining(d,e),this.prototype=this.chainPrototypes(d,e),this.desugarAfterChaining(b,c)},desugarBeforeChaining:function(a,b){a.element=this,this.publishAttributes(a,b),this.publishProperties(a,b),this.inferObservers(a),this.explodeObservers(a)},chainPrototypes:function(a,c){this.inheritMetaData(a,c);var d=this.chainObject(a,c);return b(d),d},inheritMetaData:function(a,b){this.inheritObject("observe",a,b),this.inheritObject("publish",a,b),this.inheritObject("reflect",a,b),this.inheritObject("_publishLC",a,b),this.inheritObject("_instanceAttributes",a,b),this.inheritObject("eventDelegates",a,b)},desugarAfterChaining:function(a,b){this.optimizePropertyMaps(this.prototype),this.createPropertyAccessors(this.prototype),this.installBindingDelegate(this.fetchTemplate()),this.installSheets(),this.resolveElementPaths(this),this.accumulateInstanceAttributes(),this.parseHostEvents(),this.addResolvePathApi(),f&&Platform.ShadowCSS.shimStyling(this.templateContent(),a,b),this.prototype.registerCallback&&this.prototype.registerCallback(this)},publishConstructor:function(){var a=this.getAttribute("constructor");a&&(window[a]=this.ctor)},generateBasePrototype:function(a){var b=this.findBasePrototype(a);if(!b){var b=HTMLElement.getPrototypeForTag(a);b=this.ensureBaseApi(b),h[a]=b}return b},findBasePrototype:function(a){return h[a]},ensureBaseApi:function(a){if(a.PolymerBase)return a;var b=Object.create(a);return c.publish(c.instance,b),this.mixinMethod(b,a,c.instance.mdv,"bind"),b},mixinMethod:function(a,b,c,d){var e=function(a){return b[d].apply(this,a)};a[d]=function(){return this.mixinSuper=e,c[d].apply(this,arguments)}},inheritObject:function(a,b,c){var d=b[a]||{};b[a]=this.chainObject(d,c[a])},registerPrototype:function(a,b){var c={prototype:this.prototype},d=this.findTypeExtension(b);d&&(c.extends=d),HTMLElement.register(a,this.prototype),this.ctor=document.registerElement(a,c)},findTypeExtension:function(a){if(a&&a.indexOf("-")<0)return a;var b=this.findBasePrototype(a);return b.element?this.findTypeExtension(b.element.extends):void 0}},h={};g.chainObject=Object.__proto__?function(a,b){return a&&b&&a!==b&&(a.__proto__=b),a}:function(a,b){if(a&&b&&a!==b){var c=Object.create(b);a=e(c,a)}return a},c.declaration.prototype=g}(Polymer),function(a){function b(a){return document.contains(a)?j:i}function c(){return i.length?i[0]:j[0]}function d(a){f.waitToReady=!0,Platform.endOfMicrotask(function(){HTMLImports.whenReady(function(){f.addReadyCallback(a),f.waitToReady=!1,f.check()})})}function e(a){if(void 0===a)return void f.ready();var b=setTimeout(function(){f.ready()},a);Polymer.whenReady(function(){clearTimeout(b)})}var f={wait:function(a){a.__queue||(a.__queue={},g.push(a))},enqueue:function(a,c,d){var e=a.__queue&&!a.__queue.check;return e&&(b(a).push(a),a.__queue.check=c,a.__queue.go=d),0!==this.indexOf(a)},indexOf:function(a){var c=b(a).indexOf(a);return c>=0&&document.contains(a)&&(c+=HTMLImports.useNative||HTMLImports.ready?i.length:1e9),c},go:function(a){var b=this.remove(a);b&&(a.__queue.flushable=!0,this.addToFlushQueue(b),this.check())},remove:function(a){var c=this.indexOf(a);if(0===c)return b(a).shift()},check:function(){var a=this.nextElement();return a&&a.__queue.check.call(a),this.canReady()?(this.ready(),!0):void 0},nextElement:function(){return c()},canReady:function(){return!this.waitToReady&&this.isEmpty()},isEmpty:function(){for(var a,b=0,c=g.length;c>b&&(a=g[b]);b++)if(a.__queue&&!a.__queue.flushable)return;return!0},addToFlushQueue:function(a){h.push(a)},flush:function(){if(!this.flushing){this.flushing=!0;for(var a;h.length;)a=h.shift(),a.__queue.go.call(a),a.__queue=null;this.flushing=!1}},ready:function(){var a=CustomElements.ready;CustomElements.ready=!1,this.flush(),CustomElements.useNative||CustomElements.upgradeDocumentTree(document),CustomElements.ready=a,Platform.flush(),requestAnimationFrame(this.flushReadyCallbacks)},addReadyCallback:function(a){a&&k.push(a)},flushReadyCallbacks:function(){if(k)for(var a;k.length;)(a=k.shift())()},waitingFor:function(){for(var a,b=[],c=0,d=g.length;d>c&&(a=g[c]);c++)a.__queue&&!a.__queue.flushable&&b.push(a);return b},waitToReady:!0},g=[],h=[],i=[],j=[],k=[];a.elements=g,a.waitingFor=f.waitingFor.bind(f),a.forceReady=e,a.queue=f,a.whenReady=a.whenPolymerReady=d}(Polymer),function(a){function b(a){return Boolean(HTMLElement.getPrototypeForTag(a))}function c(a){return a&&a.indexOf("-")>=0}var d=a.extend,e=a.api,f=a.queue,g=a.whenReady,h=a.getRegisteredPrototype,i=a.waitingForPrototype,j=d(Object.create(HTMLElement.prototype),{createdCallback:function(){this.getAttribute("name")&&this.init()},init:function(){this.name=this.getAttribute("name"),this.extends=this.getAttribute("extends"),f.wait(this),this.loadResources(),this.registerWhenReady()},registerWhenReady:function(){this.registered||this.waitingForPrototype(this.name)||this.waitingForQueue()||this.waitingForResources()||f.go(this)},_register:function(){c(this.extends)&&!b(this.extends)&&console.warn("%s is attempting to extend %s, an unregistered element or one that was not registered with Polymer.",this.name,this.extends),this.register(this.name,this.extends),this.registered=!0},waitingForPrototype:function(a){return h(a)?void 0:(i(a,this),this.handleNoScript(a),!0)},handleNoScript:function(a){this.hasAttribute("noscript")&&!this.noscript&&(this.noscript=!0,Polymer(a))},waitingForResources:function(){return this._needsResources},waitingForQueue:function(){return f.enqueue(this,this.registerWhenReady,this._register)},loadResources:function(){this._needsResources=!0,this.loadStyles(function(){this._needsResources=!1,this.registerWhenReady()}.bind(this))}});e.publish(e.declaration,j),g(function(){document.body.removeAttribute("unresolved"),document.dispatchEvent(new CustomEvent("polymer-ready",{bubbles:!0}))}),document.registerElement("polymer-element",{prototype:j})}(Polymer),function(a){function b(a,b){a?(document.head.appendChild(a),d(b)):b&&b()}function c(a,c){if(a&&a.length){for(var d,e,f=document.createDocumentFragment(),g=0,h=a.length;h>g&&(d=a[g]);g++)e=document.createElement("link"),e.rel="import",e.href=d,f.appendChild(e);b(f,c)}else c&&c()}var d=a.whenPolymerReady;a.import=c,a.importElements=b}(Polymer),function(){var a=document.createElement("polymer-element");a.setAttribute("name","auto-binding"),a.setAttribute("extends","template"),a.init(),Polymer("auto-binding",{createdCallback:function(){this.syntax=this.bindingDelegate=this.makeSyntax(),Polymer.whenPolymerReady(function(){this.model=this,this.setAttribute("bind",""),this.async(function(){this.marshalNodeReferences(this.parentNode),this.fire("template-bound")})}.bind(this))},makeSyntax:function(){var a=Object.create(Polymer.api.declaration.events),b=this;a.findController=function(){return b.model};var c=new PolymerExpressions,d=c.prepareBinding;return c.prepareBinding=function(b,e,f){return a.prepareEventBinding(b,e,f)||d.call(c,b,e,f)},c}})}(); //# sourceMappingURL=polymer.js.map</script> <!--<link rel="import" href="../polymer-dev/polymer.html">--> - -<polymer-element name="core-header-panel" assetpath="polymer/bower_components/core-header-panel/"> -<template> - - <style>/* +<!-- Copyright (c) 2014 The Polymer Project Authors. All rights reserved. This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt Code distributed by Google as part of the polymer project is also subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt -*/ - -:host { - display: block; - position: relative; -} +--> +<!-- -#outerContainer { - position: absolute; - top: 0; - right: 0; - bottom: 0; - left: 0; -} +The `core-icon` element displays an icon. By default an icon renders as a 24px square. -#mainPanel { - position: relative; -} +Example using src: -#mainContainer { - position: relative; - overflow-y: auto; - overflow-x: hidden; - -webkit-overflow-scrolling: touch; -} + <core-icon src="star.png"></core-icon> -#dropShadow { - position: absolute; - top: 0; - left: 0; - right: 0; - height: 6px; - box-shadow: inset 0px 5px 6px -3px rgba(0, 0, 0, 0.4); -} +Example setting size to 32px x 32px: -#dropShadow.hidden { - display: none; -} + <core-icon class="big" src="big_star.png"></core-icon> -/* -mode: scroll -*/ -:host([mode=scroll]) #mainContainer { - overflow: visible; -} + <style> + .big { + height: 32px; + width: 32px; + } + </style> -:host([mode=scroll]) #outerContainer { - overflow-y: auto; - overflow-x: hidden; - -webkit-overflow-scrolling: touch; -} +The core elements include several sets of icons. +To use the default set of icons, import `core-icons.html` and use the `icon` attribute to specify an icon: -/* -mode: cover -*/ -:host([mode=cover]) #mainPanel { - position: static; -} + <!-- import default iconset and core-icon --> + <link rel="import" href="/components/core-icons/core-icons.html"> -:host([mode=cover]) #mainContainer { - position: absolute; - top: 0; - right: 0; - bottom: 0; - left: 0; -} + <core-icon icon="menu"></core-icon> + +To use a different built-in set of icons, import `core-icons/<iconset>-icons.html`, and +specify the icon as `<iconset>:<icon>`. For example: -:host([mode=cover]) #dropShadow { - position: static; - width: 100%; -} -</style> + <!-- import communication iconset and core-icon --> + <link rel="import" href="/components/core-icons/communication-icons.html"> - <div id="outerContainer" vertical="" layout=""> + <core-icon icon="communication:email"></core-icon> + +You can also create custom icon sets of bitmap or SVG icons. - <content id="headerContent" select="core-toolbar, .core-header"></content> +Example of using an icon named `cherry` from a custom iconset with the ID `fruit`: - <div id="mainPanel" flex="" vertical="" layout=""> + <core-icon icon="fruit:cherry"></core-icon> - <div id="mainContainer" flex?="{{mode !== 'cover'}}"> - <content id="mainContent" select="*"></content> - </div> +See [core-iconset](#core-iconset) and [core-iconset-svg](#core-iconset-svg) for more information about +how to create a custom iconset. - <div id="dropShadow"></div> +See [core-icons](http://www.polymer-project.org/components/core-icons/demo.html) for the default set of icons. - </div> +@group Polymer Core Elements +@element core-icon +@homepage polymer.github.io +--> +<!-- +Copyright (c) 2014 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--> - </div> +<!-- +/** + * @group Polymer Core Elements + * + * The `core-iconset` element allows users to define their own icon sets. + * The `src` property specifies the url of the icon image. Multiple icons may + * be included in this image and they may be organized into rows. + * The `icons` property is a space separated list of names corresponding to the + * icons. The names must be ordered as the icons are ordered in the icon image. + * Icons are expected to be square and are the size specified by the `iconSize` + * property. The `width` property corresponds to the width of the icon image + * and must be specified if icons are arranged into multiple rows in the image. + * + * All `core-iconset` elements are available for use by other `core-iconset` + * elements via a database keyed by id. Typically, an element author that wants + * to support a set of custom icons uses a `core-iconset` to retrieve + * and use another, user-defined iconset. + * + * Example: + * + * <core-iconset id="my-icons" src="my-icons.png" width="96" iconSize="24" + * icons="location place starta stopb bus car train walk"> + * </core-iconset> + * + * This will automatically register the icon set "my-icons" to the iconset + * database. To use these icons from within another element, make a + * `core-iconset` element and call the `byId` method to retrieve a + * given iconset. To apply a particular icon to an element, use the + * `applyIcon` method. For example: + * + * iconset.applyIcon(iconNode, 'car'); + * + * Themed icon sets are also supported. The `core-iconset` can contain child + * `property` elements that specify a theme with an offsetX and offsetY of the + * theme within the icon resource. For example. + * + * <core-iconset id="my-icons" src="my-icons.png" width="96" iconSize="24" + * icons="location place starta stopb bus car train walk"> + * <property theme="special" offsetX="256" offsetY="24"></property> + * </core-iconset> + * + * Then a themed icon can be applied like this: + * + * iconset.applyIcon(iconNode, 'car', 'special'); + * + * @element core-iconset + * @extends core-meta + * @homepage github.io + */ +--> -</template> -<script> +<!-- +Copyright (c) 2014 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--> - Polymer('core-header-panel', { +<!-- +`core-meta` provides a method of constructing a self-organizing database. +It is useful to collate element meta-data for things like catalogs and for +designer. - /** - * Fired when the content has been scrolled. `event.detail.target` returns - * the scrollable element which you can use to access scroll info such as - * `scrollTop`. - * - * <core-header-panel on-scroll="{{scrollHandler}}"> - * ... - * </core-header-panel> - * - * - * scrollHandler: function(event) { - * var scroller = event.detail.target; - * console.log(scroller.scrollTop); - * } - * - * @event scroll - */ +Example, an element folder has a `metadata.html` file in it, that contains a +`core-meta`, something like this: - publish: { + <core-meta id="my-element" label="My Element"> + <property name="color" value="blue"></property> + </core-meta> + +An application can import as many of these files as it wants, and then use +`core-meta` again to access the collected data. + + <script> + var meta = document.createElement('core-meta'); + console.log(meta.list); // dump a list of all meta-data elements that have been created + </script> + +Use `byId(id)` to retrive a specific core-meta. + + <script> + var meta = document.createElement('core-meta'); + console.log(meta.byId('my-element')); + </script> + +By default all meta-data are stored in a single databse. If your meta-data +have different types and want them to be stored separately, use `type` to +differentiate them. + +Example: + + <core-meta id="x-foo" type="xElt"></core-meta> + <core-meta id="x-bar" type="xElt"></core-meta> + <core-meta id="y-bar" type="yElt"></core-meta> + + <script> + var meta = document.createElement('core-meta'); + meta.type = 'xElt'; + console.log(meta.list); + </script> + +@group Polymer Core Elements +@element core-meta +@homepage github.io +--> + + + +<polymer-element name="core-meta" attributes="label type" hidden assetpath="polymer/bower_components/core-meta/"> +<script> + + (function() { + + var SKIP_ID = 'meta'; + var metaData = {}, metaArray = {}; + + Polymer('core-meta', { + /** - * Controls header and scrolling behavior. Options are - * `standard`, `seamed`, `waterfall`, `waterfall-tall`, `scroll` and - * `cover`. Default is `standard`. - * - * `standard`: The header is a step above the panel. The header will consume the - * panel at the point of entry, preventing it from passing through to the - * opposite side. - * - * `seamed`: The header is presented as seamed with the panel. - * - * `waterfall`: Similar to standard mode, but header is initially presented as - * seamed with panel, but then separates to form the step. - * - * `waterfall-tall`: The header is initially taller (`tall` class is added to - * the header). As the user scrolls, the header separates (forming an edge) - * while condensing (`tall` class is removed from the header). - * - * `scroll`: The header keeps its seam with the panel, and is pushed off screen. - * - * `cover`: The panel covers the whole `core-header-panel` including the - * header. This allows user to style the panel in such a way that the panel is - * partially covering the header. - * - * <style> - * core-header-panel[mode=cover]::shadow #mainContainer { - * left: 80px; - * } - * .content { - * margin: 60px 60px 60px 0; - * } - * </style> + * The type of meta-data. All meta-data with the same type with be + * stored together. + * + * @attribute type + * @type string + * @default 'default' + */ + type: 'default', + + alwaysPrepare: true, + + ready: function() { + this.register(this.id); + }, + + get metaArray() { + var t = this.type; + if (!metaArray[t]) { + metaArray[t] = []; + } + return metaArray[t]; + }, + + get metaData() { + var t = this.type; + if (!metaData[t]) { + metaData[t] = {}; + } + return metaData[t]; + }, + + register: function(id, old) { + if (id && id !== SKIP_ID) { + this.unregister(this, old); + this.metaData[id] = this; + this.metaArray.push(this); + } + }, + + unregister: function(meta, id) { + delete this.metaData[id || meta.id]; + var i = this.metaArray.indexOf(meta); + if (i >= 0) { + this.metaArray.splice(i, 1); + } + }, + + /** + * Returns a list of all meta-data elements with the same type. + * + * @property list + * @type array + * @default [] + */ + get list() { + return this.metaArray; + }, + + /** + * Retrieves meta-data by ID. * - * <core-header-panel mode="cover"> - * <core-appbar class="tall"> - * <core-icon-button icon="menu"></core-icon-button> - * </core-appbar> - * <div class="content"></div> - * </core-header-panel> + * @method byId + * @param {String} id The ID of the meta-data to be returned. + * @returns Returns meta-data. + */ + byId: function(id) { + return this.metaData[id]; + } + + }); + + })(); + +</script> +</polymer-element> + + +<polymer-element name="core-iconset" extends="core-meta" attributes="src width icons iconSize" assetpath="polymer/bower_components/core-iconset/"> + + <script> + + Polymer('core-iconset', { + + /** + * The URL of the iconset image. * - * @attribute mode + * @attribute src * @type string * @default '' */ - mode: {value: '', reflect: true}, + src: '', /** - * The class used in waterfall-tall mode. Change this if the header - * accepts a different class for toggling height, e.g. "medium-tall" + * The width of the iconset image. This must only be specified if the + * icons are arranged into separate rows inside the image. * - * @attribute tallClass + * @attribute width + * @type number + * @default 0 + */ + width: 0, + + /** + * A space separated list of names corresponding to icons in the iconset + * image file. This list must be ordered the same as the icon images + * in the image file. + * + * @attribute icons * @type string - * @default 'tall' + * @default '' */ - tallClass: 'tall', + icons: '', /** - * If true, the drop-shadow is always shown no matter what mode is set to. + * The size of an individual icon. Note that icons must be square. * - * @attribute shadow - * @type boolean - * @default false + * @attribute iconSize + * @type number + * @default 24 */ - shadow: false - }, + iconSize: 24, - animateDuration: 200, + /** + * The horizontal offset of the icon images in the inconset src image. + * This is typically used if the image resource contains additional images + * beside those intended for the iconset. + * + * @attribute offsetX + * @type number + * @default 0 + */ + offsetX: 0, + /** + * The vertical offset of the icon images in the inconset src image. + * This is typically used if the image resource contains additional images + * beside those intended for the iconset. + * + * @attribute offsetY + * @type number + * @default 0 + */ + offsetY: 0, + type: 'iconset', - modeConfigs: { - shadowMode: {'waterfall': 1, 'waterfall-tall': 1}, - noShadow: {'seamed': 1, 'cover': 1, 'scroll': 1}, - tallMode: {'waterfall-tall': 1}, - outerScroll: {'scroll': 1} - }, - - ready: function() { - this.scrollHandler = this.scroll.bind(this); - this.addListener(); - }, - - detached: function() { - this.removeListener(this.mode); - }, - - addListener: function() { - this.scroller.addEventListener('scroll', this.scrollHandler); - }, - - removeListener: function(mode) { - var s = this.getScrollerForMode(mode); - s.removeEventListener('scroll', this.scrollHandler); - }, - - domReady: function() { - this.async('scroll'); - }, - - modeChanged: function(old) { - var header = this.header; - if (header) { - var configs = this.modeConfigs; - // in tallMode it may add tallClass to the header; so do the cleanup - // when mode is changed from tallMode to not tallMode - if (configs.tallMode[old] && !configs.tallMode[this.mode]) { - header.classList.remove(this.tallClass); - this.async(function() { - header.classList.remove('animate'); - }, null, this.animateDuration); - } else { - header.classList.toggle('animate', configs.tallMode[this.mode]); + created: function() { + this.iconMap = {}; + this.iconNames = []; + this.themes = {}; + }, + + ready: function() { + // TODO(sorvell): ensure iconset's src is always relative to the main + // document + if (this.src && (this.ownerDocument !== document)) { + this.src = this.resolvePath(this.src, this.ownerDocument.baseURI); } - } - if (configs.outerScroll[this.mode] || configs.outerScroll[old]) { - this.removeListener(old); - this.addListener(); - } - this.scroll(); - }, - - get header() { - return this.$.headerContent.getDistributedNodes()[0]; - }, - - getScrollerForMode: function(mode) { - return this.modeConfigs.outerScroll[mode] ? - this.$.outerContainer : this.$.mainContainer; - }, - - /** - * Returns the scrollable element. - * - * @property scroller - * @type Object - */ - get scroller() { - return this.getScrollerForMode(this.mode); - }, + this.super(); + this.updateThemes(); + }, - scroll: function() { - var configs = this.modeConfigs; - var main = this.$.mainContainer; - var header = this.header; + iconsChanged: function() { + var ox = this.offsetX; + var oy = this.offsetY; + this.icons && this.icons.split(/\s+/g).forEach(function(name, i) { + this.iconNames.push(name); + this.iconMap[name] = { + offsetX: ox, + offsetY: oy + } + if (ox + this.iconSize < this.width) { + ox += this.iconSize; + } else { + ox = this.offsetX; + oy += this.iconSize; + } + }, this); + }, - var sTop = main.scrollTop; - var atTop = sTop === 0; + updateThemes: function() { + var ts = this.querySelectorAll('property[theme]'); + ts && ts.array().forEach(function(t) { + this.themes[t.getAttribute('theme')] = { + offsetX: parseInt(t.getAttribute('offsetX')) || 0, + offsetY: parseInt(t.getAttribute('offsetY')) || 0 + }; + }, this); + }, - this.$.dropShadow.classList.toggle('hidden', !this.shadow && - (atTop && configs.shadowMode[this.mode] || configs.noShadow[this.mode])); + // TODO(ffu): support retrived by index e.g. getOffset(10); + /** + * Returns an object containing `offsetX` and `offsetY` properties which + * specify the pixel locaion in the iconset's src file for the given + * `icon` and `theme`. It's uncommon to call this method. It is useful, + * for example, to manually position a css backgroundImage to the proper + * offset. It's more common to use the `applyIcon` method. + * + * @method getOffset + * @param {String|Number} icon The name of the icon or the index of the + * icon within in the icon image. + * @param {String} theme The name of the theme. + * @returns {Object} An object specifying the offset of the given icon + * within the icon resource file; `offsetX` is the horizontal offset and + * `offsetY` is the vertical offset. Both values are in pixel units. + */ + getOffset: function(icon, theme) { + var i = this.iconMap[icon]; + if (!i) { + var n = this.iconNames[Number(icon)]; + i = this.iconMap[n]; + } + var t = this.themes[theme]; + if (i && t) { + return { + offsetX: i.offsetX + t.offsetX, + offsetY: i.offsetY + t.offsetY + } + } + return i; + }, - if (header && configs.tallMode[this.mode]) { - header.classList.toggle(this.tallClass, atTop || - header.classList.contains(this.tallClass) && - main.scrollHeight < this.$.outerContainer.offsetHeight); + /** + * Applies an icon to the given element as a css background image. This + * method does not size the element, and it's often necessary to set + * the element's height and width so that the background image is visible. + * + * @method applyIcon + * @param {Element} element The element to which the background is + * applied. + * @param {String|Number} icon The name or index of the icon to apply. + * @param {Number} scale (optional, defaults to 1) A scaling factor + * with which the icon can be magnified. + * @return {Element} The icon element. + */ + applyIcon: function(element, icon, scale) { + var offset = this.getOffset(icon); + scale = scale || 1; + if (element && offset) { + var icon = element._icon || document.createElement('div'); + var style = icon.style; + style.backgroundImage = 'url(' + this.src + ')'; + style.backgroundPosition = (-offset.offsetX * scale + 'px') + + ' ' + (-offset.offsetY * scale + 'px'); + style.backgroundSize = scale === 1 ? 'auto' : + this.width * scale + 'px'; + if (icon.parentNode !== element) { + element.appendChild(icon); + } + return icon; + } } - this.fire('scroll', {target: this.scroller}, this, false); - } + }); - }); + </script> -</script> </polymer-element> -<!-- -Copyright (c) 2014 The Polymer Project Authors. All rights reserved. + +<style shim-shadowdom="">/* Copyright (c) 2014 The Polymer Project Authors. All rights reserved. This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt Code distributed by Google as part of the polymer project is also -subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt ---> - -<!-- -`core-toolbar` is a horizontal bar containing elements that can be used for -label, navigation, search and actions. - - <core-toolbar> - <core-icon-button icon="menu" on-tap="{{menuAction}}"></core-icon-button> - <div flex>Title</div> - <core-icon-button icon="more" on-tap="{{moreAction}}"></core-icon-button> - </core-toolbar> +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt */ -`core-toolbar` has a standard height, but can made be taller by setting `tall` -class on the `core-toolbar`. This will make the toolbar 3x the normal height. +html /deep/ core-icon { + display: inline-block; + vertical-align: middle; + background-repeat: no-repeat; + fill: currentcolor; + position: relative; + height: 24px; + width: 24px; +}</style> - <core-toolbar class="tall"> - <core-icon-button icon="menu"></core-icon-button> - </core-toolbar> - -Apply `medium-tall` class to make the toolbar medium tall. This will make the -toolbar 2x the normal height. +<polymer-element name="core-icon" attributes="src icon alt" assetpath="polymer/bower_components/core-icon/"> +<script> +(function() { + + // mono-state + var meta; + + Polymer('core-icon', { - <core-toolbar class="medium-tall"> - <core-icon-button icon="menu"></core-icon-button> - </core-toolbar> + /** + * The URL of an image for the icon. If the src property is specified, + * the icon property should not be. + * + * @attribute src + * @type string + * @default '' + */ + src: '', -When taller, elements can pin to either the top (default), middle or bottom. + /** + * Specifies the icon name or index in the set of icons available in + * the icon's icon set. If the icon property is specified, + * the src property should not be. + * + * @attribute icon + * @type string + * @default '' + */ + icon: '', - <core-toolbar class="tall"> - <core-icon-button icon="menu"></core-icon-button> - <div class="middle indent">Middle Title</div> - <div class="bottom indent">Bottom Title</div> - </core-toolbar> - -To make an element completely fit at the bottom of the toolbar, use `fit` along -with `bottom`. + /** + * Alternative text content for accessibility support. + * If alt is present and not empty, it will set the element's role to img and add an aria-label whose content matches alt. + * If alt is present and is an empty string, '', it will hide the element from the accessibility layer + * If alt is not present, it will set the element's role to img and the element will fallback to using the icon attribute for its aria-label. + * + * @attribute alt + * @type string + * @default '' + */ + alt: null, - <core-toolbar class="tall"> - <div id="progressBar" class="bottom fit"></div> - </core-toolbar> - -`core-toolbar` adapts to mobile/narrow layout when there is a `core-narrow` class set -on itself or any of its ancestors. + observe: { + 'icon': 'updateIcon', + 'alt': 'updateAlt' + }, -@group Polymer Core Elements -@element core-toolbar -@homepage github.io ---> + defaultIconset: 'icons', + + ready: function() { + if (!meta) { + meta = document.createElement('core-iconset'); + } + // Allow user-provided `aria-label` in preference to any other text alternative. + if (this.hasAttribute('aria-label')) { + // Set `role` if it has not been overridden. + if (!this.hasAttribute('role')) { + this.setAttribute('role', 'img'); + } + return; + } + this.updateAlt(); + }, + srcChanged: function() { + var icon = this._icon || document.createElement('div'); + icon.textContent = ''; + icon.setAttribute('fit', ''); + icon.style.backgroundImage = 'url(' + this.src + ')'; + icon.style.backgroundPosition = 'center'; + icon.style.backgroundSize = '100%'; + if (!icon.parentNode) { + this.appendChild(icon); + } + this._icon = icon; + }, -<polymer-element name="core-toolbar" assetpath="polymer/bower_components/core-toolbar/"> -<template> + getIconset: function(name) { + return meta.byId(name || this.defaultIconset); + }, - <style>/* + updateIcon: function(oldVal, newVal) { + if (!this.icon) { + this.updateAlt(); + return; + } + var parts = String(this.icon).split(':'); + var icon = parts.pop(); + if (icon) { + var set = this.getIconset(parts.pop()); + if (set) { + this._icon = set.applyIcon(this, icon); + if (this._icon) { + this._icon.setAttribute('fit', ''); + } + } + } + // Check to see if we're using the old icon's name for our a11y fallback + if (oldVal) { + if (oldVal.split(':').pop() == this.getAttribute('aria-label')) { + this.updateAlt(); + } + } + }, + + updateAlt: function() { + // Respect the user's decision to remove this element from + // the a11y tree + if (this.getAttribute('aria-hidden')) { + return; + } + + // Remove element from a11y tree if `alt` is empty, otherwise + // use `alt` as `aria-label`. + if (this.alt === '') { + this.setAttribute('aria-hidden', 'true'); + if (this.hasAttribute('role')) { + this.removeAttribute('role'); + } + if (this.hasAttribute('aria-label')) { + this.removeAttribute('aria-label'); + } + } else { + this.setAttribute('aria-label', this.alt || + this.icon.split(':').pop()); + if (!this.hasAttribute('role')) { + this.setAttribute('role', 'img'); + } + if (this.hasAttribute('aria-hidden')) { + this.removeAttribute('aria-hidden'); + } + } + } + + }); + +})(); +</script> + +</polymer-element> + +<!-- Copyright (c) 2014 The Polymer Project Authors. All rights reserved. This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt Code distributed by Google as part of the polymer project is also subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt -*/ +--> -:host { - /* technical */ - display: block; - position: relative; - box-sizing: border-box; - -moz-box-sizing: border-box; - /* size */ - height: 64px; - /* typography */ - font-size: 1.3em; - /* background */ - background-color: #CFD8DC; -} +<!-- +`paper-ripple` provides a visual effect that other paper elements can +use to simulate a rippling effect emanating from the point of contact. The +effect can be visualized as a concentric circle with motion. -:host(.animate) { - /* transition */ - transition: height 0.18s ease-in; -} +Example: -:host(.medium-tall) { - height: 128px; -} + <paper-ripple></paper-ripple> -:host(.tall) { - height: 192px; -} +`paper-ripple` listens to "down" and "up" events so it would display ripple +effect when touches on it. You can also defeat the default behavior and +manually route the down and up actions to the ripple element. Note that it is +important if you call downAction() you will have to make sure to call upAction() +so that `paper-ripple` would end the animation loop. -.toolbar-tools { - position: relative; - height: 64px; - padding: 0 8px; - pointer-events: none; -} +Example: -/* narrow layout */ -:host(.core-narrow), -:host-context(.core-narrow) { - height: 56px; -} + <paper-ripple id="ripple" style="pointer-events: none;"></paper-ripple> + ... + downAction: function(e) { + this.$.ripple.downAction({x: e.x, y: e.y}); + }, + upAction: function(e) { + this.$.ripple.upAction(); + } -polyfill-next-selector { content: ':host.core-narrow.medium-tall, .core-narrow :host.medium-tall'; } -:host(.core-narrow.medium-tall), -:host-context(.core-narrow):host(.medium-tall) { - height: 112px; -} +Styling ripple effect: -polyfill-next-selector { content: ':host.core-narrow.tall, .core-narrow :host.tall'; } -:host(.core-narrow.tall), -:host-context(.core-narrow):host(.tall) { - height: 168px; -} + Use CSS color property to style the ripple: -polyfill-next-selector { content: ':host.core-narrow .toolbar-tools, .core-narrow :host .toolbar-tools'; } -:host(.core-narrow) .toolbar-tools, -:host-context(.core-narrow) .toolbar-tools { - height: 56px; - padding: 0; -} + paper-ripple { + color: #4285f4; + } -/* middle bar */ -#middleBar { - position: absolute; - top: 0; - right: 0; - left: 0; -} + Note that CSS color property is inherited so it is not required to set it on + the `paper-ripple` element directly. -:host(.tall, .medium-tall) #middleBar { - -webkit-transform: translateY(100%); - transform: translateY(100%); -} +Apply `recenteringTouch` class to make the recentering rippling effect. -/* bottom bar */ -#bottomBar { - position: absolute; - right: 0; - bottom: 0; - left: 0; -} + <paper-ripple class="recenteringTouch"></paper-ripple> -/* make elements (e.g. buttons) respond to mouse/touch events */ -polyfill-next-selector { content: '.toolbar-tools > *'; } -::content > * { - pointer-events: auto; -} +Apply `circle` class to make the rippling effect within a circle. -/* elements spacing */ -polyfill-next-selector { content: '.toolbar-tools > *'; } -::content > * { - margin: 0 8px; -} + <paper-ripple class="circle"></paper-ripple> -/* misc helpers */ -polyfill-next-selector { content: '.toolbar-tools > .fit'; } -::content > .fit { - position: absolute; - top: auto; - right: 0; - bottom: 0; - left: 0; - width: auto; - margin: 0; -} +@group Paper Elements +@element paper-ripple +@homepage github.io +--> -polyfill-next-selector { content: ':host .indent'; } -::content > .indent { - margin-left: 60px; -} -</style> - <div id="bottomBar" class="toolbar-tools" center="" horizontal="" layout=""> - <content select=".bottom"></content> - </div> - - <div id="middleBar" class="toolbar-tools" center="" horizontal="" layout=""> - <content select=".middle"></content> - </div> - <div id="topBar" class="toolbar-tools" center="" horizontal="" layout=""> - <content></content> - </div> +<polymer-element name="paper-ripple" attributes="initialOpacity opacityDecayVelocity" assetpath="polymer/bower_components/paper-ripple/"> +<template> -</template> -<script>Polymer('core-toolbar');</script></polymer-element> + <style> -<!-- -Copyright (c) 2014 The Polymer Project Authors. All rights reserved. -This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt -The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt -The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt -Code distributed by Google as part of the polymer project is also -subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt ---> + :host { + display: block; + position: relative; + border-radius: inherit; + overflow: hidden; + } -<!-- -`core-icon-button` is an icon with button behaviors. + :host-context([noink]) { + pointer-events: none; + } - <core-icon-button src="star.png"></core-icon-button> + #bg, #waves, .wave-container, .wave { + pointer-events: none; + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + } -`core-icon-button` includes a default icon set. Use `icon` to specify -which icon from the icon set to use. + #bg, .wave { + opacity: 0; + } - <core-icon-button icon="menu"></core-icon-button> + #waves, .wave { + overflow: hidden; + } -See [`core-iconset`](#core-iconset) for more information about -how to use a custom icon set. + .wave-container, .wave { + border-radius: 50%; + } -@group Polymer Core Elements -@element core-icon-button -@homepage github.io ---> + :host(.circle) #bg, + :host(.circle) #waves { + border-radius: 50%; + } -<!-- -Copyright (c) 2014 The Polymer Project Authors. All rights reserved. -This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt -The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt -The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt -Code distributed by Google as part of the polymer project is also -subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt ---> -<!-- + :host(.circle) .wave-container { + overflow: hidden; + } -The `core-icon` element displays an icon. By default an icon renders as a 24px square. + </style> -Example using src: + <div id="bg"></div> + <div id="waves"> + </div> - <core-icon src="star.png"></core-icon> +</template> +<script> -Example setting size to 32px x 32px: + (function() { - <core-icon class="big" src="big_star.png"></core-icon> + var waveMaxRadius = 150; + // + // INK EQUATIONS + // + function waveRadiusFn(touchDownMs, touchUpMs, anim) { + // Convert from ms to s. + var touchDown = touchDownMs / 1000; + var touchUp = touchUpMs / 1000; + var totalElapsed = touchDown + touchUp; + var ww = anim.width, hh = anim.height; + // use diagonal size of container to avoid floating point math sadness + var waveRadius = Math.min(Math.sqrt(ww * ww + hh * hh), waveMaxRadius) * 1.1 + 5; + var duration = 1.1 - .2 * (waveRadius / waveMaxRadius); + var tt = (totalElapsed / duration); - <style> - .big { - height: 32px; - width: 32px; + var size = waveRadius * (1 - Math.pow(80, -tt)); + return Math.abs(size); + } + + function waveOpacityFn(td, tu, anim) { + // Convert from ms to s. + var touchDown = td / 1000; + var touchUp = tu / 1000; + var totalElapsed = touchDown + touchUp; + + if (tu <= 0) { // before touch up + return anim.initialOpacity; } - </style> + return Math.max(0, anim.initialOpacity - touchUp * anim.opacityDecayVelocity); + } -The core elements include several sets of icons. -To use the default set of icons, import `core-icons.html` and use the `icon` attribute to specify an icon: + function waveOuterOpacityFn(td, tu, anim) { + // Convert from ms to s. + var touchDown = td / 1000; + var touchUp = tu / 1000; - <!-- import default iconset and core-icon --> - <link rel="import" href="/components/core-icons/core-icons.html"> + // Linear increase in background opacity, capped at the opacity + // of the wavefront (waveOpacity). + var outerOpacity = touchDown * 0.3; + var waveOpacity = waveOpacityFn(td, tu, anim); + return Math.max(0, Math.min(outerOpacity, waveOpacity)); + } - <core-icon icon="menu"></core-icon> - -To use a different built-in set of icons, import `core-icons/<iconset>-icons.html`, and -specify the icon as `<iconset>:<icon>`. For example: + // Determines whether the wave should be completely removed. + function waveDidFinish(wave, radius, anim) { + var waveOpacity = waveOpacityFn(wave.tDown, wave.tUp, anim); - <!-- import communication iconset and core-icon --> - <link rel="import" href="/components/core-icons/communication-icons.html"> + // If the wave opacity is 0 and the radius exceeds the bounds + // of the element, then this is finished. + return waveOpacity < 0.01 && radius >= Math.min(wave.maxRadius, waveMaxRadius); + }; - <core-icon icon="communication:email"></core-icon> - -You can also create custom icon sets of bitmap or SVG icons. + function waveAtMaximum(wave, radius, anim) { + var waveOpacity = waveOpacityFn(wave.tDown, wave.tUp, anim); -Example of using an icon named `cherry` from a custom iconset with the ID `fruit`: + return waveOpacity >= anim.initialOpacity && radius >= Math.min(wave.maxRadius, waveMaxRadius); + } - <core-icon icon="fruit:cherry"></core-icon> + // + // DRAWING + // + function drawRipple(ctx, x, y, radius, innerAlpha, outerAlpha) { + // Only animate opacity and transform + if (outerAlpha !== undefined) { + ctx.bg.style.opacity = outerAlpha; + } + ctx.wave.style.opacity = innerAlpha; -See [core-iconset](#core-iconset) and [core-iconset-svg](#core-iconset-svg) for more information about -how to create a custom iconset. + var s = radius / (ctx.containerSize / 2); + var dx = x - (ctx.containerWidth / 2); + var dy = y - (ctx.containerHeight / 2); -See [core-icons](http://www.polymer-project.org/components/core-icons/demo.html) for the default set of icons. + ctx.wc.style.webkitTransform = 'translate3d(' + dx + 'px,' + dy + 'px,0)'; + ctx.wc.style.transform = 'translate3d(' + dx + 'px,' + dy + 'px,0)'; -@group Polymer Core Elements -@element core-icon -@homepage polymer.github.io ---> -<!-- -Copyright (c) 2014 The Polymer Project Authors. All rights reserved. -This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt -The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt -The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt -Code distributed by Google as part of the polymer project is also -subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt ---> + // 2d transform for safari because of border-radius and overflow:hidden clipping bug. + // https://bugs.webkit.org/show_bug.cgi?id=98538 + ctx.wave.style.webkitTransform = 'scale(' + s + ',' + s + ')'; + ctx.wave.style.transform = 'scale3d(' + s + ',' + s + ',1)'; + } -<!-- -/** - * @group Polymer Core Elements - * - * The `core-iconset` element allows users to define their own icon sets. - * The `src` property specifies the url of the icon image. Multiple icons may - * be included in this image and they may be organized into rows. - * The `icons` property is a space separated list of names corresponding to the - * icons. The names must be ordered as the icons are ordered in the icon image. - * Icons are expected to be square and are the size specified by the `iconSize` - * property. The `width` property corresponds to the width of the icon image - * and must be specified if icons are arranged into multiple rows in the image. - * - * All `core-iconset` elements are available for use by other `core-iconset` - * elements via a database keyed by id. Typically, an element author that wants - * to support a set of custom icons uses a `core-iconset` to retrieve - * and use another, user-defined iconset. - * - * Example: - * - * <core-iconset id="my-icons" src="my-icons.png" width="96" iconSize="24" - * icons="location place starta stopb bus car train walk"> - * </core-iconset> - * - * This will automatically register the icon set "my-icons" to the iconset - * database. To use these icons from within another element, make a - * `core-iconset` element and call the `byId` method to retrieve a - * given iconset. To apply a particular icon to an element, use the - * `applyIcon` method. For example: - * - * iconset.applyIcon(iconNode, 'car'); - * - * Themed icon sets are also supported. The `core-iconset` can contain child - * `property` elements that specify a theme with an offsetX and offsetY of the - * theme within the icon resource. For example. - * - * <core-iconset id="my-icons" src="my-icons.png" width="96" iconSize="24" - * icons="location place starta stopb bus car train walk"> - * <property theme="special" offsetX="256" offsetY="24"></property> - * </core-iconset> - * - * Then a themed icon can be applied like this: - * - * iconset.applyIcon(iconNode, 'car', 'special'); - * - * @element core-iconset - * @extends core-meta - * @homepage github.io - */ ---> + // + // SETUP + // + function createWave(elem) { + var elementStyle = window.getComputedStyle(elem); + var fgColor = elementStyle.color; -<!-- -Copyright (c) 2014 The Polymer Project Authors. All rights reserved. -This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt -The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt -The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt -Code distributed by Google as part of the polymer project is also -subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt ---> + var inner = document.createElement('div'); + inner.style.backgroundColor = fgColor; + inner.classList.add('wave'); -<!-- -`core-meta` provides a method of constructing a self-organizing database. -It is useful to collate element meta-data for things like catalogs and for -designer. - -Example, an element folder has a `metadata.html` file in it, that contains a -`core-meta`, something like this: - - <core-meta id="my-element" label="My Element"> - <property name="color" value="blue"></property> - </core-meta> - -An application can import as many of these files as it wants, and then use -`core-meta` again to access the collected data. - - <script> - var meta = document.createElement('core-meta'); - console.log(meta.list); // dump a list of all meta-data elements that have been created - </script> - -Use `byId(id)` to retrive a specific core-meta. - - <script> - var meta = document.createElement('core-meta'); - console.log(meta.byId('my-element')); - </script> - -By default all meta-data are stored in a single databse. If your meta-data -have different types and want them to be stored separately, use `type` to -differentiate them. - -Example: - - <core-meta id="x-foo" type="xElt"></core-meta> - <core-meta id="x-bar" type="xElt"></core-meta> - <core-meta id="y-bar" type="yElt"></core-meta> - - <script> - var meta = document.createElement('core-meta'); - meta.type = 'xElt'; - console.log(meta.list); - </script> + var outer = document.createElement('div'); + outer.classList.add('wave-container'); + outer.appendChild(inner); -@group Polymer Core Elements -@element core-meta -@homepage github.io ---> + var container = elem.$.waves; + container.appendChild(outer); + elem.$.bg.style.backgroundColor = fgColor; + var wave = { + bg: elem.$.bg, + wc: outer, + wave: inner, + waveColor: fgColor, + maxRadius: 0, + isMouseDown: false, + mouseDownStart: 0.0, + mouseUpStart: 0.0, + tDown: 0, + tUp: 0 + }; + return wave; + } -<polymer-element name="core-meta" attributes="label type" hidden assetpath="polymer/bower_components/core-meta/"> -<script> + function removeWaveFromScope(scope, wave) { + if (scope.waves) { + var pos = scope.waves.indexOf(wave); + scope.waves.splice(pos, 1); + // FIXME cache nodes + wave.wc.remove(); + } + }; - (function() { - - var SKIP_ID = 'meta'; - var metaData = {}, metaArray = {}; + // Shortcuts. + var pow = Math.pow; + var now = Date.now; + if (window.performance && performance.now) { + now = performance.now.bind(performance); + } - Polymer('core-meta', { - - /** - * The type of meta-data. All meta-data with the same type with be - * stored together. - * - * @attribute type - * @type string - * @default 'default' - */ - type: 'default', - - alwaysPrepare: true, - - ready: function() { - this.register(this.id); - }, - - get metaArray() { - var t = this.type; - if (!metaArray[t]) { - metaArray[t] = []; - } - return metaArray[t]; - }, - - get metaData() { - var t = this.type; - if (!metaData[t]) { - metaData[t] = {}; - } - return metaData[t]; - }, - - register: function(id, old) { - if (id && id !== SKIP_ID) { - this.unregister(this, old); - this.metaData[id] = this; - this.metaArray.push(this); + function cssColorWithAlpha(cssColor, alpha) { + var parts = cssColor.match(/^rgb\((\d+),\s*(\d+),\s*(\d+)\)$/); + if (typeof alpha == 'undefined') { + alpha = 1; } - }, - - unregister: function(meta, id) { - delete this.metaData[id || meta.id]; - var i = this.metaArray.indexOf(meta); - if (i >= 0) { - this.metaArray.splice(i, 1); + if (!parts) { + return 'rgba(255, 255, 255, ' + alpha + ')'; } - }, - - /** - * Returns a list of all meta-data elements with the same type. - * - * @property list - * @type array - * @default [] - */ - get list() { - return this.metaArray; - }, - - /** - * Retrieves meta-data by ID. - * - * @method byId - * @param {String} id The ID of the meta-data to be returned. - * @returns Returns meta-data. - */ - byId: function(id) { - return this.metaData[id]; - } - - }); - - })(); - -</script> -</polymer-element> - + return 'rgba(' + parts[1] + ', ' + parts[2] + ', ' + parts[3] + ', ' + alpha + ')'; + } -<polymer-element name="core-iconset" extends="core-meta" attributes="src width icons iconSize" assetpath="polymer/bower_components/core-iconset/"> - - <script> - - Polymer('core-iconset', { - - /** - * The URL of the iconset image. - * - * @attribute src - * @type string - * @default '' - */ - src: '', + function dist(p1, p2) { + return Math.sqrt(pow(p1.x - p2.x, 2) + pow(p1.y - p2.y, 2)); + } - /** - * The width of the iconset image. This must only be specified if the - * icons are arranged into separate rows inside the image. - * - * @attribute width - * @type number - * @default 0 - */ - width: 0, + function distanceFromPointToFurthestCorner(point, size) { + var tl_d = dist(point, {x: 0, y: 0}); + var tr_d = dist(point, {x: size.w, y: 0}); + var bl_d = dist(point, {x: 0, y: size.h}); + var br_d = dist(point, {x: size.w, y: size.h}); + return Math.max(tl_d, tr_d, bl_d, br_d); + } - /** - * A space separated list of names corresponding to icons in the iconset - * image file. This list must be ordered the same as the icon images - * in the image file. - * - * @attribute icons - * @type string - * @default '' - */ - icons: '', + Polymer('paper-ripple', { /** - * The size of an individual icon. Note that icons must be square. + * The initial opacity set on the wave. * - * @attribute iconSize + * @attribute initialOpacity * @type number - * @default 24 + * @default 0.25 */ - iconSize: 24, + initialOpacity: 0.25, /** - * The horizontal offset of the icon images in the inconset src image. - * This is typically used if the image resource contains additional images - * beside those intended for the iconset. - * - * @attribute offsetX - * @type number - * @default 0 - */ - offsetX: 0, - /** - * The vertical offset of the icon images in the inconset src image. - * This is typically used if the image resource contains additional images - * beside those intended for the iconset. + * How fast (opacity per second) the wave fades out. * - * @attribute offsetY + * @attribute opacityDecayVelocity * @type number - * @default 0 + * @default 0.8 */ - offsetY: 0, - type: 'iconset', + opacityDecayVelocity: 0.8, - created: function() { - this.iconMap = {}; - this.iconNames = []; - this.themes = {}; + backgroundFill: true, + pixelDensity: 2, + + eventDelegates: { + down: 'downAction', + up: 'upAction' }, - + ready: function() { - // TODO(sorvell): ensure iconset's src is always relative to the main - // document - if (this.src && (this.ownerDocument !== document)) { - this.src = this.resolvePath(this.src, this.ownerDocument.baseURI); + this.waves = []; + }, + + downAction: function(e) { + var wave = createWave(this); + + this.cancelled = false; + wave.isMouseDown = true; + wave.tDown = 0.0; + wave.tUp = 0.0; + wave.mouseUpStart = 0.0; + wave.mouseDownStart = now(); + + var rect = this.getBoundingClientRect(); + var width = rect.width; + var height = rect.height; + var touchX = e.x - rect.left; + var touchY = e.y - rect.top; + + wave.startPosition = {x:touchX, y:touchY}; + + if (this.classList.contains("recenteringTouch")) { + wave.endPosition = {x: width / 2, y: height / 2}; + wave.slideDistance = dist(wave.startPosition, wave.endPosition); } - this.super(); - this.updateThemes(); + wave.containerSize = Math.max(width, height); + wave.containerWidth = width; + wave.containerHeight = height; + wave.maxRadius = distanceFromPointToFurthestCorner(wave.startPosition, {w: width, h: height}); + + // The wave is circular so constrain its container to 1:1 + wave.wc.style.top = (wave.containerHeight - wave.containerSize) / 2 + 'px'; + wave.wc.style.left = (wave.containerWidth - wave.containerSize) / 2 + 'px'; + wave.wc.style.width = wave.containerSize + 'px'; + wave.wc.style.height = wave.containerSize + 'px'; + + this.waves.push(wave); + + if (!this._loop) { + this._loop = this.animate.bind(this, { + width: width, + height: height + }); + requestAnimationFrame(this._loop); + } + // else there is already a rAF }, - iconsChanged: function() { - var ox = this.offsetX; - var oy = this.offsetY; - this.icons && this.icons.split(/\s+/g).forEach(function(name, i) { - this.iconNames.push(name); - this.iconMap[name] = { - offsetX: ox, - offsetY: oy - } - if (ox + this.iconSize < this.width) { - ox += this.iconSize; - } else { - ox = this.offsetX; - oy += this.iconSize; + upAction: function() { + for (var i = 0; i < this.waves.length; i++) { + // Declare the next wave that has mouse down to be mouse'ed up. + var wave = this.waves[i]; + if (wave.isMouseDown) { + wave.isMouseDown = false + wave.mouseUpStart = now(); + wave.mouseDownStart = 0; + wave.tUp = 0.0; + break; } - }, this); + } + this._loop && requestAnimationFrame(this._loop); }, - updateThemes: function() { - var ts = this.querySelectorAll('property[theme]'); - ts && ts.array().forEach(function(t) { - this.themes[t.getAttribute('theme')] = { - offsetX: parseInt(t.getAttribute('offsetX')) || 0, - offsetY: parseInt(t.getAttribute('offsetY')) || 0 - }; - }, this); + cancel: function() { + this.cancelled = true; }, - // TODO(ffu): support retrived by index e.g. getOffset(10); - /** - * Returns an object containing `offsetX` and `offsetY` properties which - * specify the pixel locaion in the iconset's src file for the given - * `icon` and `theme`. It's uncommon to call this method. It is useful, - * for example, to manually position a css backgroundImage to the proper - * offset. It's more common to use the `applyIcon` method. - * - * @method getOffset - * @param {String|Number} icon The name of the icon or the index of the - * icon within in the icon image. - * @param {String} theme The name of the theme. - * @returns {Object} An object specifying the offset of the given icon - * within the icon resource file; `offsetX` is the horizontal offset and - * `offsetY` is the vertical offset. Both values are in pixel units. - */ - getOffset: function(icon, theme) { - var i = this.iconMap[icon]; - if (!i) { - var n = this.iconNames[Number(icon)]; - i = this.iconMap[n]; + animate: function(ctx) { + var shouldRenderNextFrame = false; + + var deleteTheseWaves = []; + // The oldest wave's touch down duration + var longestTouchDownDuration = 0; + var longestTouchUpDuration = 0; + // Save the last known wave color + var lastWaveColor = null; + // wave animation values + var anim = { + initialOpacity: this.initialOpacity, + opacityDecayVelocity: this.opacityDecayVelocity, + height: ctx.height, + width: ctx.width } - var t = this.themes[theme]; - if (i && t) { - return { - offsetX: i.offsetX + t.offsetX, - offsetY: i.offsetY + t.offsetY + + for (var i = 0; i < this.waves.length; i++) { + var wave = this.waves[i]; + + if (wave.mouseDownStart > 0) { + wave.tDown = now() - wave.mouseDownStart; + } + if (wave.mouseUpStart > 0) { + wave.tUp = now() - wave.mouseUpStart; } - } - return i; - }, - /** - * Applies an icon to the given element as a css background image. This - * method does not size the element, and it's often necessary to set - * the element's height and width so that the background image is visible. - * - * @method applyIcon - * @param {Element} element The element to which the background is - * applied. - * @param {String|Number} icon The name or index of the icon to apply. - * @param {Number} scale (optional, defaults to 1) A scaling factor - * with which the icon can be magnified. - * @return {Element} The icon element. - */ - applyIcon: function(element, icon, scale) { - var offset = this.getOffset(icon); - scale = scale || 1; - if (element && offset) { - var icon = element._icon || document.createElement('div'); - var style = icon.style; - style.backgroundImage = 'url(' + this.src + ')'; - style.backgroundPosition = (-offset.offsetX * scale + 'px') + - ' ' + (-offset.offsetY * scale + 'px'); - style.backgroundSize = scale === 1 ? 'auto' : - this.width * scale + 'px'; - if (icon.parentNode !== element) { - element.appendChild(icon); + // Determine how long the touch has been up or down. + var tUp = wave.tUp; + var tDown = wave.tDown; + longestTouchDownDuration = Math.max(longestTouchDownDuration, tDown); + longestTouchUpDuration = Math.max(longestTouchUpDuration, tUp); + + // Obtain the instantenous size and alpha of the ripple. + var radius = waveRadiusFn(tDown, tUp, anim); + var waveAlpha = waveOpacityFn(tDown, tUp, anim); + var waveColor = cssColorWithAlpha(wave.waveColor, waveAlpha); + lastWaveColor = wave.waveColor; + + // Position of the ripple. + var x = wave.startPosition.x; + var y = wave.startPosition.y; + + // Ripple gravitational pull to the center of the canvas. + if (wave.endPosition) { + + // This translates from the origin to the center of the view based on the max dimension of + var translateFraction = Math.min(1, radius / wave.containerSize * 2 / Math.sqrt(2) ); + + x += translateFraction * (wave.endPosition.x - wave.startPosition.x); + y += translateFraction * (wave.endPosition.y - wave.startPosition.y); } - return icon; + + // If we do a background fill fade too, work out the correct color. + var bgFillColor = null; + if (this.backgroundFill) { + var bgFillAlpha = waveOuterOpacityFn(tDown, tUp, anim); + bgFillColor = cssColorWithAlpha(wave.waveColor, bgFillAlpha); + } + + // Draw the ripple. + drawRipple(wave, x, y, radius, waveAlpha, bgFillAlpha); + + // Determine whether there is any more rendering to be done. + var maximumWave = waveAtMaximum(wave, radius, anim); + var waveDissipated = waveDidFinish(wave, radius, anim); + var shouldKeepWave = !waveDissipated || maximumWave; + // keep rendering dissipating wave when at maximum radius on upAction + var shouldRenderWaveAgain = wave.mouseUpStart ? !waveDissipated : !maximumWave; + shouldRenderNextFrame = shouldRenderNextFrame || shouldRenderWaveAgain; + if (!shouldKeepWave || this.cancelled) { + deleteTheseWaves.push(wave); + } + } + + if (shouldRenderNextFrame) { + requestAnimationFrame(this._loop); + } + + for (var i = 0; i < deleteTheseWaves.length; ++i) { + var wave = deleteTheseWaves[i]; + removeWaveFromScope(this, wave); + } + + if (!this.waves.length && this._loop) { + // clear the background color + this.$.bg.style.backgroundColor = null; + this._loop = null; + this.fire('core-transitionend'); } } }); - </script> + })(); +</script> </polymer-element> - -<style shim-shadowdom="">/* Copyright (c) 2014 The Polymer Project Authors. All rights reserved. +<!-- +Copyright (c) 2014 The Polymer Project Authors. All rights reserved. This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt Code distributed by Google as part of the polymer project is also -subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt */ - -html /deep/ core-icon { - display: inline-block; - vertical-align: middle; - background-repeat: no-repeat; - fill: currentcolor; - position: relative; - height: 24px; - width: 24px; -}</style> +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--> -<polymer-element name="core-icon" attributes="src icon alt" assetpath="polymer/bower_components/core-icon/"> -<script> -(function() { - - // mono-state - var meta; - - Polymer('core-icon', { +<!-- +The `paper-shadow` element is a helper to add shadows to elements. +Paper shadows are composed of two shadows on top of each other. We +mimic this effect by using two elements on top of each other, each with a +different drop shadow. You can apply the shadow to an element by assigning +it as the target. If you do not specify a target, the shadow is applied to +the `paper-shadow` element's parent element or shadow host element if its +parent is a shadow root. Alternatively, you can use the CSS classes included +by this element directly. - /** - * The URL of an image for the icon. If the src property is specified, - * the icon property should not be. - * - * @attribute src - * @type string - * @default '' - */ - src: '', +Example: - /** - * Specifies the icon name or index in the set of icons available in - * the icon's icon set. If the icon property is specified, - * the src property should not be. - * - * @attribute icon - * @type string - * @default '' - */ - icon: '', + <div id="myCard" class="card"></div> + <paper-shadow id="myShadow" z="1"></div> - /** - * Alternative text content for accessibility support. - * If alt is present and not empty, it will set the element's role to img and add an aria-label whose content matches alt. - * If alt is present and is an empty string, '', it will hide the element from the accessibility layer - * If alt is not present, it will set the element's role to img and the element will fallback to using the icon attribute for its aria-label. - * - * @attribute alt - * @type string - * @default '' - */ - alt: null, + // Assign a target explicitly + myShadow.target = document.getElementById('myCard'); - observe: { - 'icon': 'updateIcon', - 'alt': 'updateAlt' - }, + // Auto-assign the target. + <div class="card"> + <paper-shadow z="1"></paper-shadow> + </div> - defaultIconset: 'icons', + // Use the classes directly + <div class="card paper-shadow-top paper-shadow-top-z-1"> + <div class="card-inner paper-shadow-bottom paper-shadow-bottom-z-1"></div> + </div> - ready: function() { - if (!meta) { - meta = document.createElement('core-iconset'); - } +If you assign a target to a `paper-shadow` element, it creates two nodes and inserts +them as the first children of the target, or the first children of the target's shadow +root if there is one. This implies: - // Allow user-provided `aria-label` in preference to any other text alternative. - if (this.hasAttribute('aria-label')) { - // Set `role` if it has not been overridden. - if (!this.hasAttribute('role')) { - this.setAttribute('role', 'img'); - } - return; - } - this.updateAlt(); - }, + 1. If the primary node that drops the shadow has styling that affects its shape, + the same styling must be applied to elements with class `paper-shadow`. + `border-radius` is a very common property and is inherited automatically. - srcChanged: function() { - var icon = this._icon || document.createElement('div'); - icon.textContent = ''; - icon.setAttribute('fit', ''); - icon.style.backgroundImage = 'url(' + this.src + ')'; - icon.style.backgroundPosition = 'center'; - icon.style.backgroundSize = '100%'; - if (!icon.parentNode) { - this.appendChild(icon); - } - this._icon = icon; - }, + 2. The target's overflow property will be set to `overflow: visible` because the + shadow is rendered beyond the bounds of its container. Position the shadow as a + separate layer and use a different child element for clipping if needed. - getIconset: function(name) { - return meta.byId(name || this.defaultIconset); - }, +@group Paper Elements +@class paper-shadow +--> - updateIcon: function(oldVal, newVal) { - if (!this.icon) { - this.updateAlt(); - return; - } - var parts = String(this.icon).split(':'); - var icon = parts.pop(); - if (icon) { - var set = this.getIconset(parts.pop()); - if (set) { - this._icon = set.applyIcon(this, icon); - if (this._icon) { - this._icon.setAttribute('fit', ''); - } - } - } - // Check to see if we're using the old icon's name for our a11y fallback - if (oldVal) { - if (oldVal.split(':').pop() == this.getAttribute('aria-label')) { - this.updateAlt(); - } - } - }, - updateAlt: function() { - // Respect the user's decision to remove this element from - // the a11y tree - if (this.getAttribute('aria-hidden')) { - return; - } - // Remove element from a11y tree if `alt` is empty, otherwise - // use `alt` as `aria-label`. - if (this.alt === '') { - this.setAttribute('aria-hidden', 'true'); - if (this.hasAttribute('role')) { - this.removeAttribute('role'); - } - if (this.hasAttribute('aria-label')) { - this.removeAttribute('aria-label'); - } - } else { - this.setAttribute('aria-label', this.alt || - this.icon.split(':').pop()); - if (!this.hasAttribute('role')) { - this.setAttribute('role', 'img'); - } - if (this.hasAttribute('aria-hidden')) { - this.removeAttribute('aria-hidden'); - } - } - } +<polymer-element name="paper-shadow" assetpath="polymer/bower_components/paper-shadow/"> - }); - -})(); -</script> + <template> -</polymer-element> + <style no-shim="">/* + * @license + * Copyright (c) 2014 The Polymer Project Authors. All rights reserved. + * This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt + * The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt + * The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt + * Code distributed by Google as part of the polymer project is also + * subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt + */ -<!-- -Copyright (c) 2014 The Polymer Project Authors. All rights reserved. -This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt -The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt -The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt -Code distributed by Google as part of the polymer project is also -subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt ---> +.paper-shadow { + position: absolute; + top: 0; + left: 0; + bottom: 0; + right: 0; + border-radius: inherit; + pointer-events: none; +} +.paper-shadow-animated.paper-shadow { + transition: box-shadow 0.28s cubic-bezier(0.4, 0, 0.2, 1); +} -<!-- -Copyright (c) 2014 The Polymer Project Authors. All rights reserved. -This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt -The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt -The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt -Code distributed by Google as part of the polymer project is also -subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt ---> +.paper-shadow-top-z-1 { + box-shadow: 0 2px 10px 0 rgba(0, 0, 0, 0.16); +} -<!-- -/** - * @group Polymer Core Elements - * - * The `core-iconset-svg` element allows users to define their own icon sets - * that contain svg icons. The svg icon elements should be children of the - * `core-iconset-svg` element. Multiple icons should be given distinct id's. - * - * Using svg elements to create icons has a few advantages over traditional - * bitmap graphics like jpg or png. Icons that use svg are vector based so they - * are resolution independent and should look good on any device. They are - * stylable via css. Icons can be themed, colorized, and even animated. - * - * Example: - * - * <core-iconset-svg id="my-svg-icons" iconSize="24"> - * <svg> - * <defs> - * <g id="shape"> - * <rect x="50" y="50" width="50" height="50" /> - * <circle cx="50" cy="50" r="50" /> - * </g> - * </defs> - * </svg> - * </core-iconset-svg> - * - * This will automatically register the icon set "my-svg-icons" to the iconset - * database. To use these icons from within another element, make a - * `core-iconset` element and call the `byId` method - * to retrieve a given iconset. To apply a particular icon inside an - * element use the `applyIcon` method. For example: - * - * iconset.applyIcon(iconNode, 'car'); - * - * @element core-iconset-svg - * @extends core-meta - * @homepage github.io - */ ---> +.paper-shadow-bottom-z-1 { + box-shadow: 0 2px 5px 0 rgba(0, 0, 0, 0.26); +} +.paper-shadow-top-z-2 { + box-shadow: 0 6px 20px 0 rgba(0, 0, 0, 0.19); +} +.paper-shadow-bottom-z-2 { + box-shadow: 0 8px 17px 0 rgba(0, 0, 0, 0.2); +} -<polymer-element name="core-iconset-svg" extends="core-meta" attributes="iconSize" assetpath="polymer/bower_components/core-iconset-svg/"> +.paper-shadow-top-z-3 { + box-shadow: 0 17px 50px 0 rgba(0, 0, 0, 0.19); +} - <script> +.paper-shadow-bottom-z-3 { + box-shadow: 0 12px 15px 0 rgba(0, 0, 0, 0.24); +} - Polymer('core-iconset-svg', { +.paper-shadow-top-z-4 { + box-shadow: 0 25px 55px 0 rgba(0, 0, 0, 0.21); +} +.paper-shadow-bottom-z-4 { + box-shadow: 0 16px 28px 0 rgba(0, 0, 0, 0.22); +} - /** - * The size of an individual icon. Note that icons must be square. - * - * @attribute iconSize - * @type number - * @default 24 - */ - iconSize: 24, - type: 'iconset', +.paper-shadow-top-z-5 { + box-shadow: 0 40px 77px 0 rgba(0, 0, 0, 0.22); +} - created: function() { - this._icons = {}; +.paper-shadow-bottom-z-5 { + box-shadow: 0 27px 24px 0 rgba(0, 0, 0, 0.2); +} + +.paper-shadow-animate-z-1-z-2.paper-shadow-top { + -webkit-transition: none; + -webkit-animation: animate-shadow-top-z-1-z-2 0.7s infinite alternate; +} + +.paper-shadow-animate-z-1-z-2 .paper-shadow-bottom { + -webkit-transition: none; + -webkit-animation: animate-shadow-bottom-z-1-z-2 0.7s infinite alternate; +} + +@-webkit-keyframes animate-shadow-top-z-1-z-2 { + 0% { + box-shadow: 0 2px 10px 0 rgba(0, 0, 0, 0.16); + } + 100% { + box-shadow: 0 6px 20px 0 rgba(0, 0, 0, 0.19); + } +} + +@-webkit-keyframes animate-shadow-bottom-z-1-z-2 { + 0% { + box-shadow: 0 2px 5px 0 rgba(0, 0, 0, 0.26); + } + 100% { + box-shadow: 0 8px 17px 0 rgba(0, 0, 0, 0.2); + } +}</style> + + </template> + + <script> + Polymer('paper-shadow', { + + publish: { + /** + * If set, the shadow is applied to this node. + * + * @attribute target + * @type Element + * @default null + */ + target: {value: null, reflect: true}, + + /** + * The z-depth of this shadow, from 0-5. + * + * @attribute z + * @type number + * @default 1 + */ + z: {value: 1, reflect: true}, + + /** + * If true, the shadow animates between z-depth changes. + * + * @attribute animated + * @type boolean + * @default false + */ + animated: {value: false, reflect: true}, + + /** + * Workaround: getComputedStyle is wrong sometimes so `paper-shadow` + * may overwrite the `position` CSS property. Set this property to + * true to prevent this. + * + * @attribute hasPosition + * @type boolean + * @default false + */ + hasPosition: false }, - ready: function() { - this.super(); - this.updateIcons(); + // NOTE: include template so that styles are loaded, but remove + // so that we can decide dynamically what part to include + registerCallback: function(polymerElement) { + var template = polymerElement.querySelector('template'); + this._style = template.content.querySelector('style'); + this._style.removeAttribute('no-shim'); }, - iconById: function(id) { - return this._icons[id] || (this._icons[id] = this.querySelector('#' + id)); + fetchTemplate: function() { + return null; }, - cloneIcon: function(id) { - var icon = this.iconById(id); - if (icon) { - var content = icon.cloneNode(true); - content.removeAttribute('id'); - var svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg'); - svg.setAttribute('viewBox', '0 0 ' + this.iconSize + ' ' + - this.iconSize); - // NOTE(dfreedm): work around https://crbug.com/370136 - svg.style.pointerEvents = 'none'; - svg.appendChild(content); - return svg; + attached: function() { + // If no target is bound at attach, default the target to the parent + // element or shadow host. + if (!this.target) { + if (!this.parentElement && this.parentNode.host) { + this.target = this.parentNode.host; + } else if (this.parentElement && (window.ShadowDOMPolyfill ? this.parentElement !== wrap(document.body) : this.parentElement !== document.body)) { + this.target = this.parentElement; + } } }, - get iconNames() { - if (!this._iconNames) { - this._iconNames = this.findIconNames(); + targetChanged: function(old) { + if (old) { + this.removeShadow(old); + } + if (this.target) { + this.addShadow(this.target); } - return this._iconNames; }, - findIconNames: function() { - var icons = this.querySelectorAll('[id]').array(); - if (icons.length) { - return icons.map(function(n){ return n.id }); + zChanged: function(old) { + if (this.target && this.target._paperShadow) { + var shadow = this.target._paperShadow; + ['top', 'bottom'].forEach(function(s) { + shadow[s].classList.remove('paper-shadow-' + s + '-z-' + old); + shadow[s].classList.add('paper-shadow-' + s + '-z-' + this.z); + }.bind(this)); } }, - /** - * Applies an icon to the given element. The svg icon is added to the - * element's shadowRoot if one exists or directly to itself. - * - * @method applyIcon - * @param {Element} element The element to which the icon is - * applied. - * @param {String|Number} icon The name the icon to apply. - * @return {Element} The icon element - */ - applyIcon: function(element, icon) { - var root = element; - // remove old - var old = root.querySelector('svg'); - if (old) { - old.remove(); + animatedChanged: function() { + if (this.target && this.target._paperShadow) { + var shadow = this.target._paperShadow; + ['top', 'bottom'].forEach(function(s) { + if (this.animated) { + shadow[s].classList.add('paper-shadow-animated'); + } else { + shadow[s].classList.remove('paper-shadow-animated'); + } + }.bind(this)); } - // install new - var svg = this.cloneIcon(icon); - if (!svg) { + }, + + addShadow: function(node) { + if (node._paperShadow) { return; } - svg.setAttribute('height', '100%'); - svg.setAttribute('width', '100%'); - svg.setAttribute('preserveAspectRatio', 'xMidYMid meet'); - svg.style.display = 'block'; - root.insertBefore(svg, root.firstElementChild); - return svg; - }, - - /** - * Tell users of the iconset, that the set has loaded. - * This finds all elements matching the selector argument and calls - * the method argument on them. - * @method updateIcons - * @param selector {string} css selector to identify iconset users, - * defaults to '[icon]' - * @param method {string} method to call on found elements, - * defaults to 'updateIcon' - */ - updateIcons: function(selector, method) { - selector = selector || '[icon]'; - method = method || 'updateIcon'; - var deep = window.ShadowDOMPolyfill ? '' : 'html /deep/ '; - var i$ = document.querySelectorAll(deep + selector); - for (var i=0, e; e=i$[i]; i++) { - if (e[method]) { - e[method].call(e); + + if (!node._hasShadowStyle) { + if (!node.shadowRoot) { + node.createShadowRoot().innerHTML = '<content></content>'; + } + this.installScopeStyle(this._style, 'shadow', node.shadowRoot); + node._hasShadowStyle = true; + } + + var computed = getComputedStyle(node); + if (!this.hasPosition && computed.position === 'static') { + node.style.position = 'relative'; + } + node.style.overflow = 'visible'; + + // Both the top and bottom shadows are children of the target, so + // it does not affect the classes and CSS properties of the target. + ['top', 'bottom'].forEach(function(s) { + var inner = (node._paperShadow && node._paperShadow[s]) || document.createElement('div'); + inner.classList.add('paper-shadow'); + inner.classList.add('paper-shadow-' + s + '-z-' + this.z); + if (this.animated) { + inner.classList.add('paper-shadow-animated'); + } + + if (node.shadowRoot) { + node.shadowRoot.insertBefore(inner, node.shadowRoot.firstChild); + } else { + node.insertBefore(inner, node.firstChild); } + + node._paperShadow = node._paperShadow || {}; + node._paperShadow[s] = inner; + }.bind(this)); + + }, + + removeShadow: function(node) { + if (!node._paperShadow) { + return; } + + ['top', 'bottom'].forEach(function(s) { + node._paperShadow[s].remove(); + }); + node._paperShadow = null; + + node.style.position = null; } - }); - </script> - </polymer-element> -<core-iconset-svg id="icons" iconsize="24"> -<svg><defs> -<g id="accessibility"><path d="M12,2c1.1,0,2,0.9,2,2s-0.9,2-2,2s-2-0.9-2-2S10.9,2,12,2z M21,9h-6v13h-2v-6h-2v6H9V9H3V7h18V9z"/></g> -<g id="account-balance"><path d="M4,10v7h3v-7H4z M10,10v7h3v-7H10z M2,22h19v-3H2V22z M16,10v7h3v-7H16z M11.5,1L2,6v2h19V6L11.5,1z"/></g> -<g id="account-box"><path d="M3,5l0,14c0,1.1,0.9,2,2,2h14c1.1,0,2-0.9,2-2V5c0-1.1-0.9-2-2-2H5C3.9,3,3,3.9,3,5z M15,9c0,1.7-1.3,3-3,3c-1.7,0-3-1.3-3-3c0-1.7,1.3-3,3-3C13.7,6,15,7.3,15,9z M6,17c0-2,4-3.1,6-3.1s6,1.1,6,3.1v1H6V17z"/></g> -<g id="account-child"><path d="M16.5,12c1.4,0,2.5-1.1,2.5-2.5C19,8.1,17.9,7,16.5,7C15.1,7,14,8.1,14,9.5C14,10.9,15.1,12,16.5,12z M9,11c1.7,0,3-1.3,3-3s-1.3-3-3-3C7.3,5,6,6.3,6,8S7.3,11,9,11z M16.5,14c-1.8,0-5.5,0.9-5.5,2.7V19h11v-2.2C22,14.9,18.3,14,16.5,14z M9,13c-2.3,0-7,1.2-7,3.5V19h7v-2.2c0-0.8,0.3-2.3,2.4-3.5C10.5,13.1,9.7,13,9,13z"/></g> -<g id="account-circle"><path d="M12,2C6.5,2,2,6.5,2,12s4.5,10,10,10c5.5,0,10-4.5,10-10S17.5,2,12,2z M12,5c1.7,0,3,1.3,3,3c0,1.7-1.3,3-3,3c-1.7,0-3-1.3-3-3C9,6.3,10.3,5,12,5z M12,19.2c-2.5,0-4.7-1.3-6-3.2c0-2,4-3.1,6-3.1c2,0,6,1.1,6,3.1C16.7,17.9,14.5,19.2,12,19.2z"/></g> -<g id="add"><path d="M19,13h-6v6h-2v-6H5v-2h6V5h2v6h6V13z"/></g> -<g id="add-box"><path d="M19,3H5C3.9,3,3,3.9,3,5v14c0,1.1,0.9,2,2,2h14c1.1,0,2-0.9,2-2V5C21,3.9,20.1,3,19,3z M17,13h-4v4h-2v-4H7v-2h4V7h2v4h4V13z"/></g> -<g id="add-circle"><path d="M12,2C6.5,2,2,6.5,2,12s4.5,10,10,10c5.5,0,10-4.5,10-10S17.5,2,12,2z M17,13h-4v4h-2v-4H7v-2h4V7h2v4h4V13z"/></g> -<g id="add-circle-outline"><path d="M13,7h-2v4H7v2h4v4h2v-4h4v-2h-4V7z M12,2C6.5,2,2,6.5,2,12s4.5,10,10,10c5.5,0,10-4.5,10-10S17.5,2,12,2z M12,20c-4.4,0-8-3.6-8-8s3.6-8,8-8c4.4,0,8,3.6,8,8S16.4,20,12,20z"/></g> -<g id="add-shopping-cart"><polygon points="18.3,6 18.3,6 15.6,11 "/></g> -<g id="alarm"><path d="M22,5.7l-4.6-3.9l-1.3,1.5l4.6,3.9L22,5.7z M7.9,3.4L6.6,1.9L2,5.7l1.3,1.5L7.9,3.4z M12.5,8H11v6l4.7,2.9l0.8-1.2l-4-2.4V8z M12,4c-5,0-9,4-9,9c0,5,4,9,9,9c5,0,9-4,9-9C21,8,17,4,12,4z M12,20c-3.9,0-7-3.1-7-7c0-3.9,3.1-7,7-7c3.9,0,7,3.1,7,7C19,16.9,15.9,20,12,20z"/></g> -<g id="alarm-add"><path d="M7.9,3.4L6.6,1.9L2,5.7l1.3,1.5L7.9,3.4z M22,5.7l-4.6-3.9l-1.3,1.5l4.6,3.9L22,5.7z M12,4c-5,0-9,4-9,9c0,5,4,9,9,9c5,0,9-4,9-9C21,8,17,4,12,4z M12,20c-3.9,0-7-3.1-7-7c0-3.9,3.1-7,7-7c3.9,0,7,3.1,7,7C19,16.9,15.9,20,12,20z M13,9h-2v3H8v2h3v3h2v-3h3v-2h-3V9z"/></g> -<g id="alarm-off"><path d="M12,6c3.9,0,7,3.1,7,7c0,0.8-0.2,1.6-0.4,2.4l1.5,1.5c0.6-1.2,0.9-2.5,0.9-3.9c0-5-4-9-9-9c-1.4,0-2.7,0.3-3.9,0.9l1.5,1.5C10.4,6.2,11.2,6,12,6z M22,5.7l-4.6-3.9l-1.3,1.5l4.6,3.9L22,5.7z M2.9,2.3L1.6,3.6L3,4.9L1.9,5.8l1.4,1.4l1.1-0.9l0.8,0.8C3.8,8.7,3,10.7,3,13c0,5,4,9,9,9c2.3,0,4.3-0.8,5.9-2.2l2.2,2.2l1.3-1.3L3.9,3.3L2.9,2.3z M16.5,18.4c-1.2,1-2.8,1.6-4.5,1.6c-3.9,0-7-3.1-7-7c0-1.7,0.6-3.3,1.6-4.5L16.5,18.4z M8,3.3L6.6,1.9L5.7,2.6L7.2,4L8,3.3z"/></g> -<g id="alarm-on"><path d="M22,5.7l-4.6-3.9l-1.3,1.5l4.6,3.9L22,5.7z M7.9,3.4L6.6,1.9L2,5.7l1.3,1.5L7.9,3.4z M12,4c-5,0-9,4-9,9c0,5,4,9,9,9c5,0,9-4,9-9C21,8,17,4,12,4z M12,20c-3.9,0-7-3.1-7-7c0-3.9,3.1-7,7-7s7,3.1,7,7C19,16.9,15.9,20,12,20z M10.5,14.5l-2.1-2.1l-1.1,1.1l3.2,3.2l6-6l-1.1-1.1L10.5,14.5z"/></g> -<g id="android"><path d="M6,18c0,0.6,0.4,1,1,1h1v3.5C8,23.3,8.7,24,9.5,24c0.8,0,1.5-0.7,1.5-1.5V19h2v3.5c0,0.8,0.7,1.5,1.5,1.5c0.8,0,1.5-0.7,1.5-1.5V19h1c0.6,0,1-0.4,1-1V8H6V18z M3.5,8C2.7,8,2,8.7,2,9.5v7C2,17.3,2.7,18,3.5,18C4.3,18,5,17.3,5,16.5v-7C5,8.7,4.3,8,3.5,8z M20.5,8C19.7,8,19,8.7,19,9.5v7c0,0.8,0.7,1.5,1.5,1.5c0.8,0,1.5-0.7,1.5-1.5v-7C22,8.7,21.3,8,20.5,8z M15.5,2.2l1.3-1.3c0.2-0.2,0.2-0.5,0-0.7c-0.2-0.2-0.5-0.2-0.7,0l-1.5,1.5C13.9,1.2,13,1,12,1c-1,0-1.9,0.2-2.7,0.6L7.9,0.1C7.7,0,7.3,0,7.1,0.1C7,0.3,7,0.7,7.1,0.9l1.3,1.3C7,3.3,6,5,6,7h12C18,5,17,3.2,15.5,2.2z M10,5H9V4h1V5z M15,5h-1V4h1V5z"/></g> -<g id="announcement"><path d="M20,2H4C2.9,2,2,2.9,2,4l0,18l4-4h14c1.1,0,2-0.9,2-2V4C22,2.9,21.1,2,20,2z M13,11h-2V5h2V11z M13,15h-2v-2h2V15z"/></g> -<g id="apps"><path d="M4,8h4V4H4V8z M10,20h4v-4h-4V20z M4,20h4v-4H4V20z M4,14h4v-4H4V14z M10,14h4v-4h-4V14z M16,4v4h4V4H16z M10,8h4V4h-4V8z M16,14h4v-4h-4V14z M16,20h4v-4h-4V20z"/></g> -<g id="archive"><path d="M20.5,5.2l-1.4-1.7C18.9,3.2,18.5,3,18,3H6C5.5,3,5.1,3.2,4.8,3.5L3.5,5.2C3.2,5.6,3,6,3,6.5V19c0,1.1,0.9,2,2,2h14c1.1,0,2-0.9,2-2V6.5C21,6,20.8,5.6,20.5,5.2z M12,17.5L6.5,12H10v-2h4v2h3.5L12,17.5z M5.1,5l0.8-1h12l0.9,1H5.1z"/></g> -<g id="arrow-back"><path d="M20,11H7.8l5.6-5.6L12,4l-8,8l8,8l1.4-1.4L7.8,13H20V11z"/></g> -<g id="arrow-drop-down"><polygon points="7,10 12,15 17,10 "/></g> -<g id="arrow-drop-down-circle"><path d="M12,2C6.5,2,2,6.5,2,12s4.5,10,10,10c5.5,0,10-4.5,10-10S17.5,2,12,2z M12,14l-4-4h8L12,14z"/></g> -<g id="arrow-drop-up"><polygon points="7,14 12,9 17,14 "/></g> -<g id="arrow-forward"><polygon points="12,4 10.6,5.4 16.2,11 4,11 4,13 16.2,13 10.6,18.6 12,20 20,12 "/></g> -<g id="aspect-ratio"><path d="M19,12h-2v3h-3v2h5V12z M7,9h3V7H5v5h2V9z M21,3H3C1.9,3,1,3.9,1,5v14c0,1.1,0.9,2,2,2h18c1.1,0,2-0.9,2-2V5C23,3.9,22.1,3,21,3z M21,19H3V5h18V19z"/></g> -<g id="assessment"><path d="M19,3H5C3.9,3,3,3.9,3,5v14c0,1.1,0.9,2,2,2h14c1.1,0,2-0.9,2-2V5C21,3.9,20.1,3,19,3z M9,17H7v-7h2V17z M13,17h-2V7h2V17z M17,17h-2v-4h2V17z"/></g> -<g id="assignment"><path d="M19,3h-4.2c-0.4-1.2-1.5-2-2.8-2c-1.3,0-2.4,0.8-2.8,2H5C3.9,3,3,3.9,3,5v14c0,1.1,0.9,2,2,2h14c1.1,0,2-0.9,2-2V5C21,3.9,20.1,3,19,3z M12,3c0.6,0,1,0.4,1,1s-0.4,1-1,1s-1-0.4-1-1S11.4,3,12,3z M14,17H7v-2h7V17z M17,13H7v-2h10V13z M17,9H7V7h10V9z"/></g> -<g id="assignment-ind"><path d="M19,3h-4.2c-0.4-1.2-1.5-2-2.8-2c-1.3,0-2.4,0.8-2.8,2H5C3.9,3,3,3.9,3,5v14c0,1.1,0.9,2,2,2h14c1.1,0,2-0.9,2-2V5C21,3.9,20.1,3,19,3z M12,3c0.6,0,1,0.4,1,1s-0.4,1-1,1s-1-0.4-1-1S11.4,3,12,3z M12,7c1.7,0,3,1.3,3,3c0,1.7-1.3,3-3,3c-1.7,0-3-1.3-3-3C9,8.3,10.3,7,12,7z M18,19H6v-1.4c0-2,4-3.1,6-3.1s6,1.1,6,3.1V19z"/></g> -<g id="assignment-late"><path d="M19,3h-4.2c-0.4-1.2-1.5-2-2.8-2c-1.3,0-2.4,0.8-2.8,2H5C3.9,3,3,3.9,3,5v14c0,1.1,0.9,2,2,2h14c1.1,0,2-0.9,2-2V5C21,3.9,20.1,3,19,3z M12,3c0.6,0,1,0.4,1,1s-0.4,1-1,1s-1-0.4-1-1S11.4,3,12,3z M17,15.6L15.6,17L12,13.4L8.4,17L7,15.6l3.6-3.6L7,8.4L8.4,7l3.6,3.6L15.6,7L17,8.4L13.4,12L17,15.6z"/></g> -<g id="assignment-return"><path d="M19,3h-4.2c-0.4-1.2-1.5-2-2.8-2c-1.3,0-2.4,0.8-2.8,2H5C3.9,3,3,3.9,3,5v14c0,1.1,0.9,2,2,2h14c1.1,0,2-0.9,2-2V5C21,3.9,20.1,3,19,3z M12,3c0.6,0,1,0.4,1,1s-0.4,1-1,1c-0.6,0-1-0.4-1-1S11.4,3,12,3z M16,15h-4v3l-5-5l5-5v3h4V15z"/></g> -<g id="assignment-returned"><path d="M19,3h-4.2c-0.4-1.2-1.5-2-2.8-2c-1.3,0-2.4,0.8-2.8,2H5C3.9,3,3,3.9,3,5v14c0,1.1,0.9,2,2,2h14c1.1,0,2-0.9,2-2V5C21,3.9,20.1,3,19,3z M12,3c0.6,0,1,0.4,1,1s-0.4,1-1,1s-1-0.4-1-1S11.4,3,12,3z M12,18l-5-5h3V9h4v4h3L12,18z"/></g> -<g id="attachment"><path d="M7.5,18c-3,0-5.5-2.5-5.5-5.5S4.5,7,7.5,7H18c2.2,0,4,1.8,4,4s-1.8,4-4,4H9.5C8.1,15,7,13.9,7,12.5S8.1,10,9.5,10H17v1.5H9.5c-0.6,0-1,0.4-1,1s0.4,1,1,1H18c1.4,0,2.5-1.1,2.5-2.5S19.4,8.5,18,8.5H7.5c-2.2,0-4,1.8-4,4s1.8,4,4,4H17V18H7.5z"/></g> -<g id="backspace"><path d="M22,3H7C6.3,3,5.8,3.3,5.4,3.9L0,12l5.4,8.1C5.8,20.6,6.3,21,7,21h15c1.1,0,2-0.9,2-2V5C24,3.9,23.1,3,22,3z M19,15.6L17.6,17L14,13.4L10.4,17L9,15.6l3.6-3.6L9,8.4L10.4,7l3.6,3.6L17.6,7L19,8.4L15.4,12L19,15.6z"/></g> -<g id="backup"><path d="M19.4,10c-0.7-3.4-3.7-6-7.4-6C9.1,4,6.6,5.6,5.4,8C2.3,8.4,0,10.9,0,14c0,3.3,2.7,6,6,6h13c2.8,0,5-2.2,5-5C24,12.4,21.9,10.2,19.4,10z M14,13v4h-4v-4H7l5-5l5,5H14z"/></g> -<g id="block"><path d="M12,2C6.5,2,2,6.5,2,12s4.5,10,10,10c5.5,0,10-4.5,10-10S17.5,2,12,2z M4,12c0-4.4,3.6-8,8-8c1.8,0,3.5,0.6,4.9,1.7L5.7,16.9C4.6,15.5,4,13.8,4,12z M12,20c-1.8,0-3.5-0.6-4.9-1.7L18.3,7.1C19.4,8.5,20,10.2,20,12C20,16.4,16.4,20,12,20z"/></g> -<g id="book"><path d="M18,2H6C4.9,2,4,2.9,4,4v16c0,1.1,0.9,2,2,2h12c1.1,0,2-0.9,2-2V4C20,2.9,19.1,2,18,2z M6,4h5v8l-2.5-1.5L6,12V4z"/></g> -<g id="bookmark"><path d="M17,3H7C5.9,3,5,3.9,5,5l0,16l7-3l7,3V5C19,3.9,18.1,3,17,3z"/></g> -<g id="bookmark-outline"><path d="M17,3H7C5.9,3,5,3.9,5,5l0,16l7-3l7,3V5C19,3.9,18.1,3,17,3z M17,18l-5-2.2L7,18V5h10V18z"/></g> -<g id="bug-report"><path d="M20,8h-2.8c-0.5-0.8-1.1-1.5-1.8-2L17,4.4L15.6,3l-2.2,2.2C13,5.1,12.5,5,12,5s-1,0.1-1.4,0.2L8.4,3L7,4.4L8.6,6C7.9,6.5,7.3,7.2,6.8,8H4v2h2.1C6,10.3,6,10.7,6,11v1H4v2h2v1c0,0.3,0,0.7,0.1,1H4v2h2.8c1,1.8,3,3,5.2,3s4.2-1.2,5.2-3H20v-2h-2.1c0.1-0.3,0.1-0.7,0.1-1v-1h2v-2h-2v-1c0-0.3,0-0.7-0.1-1H20V8z M14,16h-4v-2h4V16z M14,12h-4v-2h4V12z"/></g> -<g id="cached"><path d="M19,8l-4,4h3c0,3.3-2.7,6-6,6c-1,0-2-0.3-2.8-0.7l-1.5,1.5C9,19.5,10.4,20,12,20c4.4,0,8-3.6,8-8h3L19,8z M6,12c0-3.3,2.7-6,6-6c1,0,2,0.3,2.8,0.7l1.5-1.5C15,4.5,13.6,4,12,4c-4.4,0-8,3.6-8,8H1l4,4l4-4H6z"/></g> -<g id="cancel"><path d="M12,2C6.5,2,2,6.5,2,12s4.5,10,10,10c5.5,0,10-4.5,10-10S17.5,2,12,2z M17,15.6L15.6,17L12,13.4L8.4,17L7,15.6l3.6-3.6L7,8.4L8.4,7l3.6,3.6L15.6,7L17,8.4L13.4,12L17,15.6z"/></g> -<g id="check"><polygon points="9,16.2 4.8,12 3.4,13.4 9,19 21,7 19.6,5.6 "/></g> -<g id="check-box"><path d="M19,3H5C3.9,3,3,3.9,3,5v14c0,1.1,0.9,2,2,2h14c1.1,0,2-0.9,2-2V5C21,3.9,20.1,3,19,3z M10,17l-5-5l1.4-1.4l3.6,3.6l7.6-7.6L19,8L10,17z"/></g> -<g id="check-box-blank"><path d="M19,3H5C3.9,3,3,3.9,3,5l0,14c0,1.1,0.9,2,2,2h14c1.1,0,2-0.9,2-2V5C21,3.9,20.1,3,19,3z"/></g> -<g id="check-box-outline"><path d="M7.9,10.1l-1.4,1.4L11,16L21,6l-1.4-1.4L11,13.2L7.9,10.1z M19,19L5,19V5h10V3H5C3.9,3,3,3.9,3,5v14c0,1.1,0.9,2,2,2h14c1.1,0,2-0.9,2-2v-8h-2V19z"/></g> -<g id="check-box-outline-blank"><path d="M19,5v14L5,19V5H19 M19,3H5C3.9,3,3,3.9,3,5v14c0,1.1,0.9,2,2,2h14c1.1,0,2-0.9,2-2V5C21,3.9,20.1,3,19,3L19,3z"/></g> -<g id="check-circle"><path d="M12,2C6.5,2,2,6.5,2,12c0,5.5,4.5,10,10,10c5.5,0,10-4.5,10-10C22,6.5,17.5,2,12,2z M10,17l-5-5l1.4-1.4l3.6,3.6l7.6-7.6L19,8L10,17z"/></g> -<g id="check-circle-blank"><path d="M12,2C6.5,2,2,6.5,2,12c0,5.5,4.5,10,10,10c5.5,0,10-4.5,10-10C22,6.5,17.5,2,12,2z"/></g> -<g id="check-circle-outline"><path d="M7.9,10.1l-1.4,1.4L11,16L21,6l-1.4-1.4L11,13.2L7.9,10.1z M20,12c0,4.4-3.6,8-8,8s-8-3.6-8-8s3.6-8,8-8c0.8,0,1.5,0.1,2.2,0.3l1.6-1.6C14.6,2.3,13.3,2,12,2C6.5,2,2,6.5,2,12s4.5,10,10,10s10-4.5,10-10H20z"/></g> -<g id="check-circle-outline-blank"><path d="M12,2C6.5,2,2,6.5,2,12s4.5,10,10,10c5.5,0,10-4.5,10-10S17.5,2,12,2z M12,20c-4.4,0-8-3.6-8-8s3.6-8,8-8c4.4,0,8,3.6,8,8S16.4,20,12,20z"/></g> -<g id="chevron-left"><polygon points="15.4,7.4 14,6 8,12 14,18 15.4,16.6 10.8,12 "/></g> -<g id="chevron-right"><polygon points="10,6 8.6,7.4 13.2,12 8.6,16.6 10,18 16,12 "/></g> -<g id="class"><path d="M18,2H6C4.9,2,4,2.9,4,4v16c0,1.1,0.9,2,2,2h12c1.1,0,2-0.9,2-2V4C20,2.9,19.1,2,18,2z M6,4h5v8l-2.5-1.5L6,12V4z"/></g> -<g id="clear"><polygon points="19,6.4 17.6,5 12,10.6 6.4,5 5,6.4 10.6,12 5,17.6 6.4,19 12,13.4 17.6,19 19,17.6 13.4,12 "/></g> -<g id="close"><polygon points="19,6.4 17.6,5 12,10.6 6.4,5 5,6.4 10.6,12 5,17.6 6.4,19 12,13.4 17.6,19 19,17.6 13.4,12 "/></g> -<g id="cloud"><path d="M19.4,10c-0.7-3.4-3.7-6-7.4-6C9.1,4,6.6,5.6,5.4,8C2.3,8.4,0,10.9,0,14c0,3.3,2.7,6,6,6h13c2.8,0,5-2.2,5-5C24,12.4,21.9,10.2,19.4,10z"/></g> -<g id="cloud-circle"><path d="M12,2C6.5,2,2,6.5,2,12c0,5.5,4.5,10,10,10c5.5,0,10-4.5,10-10C22,6.5,17.5,2,12,2z M16.5,16c0,0-8.5,0-8.5,0c-1.7,0-3-1.3-3-3s1.3-3,3-3c0,0,0.1,0,0.1,0c0.4-1.7,2-3,3.9-3c2.2,0,4,1.8,4,4h0.5c1.4,0,2.5,1.1,2.5,2.5C19,14.9,17.9,16,16.5,16z"/></g> -<g id="cloud-done"><path d="M19.4,10c-0.7-3.4-3.7-6-7.4-6C9.1,4,6.6,5.6,5.4,8C2.3,8.4,0,10.9,0,14c0,3.3,2.7,6,6,6h13c2.8,0,5-2.2,5-5C24,12.4,21.9,10.2,19.4,10z M10,17l-3.5-3.5l1.4-1.4l2.1,2.1L15.2,9l1.4,1.4L10,17z"/></g> -<g id="cloud-download"><path d="M19.4,10c-0.7-3.4-3.7-6-7.4-6C9.1,4,6.6,5.6,5.4,8C2.3,8.4,0,10.9,0,14c0,3.3,2.7,6,6,6h13c2.8,0,5-2.2,5-5C24,12.4,21.9,10.2,19.4,10z M17,13l-5,5l-5-5h3V9h4v4H17z"/></g> -<g id="cloud-off"><path d="M19.4,10c-0.7-3.4-3.7-6-7.4-6c-1.5,0-2.9,0.4-4,1.2l1.5,1.5C10.2,6.2,11.1,6,12,6c3,0,5.5,2.5,5.5,5.5V12H19c1.7,0,3,1.3,3,3c0,1.1-0.6,2.1-1.6,2.6l1.5,1.5c1.3-0.9,2.1-2.4,2.1-4.1C24,12.4,21.9,10.2,19.4,10z M3,5.3L5.8,8C2.6,8.2,0,10.8,0,14c0,3.3,2.7,6,6,6h11.7l2,2l1.3-1.3L4.3,4L3,5.3z M7.7,10l8,8H6c-2.2,0-4-1.8-4-4c0-2.2,1.8-4,4-4H7.7z"/></g> -<g id="cloud-queue"><path d="M19.4,10c-0.7-3.4-3.7-6-7.4-6C9.1,4,6.6,5.6,5.4,8C2.3,8.4,0,10.9,0,14c0,3.3,2.7,6,6,6h13c2.8,0,5-2.2,5-5C24,12.4,21.9,10.2,19.4,10z M19,18H6c-2.2,0-4-1.8-4-4c0-2.2,1.8-4,4-4h0.7C7.4,7.7,9.5,6,12,6c3,0,5.5,2.5,5.5,5.5V12H19c1.7,0,3,1.3,3,3S20.7,18,19,18z"/></g> -<g id="cloud-upload"><path d="M19.4,10c-0.7-3.4-3.7-6-7.4-6C9.1,4,6.6,5.6,5.4,8C2.3,8.4,0,10.9,0,14c0,3.3,2.7,6,6,6h13c2.8,0,5-2.2,5-5C24,12.4,21.9,10.2,19.4,10z M14,13v4h-4v-4H7l5-5l5,5H14z"/></g> -<g id="content-copy"><path d="M16,1H4C2.9,1,2,1.9,2,3v14h2V3h12V1z M19,5H8C6.9,5,6,5.9,6,7v14c0,1.1,0.9,2,2,2h11c1.1,0,2-0.9,2-2V7C21,5.9,20.1,5,19,5z M19,21H8V7h11V21z"/></g> -<g id="content-cut"><path d="M10,6c0-2.2-1.8-4-4-4S2,3.8,2,6c0,2.2,1.8,4,4,4c0.6,0,1.1-0.1,1.6-0.4L10,12l-2.4,2.4C7.1,14.1,6.6,14,6,14c-2.2,0-4,1.8-4,4c0,2.2,1.8,4,4,4s4-1.8,4-4c0-0.6-0.1-1.1-0.4-1.6L12,14l7,7h4L9.6,7.6C9.9,7.1,10,6.6,10,6z M6,8C4.9,8,4,7.1,4,6s0.9-2,2-2c1.1,0,2,0.9,2,2S7.1,8,6,8z M6,20c-1.1,0-2-0.9-2-2s0.9-2,2-2c1.1,0,2,0.9,2,2S7.1,20,6,20z M12,11.5c0.3,0,0.5,0.2,0.5,0.5c0,0.3-0.2,0.5-0.5,0.5c-0.3,0-0.5-0.2-0.5-0.5C11.5,11.7,11.7,11.5,12,11.5z M23,3h-4l-6,6l2,2L23,3z"/></g> -<g id="content-paste"><path d="M19,2h-4.2c-0.4-1.2-1.5-2-2.8-2c-1.3,0-2.4,0.8-2.8,2H5C3.9,2,3,2.9,3,4v16c0,1.1,0.9,2,2,2h14c1.1,0,2-0.9,2-2V4C21,2.9,20.1,2,19,2z M12,2c0.6,0,1,0.4,1,1s-0.4,1-1,1c-0.6,0-1-0.4-1-1S11.4,2,12,2z M19,20H5V4h2v3h10V4h2V20z"/></g> -<g id="create"><path d="M3,17.2V21h3.8L17.8,9.9l-3.8-3.8L3,17.2z M20.7,7c0.4-0.4,0.4-1,0-1.4l-2.3-2.3c-0.4-0.4-1-0.4-1.4,0l-1.8,1.8l3.8,3.8L20.7,7z"/></g> -<g id="credit-card"><path d="M20,4H4C2.9,4,2,4.9,2,6v12c0,1.1,0.9,2,2,2h16c1.1,0,2-0.9,2-2V6C22,4.9,21.1,4,20,4z M20,18H4v-6h16V18z M20,8H4V6h16V8z"/></g> -<g id="delete"><path d="M6,19c0,1.1,0.9,2,2,2h8c1.1,0,2-0.9,2-2V7H6V19z M19,4h-3.5l-1-1h-5l-1,1H5v2h14V4z"/></g> -<g id="description"><path d="M14,2H6C4.9,2,4,2.9,4,4l0,16c0,1.1,0.9,2,2,2h12c1.1,0,2-0.9,2-2V8L14,2z M16,18H8v-2h8V18z M16,14H8v-2h8V14z M13,9V3.5L18.5,9H13z"/></g> -<g id="developer-mode-tv"><path d="M4,5h16v2h2l0-2c0-1.1-0.9-2-2-2H4C2.9,3,2,3.9,2,5v2h2V5z M7.6,13.8L4.7,11l2.8-2.8L6.1,6.8L1.9,11l4.2,4.2L7.6,13.8z M20,17H4v-2H2v2c0,1.1,0.9,2,2,2h4v2h8v-2h4c1.1,0,2-0.9,2-2l0-2h-2V17z M22,11l-4.2-4.2l-1.4,1.4l2.8,2.8l-2.8,2.8l1.4,1.4L22,11L22,11L22,11L22,11L22,11z"/></g> -<g id="done"><polygon points="9,16.2 4.8,12 3.4,13.4 9,19 21,7 19.6,5.6 "/></g> -<g id="done-all"><path d="M18,7l-1.4-1.4l-6.3,6.3l1.4,1.4L18,7z M22.2,5.6L11.7,16.2L7.5,12l-1.4,1.4l5.6,5.6l12-12L22.2,5.6z M0.4,13.4L6,19l1.4-1.4L1.8,12L0.4,13.4z"/></g> -<g id="drafts"><path d="M22,8c0-0.7-0.4-1.3-0.9-1.7L12,1L2.9,6.3C2.4,6.7,2,7.3,2,8v10c0,1.1,0.9,2,2,2h16c1.1,0,2-0.9,2-2L22,8z M12,13L3.7,7.8L12,3l8.3,4.8L12,13z"/></g> -<g id="drawer"><path d="M12,8c1.1,0,2-0.9,2-2s-0.9-2-2-2c-1.1,0-2,0.9-2,2S10.9,8,12,8z M12,10c-1.1,0-2,0.9-2,2s0.9,2,2,2c1.1,0,2-0.9,2-2S13.1,10,12,10z M12,16c-1.1,0-2,0.9-2,2s0.9,2,2,2c1.1,0,2-0.9,2-2S13.1,16,12,16z"/></g> -<g id="drive"><path d="M22.3,14L15.4,2H8.6l0,0l6.9,12H22.3z M9.7,15l-3.4,6h13.1l3.4-6H9.7z M7.7,3.5L1.2,15l3.4,6l6.6-11.5L7.7,3.5z"/></g> -<g id="drive-archive"><path d="M19,3H5C3.9,3,3,3.9,3,5v14c0,1.1,0.9,2,2,2h14c1.1,0,2-0.9,2-2V5C21,3.9,20.1,3,19,3z M12,18l-4-4h8L12,18z M16,12H8v-2h8V12z M16,8H8V6h8V8z"/></g> -<g id="drive-audio"><path d="M19,3H5C3.9,3,3,3.9,3,5v14c0,1.1,0.9,2,2,2h14c1.1,0,2-0.9,2-2V5C21,3.9,20.1,3,19,3z M7.2,18C6.5,18,6,17.5,6,16.8v-3.6V12c0-3.3,2.7-6,6-6s6,2.7,6,6v1.2v3.6c0,0.7-0.5,1.2-1.2,1.2H14v-4h2v-2c0-2.2-1.8-4-4-4s-4,1.8-4,4v2h2v4H7.2z"/></g> -<g id="drive-chart"><path d="M19,3H5C3.9,3,3,3.9,3,5v14c0,1.1,0.9,2,2,2h14c1.1,0,2-0.9,2-2V5C21,3.9,20.1,3,19,3z M9,17H7v-7h2V17z M13,17h-2V7h2V17z M17,17h-2v-4h2V17z"/></g> -<g id="drive-document"><path d="M19,3H5C3.9,3,3,3.9,3,5v14c0,1.1,0.9,2,2,2h14c1.1,0,2-0.9,2-2V5C21,3.9,20.1,3,19,3z M17,9H7V7h10V9z M17,13H7v-2h10V13z M14,17H7v-2h7V17z"/></g> -<g id="drive-drawing"><path d="M19,3H5C3.9,3,3,3.9,3,5v14c0,1.1,0.9,2,2,2h14c1.1,0,2-0.9,2-2V5C21,3.9,20.1,3,19,3z M18,18h-6v-5.8c-0.7,0.6-1.5,1-2.5,1c-2,0-3.7-1.7-3.7-3.7s1.7-3.7,3.7-3.7c2,0,3.7,1.7,3.7,3.7c0,1-0.4,1.8-1,2.5H18V18z"/></g> -<g id="drive-file"><path d="M6,2C4.9,2,4,2.9,4,4l0,16c0,1.1,0.9,2,2,2h12c1.1,0,2-0.9,2-2V8l-6-6H6z M13,9V3.5L18.5,9H13z"/></g> -<g id="drive-file-move"><path d="M20,6h-8l-2-2H4C2.9,4,2,4.9,2,6v12c0,1.1,0.9,2,2,2h16c1.1,0,2-0.9,2-2V8C22,6.9,21.1,6,20,6z M9,18v-3H5v-4h4V8l5,5L9,18z"/></g> -<g id="drive-file-rename"><path d="M19,3H5C3.9,3,3,3.9,3,5v14c0,1.1,0.9,2,2,2h14c1.1,0,2-0.9,2-2V5C21,3.9,20.1,3,19,3z M6,17v-2.5l7.9-7.9c0.2-0.2,0.5-0.2,0.7,0l1.8,1.8c0.2,0.2,0.2,0.5,0,0.7L8.5,17H6z M18,17h-7.5l2-2H18V17z"/></g> -<g id="drive-form"><path d="M19,3H5C3.9,3,3,3.9,3,5v14c0,1.1,0.9,2,2,2h14c1.1,0,2-0.9,2-2V5C21,3.9,20.1,3,19,3z M9,17H7v-2h2V17z M9,13H7v-2h2V13z M9,9H7V7h2V9z M17,17h-7v-2h7V17z M17,13h-7v-2h7V13z M17,9h-7V7h7V9z"/></g> -<g id="drive-fusiontable"><path d="M19,3H5C3.9,3,3,3.9,3,5v14c0,1.1,0.9,2,2,2h14c1.1,0,2-0.9,2-2V5C21,3.9,20.1,3,19,3z M19,10.2L13,17l-4-4l-4,4v-3l4-4l4,4l6-6.8V10.2z"/></g> -<g id="drive-image"><path d="M21,19V5c0-1.1-0.9-2-2-2H5C3.9,3,3,3.9,3,5v14c0,1.1,0.9,2,2,2h14C20.1,21,21,20.1,21,19z M8.5,13.5l2.5,3l3.5-4.5l4.5,6H5L8.5,13.5z"/></g> -<g id="drive-keep"><path d="M9,21c0,0.6,0.4,1,1,1h4c0.6,0,1-0.4,1-1v-1H9V21z M12,2C8.1,2,5,5.1,5,9c0,2.4,1.2,4.5,3,5.7V17c0,0.6,0.4,1,1,1h6c0.6,0,1-0.4,1-1v-2.3c1.8-1.3,3-3.4,3-5.7C19,5.1,15.9,2,12,2z"/></g> -<g id="drive-ms-excel"><path d="M19,3H5C3.9,3,3,3.9,3,5v14c0,1.1,0.9,2,2,2h14c1.1,0,2-0.9,2-2V5C21,3.9,20.1,3,19,3z M16.2,17h-2L12,13.2L9.8,17h-2l3.2-5L7.8,7h2l2.2,3.8L14.2,7h2L13,12L16.2,17z"/></g> -<g id="drive-ms-powerpoint"><path d="M19,3H5C3.9,3,3,3.9,3,5v14c0,1.1,0.9,2,2,2h14c1.1,0,2-0.9,2-2V5C21,3.9,20.1,3,19,3z M9.8,13.4V17H8V7h4.3c1.5,0,2.2,0.3,2.8,0.9c0.7,0.6,0.9,1.4,0.9,2.3c0,1-0.3,1.8-0.9,2.3c-0.6,0.5-1.3,0.8-2.8,0.8H9.8z"/><path d="M9.8,12V8.4h2.3c0.7,0,1.2,0.2,1.5,0.6c0.3,0.4,0.5,0.7,0.5,1.2c0,0.6-0.2,0.9-0.5,1.3c-0.3,0.3-0.7,0.5-1.4,0.5H9.8z"/></g> -<g id="drive-ms-word"><path d="M19,3H5C3.9,3,3,3.9,3,5v14c0,1.1,0.9,2,2,2h14c1.1,0,2-0.9,2-2V5C21,3.9,20.1,3,19,3z M15.5,17H14l-2-7.5L10,17H8.5L6.1,7h1.7l1.5,7.5l2-7.5h1.4l2,7.5L16.2,7h1.7L15.5,17z"/></g> -<g id="drive-pdf"><path d="M11.3,8.6L11.3,8.6C11.4,8.6,11.4,8.6,11.3,8.6c0.1-0.4,0.2-0.6,0.2-0.9l0-0.2c0.1-0.5,0.1-0.9,0-1c0,0,0,0,0-0.1l-0.1-0.1c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0.1-0.1,0.1C11.1,7,11.1,7.7,11.3,8.6C11.3,8.6,11.3,8.6,11.3,8.6z M8.3,15.5c-0.2,0.1-0.4,0.2-0.5,0.3c-0.7,0.6-1.2,1.3-1.3,1.6c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0C7.1,17.3,7.7,16.7,8.3,15.5C8.4,15.5,8.4,15.5,8.3,15.5C8.4,15.5,8.3,15.5,8.3,15.5z M17.5,14c-0.1-0.1-0.5-0.4-1.9-0.4c-0.1,0-0.1,0-0.2,0c0,0,0,0,0,0c0,0,0,0,0,0.1c0.7,0.3,1.4,0.5,1.9,0.5c0.1,0,0.1,0,0.2,0l0,0c0,0,0.1,0,0.1,0c0,0,0,0,0-0.1c0,0,0,0,0,0C17.6,14.1,17.5,14.1,17.5,14z M19,3H5C3.9,3,3,3.9,3,5v14c0,1.1,0.9,2,2,2h14c1.1,0,2-0.9,2-2V5C21,3.9,20.1,3,19,3z M17.9,14.8C17.7,14.9,17.4,15,17,15c-0.8,0-2-0.2-3-0.7c-1.7,0.2-3,0.4-4,0.8c-0.1,0-0.1,0-0.2,0.1c-1.2,2.1-2.2,3.1-3,3.1c-0.2,0-0.3,0-0.4-0.1l-0.5-0.3l0-0.1c-0.1-0.2-0.1-0.3-0.1-0.5c0.1-0.5,0.7-1.4,1.9-2.1c0.2-0.1,0.5-0.3,0.9-0.5c0.3-0.5,0.6-1.1,1-1.8c0.5-1,0.8-2,1.1-2.9l0,0c-0.4-1.2-0.6-1.9-0.2-3.3c0.1-0.4,0.4-0.8,0.8-0.8l0.2,0c0.2,0,0.4,0.1,0.6,0.2c0.7,0.7,0.4,2.3,0,3.6c0,0.1,0,0.1,0,0.1c0.4,1.1,1,2,1.6,2.6c0.3,0.2,0.5,0.4,0.9,0.6c0.5,0,0.9-0.1,1.3-0.1c1.2,0,2,0.2,2.3,0.7c0.1,0.2,0.1,0.4,0.1,0.6C18.2,14.3,18.1,14.6,17.9,14.8z M11.4,10.9c-0.2,0.7-0.6,1.5-1,2.4c-0.2,0.4-0.4,0.7-0.6,1.1c0,0,0.1,0,0.1,0l0.1,0v0c1.3-0.5,2.5-0.8,3.3-0.9c-0.2-0.1-0.3-0.2-0.4-0.3C12.4,12.6,11.8,11.8,11.4,10.9z"/></g> -<g id="drive-presentation"><path d="M19,3H5C3.9,3,3,3.9,3,5v14c0,1.1,0.9,2,2,2h14c1.1,0,2-0.9,2-2V5C21,3.9,20.1,3,19,3z M19,16H5V8h14V16z"/></g> -<g id="drive-script"><path d="M19,3H5C3.9,3,3,3.9,3,5l0,4h0v6h0l0,4c0,1.1,0.9,2,2,2h14c1.1,0,2-0.9,2-2V5C21,3.9,20.1,3,19,3z M11,17v-3H5v-4h6V7l5,5L11,17z"/></g> -<g id="drive-site"><path d="M19,4H5C3.9,4,3,4.9,3,6l0,12c0,1.1,0.9,2,2,2h14c1.1,0,2-0.9,2-2V6C21,4.9,20.1,4,19,4z M14,18H5v-4h9V18z M14,13H5V9h9V13z M19,18h-4V9h4V18z"/></g> -<g id="drive-spreadsheet"><path d="M19,3H5C3.9,3,3,3.9,3,5l0,3h0v11c0,1.1,0.9,2,2,2h14c1.1,0,2-0.9,2-2V5C21,3.9,20.1,3,19,3z M19,11h-8v8H9v-8H5V9h4V5h2v4h8V11z"/></g> -<g id="drive-text"><path d="M14,2H6C4.9,2,4,2.9,4,4l0,16c0,1.1,0.9,2,2,2h12c1.1,0,2-0.9,2-2V8L14,2z M16,18H8v-2h8V18z M16,14H8v-2h8V14z M13,9V3.5L18.5,9H13z"/></g> -<g id="drive-video"><path d="M18,4l2,4h-3l-2-4h-2l2,4h-3l-2-4H8l2,4H7L5,4H4C2.9,4,2,4.9,2,6l0,12c0,1.1,0.9,2,2,2h16c1.1,0,2-0.9,2-2V4H18z"/></g> -<g id="drive-zip"><path d="M19,3H5C3.9,3,3,3.9,3,5v14c0,1.1,0.9,2,2,2h14c1.1,0,2-0.9,2-2V5C21,3.9,20.1,3,19,3z M14,9h-2v2h2v2h-2v-2h-2V9h2V7h-2V5h2v2h2V9z M14,17h-2v-2h-2v-2h2v2h2V17z"/></g> -<g id="due-date"><path d="M17,12h-5v5h5V12z M16,1v2H8V1H6v2H5C3.9,3,3,3.9,3,5l0,14c0,1.1,0.9,2,2,2h14c1.1,0,2-0.9,2-2V5c0-1.1-0.9-2-2-2h-1V1H16z M19,19H5V8h14V19z"/></g> -<g id="error"><path d="M12,2C6.5,2,2,6.5,2,12s4.5,10,10,10c5.5,0,10-4.5,10-10S17.5,2,12,2z M13,17h-2v-2h2V17z M13,13h-2V7h2V13z"/></g> -<g id="event"><path d="M17,12h-5v5h5V12z M16,1v2H8V1H6v2H5C3.9,3,3,3.9,3,5l0,14c0,1.1,0.9,2,2,2h14c1.1,0,2-0.9,2-2V5c0-1.1-0.9-2-2-2h-1V1H16z M19,19H5V8h14V19z"/></g> -<g id="exit-to-app"><path d="M10.1,15.6l1.4,1.4l5-5l-5-5l-1.4,1.4l2.6,2.6H3v2h9.7L10.1,15.6z M19,3H5C3.9,3,3,3.9,3,5v4h2V5h14v14H5v-4H3v4c0,1.1,0.9,2,2,2h14c1.1,0,2-0.9,2-2V5C21,3.9,20.1,3,19,3z"/></g> -<g id="expand-less"><polygon points="12,8 6,14 7.4,15.4 12,10.8 16.6,15.4 18,14 "/></g> -<g id="expand-more"><polygon points="16.6,8.6 12,13.2 7.4,8.6 6,10 12,16 18,10 "/></g> -<g id="explore"><path d="M12,10.9c-0.6,0-1.1,0.5-1.1,1.1s0.5,1.1,1.1,1.1c0.6,0,1.1-0.5,1.1-1.1S12.6,10.9,12,10.9z M12,2C6.5,2,2,6.5,2,12c0,5.5,4.5,10,10,10c5.5,0,10-4.5,10-10C22,6.5,17.5,2,12,2z M14.2,14.2L6,18l3.8-8.2L18,6L14.2,14.2z"/></g> -<g id="extension"><path d="M20.5,11H19V7c0-1.1-0.9-2-2-2h-4V3.5C13,2.1,11.9,1,10.5,1C9.1,1,8,2.1,8,3.5V5H4C2.9,5,2,5.9,2,7l0,3.8h1.5c1.5,0,2.7,1.2,2.7,2.7S5,16.2,3.5,16.2H2L2,20c0,1.1,0.9,2,2,2h3.8v-1.5c0-1.5,1.2-2.7,2.7-2.7c1.5,0,2.7,1.2,2.7,2.7V22H17c1.1,0,2-0.9,2-2v-4h1.5c1.4,0,2.5-1.1,2.5-2.5S21.9,11,20.5,11z"/></g> -<g id="favorite"><path d="M12,21.4L10.6,20C5.4,15.4,2,12.3,2,8.5C2,5.4,4.4,3,7.5,3c1.7,0,3.4,0.8,4.5,2.1C13.1,3.8,14.8,3,16.5,3C19.6,3,22,5.4,22,8.5c0,3.8-3.4,6.9-8.6,11.5L12,21.4z"/></g> -<g id="favorite-outline"><path d="M16.5,3c-1.7,0-3.4,0.8-4.5,2.1C10.9,3.8,9.2,3,7.5,3C4.4,3,2,5.4,2,8.5c0,3.8,3.4,6.9,8.6,11.5l1.4,1.3l1.4-1.3c5.1-4.7,8.6-7.8,8.6-11.5C22,5.4,19.6,3,16.5,3z M12.1,18.6L12,18.6l-0.1-0.1C7.1,14.2,4,11.4,4,8.5C4,6.5,5.5,5,7.5,5c1.5,0,3,1,3.6,2.4h1.9C13.5,6,15,5,16.5,5c2,0,3.5,1.5,3.5,3.5C20,11.4,16.9,14.2,12.1,18.6z"/></g> -<g id="file-download"><path d="M19,9h-4V3H9v6H5l7,7L19,9z M5,18v2h14v-2H5z"/></g> -<g id="file-map"><path d="M12,6.5c-0.8,0-1.5,0.7-1.5,1.5s0.7,1.5,1.5,1.5c0.8,0,1.5-0.7,1.5-1.5S12.8,6.5,12,6.5z M19,1H5C3.9,1,3,1.9,3,3v14c0,1.1,0.9,2,2,2h14c1.1,0,2-0.9,2-2V3C21,1.9,20.1,1,19,1z M12.5,17h-1c-1-4.1-4-5.8-4-9c0-2.5,2-4.5,4.5-4.5c2.5,0,4.5,2,4.5,4.5C16.5,11.2,13.5,12.9,12.5,17z"/></g> -<g id="file-upload"><polygon points="9,16 15,16 15,10 19,10 12,3 5,10 9,10 "/></g> -<g id="filter"><path d="M10,18h4v-2h-4V18z M3,6v2h18V6H3z M6,13h12v-2H6V13z"/></g> -<g id="flag"><polygon points="14.4,6 14,4 5,4 5,21 7,21 7,14 12.6,14 13,16 20,16 20,6 "/></g> -<g id="flip-to-back"><path d="M9,7H7l0,2h2V7z M9,11H7v2h2V11z M9,3C7.9,3,7,3.9,7,5h2V3z M13,15h-2v2h2V15z M19,3v2h2C21,3.9,20.1,3,19,3z M13,3h-2v2h2V3z M9,17v-2H7C7,16.1,7.9,17,9,17z M19,13h2v-2h-2V13z M19,9h2V7h-2V9z M19,17c1.1,0,2-0.9,2-2h-2V17z M5,7H3v2h0l0,10c0,1.1,0.9,2,2,2h12v-2H5V7z M15,5h2V3h-2V5z M15,17h2v-2h-2V17z"/></g> -<g id="flip-to-front"><path d="M3,13h2v-2H3L3,13z M3,17h2v-2H3V17z M5,21v-2H3C3,20.1,3.9,21,5,21z M3,9h2V7H3V9z M15,21h2v-2h-2V21z M19,3H9C7.9,3,7,3.9,7,5v2h0v2v6c0,1.1,0.9,2,2,2h5h4h1c1.1,0,2-0.9,2-2V5C21,3.9,20.1,3,19,3z M19,15H9V5h10V15z M11,21h2v-2h-2V21z M7,21h2v-2H7V21z"/></g> -<g id="folder"><path d="M10,4H4C2.9,4,2,4.9,2,6l0,12c0,1.1,0.9,2,2,2h16c1.1,0,2-0.9,2-2V8c0-1.1-0.9-2-2-2h-8L10,4z"/></g> -<g id="folder-mydrive"><path d="M20,6h-8l-2-2H4C2.9,4,2,4.9,2,6l0,12c0,1.1,0.9,2,2,2h16c1.1,0,2-0.9,2-2V8C22,6.9,21.1,6,20,6z M11.5,17l-1.1-2.1l2.8-5l1.5,2.7L12.3,17H11.5z M18.3,17h-5.5l1.4-2.5h5.1l0.3,0.5L18.3,17z M13.8,9h2.4l2.8,5H16l-2.6-4.5L13.8,9z"/></g> -<g id="folder-open"><path d="M20,6h-8l-2-2H4C2.9,4,2,4.9,2,6l0,12c0,1.1,0.9,2,2,2h16c1.1,0,2-0.9,2-2V8C22,6.9,21.1,6,20,6z M20,18H4V8h16V18z"/></g> -<g id="folder-shared"><path d="M20,6h-8l-2-2H4C2.9,4,2,4.9,2,6l0,12c0,1.1,0.9,2,2,2h16c1.1,0,2-0.9,2-2V8C22,6.9,21.1,6,20,6z M15,9c1.1,0,2,0.9,2,2c0,1.1-0.9,2-2,2c-1.1,0-2-0.9-2-2C13,9.9,13.9,9,15,9z M19,17h-8v-1c0-1.3,2.7-2,4-2c1.3,0,4,0.7,4,2V17z"/></g> -<g id="forward"><polygon points="12,8 12,4 20,12 12,20 12,16 4,16 4,8 "/></g> -<g id="fullscreen"><path d="M7,14H5v5h5v-2H7V14z M5,10h2V7h3V5H5V10z M17,17h-3v2h5v-5h-2V17z M14,5v2h3v3h2V5H14z"/></g> -<g id="fullscreen-exit"><path d="M5,16h3v3h2v-5H5V16z M8,8H5v2h5V5H8V8z M14,19h2v-3h3v-2h-5V19z M16,8V5h-2v5h5V8H16z"/></g> -<g id="gesture"><path d="M4.6,6.9C5.3,6.2,6,5.5,6.3,5.7c0.5,0.2,0,1-0.3,1.5c-0.3,0.4-2.9,3.9-2.9,6.3c0,1.3,0.5,2.3,1.3,3c0.8,0.6,1.7,0.7,2.6,0.5c1.1-0.3,1.9-1.4,3.1-2.8c1.2-1.5,2.8-3.4,4.1-3.4c1.6,0,1.6,1,1.8,1.8c-3.8,0.6-5.4,3.7-5.4,5.4c0,1.7,1.4,3.1,3.2,3.1c1.6,0,4.3-1.3,4.7-6.1H21v-2.5h-2.5c-0.2-1.6-1.1-4.2-4-4.2c-2.2,0-4.2,1.9-4.9,2.8c-0.6,0.7-2.1,2.5-2.3,2.7c-0.3,0.3-0.7,0.8-1.1,0.8c-0.4,0-0.7-0.8-0.4-1.9c0.4-1.1,1.4-2.9,1.9-3.5C8.4,8,8.9,7.2,8.9,5.9C8.9,3.7,7.3,3,6.4,3C5.1,3,4,4,3.7,4.3C3.4,4.6,3.1,4.9,2.8,5.2L4.6,6.9z M13.9,18.6c-0.3,0-0.7-0.3-0.7-0.7c0-0.6,0.7-2.2,2.9-2.8C15.7,17.8,14.6,18.6,13.9,18.6z"/></g> -<g id="get-app"><path d="M19,9h-4V3H9v6H5l7,7L19,9z M5,18v2h14v-2H5z"/></g> -<g id="google"><path d="M16.3,13.4l-1.1-0.8c-0.4-0.3-0.8-0.7-0.8-1.4c0-0.7,0.5-1.3,1-1.6c1.3-1,2.6-2.1,2.6-4.3c0-2.1-1.3-3.3-2-3.9h1.7L18.9,0h-6.2C8.3,0,6.1,2.8,6.1,5.8c0,2.3,1.8,4.8,5,4.8h0.8c-0.1,0.3-0.4,0.8-0.4,1.3c0,1,0.4,1.4,0.9,2c-1.4,0.1-4,0.4-5.9,1.6c-1.8,1.1-2.3,2.6-2.3,3.7c0,2.3,2.1,4.5,6.6,4.5c5.4,0,8-3,8-5.9C18.8,15.7,17.7,14.6,16.3,13.4z M8.7,4.3c0-2.2,1.3-3.2,2.7-3.2c2.6,0,4,3.5,4,5.5c0,2.6-2.1,3.1-2.9,3.1C10,9.7,8.7,6.6,8.7,4.3z M12.3,22.3c-3.3,0-5.4-1.5-5.4-3.7c0-2.2,2-2.9,2.6-3.2c1.3-0.4,3-0.5,3.3-0.5c0.3,0,0.5,0,0.7,0c2.4,1.7,3.4,2.4,3.4,4C16.9,20.8,15,22.3,12.3,22.3z"/></g> -<g id="google-plus"><path d="M21,10V7h-2v3h-3v2h3v3h2v-3h3v-2H21z M13.3,13.4l-1.1-0.8c-0.4-0.3-0.8-0.7-0.8-1.4c0-0.7,0.5-1.3,1-1.6c1.3-1,2.6-2.1,2.6-4.3c0-2.1-1.3-3.3-2-3.9h1.7L15.9,0H9.7C5.3,0,3.1,2.8,3.1,5.8c0,2.3,1.8,4.8,5,4.8h0.8c-0.1,0.3-0.4,0.8-0.4,1.3c0,1,0.4,1.4,0.9,2c-1.4,0.1-4,0.4-5.9,1.6c-1.8,1.1-2.3,2.6-2.3,3.7c0,2.3,2.1,4.5,6.6,4.5c5.4,0,8-3,8-5.9C15.8,15.7,14.7,14.6,13.3,13.4z M5.7,4.3c0-2.2,1.3-3.2,2.7-3.2c2.6,0,4,3.5,4,5.5c0,2.6-2.1,3.1-2.9,3.1C7,9.7,5.7,6.6,5.7,4.3z M9.3,22.3c-3.3,0-5.4-1.5-5.4-3.7c0-2.2,2-2.9,2.6-3.2c1.3-0.4,3-0.5,3.3-0.5c0.3,0,0.5,0,0.7,0c2.4,1.7,3.4,2.4,3.4,4C13.9,20.8,12,22.3,9.3,22.3z"/></g> -<g id="grade"><polygon points="12,17.3 18.2,21 16.5,14 22,9.2 14.8,8.6 12,2 9.2,8.6 2,9.2 7.5,14 5.8,21 "/></g> -<g id="group-work"><path d="M12,2C6.5,2,2,6.5,2,12c0,5.5,4.5,10,10,10c5.5,0,10-4.5,10-10C22,6.5,17.5,2,12,2z M8,17.5c-1.4,0-2.5-1.1-2.5-2.5s1.1-2.5,2.5-2.5s2.5,1.1,2.5,2.5S9.4,17.5,8,17.5z M9.5,8c0-1.4,1.1-2.5,2.5-2.5s2.5,1.1,2.5,2.5s-1.1,2.5-2.5,2.5S9.5,9.4,9.5,8z M16,17.5c-1.4,0-2.5-1.1-2.5-2.5s1.1-2.5,2.5-2.5s2.5,1.1,2.5,2.5S17.4,17.5,16,17.5z"/></g> -<g id="help"><path d="M12,2C6.5,2,2,6.5,2,12s4.5,10,10,10c5.5,0,10-4.5,10-10S17.5,2,12,2z M13,19h-2v-2h2V19z M15.1,11.3l-0.9,0.9C13.4,12.9,13,13.5,13,15h-2v-0.5c0-1.1,0.4-2.1,1.2-2.8l1.2-1.3C13.8,10.1,14,9.6,14,9c0-1.1-0.9-2-2-2c-1.1,0-2,0.9-2,2H8c0-2.2,1.8-4,4-4c2.2,0,4,1.8,4,4C16,9.9,15.6,10.7,15.1,11.3z"/></g> -<g id="highlight-remove"><path d="M14.6,8L12,10.6L9.4,8L8,9.4l2.6,2.6L8,14.6L9.4,16l2.6-2.6l2.6,2.6l1.4-1.4L13.4,12L16,9.4L14.6,8z M12,2C6.5,2,2,6.5,2,12s4.5,10,10,10c5.5,0,10-4.5,10-10S17.5,2,12,2z M12,20c-4.4,0-8-3.6-8-8s3.6-8,8-8s8,3.6,8,8S16.4,20,12,20z"/></g> -<g id="history"><path opacity="0.9" d="M13,3c-5,0-9,4-9,9H1l3.9,3.9c0,0,0,0.1,0.1,0.1l4-4H6c0-3.9,3.1-7,7-7c3.9,0,7,3.1,7,7s-3.1,7-7,7c-1.9,0-3.7-0.8-4.9-2.1l-1.4,1.4C8.3,20,10.5,21,13,21c5,0,9-4,9-9S18,3,13,3z M12,8v5l4.3,2.5l0.7-1.2l-3.5-2.1V8H12z"/></g> -<g id="home"><polygon points="10,20 10,14 14,14 14,20 19,20 19,12 22,12 12,3 2,12 5,12 5,20 "/></g> -<g id="https"><path d="M18,8h-1V6c0-2.8-2.2-5-5-5C9.2,1,7,3.2,7,6v2H6c-1.1,0-2,0.9-2,2v10c0,1.1,0.9,2,2,2h12c1.1,0,2-0.9,2-2V10C20,8.9,19.1,8,18,8z M12,17c-1.1,0-2-0.9-2-2s0.9-2,2-2c1.1,0,2,0.9,2,2S13.1,17,12,17z M15.1,8H8.9V6c0-1.7,1.4-3.1,3.1-3.1c1.7,0,3.1,1.4,3.1,3.1V8z"/></g> -<g id="inbox"><path d="M19,3H5C3.9,3,3,3.9,3,5l0,14c0,1.1,0.9,2,2,2h14c1.1,0,2-0.9,2-2V5C21,3.9,20.1,3,19,3z M19,15h-4c0,1.7-1.3,3-3,3c-1.7,0-3-1.3-3-3H5V5h14V15z M16,10h-2V7h-4v3H8l4,4L16,10z"/></g> -<g id="info"><path d="M12,2C6.5,2,2,6.5,2,12s4.5,10,10,10c5.5,0,10-4.5,10-10S17.5,2,12,2z M13,17h-2v-6h2V17z M13,9h-2V7h2V9z"/></g> -<g id="info-outline"><path d="M11,17h2v-6h-2V17z M12,2C6.5,2,2,6.5,2,12s4.5,10,10,10c5.5,0,10-4.5,10-10S17.5,2,12,2z M12,20c-4.4,0-8-3.6-8-8s3.6-8,8-8c4.4,0,8,3.6,8,8S16.4,20,12,20z M11,9h2V7h-2V9z"/></g> -<g id="input"><path d="M21,3H3C1.9,3,1,3.9,1,5v4h2V5h18v14H3v-4H1v4c0,1.1,0.9,2,2,2h18c1.1,0,2-0.9,2-2V5C23,3.9,22.1,3,21,3z M11,16l4-4l-4-4v3H1v2h10V16z"/></g> -<g id="invert-colors"><path d="M17.7,7.9L12,2.3l0,0v0L6.3,7.9c-3.1,3.1-3.1,8.2,0,11.3c1.6,1.6,3.6,2.3,5.7,2.3c2,0,4.1-0.8,5.7-2.3C20.8,16.1,20.8,11.1,17.7,7.9z M12,19.6L12,19.6c-1.6,0-3.1-0.6-4.2-1.8C6.6,16.7,6,15.2,6,13.6c0-1.6,0.6-3.1,1.8-4.2L12,5.1L12,19.6z"/></g> -<g id="keep"><path d="M16,12V4h1V2H7v2h1v8l-2,2v2h5.2v6h1.6v-6H18v-2L16,12z"/></g> -<g id="label"><path d="M17.6,5.8C17.3,5.3,16.7,5,16,5L5,5C3.9,5,3,5.9,3,7v10c0,1.1,0.9,2,2,2l11,0c0.7,0,1.3-0.3,1.6-0.8L22,12L17.6,5.8z"/></g> -<g id="label-outline"><path d="M17.6,5.8C17.3,5.3,16.7,5,16,5L5,5C3.9,5,3,5.9,3,7v10c0,1.1,0.9,2,2,2l11,0c0.7,0,1.3-0.3,1.6-0.8L22,12L17.6,5.8z M16,17H5V7h11l3.5,5L16,17z"/></g> -<g id="language"><path d="M12,2C6.5,2,2,6.5,2,12s4.5,10,10,10c5.5,0,10-4.5,10-10S17.5,2,12,2z M18.9,8H16c-0.3-1.3-0.8-2.4-1.4-3.6C16.4,5.1,18,6.3,18.9,8z M12,4c0.8,1.2,1.5,2.5,1.9,4h-3.8C10.5,6.6,11.2,5.2,12,4z M4.3,14C4.1,13.4,4,12.7,4,12s0.1-1.4,0.3-2h3.4c-0.1,0.7-0.1,1.3-0.1,2s0.1,1.3,0.1,2H4.3z M5.1,16H8c0.3,1.3,0.8,2.4,1.4,3.6C7.6,18.9,6,17.7,5.1,16z M8,8H5.1c1-1.7,2.5-2.9,4.3-3.6C8.8,5.6,8.3,6.7,8,8z M12,20c-0.8-1.2-1.5-2.5-1.9-4h3.8C13.5,17.4,12.8,18.8,12,20z M14.3,14H9.7c-0.1-0.7-0.2-1.3-0.2-2s0.1-1.3,0.2-2h4.7c0.1,0.7,0.2,1.3,0.2,2S14.4,13.3,14.3,14z M14.6,19.6c0.6-1.1,1.1-2.3,1.4-3.6h2.9C18,17.7,16.4,18.9,14.6,19.6z M16.4,14c0.1-0.7,0.1-1.3,0.1-2s-0.1-1.3-0.1-2h3.4c0.2,0.6,0.3,1.3,0.3,2s-0.1,1.4-0.3,2H16.4z"/></g> -<g id="launch"><path d="M19,19H5V5h7V3H5C3.9,3,3,3.9,3,5v14c0,1.1,0.9,2,2,2h14c1.1,0,2-0.9,2-2v-7h-2V19z M14,3v2h3.6l-9.8,9.8l1.4,1.4L19,6.4V10h2V3H14z"/></g> -<g id="link"><path d="M3.9,12c0-1.7,1.4-3.1,3.1-3.1h4V7H7c-2.8,0-5,2.2-5,5s2.2,5,5,5h4v-1.9H7C5.3,15.1,3.9,13.7,3.9,12z M8,13h8v-2H8V13z M17,7h-4v1.9h4c1.7,0,3.1,1.4,3.1,3.1s-1.4,3.1-3.1,3.1h-4V17h4c2.8,0,5-2.2,5-5S19.8,7,17,7z"/></g> -<g id="list"><path d="M3,13h2v-2H3V13z M3,17h2v-2H3V17z M3,9h2V7H3V9z M7,13h14v-2H7V13z M7,17h14v-2H7V17z M7,7v2h14V7H7z"/></g> -<g id="lock"><path d="M18,8h-1V6c0-2.8-2.2-5-5-5C9.2,1,7,3.2,7,6v2H6c-1.1,0-2,0.9-2,2v10c0,1.1,0.9,2,2,2h12c1.1,0,2-0.9,2-2V10C20,8.9,19.1,8,18,8z M12,17c-1.1,0-2-0.9-2-2s0.9-2,2-2c1.1,0,2,0.9,2,2S13.1,17,12,17z M15.1,8H8.9V6c0-1.7,1.4-3.1,3.1-3.1c1.7,0,3.1,1.4,3.1,3.1V8z"/></g> -<g id="lock-open"><path d="M12,17c1.1,0,2-0.9,2-2s-0.9-2-2-2c-1.1,0-2,0.9-2,2S10.9,17,12,17z M18,8h-1V6c0-2.8-2.2-5-5-5C9.2,1,7,3.2,7,6h1.9c0-1.7,1.4-3.1,3.1-3.1c1.7,0,3.1,1.4,3.1,3.1v2H6c-1.1,0-2,0.9-2,2v10c0,1.1,0.9,2,2,2h12c1.1,0,2-0.9,2-2V10C20,8.9,19.1,8,18,8z M18,20H6V10h12V20z"/></g> -<g id="lock-outline"><path d="M18,8h-1V6c0-2.8-2.2-5-5-5C9.2,1,7,3.2,7,6v2H6c-1.1,0-2,0.9-2,2v10c0,1.1,0.9,2,2,2h12c1.1,0,2-0.9,2-2V10C20,8.9,19.1,8,18,8z M12,2.9c1.7,0,3.1,1.4,3.1,3.1v2H9V6H8.9C8.9,4.3,10.3,2.9,12,2.9z M18,20H6V10h12V20z M12,17c1.1,0,2-0.9,2-2s-0.9-2-2-2c-1.1,0-2,0.9-2,2S10.9,17,12,17z"/></g> -<g id="loyalty"><path d="M21.4,11.6l-9-9C12.1,2.2,11.6,2,11,2H4C2.9,2,2,2.9,2,4v7c0,0.6,0.2,1.1,0.6,1.4l9,9c0.4,0.4,0.9,0.6,1.4,0.6c0.6,0,1.1-0.2,1.4-0.6l7-7c0.4-0.4,0.6-0.9,0.6-1.4C22,12.4,21.8,11.9,21.4,11.6z M5.5,7C4.7,7,4,6.3,4,5.5S4.7,4,5.5,4S7,4.7,7,5.5S6.3,7,5.5,7z M17.3,15.3L13,19.5l-4.3-4.3l0,0C8.3,14.8,8,14.2,8,13.5c0-1.4,1.1-2.5,2.5-2.5c0.7,0,1.3,0.3,1.8,0.7l0.7,0.7l0.7-0.7c0.5-0.5,1.1-0.7,1.8-0.7c1.4,0,2.5,1.1,2.5,2.5C18,14.2,17.7,14.8,17.3,15.3L17.3,15.3z"/></g> -<g id="mail"><path d="M20,4H4C2.9,4,2,4.9,2,6l0,12c0,1.1,0.9,2,2,2h16c1.1,0,2-0.9,2-2V6C22,4.9,21.1,4,20,4z M20,8l-8,5L4,8V6l8,5l8-5V8z"/></g> -<g id="markunread"><path d="M20,6H10v6H8V4h6V0H6v6H4C2.9,6,2,6.9,2,8l0,12c0,1.1,0.9,2,2,2h16c1.1,0,2-0.9,2-2V8C22,6.9,21.1,6,20,6z"/></g> -<g id="markunread"><path d="M22,6l2-2l-2-2l-2,2l-2-2l-2,2l-2-2l-2,2l-2-2L8,4L6,2L4,4L2,2L0,4l2,2L0,8l2,2l-2,2l2,2l-2,2l2,2l-2,2l2,2l2-2l2,2l2-2l2,2l2-2l2,2l2-2l2,2l2-2l2,2l2-2l-2-2l2-2l-2-2l2-2l-2-2l2-2L22,6z M20,8l-8,5L4,8V6l8,5l8-5V8z"/></g> -<g id="menu"><path d="M3,18h18v-2H3V18z M3,13h18v-2H3V13z M3,6v2h18V6H3z"/></g> -<g id="more-horiz"><path d="M6,10c-1.1,0-2,0.9-2,2s0.9,2,2,2c1.1,0,2-0.9,2-2S7.1,10,6,10z M18,10c-1.1,0-2,0.9-2,2s0.9,2,2,2c1.1,0,2-0.9,2-2S19.1,10,18,10z M12,10c-1.1,0-2,0.9-2,2s0.9,2,2,2c1.1,0,2-0.9,2-2S13.1,10,12,10z"/></g> -<g id="more-vert"><path d="M12,8c1.1,0,2-0.9,2-2s-0.9-2-2-2c-1.1,0-2,0.9-2,2S10.9,8,12,8z M12,10c-1.1,0-2,0.9-2,2s0.9,2,2,2c1.1,0,2-0.9,2-2S13.1,10,12,10z M12,16c-1.1,0-2,0.9-2,2s0.9,2,2,2c1.1,0,2-0.9,2-2S13.1,16,12,16z"/></g> -<g id="note-add"><path d="M14,2H6C4.9,2,4,2.9,4,4l0,16c0,1.1,0.9,2,2,2h12c1.1,0,2-0.9,2-2V8L14,2z M16,16h-3v3h-2v-3H8v-2h3v-3h2v3h3V16z M13,9V3.5L18.5,9H13z"/></g> -<g id="open-in-browser"><path d="M19,4H5C3.9,4,3,4.9,3,6v12c0,1.1,0.9,2,2,2h3v-2H5V8h14v10h-3v2h3c1.1,0,2-0.9,2-2V6C21,4.9,20.1,4,19,4z M12,10l-5,5h3v5h4v-5h3L12,10z"/></g> -<g id="open-in-new"><path d="M19,19H5V5h7V3H5C3.9,3,3,3.9,3,5v14c0,1.1,0.9,2,2,2h14c1.1,0,2-0.9,2-2v-7h-2V19z M14,3v2h3.6l-9.8,9.8l1.4,1.4L19,6.4V10h2V3H14z"/></g> -<g id="open-with"><path d="M10,9h4V6h3l-5-5L7,6h3V9z M9,10H6V7l-5,5l5,5v-3h3V10z M23,12l-5-5v3h-3v4h3v3L23,12z M14,15h-4v3H7l5,5l5-5h-3V15z"/></g> -<g id="payment"><path d="M20,4H4C2.9,4,2,4.9,2,6l0,12c0,1.1,0.9,2,2,2h16c1.1,0,2-0.9,2-2V6C22,4.9,21.1,4,20,4z M20,18H4v-6h16V18z M20,8H4V6h16V8z"/></g> -<g id="perm-camera-mic"><path d="M20,5h-3.2L15,3H9L7.2,5H4C2.9,5,2,5.9,2,7v12c0,1.1,0.9,2,2,2h7v-2.1C8.2,18.4,6,16,6,13h2c0,2.2,1.8,4,4,4s4-1.8,4-4h2c0,3-2.2,5.4-5,5.9V21h7c1.1,0,2-0.9,2-2V7C22,5.9,21.1,5,20,5z M14,13c0,1.1-0.9,2-2,2s-2-0.9-2-2V9c0-1.1,0.9-2,2-2s2,0.9,2,2V13z"/></g> -<g id="perm-contact-cal"><path d="M19,3h-1V1h-2v2H8V1H6v2H5C3.9,3,3,3.9,3,5l0,14c0,1.1,0.9,2,2,2h14c1.1,0,2-0.9,2-2V5C21,3.9,20.1,3,19,3z M12,6c1.7,0,3,1.3,3,3c0,1.7-1.3,3-3,3s-3-1.3-3-3C9,7.3,10.3,6,12,6z M18,18H6v-1c0-2,4-3.1,6-3.1s6,1.1,6,3.1V18z"/></g> -<g id="perm-data-setting"><path d="M19,11.5c0.3,0,0.7,0,1,0.1V0L0,20h11.6c0-0.3-0.1-0.7-0.1-1C11.5,14.9,14.9,11.5,19,11.5z M22.7,19.5c0-0.2,0-0.3,0-0.5c0-0.2,0-0.3,0-0.5l1.1-0.8c0.1-0.1,0.1-0.2,0.1-0.3l-1-1.7c-0.1-0.1-0.2-0.2-0.3-0.1L21.3,16c-0.3-0.2-0.5-0.4-0.8-0.5l-0.2-1.3c0-0.1-0.1-0.2-0.2-0.2h-2c-0.1,0-0.2,0.1-0.2,0.2l-0.2,1.3c-0.3,0.1-0.6,0.3-0.8,0.5l-1.2-0.5c-0.1,0-0.2,0-0.3,0.1l-1,1.7c-0.1,0.1,0,0.2,0.1,0.3l1.1,0.8c0,0.2,0,0.3,0,0.5c0,0.2,0,0.3,0,0.5l-1.1,0.8c-0.1,0.1-0.1,0.2-0.1,0.3l1,1.7c0.1,0.1,0.2,0.2,0.3,0.1l1.2-0.5c0.3,0.2,0.5,0.4,0.8,0.5l0.2,1.3c0,0.1,0.1,0.2,0.2,0.2h2c0.1,0,0.2-0.1,0.2-0.2l0.2-1.3c0.3-0.1,0.6-0.3,0.8-0.5l1.2,0.5c0.1,0,0.2,0,0.3-0.1l1-1.7c0.1-0.1,0-0.2-0.1-0.3L22.7,19.5z M19,20.5c-0.8,0-1.5-0.7-1.5-1.5s0.7-1.5,1.5-1.5s1.5,0.7,1.5,1.5S19.8,20.5,19,20.5z"/></g> -<g id="perm-device-info"><path d="M13,7h-2v2h2V7z M13,11h-2v6h2V11z M17,1L7,1C5.9,1,5,1.9,5,3v18c0,1.1,0.9,2,2,2h10c1.1,0,2-0.9,2-2V3C19,1.9,18.1,1,17,1z M17,19H7V5h10V19z"/></g> -<g id="perm-identity"><path d="M12,5.9c1.2,0,2.1,0.9,2.1,2.1s-0.9,2.1-2.1,2.1S9.9,9.2,9.9,8S10.8,5.9,12,5.9 M12,14.9c3,0,6.1,1.5,6.1,2.1v1.1H5.9V17C5.9,16.4,9,14.9,12,14.9 M12,4C9.8,4,8,5.8,8,8c0,2.2,1.8,4,4,4c2.2,0,4-1.8,4-4C16,5.8,14.2,4,12,4L12,4z M12,13c-2.7,0-8,1.3-8,4v3h16v-3C20,14.3,14.7,13,12,13L12,13z"/></g> -<g id="perm-media"><path d="M2,6H0v5h0l0,9c0,1.1,0.9,2,2,2h18v-2H2V6z M22,4h-8l-2-2H6C4.9,2,4,2.9,4,4l0,12c0,1.1,0.9,2,2,2h16c1.1,0,2-0.9,2-2V6C24,4.9,23.1,4,22,4z M7,15l4.5-6l3.5,4.5l2.5-3L21,15H7z"/></g> -<g id="perm-phone-msg"><path d="M20,15.5c-1.2,0-2.4-0.2-3.6-0.6c-0.3-0.1-0.7,0-1,0.2l-2.2,2.2c-2.8-1.4-5.1-3.8-6.6-6.6l2.2-2.2c0.3-0.3,0.4-0.7,0.2-1C8.7,6.4,8.5,5.2,8.5,4c0-0.6-0.4-1-1-1H4C3.5,3,3,3.4,3,4c0,9.4,7.6,17,17,17c0.6,0,1-0.4,1-1v-3.5C21,15.9,20.6,15.5,20,15.5z M12,3v10l3-3h6V3H12z"/></g> -<g id="perm-scan-wifi"><path d="M12,3C7,3,3.2,4.9,0,7.2L12,22L24,7.3C20.9,4.9,17.1,3,12,3z M13,16h-2v-6h2V16z M11,8V6h2v2H11z"/></g> -<g id="picture-in-picture"><path d="M19,7h-8v6h8V7z M21,3H3C1.9,3,1,3.9,1,5v14c0,1.1,0.9,2,2,2h18c1.1,0,2-0.9,2-2V5C23,3.9,22.1,3,21,3z M21,19H3V5h18V19z"/></g> -<g id="polymer"><polygon points="19,4 15,4 7.1,16.6 4.5,12 9,4 5,4 0.5,12 5,20 9,20 16.9,7.4 19.5,12 15,20 19,20 23.5,12 "/></g> -<g id="print"><path d="M19,8H5c-1.7,0-3,1.3-3,3v6h4v4h12v-4h4v-6C22,9.3,20.7,8,19,8z M16,19H8v-5h8V19z M19,12c-0.6,0-1-0.4-1-1s0.4-1,1-1c0.6,0,1,0.4,1,1S19.6,12,19,12z M18,3H6v4h12V3z"/></g> -<g id="query-builder"><path d="M12,2C6.5,2,2,6.5,2,12s4.5,10,10,10c5.5,0,10-4.5,10-10S17.5,2,12,2z M12,20c-4.4,0-8-3.6-8-8s3.6-8,8-8c4.4,0,8,3.6,8,8S16.4,20,12,20z"/><polygon points="12.5,7 11,7 11,13 16.2,16.2 17,14.9 12.5,12.3 "/></g> -<g id="question-answer"><path d="M21,6h-2v9H6v2c0,0.6,0.4,1,1,1h11l4,4V7C22,6.4,21.6,6,21,6z M17,12V3c0-0.6-0.4-1-1-1H3C2.4,2,2,2.4,2,3v14l4-4h10C16.6,13,17,12.6,17,12z"/></g> -<g id="radio-button-off"><path d="M12,2C6.5,2,2,6.5,2,12s4.5,10,10,10c5.5,0,10-4.5,10-10S17.5,2,12,2z M12,20c-4.4,0-8-3.6-8-8s3.6-8,8-8c4.4,0,8,3.6,8,8S16.4,20,12,20z"/></g> -<g id="radio-button-on"><path d="M12,7c-2.8,0-5,2.2-5,5s2.2,5,5,5c2.8,0,5-2.2,5-5S14.8,7,12,7z M12,2C6.5,2,2,6.5,2,12s4.5,10,10,10c5.5,0,10-4.5,10-10S17.5,2,12,2z M12,20c-4.4,0-8-3.6-8-8s3.6-8,8-8c4.4,0,8,3.6,8,8S16.4,20,12,20z"/></g> -<g id="receipt"><path d="M18,17H6v-2h12V17z M18,13H6v-2h12V13z M18,9H6V7h12V9z M3,22l1.5-1.5L6,22l1.5-1.5L9,22l1.5-1.5L12,22l1.5-1.5L15,22l1.5-1.5L18,22l1.5-1.5L21,22V2l-1.5,1.5L18,2l-1.5,1.5L15,2l-1.5,1.5L12,2l-1.5,1.5L9,2L7.5,3.5L6,2L4.5,3.5L3,2V22z"/></g> -<g id="redeem"><path d="M20,6h-2.2C17.9,5.7,18,5.4,18,5c0-1.7-1.3-3-3-3c-1,0-2,0.5-2.5,1.3l0,0L12,4l-0.5-0.7l0,0C11,2.5,10.1,2,9,2C7.4,2,6,3.3,6,5c0,0.4,0.1,0.7,0.2,1H4C2.9,6,2,6.9,2,8l0,11c0,1.1,0.9,2,2,2h16c1.1,0,2-0.9,2-2V8C22,6.9,21.1,6,20,6z M15,4c0.6,0,1,0.4,1,1s-0.4,1-1,1s-1-0.4-1-1S14.5,4,15,4z M9,4c0.6,0,1,0.4,1,1S9.6,6,9,6S8,5.6,8,5S8.5,4,9,4z M20,19H4v-2h16V19z M20,14H4V8h5.1L7,10.8L8.6,12L11,8.8l1-1.4l1,1.4l2.4,3.2l1.6-1.2L14.9,8H20V14z"/></g> -<g id="refresh"><path d="M17.6,6.4C16.2,4.9,14.2,4,12,4c-4.4,0-8,3.6-8,8s3.6,8,8,8c3.7,0,6.8-2.6,7.7-6h-2.1c-0.8,2.3-3,4-5.6,4c-3.3,0-6-2.7-6-6s2.7-6,6-6c1.7,0,3.1,0.7,4.2,1.8L13,11h7V4L17.6,6.4z"/></g> -<g id="reminder"><path d="M16.9,13c1.3-1.3,2.1-3,2.1-5c0-3.9-3.1-7-7-7C8.1,1,5,4.1,5,8c0,2,0.8,3.7,2.1,5l0,0l3.5,3.5L6,21.1l1.4,1.4L16.9,13z M15.5,11.5L15.5,11.5L12,15.1l-3.5-3.5l0,0l0,0C7.6,10.6,7,9.4,7,8c0-2.8,2.2-5,5-5c2.8,0,5,2.2,5,5C17,9.4,16.4,10.6,15.5,11.5L15.5,11.5z M13.4,19.3l3.2,3.2l1.4-1.4l-3.2-3.2L13.4,19.3z"/></g> -<g id="remove"><path d="M19,13H5v-2h14V13z"/></g> -<g id="remove-circle"><path d="M12,2C6.5,2,2,6.5,2,12s4.5,10,10,10c5.5,0,10-4.5,10-10S17.5,2,12,2z M17,13H7v-2h10V13z"/></g> -<g id="remove-circle-outline"><path d="M7,11v2h10v-2H7z M12,2C6.5,2,2,6.5,2,12s4.5,10,10,10c5.5,0,10-4.5,10-10S17.5,2,12,2z M12,20c-4.4,0-8-3.6-8-8s3.6-8,8-8c4.4,0,8,3.6,8,8S16.4,20,12,20z"/></g> -<g id="reorder"><path d="M4,16h16v-2H4V16z M4,9v2h16V9H4z"/></g> -<g id="reply"><path d="M10,9V5l-7,7l7,7v-4.1c5,0,8.5,1.6,11,5.1C20,15,17,10,10,9z"/></g> -<g id="reply-all"><path d="M7,8V5l-7,7l7,7v-3l-4-4L7,8z M13,9V5l-7,7l7,7v-4.1c5,0,8.5,1.6,11,5.1C23,15,20,10,13,9z"/></g> -<g id="report"><path d="M15.7,3H8.3L3,8.3v7.5L8.3,21h7.5l5.3-5.3V8.3L15.7,3z M12,17.3c-0.7,0-1.3-0.6-1.3-1.3c0-0.7,0.6-1.3,1.3-1.3c0.7,0,1.3,0.6,1.3,1.3C13.3,16.7,12.7,17.3,12,17.3z M13,13h-2V7h2V13z"/></g> -<g id="report-problem"><path d="M1,21h22L12,2L1,21z M13,18h-2v-2h2V18z M13,14h-2v-4h2V14z"/></g> -<g id="restore"><path d="M13,3c-5,0-9,4-9,9H1l3.9,3.9c0,0,0,0.1,0.1,0.1l4-4H6c0-3.9,3.1-7,7-7c3.9,0,7,3.1,7,7s-3.1,7-7,7c-1.9,0-3.7-0.8-4.9-2.1l-1.4,1.4C8.3,20,10.5,21,13,21c5,0,9-4,9-9S18,3,13,3z M12,8v5l4.3,2.5l0.7-1.2l-3.5-2.1V8H12z"/></g> -<g id="room"><path d="M12,2C8.1,2,5,5.1,5,9c0,5.2,7,13,7,13s7-7.8,7-13C19,5.1,15.9,2,12,2z M12,11.5c-1.4,0-2.5-1.1-2.5-2.5s1.1-2.5,2.5-2.5c1.4,0,2.5,1.1,2.5,2.5S13.4,11.5,12,11.5z"/></g> -<g id="rotate-left"><path d="M7.1,8.5L5.7,7.1C4.8,8.3,4.2,9.6,4.1,11h2C6.2,10.1,6.6,9.3,7.1,8.5z M6.1,13h-2c0.2,1.4,0.7,2.7,1.6,3.9l1.4-1.4C6.6,14.7,6.2,13.9,6.1,13z M7.1,18.3c1.2,0.9,2.5,1.4,3.9,1.6v-2c-0.9-0.1-1.7-0.5-2.5-1L7.1,18.3z M13,4.1V1L8.5,5.5L13,10V6.1c2.8,0.5,5,2.9,5,5.9s-2.2,5.4-5,5.9v2c3.9-0.5,7-3.9,7-7.9S16.9,4.6,13,4.1z"/></g> -<g id="rotate-right"><path d="M15.5,5.5L11,1v3.1C7.1,4.6,4,7.9,4,12s3.1,7.4,7,7.9v-2C8.2,17.4,6,15,6,12s2.2-5.4,5-5.9V10L15.5,5.5z M19.9,11c-0.2-1.4-0.7-2.7-1.6-3.9l-1.4,1.4c0.5,0.8,0.9,1.6,1,2.5H19.9z M13,17.9v2c1.4-0.2,2.7-0.7,3.9-1.6l-1.4-1.4C14.7,17.4,13.9,17.8,13,17.9z M16.9,15.5l1.4,1.4c0.9-1.2,1.5-2.5,1.6-3.9h-2C17.8,13.9,17.4,14.7,16.9,15.5z"/></g> -<g id="rotation-3d"><path d="M11,14v-1c0-0.6-0.4-1-1-1c0.6,0,1-0.4,1-1v-1c0-1.1-0.9-2-2-2H6v2h3v1H7v2h2v1l0,0l0,0v0h0H6v2h3C10.1,16,11,15.1,11,14z M15,8h-3v8h3c1.7,0,3-1.3,3-3v-2C18,9.3,16.7,8,15,8z M16,13c0,0.6-0.4,1-1,1h-1v-4h1c0.6,0,1,0.4,1,1V13z M12,0c-0.2,0-0.4,0-0.7,0l3.8,3.8l1.3-1.3c3.3,1.5,5.6,4.7,6,8.5h1.5C23.4,4.8,18.3,0,12,0z M7.5,21.5c-3.3-1.5-5.6-4.7-6-8.5H0.1C0.6,19.2,5.7,24,12,24c0.2,0,0.4,0,0.7,0l-3.8-3.8L7.5,21.5z"/></g> -<g id="save"><path d="M17,3H5C3.9,3,3,3.9,3,5l0,14c0,1.1,0.9,2,2,2h14c1.1,0,2-0.9,2-2V7L17,3z M12,19c-1.7,0-3-1.3-3-3s1.3-3,3-3c1.7,0,3,1.3,3,3S13.7,19,12,19z M15,9H5V5h10V9z"/></g> -<g id="schedule"><path fill-opacity="0.9" d="M12,2C6.5,2,2,6.5,2,12s4.5,10,10,10c5.5,0,10-4.5,10-10S17.5,2,12,2z M12,20c-4.4,0-8-3.6-8-8s3.6-8,8-8c4.4,0,8,3.6,8,8S16.4,20,12,20z"/><polygon fill-opacity="0.9" points="12.5,7 11,7 11,13 16.2,16.2 17,14.9 12.5,12.2 "/></g> -<g id="search"><path d="M15.5,14h-0.8l-0.3-0.3c1-1.1,1.6-2.6,1.6-4.2C16,5.9,13.1,3,9.5,3C5.9,3,3,5.9,3,9.5S5.9,16,9.5,16c1.6,0,3.1-0.6,4.2-1.6l0.3,0.3v0.8l5,5l1.5-1.5L15.5,14z M9.5,14C7,14,5,12,5,9.5S7,5,9.5,5C12,5,14,7,14,9.5S12,14,9.5,14z"/></g> -<g id="select-all"><path d="M3,5h2V3C3.9,3,3,3.9,3,5z M3,13h2v-2H3V13z M7,21h2v-2H7V21z M3,9h2V7H3V9z M13,3h-2v2h2V3z M19,3v2h2C21,3.9,20.1,3,19,3z M5,21v-2H3C3,20.1,3.9,21,5,21z M3,17h2v-2H3V17z M9,3H7v2h2V3z M11,21h2v-2h-2V21z M19,13h2v-2h-2V13z M19,21c1.1,0,2-0.9,2-2h-2V21z M19,9h2V7h-2V9z M19,17h2v-2h-2V17z M15,21h2v-2h-2V21z M15,5h2V3h-2V5z M7,17h10V7H7V17z M9,9h6v6H9V9z"/></g> -<g id="send"><polygon points="2,21 23,12 2,3 2,10 17,12 2,14 "/></g> -<g id="send-money"><path d="M2,12c0-2.6,1.7-4.8,4-5.7V4.3c-3.4,0.9-6,4-6,7.7s2.6,6.8,6,7.7v-2.1C3.7,16.8,2,14.6,2,12z M24,12l-4-4v3h-7v2h7v3L24,12z M14,18c-3.3,0-6-2.7-6-6s2.7-6,6-6c1.7,0,3.2,0.7,4.2,1.8l1.4-1.4C18.2,4.9,16.2,4,14,4c-4.4,0-8,3.6-8,8s3.6,8,8,8c2.2,0,4.2-0.9,5.7-2.3l-1.4-1.4C17.2,17.3,15.7,18,14,18z"/></g> -<g id="settings"><path d="M19.4,13c0-0.3,0.1-0.6,0.1-1s0-0.7-0.1-1l2.1-1.7c0.2-0.2,0.2-0.4,0.1-0.6l-2-3.5C19.5,5.1,19.3,5,19,5.1l-2.5,1c-0.5-0.4-1.1-0.7-1.7-1l-0.4-2.6C14.5,2.2,14.2,2,14,2h-4C9.8,2,9.5,2.2,9.5,2.4L9.1,5.1C8.5,5.3,8,5.7,7.4,6.1L5,5.1C4.7,5,4.5,5.1,4.3,5.3l-2,3.5C2.2,8.9,2.3,9.2,2.5,9.4L4.6,11c0,0.3-0.1,0.6-0.1,1s0,0.7,0.1,1l-2.1,1.7c-0.2,0.2-0.2,0.4-0.1,0.6l2,3.5C4.5,18.9,4.7,19,5,18.9l2.5-1c0.5,0.4,1.1,0.7,1.7,1l0.4,2.6c0,0.2,0.2,0.4,0.5,0.4h4c0.2,0,0.5-0.2,0.5-0.4l0.4-2.6c0.6-0.3,1.2-0.6,1.7-1l2.5,1c0.2,0.1,0.5,0,0.6-0.2l2-3.5c0.1-0.2,0.1-0.5-0.1-0.6L19.4,13z M12,15.5c-1.9,0-3.5-1.6-3.5-3.5s1.6-3.5,3.5-3.5s3.5,1.6,3.5,3.5S13.9,15.5,12,15.5z"/></g> -<g id="settings-applications"><path d="M12,10c-1.1,0-2,0.9-2,2s0.9,2,2,2s2-0.9,2-2S13.1,10,12,10z M19,3H5C3.9,3,3,3.9,3,5v14c0,1.1,0.9,2,2,2h14c1.1,0,2-0.9,2-2V5C21,3.9,20.1,3,19,3z M17.2,12c0,0.2,0,0.5,0,0.7l1.5,1.2c0.1,0.1,0.2,0.3,0.1,0.4l-1.4,2.4c-0.1,0.2-0.3,0.2-0.4,0.2l-1.7-0.7c-0.4,0.3-0.8,0.5-1.2,0.7l-0.3,1.9c0,0.2-0.2,0.3-0.3,0.3h-2.8c-0.2,0-0.3-0.1-0.3-0.3L10,16.9c-0.4-0.2-0.8-0.4-1.2-0.7l-1.7,0.7c-0.2,0.1-0.3,0-0.4-0.2l-1.4-2.4c-0.1-0.2,0-0.3,0.1-0.4l1.5-1.2c0-0.2,0-0.5,0-0.7s0-0.5,0-0.7l-1.5-1.2c-0.1-0.1-0.2-0.3-0.1-0.4l1.4-2.4c0.1-0.2,0.3-0.2,0.4-0.2l1.7,0.7C9.2,7.6,9.6,7.3,10,7.1l0.3-1.9c0-0.2,0.2-0.3,0.3-0.3h2.8c0.2,0,0.3,0.1,0.3,0.3L14,7.1c0.4,0.2,0.8,0.4,1.2,0.7l1.7-0.7c0.2-0.1,0.3,0,0.4,0.2l1.4,2.4c0.1,0.2,0,0.3-0.1,0.4l-1.5,1.2C17.2,11.5,17.2,11.8,17.2,12z"/></g> -<g id="settings-backup-restore"><path d="M14,12c0-1.1-0.9-2-2-2s-2,0.9-2,2s0.9,2,2,2S14,13.1,14,12z M12,3c-5,0-9,4-9,9H0l4,4l4-4H5c0-3.9,3.1-7,7-7s7,3.1,7,7s-3.1,7-7,7c-1.5,0-2.9-0.5-4.1-1.3l-1.4,1.4C8,20.3,9.9,21,12,21c5,0,9-4,9-9S17,3,12,3z"/></g> -<g id="settings-bluetooth"><path d="M11,24h2v-2h-2V24z M7,24h2v-2H7V24z M15,24h2v-2h-2V24z M17.7,5.7L12,0h-1v7.6L6.4,3L5,4.4l5.6,5.6L5,15.6L6.4,17l4.6-4.6V20h1l5.7-5.7L13.4,10L17.7,5.7z M13,3.8l1.9,1.9L13,7.6V3.8z M14.9,14.3L13,16.2v-3.8L14.9,14.3z"/></g> -<g id="settings-cell"><path d="M7,24h2v-2H7V24z M11,24h2v-2h-2V24z M15,24h2v-2h-2V24z M16,0L8,0C6.9,0,6,0.9,6,2v16c0,1.1,0.9,2,2,2h8c1.1,0,2-0.9,2-2V2C18,0.9,17.1,0,16,0z M16,16H8V4h8V16z"/></g> -<g id="settings-display"><path d="M21,19H3V5h18V19z M21,3H3C1.9,3,1,3.9,1,5v14c0,1.1,0.9,2,2,2h18c1.1,0,2-0.9,2-2V5C23,3.9,22.1,3,21,3L21,3z"/><path d="M10,12c0-1.1,0.9-2,2-2V8c0.3,0,0.7,0.1,1,0.1V6h-2v2.1c-0.4,0.1-0.7,0.2-1,0.4L8.5,7.1L7.1,8.5L8.6,10c-0.2,0.3-0.3,0.7-0.4,1H6v2h2.1c0.1,0.4,0.2,0.7,0.4,1l-1.5,1.5l1.4,1.4l1.5-1.5c0.3,0.2,0.7,0.3,1,0.4V18h2v-2.1c-0.3,0.1-0.7,0.1-1,0.1v-2C10.9,14,10,13.1,10,12z M15.4,10l1.5-1.5l-1.4-1.4L14,8.6C14.6,8.9,15.1,9.4,15.4,10z M14,15.4l1.5,1.5l1.4-1.4L15.4,14C15.1,14.6,14.6,15.1,14,15.4z M12,10v4c1.1,0,2-0.9,2-2C14,10.9,13.1,10,12,10z M15.9,11c0.1,0.3,0.1,0.7,0.1,1s-0.1,0.7-0.1,1H18v-2H15.9z"/></g> -<g id="settings-ethernet"><path d="M7.8,6.8L6.2,5.5L0.8,12l5.4,6.5l1.5-1.3L3.4,12L7.8,6.8z M7,13h2v-2H7V13z M17,11h-2v2h2V11z M11,13h2v-2h-2V13z M17.8,5.5l-1.5,1.3l4.3,5.2l-4.3,5.2l1.5,1.3l5.4-6.5L17.8,5.5z"/></g> -<g id="settings-input-antenna"><path d="M12,5c-3.9,0-7,3.1-7,7h2c0-2.8,2.2-5,5-5s5,2.2,5,5h2C19,8.1,15.9,5,12,5z M13,14.3c0.9-0.4,1.5-1.3,1.5-2.3c0-1.4-1.1-2.5-2.5-2.5S9.5,10.6,9.5,12c0,1,0.6,1.9,1.5,2.3v3.3L7.6,21L9,22.4l3-3l3,3l1.4-1.4L13,17.6V14.3z M12,1C5.9,1,1,5.9,1,12h2c0-5,4-9,9-9s9,4,9,9h2C23,5.9,18.1,1,12,1z"/></g> -<g id="settings-input-component"><path d="M5,2c0-0.6-0.4-1-1-1S3,1.4,3,2v4H1v6h6V6H5V2z M9,16c0,1.3,0.8,2.4,2,2.8V23h2v-4.2c1.2-0.4,2-1.5,2-2.8v-2H9V16z M1,16c0,1.3,0.8,2.4,2,2.8V23h2v-4.2c1.2-0.4,2-1.5,2-2.8v-2H1V16z M21,6V2c0-0.6-0.4-1-1-1s-1,0.4-1,1v4h-2v6h6V6H21z M13,2c0-0.6-0.4-1-1-1s-1,0.4-1,1v4H9v6h6V6h-2V2z M17,16c0,1.3,0.8,2.4,2,2.8V23h2v-4.2c1.2-0.4,2-1.5,2-2.8v-2h-6V16z"/></g> -<g id="settings-input-composite"><path d="M5,2c0-0.6-0.4-1-1-1S3,1.4,3,2v4H1v6h6V6H5V2z M9,16c0,1.3,0.8,2.4,2,2.8V23h2v-4.2c1.2-0.4,2-1.5,2-2.8v-2H9V16z M1,16c0,1.3,0.8,2.4,2,2.8V23h2v-4.2c1.2-0.4,2-1.5,2-2.8v-2H1V16z M21,6V2c0-0.6-0.4-1-1-1s-1,0.4-1,1v4h-2v6h6V6H21z M13,2c0-0.6-0.4-1-1-1s-1,0.4-1,1v4H9v6h6V6h-2V2z M17,16c0,1.3,0.8,2.4,2,2.8V23h2v-4.2c1.2-0.4,2-1.5,2-2.8v-2h-6V16z"/></g> -<g id="settings-input-hdmi"><path d="M18,7V4c0-1.1-0.9-2-2-2H8C6.9,2,6,2.9,6,4v3H5v6l3,6v3h8v-3l3-6V7H18z M8,4h8v3h-2V5h-1v2h-2V5h-1v2H8V4z"/></g> -<g id="settings-input-svideo"><path d="M8,11.5C8,10.7,7.3,10,6.5,10S5,10.7,5,11.5S5.7,13,6.5,13S8,12.3,8,11.5z M15,6.5C15,5.7,14.3,5,13.5,5h-3C9.7,5,9,5.7,9,6.5S9.7,8,10.5,8h3C14.3,8,15,7.3,15,6.5z M8.5,15C7.7,15,7,15.7,7,16.5S7.7,18,8.5,18s1.5-0.7,1.5-1.5S9.3,15,8.5,15z M12,1C5.9,1,1,5.9,1,12s4.9,11,11,11s11-4.9,11-11S18.1,1,12,1z M12,21c-5,0-9-4-9-9s4-9,9-9s9,4,9,9S17,21,12,21z M17.5,10c-0.8,0-1.5,0.7-1.5,1.5s0.7,1.5,1.5,1.5s1.5-0.7,1.5-1.5S18.3,10,17.5,10z M15.5,15c-0.8,0-1.5,0.7-1.5,1.5s0.7,1.5,1.5,1.5s1.5-0.7,1.5-1.5S16.3,15,15.5,15z"/></g> -<g id="settings-overscan"><path d="M12,5.5L10,8h4L12,5.5z M18,10v4l2.5-2L18,10z M6,10l-2.5,2L6,14V10z M14,16h-4l2,2.5L14,16z M21,3H3C1.9,3,1,3.9,1,5v14c0,1.1,0.9,2,2,2h18c1.1,0,2-0.9,2-2V5C23,3.9,22.1,3,21,3z M21,19H3V5h18V19z"/></g> -<g id="settings-phone"><path d="M13,9h-2v2h2V9z M17,9h-2v2h2V9z M20,15.5c-1.2,0-2.4-0.2-3.6-0.6c-0.3-0.1-0.7,0-1,0.2l-2.2,2.2c-2.8-1.4-5.1-3.8-6.6-6.6l2.2-2.2c0.3-0.3,0.4-0.7,0.2-1C8.7,6.4,8.5,5.2,8.5,4c0-0.6-0.4-1-1-1H4C3.4,3,3,3.4,3,4c0,9.4,7.6,17,17,17c0.6,0,1-0.4,1-1v-3.5C21,15.9,20.6,15.5,20,15.5z M19,9v2h2V9H19z"/></g> -<g id="settings-power"><path d="M7,24h2v-2H7V24z M11,24h2v-2h-2V24z M13,2h-2v10h2V2z M16.6,4.4l-1.4,1.4C16.8,6.9,18,8.8,18,11c0,3.3-2.7,6-6,6c-3.3,0-6-2.7-6-6c0-2.2,1.2-4.1,2.9-5.1L7.4,4.4C5.4,5.9,4,8.3,4,11c0,4.4,3.6,8,8,8c4.4,0,8-3.6,8-8C20,8.3,18.6,5.9,16.6,4.4z M15,24h2v-2h-2V24z"/></g> -<g id="settings-remote"><path d="M15,9H9c-0.6,0-1,0.4-1,1v12c0,0.6,0.4,1,1,1h6c0.6,0,1-0.4,1-1V10C16,9.4,15.6,9,15,9z M12,15c-1.1,0-2-0.9-2-2s0.9-2,2-2s2,0.9,2,2S13.1,15,12,15z M7.1,6.1l1.4,1.4C9.4,6.6,10.6,6,12,6s2.6,0.6,3.5,1.5l1.4-1.4C15.7,4.8,13.9,4,12,4S8.3,4.8,7.1,6.1z M12,0C9,0,6.2,1.2,4.2,3.2l1.4,1.4C7.3,3,9.5,2,12,2s4.7,1,6.4,2.6l1.4-1.4C17.8,1.2,15,0,12,0z"/></g> -<g id="settings-voice"><path d="M7,24h2v-2H7V24z M12,13c1.7,0,3-1.3,3-3l0-6c0-1.7-1.3-3-3-3c-1.7,0-3,1.3-3,3v6C9,11.7,10.3,13,12,13z M11,24h2v-2h-2V24z M15,24h2v-2h-2V24z M19,10h-1.7c0,3-2.5,5.1-5.3,5.1c-2.8,0-5.3-2.1-5.3-5.1H5c0,3.4,2.7,6.2,6,6.7V20h2v-3.3C16.3,16.2,19,13.4,19,10z"/></g> -<g id="shop"><path d="M16,6V4l-2-2h-4L8,4v2H2v13c0,1.1,0.9,2,2,2h16c1.1,0,2-0.9,2-2V6H16z M10,4h4v2h-4V4z M9,18V9l7.5,4L9,18z"/></g> -<g id="shop-two"><path d="M18,5V3l-2-2h-4l-2,2v2H5v11c0,1.1,0.9,2,2,2h14c1.1,0,2-0.9,2-2V5H18z M12,3h4v2h-4V3z M12,15V8l5.5,3L12,15z M3,9H1v11c0,1.1,0.9,2,2,2h14c1.1,0,2-0.9,2-2H3V9z"/></g> -<g id="shopping-basket"><path d="M17.2,9l-4.4-6.6C12.6,2.2,12.3,2,12,2c-0.3,0-0.6,0.1-0.8,0.4L6.8,9H2c-0.6,0-1,0.4-1,1c0,0.1,0,0.2,0,0.3l2.5,9.3c0.2,0.8,1,1.5,1.9,1.5h13c0.9,0,1.7-0.6,1.9-1.5l2.5-9.3c0-0.1,0-0.2,0-0.3c0-0.6-0.4-1-1-1H17.2z M9,9l3-4.4L15,9H9z M12,17c-1.1,0-2-0.9-2-2s0.9-2,2-2c1.1,0,2,0.9,2,2S13.1,17,12,17z"/></g> -<g id="shopping-cart"><path d="M7,18c-1.1,0-2,0.9-2,2s0.9,2,2,2c1.1,0,2-0.9,2-2S8.1,18,7,18z M1,2v2h2l3.6,7.6L5.2,14C5.1,14.3,5,14.7,5,15c0,1.1,0.9,2,2,2h12v-2H7.4c-0.1,0-0.2-0.1-0.2-0.2c0,0,0-0.1,0-0.1L8.1,13h7.4c0.8,0,1.4-0.4,1.7-1l3.6-6.5C21,5.3,21,5.2,21,5c0-0.6-0.4-1-1-1H5.2L4.3,2H1z M17,18c-1.1,0-2,0.9-2,2s0.9,2,2,2c1.1,0,2-0.9,2-2S18.1,18,17,18z"/></g> -<g id="sort"><path d="M3,18h6v-2H3V18z M3,6v2h18V6H3z M3,13h12v-2H3V13z"/></g> -<g id="star"><polygon points="12,17.273 18.18,21 16.545,13.971 22,9.244 14.809,8.627 12,2 9.191,8.627 2,9.244 7.455,13.971 5.82,21 "/></g> -<g id="star-half"><path d="M22,9.744l-7.191-0.617L12,2.5L9.191,9.127L2,9.744v0l0,0l5.455,4.727L5.82,21.5L12,17.772l0,0l6.18,3.727l-1.635-7.029L22,9.744z M12,15.896V6.595l1.71,4.036l4.38,0.376l-3.322,2.878l0.996,4.281L12,15.896z"/></g> -<g id="star-outline"><path d="M22,9.244l-7.191-0.617L12,2L9.191,8.627L2,9.244l5.455,4.727L5.82,21L12,17.272L18.18,21l-1.635-7.029L22,9.244z M12,15.396l-3.763,2.27l0.996-4.281L5.91,10.507l4.38-0.376L12,6.095l1.71,4.036l4.38,0.376l-3.322,2.878l0.996,4.281L12,15.396z"/></g> -<g id="star-rate"><polygon points="12,14.3 15.7,17 14.3,12.6 18,10 13.5,10 12,5.5 10.5,10 6,10 9.7,12.6 8.3,17 "/></g> -<g id="stars"><path d="M12,2C6.5,2,2,6.5,2,12s4.5,10,10,10c5.5,0,10-4.5,10-10S17.5,2,12,2z M16.2,18L12,15.4L7.8,18l1.1-4.8L5.2,10l4.9-0.4L12,5l1.9,4.5l4.9,0.4l-3.7,3.2L16.2,18z"/></g> -<g id="store"><path d="M20,4H4v2h16V4z M21,14v-2l-1-5H4l-1,5v2h1v6h10v-6h4v6h2v-6H21z M12,18H6v-4h6V18z"/></g> -<g id="subject"><path d="M14,17H4v2h10V17z M20,9H4v2h16V9z M4,15h16v-2H4V15z M4,5v2h16V5H4z"/></g> -<g id="swap-driving-apps"><circle cx="6.5" cy="15.5" r="1.5"/><circle cx="17.5" cy="15.5" r="1.5"/><path d="M18.9,7c-0.2-0.6-0.8-1-1.4-1H16H6V4L3,7l2,2l1,1V8h11.7l1.3,4H3v9c0,0.6,0.4,1,1,1h1c0.6,0,1-0.4,1-1v-1h12v1c0,0.6,0.4,1,1,1h1c0.6,0,1-0.4,1-1v-8L18.9,7z M6.5,17C5.7,17,5,16.3,5,15.5S5.7,14,6.5,14C7.3,14,8,14.7,8,15.5S7.3,17,6.5,17z M17.5,17c-0.8,0-1.5-0.7-1.5-1.5s0.7-1.5,1.5-1.5c0.8,0,1.5,0.7,1.5,1.5S18.3,17,17.5,17z M16,0v2H8v2h8v2l3-3L16,0z"/></g> -<g id="swap-driving-apps-wheel"><path d="M14.4,6.1c-0.5-0.2-1.1,0-1.3,0.6L11.7,10c-1,0.1-1.7,1-1.7,2c0,1.1,0.9,2,2,2s2-0.9,2-2c0-0.5-0.2-0.9-0.4-1.2l1.4-3.4C15.1,6.9,14.9,6.3,14.4,6.1z M7,9c-0.6,0-1,0.4-1,1c0,0.6,0.4,1,1,1s1-0.4,1-1C8,9.4,7.6,9,7,9z M11,7c0-0.6-0.4-1-1-1S9,6.4,9,7c0,0.6,0.4,1,1,1S11,7.6,11,7z M17,9c-0.6,0-1,0.4-1,1c0,0.6,0.4,1,1,1s1-0.4,1-1C18,9.4,17.6,9,17,9z M12,2C6.5,2,2,6.5,2,12s4.5,10,10,10s10-4.5,10-10S17.5,2,12,2z M17.3,18c-1.4-1.2-3.2-2-5.3-2s-3.9,0.8-5.3,2C5.1,16.5,4,14.4,4,12c0-4.4,3.6-8,8-8s8,3.6,8,8C20,14.4,18.9,16.5,17.3,18z"/></g> -<g id="swap-horiz"><path d="M7,11l-4,4l4,4v-3h7v-2H7V11z M21,9l-4-4v3h-7v2h7v3L21,9z"/></g> -<g id="swap-vert"><path d="M16,17v-7h-2v7h-3l4,4l4-4H16z M9,3L5,7h3v7h2V7h3L9,3z"/></g> -<g id="swap-vert-circle"><path d="M12,2C6.5,2,2,6.5,2,12s4.5,10,10,10c5.5,0,10-4.5,10-10S17.5,2,12,2z M6.5,9L10,5.5L13.5,9H11v4H9V9H6.5z M17.5,15L14,18.5L10.5,15H13v-4h2v4H17.5z"/></g> -<g id="system-update-tv"><path d="M12,15l4-4h-3V3h-2v8H8L12,15z M20,3h-5v2h5v12H4V5h5V3H4C2.9,3,2,3.9,2,5v12c0,1.1,0.9,2,2,2h4v2h8v-2h4c1.1,0,2-0.9,2-2l0-12C22,3.9,21.1,3,20,3z"/></g> -<g id="tab"><path d="M21,3H3C1.9,3,1,3.9,1,5v14c0,1.1,0.9,2,2,2h18c1.1,0,2-0.9,2-2V5C23,3.9,22.1,3,21,3z M21,19L3,19V5h10v4h8V19z"/></g> -<g id="tab-unselected"><path d="M1,9h2V7H1V9z M1,13h2v-2H1V13z M1,5h2V3C1.9,3,1,3.9,1,5z M9,21h2v-2l-2,0V21z M1,17h2v-2H1V17z M3,21v-2H1C1,20.1,1.9,21,3,21z M21,3h-8v6h10V5C23,3.9,22.1,3,21,3z M21,17h2v-2h-2V17z M9,5h2V3H9V5z M5,21h2v-2l-2,0V21z M5,5h2V3H5V5z M21,21c1.1,0,2-0.9,2-2h-2V21z M21,13h2v-2h-2V13z M13,21h2v-2l-2,0V21z M17,21h2v-2l-2,0V21z"/></g> -<g id="text-format"><path d="M5,17v2h14v-2H5z M9.5,12.8h5l0.9,2.2h2.1L12.8,4h-1.5L6.5,15h2.1L9.5,12.8z M12,6l1.9,5h-3.7L12,6z"/></g> -<g id="theaters"><path d="M18,3v2h-2V3H8v2H6V3H4v18h2v-2h2v2h8v-2h2v2h2V3H18z M8,17H6v-2h2V17z M8,13H6v-2h2V13z M8,9H6V7h2V9z M18,17h-2v-2h2V17z M18,13h-2v-2h2V13z M18,9h-2V7h2V9z"/></g> -<g id="thumb-down"><path d="M15,3H6C5.2,3,4.5,3.5,4.2,4.2l-3,7.1C1.1,11.5,1,11.7,1,12v1.9l0,0c0,0,0,0.1,0,0.1c0,1.1,0.9,2,2,2h6.3l-1,4.6c0,0.1,0,0.2,0,0.3c0,0.4,0.2,0.8,0.4,1.1L9.8,23l6.6-6.6c0.4-0.4,0.6-0.9,0.6-1.4V5C17,3.9,16.1,3,15,3z M19,3v12h4V3H19z"/></g> -<g id="thumb-up"><path d="M1,21h4V9H1V21z M23,10c0-1.1-0.9-2-2-2h-6.3l1-4.6c0-0.1,0-0.2,0-0.3c0-0.4-0.2-0.8-0.4-1.1L14.2,1L7.6,7.6C7.2,7.9,7,8.4,7,9v10c0,1.1,0.9,2,2,2h9c0.8,0,1.5-0.5,1.8-1.2l3-7.1c0.1-0.2,0.1-0.5,0.1-0.7V10L23,10C23,10.1,23,10,23,10z"/></g> -<g id="toc"><path d="M3,9h14V7H3V9z M3,13h14v-2H3V13z M3,17h14v-2H3V17z M19,17h2v-2h-2V17z M19,7v2h2V7H19z M19,13h2v-2h-2V13z"/></g> -<g id="today"><path d="M19,3h-1V1h-2v2H8V1H6v2H5C3.9,3,3,3.9,3,5l0,14c0,1.1,0.9,2,2,2h14c1.1,0,2-0.9,2-2V5C21,3.9,20.1,3,19,3z M19,19H5V8h14V19z"/><rect x="7" y="10" width="5" height="5"/></g> -<g id="translate"><path d="M12.9,15.1l-2.5-2.5l0,0c1.7-1.9,3-4.2,3.7-6.5H17V4h-7V2H8v2H1v2l11.2,0c-0.7,1.9-1.7,3.8-3.2,5.4c-0.9-1-1.7-2.2-2.3-3.4h-2c0.7,1.6,1.7,3.2,3,4.6l-5.1,5L4,19l5-5l3.1,3.1L12.9,15.1z M18.5,10h-2L12,22h2l1.1-3h4.8l1.1,3h2L18.5,10z M15.9,17l1.6-4.3l1.6,4.3H15.9z"/></g> -<g id="trending-down"><polygon points="16,18 18.3,15.7 13.4,10.8 9.4,14.8 2,7.4 3.4,6 9.4,12 13.4,8 19.7,14.3 22,12 22,18 "/></g> -<g id="trending-neutral"><polygon points="22,12 18,8 18,11 3,11 3,13 18,13 18,16 "/></g> -<g id="trending-up"><polygon points="16,6 18.3,8.3 13.4,13.2 9.4,9.2 2,16.6 3.4,18 9.4,12 13.4,16 19.7,9.7 22,12 22,6 "/></g> -<g id="turned-in"><path d="M17,3H7C5.9,3,5,3.9,5,5l0,16l7-3l7,3V5C19,3.9,18.1,3,17,3z"/></g> -<g id="turned-in-not"><path d="M17,3H7C5.9,3,5,3.9,5,5l0,16l7-3l7,3V5C19,3.9,18.1,3,17,3z M17,18l-5-2.2L7,18V5h10V18z"/></g> -<g id="undo"><path d="M12,5V1.5l-5,5l5,5V7c3.3,0,6,2.7,6,6s-2.7,6-6,6c-3.3,0-6-2.7-6-6H4c0,4.4,3.6,8,8,8c4.4,0,8-3.6,8-8S16.4,5,12,5z"/></g> -<g id="unfold-less"><path d="M7.4,18.6L8.8,20l3.2-3.2l3.2,3.2l1.4-1.4L12,14L7.4,18.6z M16.6,5.4L15.2,4L12,7.2L8.8,4L7.4,5.4L12,10L16.6,5.4z"/></g> -<g id="unfold-more"><path d="M12,5.8L15.2,9l1.4-1.4L12,3L7.4,7.6L8.8,9L12,5.8z M12,18.2L8.8,15l-1.4,1.4L12,21l4.6-4.6L15.2,15L12,18.2z"/></g> -<g id="view-array"><path d="M4,18h3V5H4V18z M18,5v13h3V5H18z M8,18h9V5H8V18z"/></g> -<g id="view-column"><path d="M10,18h5V5h-5V18z M4,18h5V5H4V18z M16,5v13h5V5H16z"/></g> -<g id="view-headline"><path d="M4,15h17v-2H4V15z M4,19h17v-2H4V19z M4,11h17V9H4V11z M4,5v2h17V5H4z"/></g> -<g id="view-list"><path d="M4,14h4v-4H4V14z M4,19h4v-4H4V19z M4,9h4V5H4V9z M9,14h12v-4H9V14z M9,19h12v-4H9V19z M9,5v4h12V5H9z"/></g> -<g id="view-module"><path d="M4,11h5V5H4V11z M4,18h5v-6H4V18z M10,18h5v-6h-5V18z M16,18h5v-6h-5V18z M10,11h5V5h-5V11z M16,5v6h5V5H16z"/></g> -<g id="view-quilt"><path d="M10,18h5v-6h-5V18z M4,18h5V5H4V18z M16,18h5v-6h-5V18z M10,5v6h11V5H10z"/></g> -<g id="view-stream"><path d="M4,18h17v-6H4V18z M4,5v6h17V5H4z"/></g> -<g id="visibility"><path d="M12,4.5C7,4.5,2.7,7.6,1,12c1.7,4.4,6,7.5,11,7.5c5,0,9.3-3.1,11-7.5C21.3,7.6,17,4.5,12,4.5z M12,17c-2.8,0-5-2.2-5-5s2.2-5,5-5c2.8,0,5,2.2,5,5S14.8,17,12,17z M12,9c-1.7,0-3,1.3-3,3s1.3,3,3,3c1.7,0,3-1.3,3-3S13.7,9,12,9z"/></g> -<g id="visibility-off"><path d="M12,7c2.8,0,5,2.2,5,5c0,0.6-0.1,1.3-0.4,1.8l2.9,2.9c1.5-1.3,2.7-2.9,3.4-4.7c-1.7-4.4-6-7.5-11-7.5c-1.4,0-2.7,0.3-4,0.7l2.2,2.2C10.7,7.1,11.4,7,12,7z M2,4.3l2.3,2.3L4.7,7c-1.7,1.3-3,3-3.7,5c1.7,4.4,6,7.5,11,7.5c1.5,0,3-0.3,4.4-0.8l0.4,0.4l2.9,2.9l1.3-1.3L3.3,3L2,4.3z M7.5,9.8l1.5,1.5C9,11.6,9,11.8,9,12c0,1.7,1.3,3,3,3c0.2,0,0.4,0,0.7-0.1l1.5,1.5C13.5,16.8,12.8,17,12,17c-2.8,0-5-2.2-5-5C7,11.2,7.2,10.5,7.5,9.8z M11.8,9l3.1,3.1c0-0.1,0-0.1,0-0.2c0-1.7-1.3-3-3-3C11.9,9,11.9,9,11.8,9z"/></g> -<g id="wallet-giftcard"><path d="M20,6h-2.2C17.9,5.7,18,5.4,18,5c0-1.7-1.3-3-3-3c-1,0-2,0.5-2.5,1.3l0,0L12,4l-0.5-0.7l0,0C11,2.5,10,2,9,2C7.3,2,6,3.3,6,5c0,0.4,0.1,0.7,0.2,1H4C2.9,6,2,6.9,2,8l0,11c0,1.1,0.9,2,2,2h16c1.1,0,2-0.9,2-2V8C22,6.9,21.1,6,20,6z M15,4c0.6,0,1,0.4,1,1s-0.4,1-1,1s-1-0.4-1-1S14.4,4,15,4z M9,4c0.6,0,1,0.4,1,1S9.6,6,9,6S8,5.6,8,5S8.4,4,9,4z M20,19H4v-2h16V19z M20,14H4V8h5.1L7,10.8L8.6,12L11,8.8l1-1.4l1,1.4l2.4,3.2l1.6-1.2L14.9,8H20V14z"/></g> -<g id="wallet-membership"><path d="M20,2H4C2.9,2,2,2.9,2,4v11c0,1.1,0.9,2,2,2h4v5l4-2l4,2v-5h4c1.1,0,2-0.9,2-2V4C22,2.9,21.1,2,20,2z M20,15H4v-2h16V15z M20,10H4V4h16V10z"/></g> -<g id="wallet-travel"><path d="M20,6h-3V4l-2-2H9L7,4v2H4C2.9,6,2,6.9,2,8v11c0,1.1,0.9,2,2,2h16c1.1,0,2-0.9,2-2V8C22,6.9,21.1,6,20,6z M9,4h6v2H9V4z M20,19H4v-2h16V19z M20,14H4V8h3v4h2V8h6v4h2V8h3V14z"/></g> -<g id="warning"><path d="M1,21h22L12,2L1,21z M13,18h-2v-2h2V18z M13,14h-2v-4h2V14z"/></g> -<g id="work"><path d="M20,6h-4V4l-2-2h-4L8,4v2H4C2.9,6,2,6.9,2,8l0,11c0,1.1,0.9,2,2,2h16c1.1,0,2-0.9,2-2V8C22,6.9,21.1,6,20,6z M14,6h-4V4h4V6z"/></g> -</defs></svg> -</core-iconset-svg> - - -<polymer-element name="core-icon-button" attributes="src icon active" assetpath="polymer/bower_components/core-icon-button/"> - - <template> - <style>/* -Copyright (c) 2014 The Polymer Project Authors. All rights reserved. -This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE -The complete set of authors may be found at http://polymer.github.io/AUTHORS -The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS -Code distributed by Google as part of the polymer project is also -subject to an additional IP rights grant found at http://polymer.github.io/PATENTS -*/ - -:host { - display: inline-block; - box-sizing: border-box; - -moz-box-sizing: border-box; - user-select: none; - -moz-user-select: none; - -webkit-user-select: none; - border-radius: 2px; - padding: 7px; - margin: 2px; - vertical-align: middle; - font-size: 1rem; - cursor: pointer; -} - -:host([disabled]) { - opacity: 0.6; - pointer-events: none; -} - -:host(.outline) { - box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.1); -} - -:host(:hover:not([disabled])) { - box-shadow: 0 1px 0 0 rgba(0, 0, 0, 0.12), 0 0 0 1px rgba(0, 0, 0, 0.1); -} - -:host(.selected:not([disabled])) { - background-color: rgba(0, 0, 0, 0.05); - box-shadow: inset 0 1px 0 0 rgba(0, 0, 0, 0.05), 0 0 0 1px rgba(0, 0, 0, 0.12); -} - -:host(:active:not([disabled]), .selected:active:not([disabled])) { - background-color: rgba(0, 0, 0, 0.05); - box-shadow: inset 0 1px 0 0 rgba(0, 0, 0, 0.1), 0 0 0 1px rgba(0, 0, 0, 0.12); -} - -:host(.core-dark-theme.outline) { - background-color: rgba(200, 200, 200, 0.05); - box-shadow: 0 0 0 1px rgba(200, 200, 200, 0.1); -} - -:host(.core-dark-theme:hover) { - background-color: rgba(200, 200, 200, 0.05); - box-shadow: 0 1px 0 0 rgba(200, 200, 200, 0.12), 0 0 0 1px rgba(200, 200, 200, 0.1); -} - -:host(.core-dark-theme.selected) { - background-color: rgba(220, 220, 220, 0.05); - box-shadow: inset 0 1px 0 0 rgba(200, 200, 200, 0.05), 0 0 0 1px rgba(200, 200, 200, 0.12); -} - -:host(.core-dark-theme:active, .core-dark-theme.selected:active) { - background-color: rgba(200, 200, 200, 0.05); - box-shadow: inset 0 1px 0 0 rgba(200, 200, 200, 0.1), 0 0 0 1px rgba(200, 200, 200, 0.12); -} - -core-icon { - pointer-events: none; -} - -/* note: this is a polyfill aware selector */ -:host ::content > :not(core-icon) { - margin-left: 4px; -} -</style> - <core-icon src="{{src}}" icon="{{icon}}"></core-icon><content></content> - </template> - - <script> - - Polymer('core-icon-button', { - - /** - * The URL of an image for the icon. Should not use `icon` property - * if you are using this property. - * - * @attribute src - * @type string - * @default '' - */ - src: '', - - /** - * If true, border is placed around the button to indicate it's - * active state. - * - * @attribute active - * @type boolean - * @default false - */ - active: false, - - /** - * Specifies the icon name or index in the set of icons available in - * the icon set. Should not use `src` property if you are using this - * property. - * - * @attribute icon - * @type string - * @default '' - */ - icon: '', - - activeChanged: function() { - this.classList.toggle('selected', this.active); - } - - }); - - </script> - -</polymer-element> - -<!-- -Copyright (c) 2014 The Polymer Project Authors. All rights reserved. -This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt -The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt -The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt -Code distributed by Google as part of the polymer project is also -subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt ---> - -<!-- -@group Paper Elements - -Material Design: <a href="https://spec.googleplex.com/quantum/components/buttons.html">Button</a> - -`paper-fab` is a floating action button. It contains an image placed in the center and -comes in two sizes: regular size and a smaller size by applying the class `mini`. When -the user touches the button, a ripple effect emanates from the center of the button. - -You may import `core-icons` to use with this element, or provide an URL to a custom icon. -See `core-iconset` for more information about how to use a custom icon set. - -Example: - - <link href="path/to/core-icons/core-icons.html" rel="import"> - - <paper-fab icon="add"></paper-fab> - <paper-fab mini icon="favorite"></paper-fab> - <paper-fab src="star.png"></paper-fab> - -Styling -------- - -Style the button with CSS as you would a normal DOM element. If you are using the icons -provided by `core-icons`, the icon will inherit the foreground color of the button. - - /* make a blue "cloud" button */ - <paper-fab icon="cloud" style="color: blue;"></paper-fab> - -By default, the ripple is the same color as the foreground at 25% opacity. You may -customize the color using this selector: - - /* make #my-button use a blue ripple instead of foreground color */ - #my-button::shadow #ripple { - color: blue; - } - -The opacity of the ripple is not customizable via CSS. - -Accessibility -------------- - -The button is accessible by default if you use the `icon` property. By default, the -`aria-label` attribute will be set to the `icon` property. If you use a custom icon, -you should ensure that the `aria-label` attribute is set. - - <paper-fab src="star.png" aria-label="star"></paper-fab> - -@element paper-fab -@extends paper-button-base -@status unstable ---> - - -<!-- -Copyright (c) 2014 The Polymer Project Authors. All rights reserved. -This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt -The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt -The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt -Code distributed by Google as part of the polymer project is also -subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt ---> - -<!-- -@group Paper Elements - -`paper-button-base` is the base class for button-like elements with ripple and optional shadow. - -@element paper-button-base -@extends paper-focusable -@status unstable ---> - - -<!-- -Copyright (c) 2014 The Polymer Project Authors. All rights reserved. -This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt -The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt -The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt -Code distributed by Google as part of the polymer project is also -subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt ---> - -<!-- -/** - * @group Paper Elements - * - * paper-focusable is a base class for paper elements that can be focused. - * - * @element paper-focusable - * @status beta - * @homepage github.io - */ ---> - - - -<polymer-element name="paper-focusable" attributes="active focused disabled isToggle" tabindex="0" on-down="{{downAction}}" on-up="{{upAction}}" on-focus="{{focusAction}}" on-blur="{{blurAction}}" on-contextmenu="{{contextMenuAction}}" assetpath="polymer/bower_components/paper-focusable/"> - - <template> - <style> - :host([disabled]) { - pointer-events: none; - } - </style> - <content></content> - </template> - - <script> - Polymer('paper-focusable', { - - publish: { - - /** - * If true, the button is currently active either because the - * user is holding down the button, or the button is a toggle - * and is currently in the active state. - * - * @attribute active - * @type boolean - * @default false - */ - active: {value: false, reflect: true}, - - /** - * If true, the element currently has focus due to keyboard - * navigation. - * - * @attribute focused - * @type boolean - * @default false - */ - focused: {value: false, reflect: true}, - - /** - * If true, the user is currently holding down the button. - * - * @attribute pressed - * @type boolean - * @default false - */ - pressed: {value: false, reflect: true}, - - /** - * If true, the user cannot interact with this element. - * - * @attribute disabled - * @type boolean - * @default false - */ - disabled: {value: false, reflect: true}, - - /** - * If true, the button toggles the active state with each tap. - * Otherwise, the button becomes active when the user is holding - * it down. - * - * @attribute isToggle - * @type boolean - * @default false - */ - isToggle: {value: false, reflect: false} - - }, - - disabledChanged: function() { - if (this.disabled) { - this.removeAttribute('tabindex'); - } else { - this.setAttribute('tabindex', 0); - } - }, - - downAction: function() { - this.pressed = true; - - if (this.isToggle) { - this.active = !this.active; - } else { - this.active = true; - } - }, - - // Pulling up the context menu for an item should focus it; but we need to - // be careful about how we deal with down/up events surrounding context - // menus. The up event typically does not fire until the context menu - // closes: so we focus immediately. - // - // This fires _after_ downAction. - contextMenuAction: function(e) { - // Note that upAction may fire _again_ on the actual up event. - this.upAction(e); - this.focusAction(); - }, - - upAction: function() { - this.pressed = false; - - if (!this.isToggle) { - this.active = false; - } - }, - - focusAction: function() { - if (!this.pressed) { - // Only render the "focused" state if the element gains focus due to - // keyboard navigation. - this.focused = true; - } - }, - - blurAction: function() { - this.focused = false; - } - - }); - - </script> -</polymer-element> - - -<polymer-element name="paper-button-base" extends="paper-focusable" assetpath="polymer/bower_components/paper-button/"> - - <script> - Polymer('paper-button-base',{ - - z: 1, - - activeChanged: function() { - this.super(); - - if (this.active) { - // FIXME: remove when paper-ripple can have a default 'down' state. - if (!this.lastEvent) { - var rect = this.getBoundingClientRect(); - this.lastEvent = { - x: rect.left + rect.width / 2, - y: rect.top + rect.height / 2 - } - } - this.$.ripple.downAction(this.lastEvent); - } else { - this.$.ripple.upAction(); - } - this.adjustZ(); - }, - - disabledChanged: function() { - this.super(); - if (this.disabled) { - this.setAttribute('aria-disabled', ''); - } else { - this.removeAttribute('aria-disabled'); - } - this.adjustZ(); - }, - - recenteringTouchChanged: function() { - if (this.$.ripple) { - this.$.ripple.classList.toggle('recenteringTouch', this.recenteringTouch); - } - }, - - fillChanged: function() { - if (this.$.ripple) { - this.$.ripple.classList.toggle('fill', this.fill); - } - }, - - adjustZ: function() { - if (this.active) { - this.z = 2; - } else if (this.disabled) { - this.z = 0; - } else { - this.z = 1; - } - }, - - downAction: function(e) { - this.super(e); - this.lastEvent = e; - if (!this.$.ripple) { - var ripple = document.createElement('paper-ripple'); - ripple.setAttribute('id', 'ripple'); - ripple.setAttribute('fit', ''); - if (this.recenteringTouch) { - ripple.classList.add('recenteringTouch'); - } - if (!this.fill) { - ripple.classList.add('circle'); - } - this.$.ripple = ripple; - this.shadowRoot.insertBefore(ripple, this.shadowRoot.firstChild); - // No need to forward the event to the ripple because the ripple - // is triggered in activeChanged - } - } - - }); - </script> -</polymer-element> - -<!-- -Copyright (c) 2014 The Polymer Project Authors. All rights reserved. -This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt -The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt -The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt -Code distributed by Google as part of the polymer project is also -subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt ---> - -<!-- -`paper-ripple` provides a visual effect that other paper elements can -use to simulate a rippling effect emanating from the point of contact. The -effect can be visualized as a concentric circle with motion. - -Example: - - <paper-ripple></paper-ripple> - -`paper-ripple` listens to "down" and "up" events so it would display ripple -effect when touches on it. You can also defeat the default behavior and -manually route the down and up actions to the ripple element. Note that it is -important if you call downAction() you will have to make sure to call upAction() -so that `paper-ripple` would end the animation loop. - -Example: - - <paper-ripple id="ripple" style="pointer-events: none;"></paper-ripple> - ... - downAction: function(e) { - this.$.ripple.downAction({x: e.x, y: e.y}); - }, - upAction: function(e) { - this.$.ripple.upAction(); - } - -Styling ripple effect: - - Use CSS color property to style the ripple: - - paper-ripple { - color: #4285f4; - } - - Note that CSS color property is inherited so it is not required to set it on - the `paper-ripple` element directly. - -Apply `recenteringTouch` class to make the recentering rippling effect. - - <paper-ripple class="recenteringTouch"></paper-ripple> - -Apply `circle` class to make the rippling effect within a circle. - - <paper-ripple class="circle"></paper-ripple> - -@group Paper Elements -@element paper-ripple -@homepage github.io ---> - - - -<polymer-element name="paper-ripple" attributes="initialOpacity opacityDecayVelocity" assetpath="polymer/bower_components/paper-ripple/"> -<template> - - <style> - - :host { - display: block; - position: relative; - border-radius: inherit; - overflow: hidden; - } - - :host-context([noink]) { - pointer-events: none; - } - - #bg, #waves, .wave-container, .wave { - pointer-events: none; - position: absolute; - top: 0; - left: 0; - width: 100%; - height: 100%; - } - - #bg, .wave { - opacity: 0; - } - - #waves, .wave { - overflow: hidden; - } - - .wave-container, .wave { - border-radius: 50%; - } - - :host(.circle) #bg, - :host(.circle) #waves { - border-radius: 50%; - } - - :host(.circle) .wave-container { - overflow: hidden; - } - - </style> - - <div id="bg"></div> - <div id="waves"> - </div> - -</template> -<script> - - (function() { - - var waveMaxRadius = 150; - // - // INK EQUATIONS - // - function waveRadiusFn(touchDownMs, touchUpMs, anim) { - // Convert from ms to s. - var touchDown = touchDownMs / 1000; - var touchUp = touchUpMs / 1000; - var totalElapsed = touchDown + touchUp; - var ww = anim.width, hh = anim.height; - // use diagonal size of container to avoid floating point math sadness - var waveRadius = Math.min(Math.sqrt(ww * ww + hh * hh), waveMaxRadius) * 1.1 + 5; - var duration = 1.1 - .2 * (waveRadius / waveMaxRadius); - var tt = (totalElapsed / duration); - - var size = waveRadius * (1 - Math.pow(80, -tt)); - return Math.abs(size); - } - - function waveOpacityFn(td, tu, anim) { - // Convert from ms to s. - var touchDown = td / 1000; - var touchUp = tu / 1000; - var totalElapsed = touchDown + touchUp; - - if (tu <= 0) { // before touch up - return anim.initialOpacity; - } - return Math.max(0, anim.initialOpacity - touchUp * anim.opacityDecayVelocity); - } - - function waveOuterOpacityFn(td, tu, anim) { - // Convert from ms to s. - var touchDown = td / 1000; - var touchUp = tu / 1000; - - // Linear increase in background opacity, capped at the opacity - // of the wavefront (waveOpacity). - var outerOpacity = touchDown * 0.3; - var waveOpacity = waveOpacityFn(td, tu, anim); - return Math.max(0, Math.min(outerOpacity, waveOpacity)); - } - - // Determines whether the wave should be completely removed. - function waveDidFinish(wave, radius, anim) { - var waveOpacity = waveOpacityFn(wave.tDown, wave.tUp, anim); - - // If the wave opacity is 0 and the radius exceeds the bounds - // of the element, then this is finished. - return waveOpacity < 0.01 && radius >= Math.min(wave.maxRadius, waveMaxRadius); - }; - - function waveAtMaximum(wave, radius, anim) { - var waveOpacity = waveOpacityFn(wave.tDown, wave.tUp, anim); - - return waveOpacity >= anim.initialOpacity && radius >= Math.min(wave.maxRadius, waveMaxRadius); - } - - // - // DRAWING - // - function drawRipple(ctx, x, y, radius, innerAlpha, outerAlpha) { - // Only animate opacity and transform - if (outerAlpha !== undefined) { - ctx.bg.style.opacity = outerAlpha; - } - ctx.wave.style.opacity = innerAlpha; - - var s = radius / (ctx.containerSize / 2); - var dx = x - (ctx.containerWidth / 2); - var dy = y - (ctx.containerHeight / 2); - - ctx.wc.style.webkitTransform = 'translate3d(' + dx + 'px,' + dy + 'px,0)'; - ctx.wc.style.transform = 'translate3d(' + dx + 'px,' + dy + 'px,0)'; - - // 2d transform for safari because of border-radius and overflow:hidden clipping bug. - // https://bugs.webkit.org/show_bug.cgi?id=98538 - ctx.wave.style.webkitTransform = 'scale(' + s + ',' + s + ')'; - ctx.wave.style.transform = 'scale3d(' + s + ',' + s + ',1)'; - } - - // - // SETUP - // - function createWave(elem) { - var elementStyle = window.getComputedStyle(elem); - var fgColor = elementStyle.color; - - var inner = document.createElement('div'); - inner.style.backgroundColor = fgColor; - inner.classList.add('wave'); - - var outer = document.createElement('div'); - outer.classList.add('wave-container'); - outer.appendChild(inner); - - var container = elem.$.waves; - container.appendChild(outer); - - elem.$.bg.style.backgroundColor = fgColor; - - var wave = { - bg: elem.$.bg, - wc: outer, - wave: inner, - waveColor: fgColor, - maxRadius: 0, - isMouseDown: false, - mouseDownStart: 0.0, - mouseUpStart: 0.0, - tDown: 0, - tUp: 0 - }; - return wave; - } - - function removeWaveFromScope(scope, wave) { - if (scope.waves) { - var pos = scope.waves.indexOf(wave); - scope.waves.splice(pos, 1); - // FIXME cache nodes - wave.wc.remove(); - } - }; - - // Shortcuts. - var pow = Math.pow; - var now = Date.now; - if (window.performance && performance.now) { - now = performance.now.bind(performance); - } - - function cssColorWithAlpha(cssColor, alpha) { - var parts = cssColor.match(/^rgb\((\d+),\s*(\d+),\s*(\d+)\)$/); - if (typeof alpha == 'undefined') { - alpha = 1; - } - if (!parts) { - return 'rgba(255, 255, 255, ' + alpha + ')'; - } - return 'rgba(' + parts[1] + ', ' + parts[2] + ', ' + parts[3] + ', ' + alpha + ')'; - } - - function dist(p1, p2) { - return Math.sqrt(pow(p1.x - p2.x, 2) + pow(p1.y - p2.y, 2)); - } - - function distanceFromPointToFurthestCorner(point, size) { - var tl_d = dist(point, {x: 0, y: 0}); - var tr_d = dist(point, {x: size.w, y: 0}); - var bl_d = dist(point, {x: 0, y: size.h}); - var br_d = dist(point, {x: size.w, y: size.h}); - return Math.max(tl_d, tr_d, bl_d, br_d); - } - - Polymer('paper-ripple', { - - /** - * The initial opacity set on the wave. - * - * @attribute initialOpacity - * @type number - * @default 0.25 - */ - initialOpacity: 0.25, - - /** - * How fast (opacity per second) the wave fades out. - * - * @attribute opacityDecayVelocity - * @type number - * @default 0.8 - */ - opacityDecayVelocity: 0.8, - - backgroundFill: true, - pixelDensity: 2, - - eventDelegates: { - down: 'downAction', - up: 'upAction' - }, - - ready: function() { - this.waves = []; - }, - - downAction: function(e) { - var wave = createWave(this); - - this.cancelled = false; - wave.isMouseDown = true; - wave.tDown = 0.0; - wave.tUp = 0.0; - wave.mouseUpStart = 0.0; - wave.mouseDownStart = now(); - - var rect = this.getBoundingClientRect(); - var width = rect.width; - var height = rect.height; - var touchX = e.x - rect.left; - var touchY = e.y - rect.top; - - wave.startPosition = {x:touchX, y:touchY}; - - if (this.classList.contains("recenteringTouch")) { - wave.endPosition = {x: width / 2, y: height / 2}; - wave.slideDistance = dist(wave.startPosition, wave.endPosition); - } - wave.containerSize = Math.max(width, height); - wave.containerWidth = width; - wave.containerHeight = height; - wave.maxRadius = distanceFromPointToFurthestCorner(wave.startPosition, {w: width, h: height}); - - // The wave is circular so constrain its container to 1:1 - wave.wc.style.top = (wave.containerHeight - wave.containerSize) / 2 + 'px'; - wave.wc.style.left = (wave.containerWidth - wave.containerSize) / 2 + 'px'; - wave.wc.style.width = wave.containerSize + 'px'; - wave.wc.style.height = wave.containerSize + 'px'; - - this.waves.push(wave); - - if (!this._loop) { - this._loop = this.animate.bind(this, { - width: width, - height: height - }); - requestAnimationFrame(this._loop); - } - // else there is already a rAF - }, - - upAction: function() { - for (var i = 0; i < this.waves.length; i++) { - // Declare the next wave that has mouse down to be mouse'ed up. - var wave = this.waves[i]; - if (wave.isMouseDown) { - wave.isMouseDown = false - wave.mouseUpStart = now(); - wave.mouseDownStart = 0; - wave.tUp = 0.0; - break; - } - } - this._loop && requestAnimationFrame(this._loop); - }, - - cancel: function() { - this.cancelled = true; - }, - - animate: function(ctx) { - var shouldRenderNextFrame = false; - - var deleteTheseWaves = []; - // The oldest wave's touch down duration - var longestTouchDownDuration = 0; - var longestTouchUpDuration = 0; - // Save the last known wave color - var lastWaveColor = null; - // wave animation values - var anim = { - initialOpacity: this.initialOpacity, - opacityDecayVelocity: this.opacityDecayVelocity, - height: ctx.height, - width: ctx.width - } - - for (var i = 0; i < this.waves.length; i++) { - var wave = this.waves[i]; - - if (wave.mouseDownStart > 0) { - wave.tDown = now() - wave.mouseDownStart; - } - if (wave.mouseUpStart > 0) { - wave.tUp = now() - wave.mouseUpStart; - } - - // Determine how long the touch has been up or down. - var tUp = wave.tUp; - var tDown = wave.tDown; - longestTouchDownDuration = Math.max(longestTouchDownDuration, tDown); - longestTouchUpDuration = Math.max(longestTouchUpDuration, tUp); - - // Obtain the instantenous size and alpha of the ripple. - var radius = waveRadiusFn(tDown, tUp, anim); - var waveAlpha = waveOpacityFn(tDown, tUp, anim); - var waveColor = cssColorWithAlpha(wave.waveColor, waveAlpha); - lastWaveColor = wave.waveColor; - - // Position of the ripple. - var x = wave.startPosition.x; - var y = wave.startPosition.y; - - // Ripple gravitational pull to the center of the canvas. - if (wave.endPosition) { - - // This translates from the origin to the center of the view based on the max dimension of - var translateFraction = Math.min(1, radius / wave.containerSize * 2 / Math.sqrt(2) ); - - x += translateFraction * (wave.endPosition.x - wave.startPosition.x); - y += translateFraction * (wave.endPosition.y - wave.startPosition.y); - } - - // If we do a background fill fade too, work out the correct color. - var bgFillColor = null; - if (this.backgroundFill) { - var bgFillAlpha = waveOuterOpacityFn(tDown, tUp, anim); - bgFillColor = cssColorWithAlpha(wave.waveColor, bgFillAlpha); - } - - // Draw the ripple. - drawRipple(wave, x, y, radius, waveAlpha, bgFillAlpha); - - // Determine whether there is any more rendering to be done. - var maximumWave = waveAtMaximum(wave, radius, anim); - var waveDissipated = waveDidFinish(wave, radius, anim); - var shouldKeepWave = !waveDissipated || maximumWave; - // keep rendering dissipating wave when at maximum radius on upAction - var shouldRenderWaveAgain = wave.mouseUpStart ? !waveDissipated : !maximumWave; - shouldRenderNextFrame = shouldRenderNextFrame || shouldRenderWaveAgain; - if (!shouldKeepWave || this.cancelled) { - deleteTheseWaves.push(wave); - } - } - - if (shouldRenderNextFrame) { - requestAnimationFrame(this._loop); - } - - for (var i = 0; i < deleteTheseWaves.length; ++i) { - var wave = deleteTheseWaves[i]; - removeWaveFromScope(this, wave); - } - - if (!this.waves.length && this._loop) { - // clear the background color - this.$.bg.style.backgroundColor = null; - this._loop = null; - this.fire('core-transitionend'); - } - } - - }); - - })(); - -</script> -</polymer-element> - -<!-- -Copyright (c) 2014 The Polymer Project Authors. All rights reserved. -This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt -The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt -The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt -Code distributed by Google as part of the polymer project is also -subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt ---> - -<!-- -The `paper-shadow` element is a helper to add shadows to elements. -Paper shadows are composed of two shadows on top of each other. We -mimic this effect by using two elements on top of each other, each with a -different drop shadow. You can apply the shadow to an element by assigning -it as the target. If you do not specify a target, the shadow is applied to -the `paper-shadow` element's parent element or shadow host element if its -parent is a shadow root. Alternatively, you can use the CSS classes included -by this element directly. - -Example: - - <div id="myCard" class="card"></div> - <paper-shadow id="myShadow" z="1"></div> - - // Assign a target explicitly - myShadow.target = document.getElementById('myCard'); - - // Auto-assign the target. - <div class="card"> - <paper-shadow z="1"></paper-shadow> - </div> - - // Use the classes directly - <div class="card paper-shadow-top paper-shadow-top-z-1"> - <div class="card-inner paper-shadow-bottom paper-shadow-bottom-z-1"></div> - </div> - -If you assign a target to a `paper-shadow` element, it creates two nodes and inserts -them as the first children of the target, or the first children of the target's shadow -root if there is one. This implies: - - 1. If the primary node that drops the shadow has styling that affects its shape, - the same styling must be applied to elements with class `paper-shadow`. - `border-radius` is a very common property and is inherited automatically. - - 2. The target's overflow property will be set to `overflow: visible` because the - shadow is rendered beyond the bounds of its container. Position the shadow as a - separate layer and use a different child element for clipping if needed. - -@group Paper Elements -@class paper-shadow ---> - - - -<polymer-element name="paper-shadow" assetpath="polymer/bower_components/paper-shadow/"> - - <template> - - <style no-shim="">/* - * @license - * Copyright (c) 2014 The Polymer Project Authors. All rights reserved. - * This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt - * The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt - * The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt - * Code distributed by Google as part of the polymer project is also - * subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt - */ - -.paper-shadow { - position: absolute; - top: 0; - left: 0; - bottom: 0; - right: 0; - border-radius: inherit; - pointer-events: none; -} - -.paper-shadow-animated.paper-shadow { - transition: box-shadow 0.28s cubic-bezier(0.4, 0, 0.2, 1); -} - -.paper-shadow-top-z-1 { - box-shadow: 0 2px 10px 0 rgba(0, 0, 0, 0.16); -} - -.paper-shadow-bottom-z-1 { - box-shadow: 0 2px 5px 0 rgba(0, 0, 0, 0.26); -} - -.paper-shadow-top-z-2 { - box-shadow: 0 6px 20px 0 rgba(0, 0, 0, 0.19); -} - -.paper-shadow-bottom-z-2 { - box-shadow: 0 8px 17px 0 rgba(0, 0, 0, 0.2); -} - -.paper-shadow-top-z-3 { - box-shadow: 0 17px 50px 0 rgba(0, 0, 0, 0.19); -} - -.paper-shadow-bottom-z-3 { - box-shadow: 0 12px 15px 0 rgba(0, 0, 0, 0.24); -} - -.paper-shadow-top-z-4 { - box-shadow: 0 25px 55px 0 rgba(0, 0, 0, 0.21); -} - -.paper-shadow-bottom-z-4 { - box-shadow: 0 16px 28px 0 rgba(0, 0, 0, 0.22); -} - -.paper-shadow-top-z-5 { - box-shadow: 0 40px 77px 0 rgba(0, 0, 0, 0.22); -} - -.paper-shadow-bottom-z-5 { - box-shadow: 0 27px 24px 0 rgba(0, 0, 0, 0.2); -} - -.paper-shadow-animate-z-1-z-2.paper-shadow-top { - -webkit-transition: none; - -webkit-animation: animate-shadow-top-z-1-z-2 0.7s infinite alternate; -} - -.paper-shadow-animate-z-1-z-2 .paper-shadow-bottom { - -webkit-transition: none; - -webkit-animation: animate-shadow-bottom-z-1-z-2 0.7s infinite alternate; -} - -@-webkit-keyframes animate-shadow-top-z-1-z-2 { - 0% { - box-shadow: 0 2px 10px 0 rgba(0, 0, 0, 0.16); - } - 100% { - box-shadow: 0 6px 20px 0 rgba(0, 0, 0, 0.19); - } -} - -@-webkit-keyframes animate-shadow-bottom-z-1-z-2 { - 0% { - box-shadow: 0 2px 5px 0 rgba(0, 0, 0, 0.26); - } - 100% { - box-shadow: 0 8px 17px 0 rgba(0, 0, 0, 0.2); - } -}</style> - - </template> - - <script> - Polymer('paper-shadow', { - - publish: { - /** - * If set, the shadow is applied to this node. - * - * @attribute target - * @type Element - * @default null - */ - target: {value: null, reflect: true}, - - /** - * The z-depth of this shadow, from 0-5. - * - * @attribute z - * @type number - * @default 1 - */ - z: {value: 1, reflect: true}, - - /** - * If true, the shadow animates between z-depth changes. - * - * @attribute animated - * @type boolean - * @default false - */ - animated: {value: false, reflect: true}, - - /** - * Workaround: getComputedStyle is wrong sometimes so `paper-shadow` - * may overwrite the `position` CSS property. Set this property to - * true to prevent this. - * - * @attribute hasPosition - * @type boolean - * @default false - */ - hasPosition: false - }, - - // NOTE: include template so that styles are loaded, but remove - // so that we can decide dynamically what part to include - registerCallback: function(polymerElement) { - var template = polymerElement.querySelector('template'); - this._style = template.content.querySelector('style'); - this._style.removeAttribute('no-shim'); - }, - - fetchTemplate: function() { - return null; - }, - - attached: function() { - // If no target is bound at attach, default the target to the parent - // element or shadow host. - if (!this.target) { - if (!this.parentElement && this.parentNode.host) { - this.target = this.parentNode.host; - } else if (this.parentElement && (window.ShadowDOMPolyfill ? this.parentElement !== wrap(document.body) : this.parentElement !== document.body)) { - this.target = this.parentElement; - } - } - }, - - targetChanged: function(old) { - if (old) { - this.removeShadow(old); - } - if (this.target) { - this.addShadow(this.target); - } - }, - - zChanged: function(old) { - if (this.target && this.target._paperShadow) { - var shadow = this.target._paperShadow; - ['top', 'bottom'].forEach(function(s) { - shadow[s].classList.remove('paper-shadow-' + s + '-z-' + old); - shadow[s].classList.add('paper-shadow-' + s + '-z-' + this.z); - }.bind(this)); - } - }, - - animatedChanged: function() { - if (this.target && this.target._paperShadow) { - var shadow = this.target._paperShadow; - ['top', 'bottom'].forEach(function(s) { - if (this.animated) { - shadow[s].classList.add('paper-shadow-animated'); - } else { - shadow[s].classList.remove('paper-shadow-animated'); - } - }.bind(this)); - } - }, - - addShadow: function(node) { - if (node._paperShadow) { - return; - } - - if (!node._hasShadowStyle) { - if (!node.shadowRoot) { - node.createShadowRoot().innerHTML = '<content></content>'; - } - this.installScopeStyle(this._style, 'shadow', node.shadowRoot); - node._hasShadowStyle = true; - } - - var computed = getComputedStyle(node); - if (!this.hasPosition && computed.position === 'static') { - node.style.position = 'relative'; - } - node.style.overflow = 'visible'; - - // Both the top and bottom shadows are children of the target, so - // it does not affect the classes and CSS properties of the target. - ['top', 'bottom'].forEach(function(s) { - var inner = (node._paperShadow && node._paperShadow[s]) || document.createElement('div'); - inner.classList.add('paper-shadow'); - inner.classList.add('paper-shadow-' + s + '-z-' + this.z); - if (this.animated) { - inner.classList.add('paper-shadow-animated'); - } - - if (node.shadowRoot) { - node.shadowRoot.insertBefore(inner, node.shadowRoot.firstChild); - } else { - node.insertBefore(inner, node.firstChild); - } - - node._paperShadow = node._paperShadow || {}; - node._paperShadow[s] = inner; - }.bind(this)); - - }, - - removeShadow: function(node) { - if (!node._paperShadow) { - return; - } - - ['top', 'bottom'].forEach(function(s) { - node._paperShadow[s].remove(); - }); - node._paperShadow = null; - - node.style.position = null; - } - - }); - </script> -</polymer-element> - - -<polymer-element name="paper-fab" extends="paper-button-base" attributes="src icon mini" role="button" assetpath="polymer/bower_components/paper-fab/"> - - <template> - - <style> - :host { - display: inline-block; - position: relative; - outline: none; - -webkit-user-select: none; - user-select: none; - cursor: pointer; - z-index: 0; - - box-sizing: border-box; - width: 56px; - height: 56px; - background: #d23f31; - color: #fff; - border-radius: 50%; - padding: 16px; - } - - :host([mini]) { - width: 40px; - height: 40px; - padding: 8px; - } - - :host([disabled]) { - color: #c9c9c9; - pointer-events: none; - cursor: auto; - } - - #ripple { - pointer-events: none; - z-index: -1; - } - </style> - - <template if="{{raised}}"> - <paper-shadow id="shadow" z="{{z}}" animated=""></paper-shadow> - </template> - - <!-- to position to ripple behind the icon --> - <core-icon relative="" id="icon" src="{{src}}" icon="{{icon}}"></core-icon> - - </template> - - <script> - Polymer('paper-fab',{ - - publish: { - - /** - * The URL of an image for the icon. If the src property is specified, - * the icon property should not be. - * - * @attribute src - * @type string - * @default '' - */ - src: '', - - /** - * Specifies the icon name or index in the set of icons available in - * the icon's icon set. If the icon property is specified, - * the src property should not be. - * - * @attribute icon - * @type string - * @default '' - */ - icon: '', - - /** - * Set this to true to style this is a "mini" FAB. - * - * @attribute mini - * @type boolean - * @default false - */ - mini: false, - - raised: true, - recenteringTouch: false, - fill: true - - }, - - iconChanged: function(oldIcon) { - this.setAttribute('aria-label', this.icon); - } - - }); - - </script> -</polymer-element> - -<!-- -Copyright (c) 2014 The Polymer Project Authors. All rights reserved. -This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt -The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt -The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt -Code distributed by Google as part of the polymer project is also -subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt ---> - -<!-- -`paper-tabs` is a `core-selector` styled to look like tabs. Tabs make it easy to -explore and switch between different views or functional aspects of an app, or -to browse categorized data sets. - -Use `selected` property to get or set the selected tab. - -Example: - - <paper-tabs selected="0"> - <paper-tab>TAB 1</paper-tab> - <paper-tab>TAB 2</paper-tab> - <paper-tab>TAB 3</paper-tab> - </paper-tabs> - -See <a href="#paper-tab">paper-tab</a> for more information about -`paper-tab`. - -Styling tabs: - -To change the sliding bar color: - - paper-tabs.pink::shadow #selectionBar { - background-color: #ff4081; - } - -@group Paper Elements -@element paper-tabs -@extends core-selector -@homepage github.io ---> - -<!-- -Copyright (c) 2014 The Polymer Project Authors. All rights reserved. -This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt -The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt -The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt -Code distributed by Google as part of the polymer project is also -subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt ---> - -<!-- -@group Polymer Core Elements - -`<core-selector>` is used to manage a list of elements that can be selected. - -The attribute `selected` indicates which item element is being selected. -The attribute `multi` indicates if multiple items can be selected at once. -Tapping on the item element would fire `core-activate` event. Use -`core-select` event to listen for selection changes. - -Example: - - <core-selector selected="0"> - <div>Item 1</div> - <div>Item 2</div> - <div>Item 3</div> - </core-selector> - -`<core-selector>` is not styled. Use the `core-selected` CSS class to style the selected element. - - <style> - .item.core-selected { - background: #eee; - } - </style> - ... - <core-selector> - <div class="item">Item 1</div> - <div class="item">Item 2</div> - <div class="item">Item 3</div> - </core-selector> - -@element core-selector -@status stable -@homepage github.io ---> - -<!-- -Fired when an item's selection state is changed. This event is fired both -when an item is selected or deselected. The `isSelected` detail property -contains the selection state. - -@event core-select -@param {Object} detail - @param {boolean} detail.isSelected true for selection and false for deselection - @param {Object} detail.item the item element ---> -<!-- -Fired when an item element is tapped. - -@event core-activate -@param {Object} detail - @param {Object} detail.item the item element ---> - - -<!-- -Copyright (c) 2014 The Polymer Project Authors. All rights reserved. -This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt -The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt -The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt -Code distributed by Google as part of the polymer project is also -subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt ---> -<!-- -@group Polymer Core Elements - -The `<core-selection>` element is used to manage selection state. It has no -visual appearance and is typically used in conjunction with another element. -For example, [core-selector](#core-selector) -use a `<core-selection>` to manage selection. - -To mark an item as selected, call the `select(item)` method on -`<core-selection>`. The item itself is an argument to this method. - -The `<core-selection>`element manages selection state for any given set of -items. When an item is selected, the `core-select` event is fired. - -The attribute `multi` indicates if multiple items can be selected at once. - -Example: - - <polymer-element name="selection-example"> - <template> - <style> - polyfill-next-selector { content: ':host > .selected'; } - ::content > .selected { - font-weight: bold; - font-style: italic; - } - </style> - <ul on-tap="{{itemTapAction}}"> - <content></content> - </ul> - <core-selection id="selection" multi - on-core-select="{{selectAction}}"></core-selection> - </template> - <script> - Polymer('selection-example', { - itemTapAction: function(e, detail, sender) { - this.$.selection.select(e.target); - }, - selectAction: function(e, detail, sender) { - detail.item.classList.toggle('selected', detail.isSelected); - } - }); - </script> - </polymer-element> - - <selection-example> - <li>Red</li> - <li>Green</li> - <li>Blue</li> - </selection-example> - -@element core-selection ---> - -<!-- -Fired when an item's selection state is changed. This event is fired both -when an item is selected or deselected. The `isSelected` detail property -contains the selection state. - -@event core-select -@param {Object} detail - @param {boolean} detail.isSelected true for selection and false for de-selection - @param {Object} detail.item the item element ---> - - -<polymer-element name="core-selection" attributes="multi" hidden assetpath="polymer/bower_components/core-selection/"> - <script> - Polymer('core-selection', { - /** - * If true, multiple selections are allowed. - * - * @attribute multi - * @type boolean - * @default false - */ - multi: false, - ready: function() { - this.clear(); - }, - clear: function() { - this.selection = []; - }, - /** - * Retrieves the selected item(s). - * @method getSelection - * @returns Returns the selected item(s). If the multi property is true, - * getSelection will return an array, otherwise it will return - * the selected item or undefined if there is no selection. - */ - getSelection: function() { - return this.multi ? this.selection : this.selection[0]; - }, - /** - * Indicates if a given item is selected. - * @method isSelected - * @param {any} item The item whose selection state should be checked. - * @returns Returns true if `item` is selected. - */ - isSelected: function(item) { - return this.selection.indexOf(item) >= 0; - }, - setItemSelected: function(item, isSelected) { - if (item !== undefined && item !== null) { - if (isSelected) { - this.selection.push(item); - } else { - var i = this.selection.indexOf(item); - if (i >= 0) { - this.selection.splice(i, 1); - } - } - this.fire("core-select", {isSelected: isSelected, item: item}); - } - }, - /** - * Set the selection state for a given `item`. If the multi property - * is true, then the selected state of `item` will be toggled; otherwise - * the `item` will be selected. - * @method select - * @param {any} item: The item to select. - */ - select: function(item) { - if (this.multi) { - this.toggle(item); - } else if (this.getSelection() !== item) { - this.setItemSelected(this.getSelection(), false); - this.setItemSelected(item, true); - } - }, - /** - * Toggles the selection state for `item`. - * @method toggle - * @param {any} item: The item to toggle. - */ - toggle: function(item) { - this.setItemSelected(item, !this.isSelected(item)); - } - }); - </script> -</polymer-element> - - -<polymer-element name="core-selector" attributes="selected multi valueattr selectedClass selectedProperty selectedAttribute selectedItem selectedModel selectedIndex notap excludedLocalNames target itemsSelector activateEvent" assetpath="polymer/bower_components/core-selector/"> - - <template> - <core-selection id="selection" multi="{{multi}}" on-core-select="{{selectionSelect}}"></core-selection> - <content id="items" select="*"></content> - </template> - - <script> - - Polymer('core-selector', { - - /** - * Gets or sets the selected element. Default to use the index - * of the item element. - * - * If you want a specific attribute value of the element to be - * used instead of index, set "valueattr" to that attribute name. - * - * Example: - * - * <core-selector valueattr="label" selected="foo"> - * <div label="foo"></div> - * <div label="bar"></div> - * <div label="zot"></div> - * </core-selector> - * - * In multi-selection this should be an array of values. - * - * Example: - * - * <core-selector id="selector" valueattr="label" multi> - * <div label="foo"></div> - * <div label="bar"></div> - * <div label="zot"></div> - * </core-selector> - * - * this.$.selector.selected = ['foo', 'zot']; - * - * @attribute selected - * @type Object - * @default null - */ - selected: null, - - /** - * If true, multiple selections are allowed. - * - * @attribute multi - * @type boolean - * @default false - */ - multi: false, - - /** - * Specifies the attribute to be used for "selected" attribute. - * - * @attribute valueattr - * @type string - * @default 'name' - */ - valueattr: 'name', - - /** - * Specifies the CSS class to be used to add to the selected element. - * - * @attribute selectedClass - * @type string - * @default 'core-selected' - */ - selectedClass: 'core-selected', - - /** - * Specifies the property to be used to set on the selected element - * to indicate its active state. - * - * @attribute selectedProperty - * @type string - * @default '' - */ - selectedProperty: '', - - /** - * Specifies the attribute to set on the selected element to indicate - * its active state. - * - * @attribute selectedAttribute - * @type string - * @default 'active' - */ - selectedAttribute: 'active', - - /** - * Returns the currently selected element. In multi-selection this returns - * an array of selected elements. - * Note that you should not use this to set the selection. Instead use - * `selected`. - * - * @attribute selectedItem - * @type Object - * @default null - */ - selectedItem: null, - - /** - * In single selection, this returns the model associated with the - * selected element. - * Note that you should not use this to set the selection. Instead use - * `selected`. - * - * @attribute selectedModel - * @type Object - * @default null - */ - selectedModel: null, - - /** - * In single selection, this returns the selected index. - * Note that you should not use this to set the selection. Instead use - * `selected`. - * - * @attribute selectedIndex - * @type number - * @default -1 - */ - selectedIndex: -1, - - /** - * Nodes with local name that are in the list will not be included - * in the selection items. In the following example, `items` returns four - * `core-item`'s and doesn't include `h3` and `hr`. - * - * <core-selector excludedLocalNames="h3 hr"> - * <h3>Header</h3> - * <core-item>Item1</core-item> - * <core-item>Item2</core-item> - * <hr> - * <core-item>Item3</core-item> - * <core-item>Item4</core-item> - * </core-selector> - * - * @attribute excludedLocalNames - * @type string - * @default '' - */ - excludedLocalNames: '', - - /** - * The target element that contains items. If this is not set - * core-selector is the container. - * - * @attribute target - * @type Object - * @default null - */ - target: null, - - /** - * This can be used to query nodes from the target node to be used for - * selection items. Note this only works if `target` is set - * and is not `core-selector` itself. - * - * Example: - * - * <core-selector target="{{$.myForm}}" itemsSelector="input[type=radio]"></core-selector> - * <form id="myForm"> - * <label><input type="radio" name="color" value="red"> Red</label> <br> - * <label><input type="radio" name="color" value="green"> Green</label> <br> - * <label><input type="radio" name="color" value="blue"> Blue</label> <br> - * <p>color = {{color}}</p> - * </form> - * - * @attribute itemsSelector - * @type string - * @default '' - */ - itemsSelector: '', - - /** - * The event that would be fired from the item element to indicate - * it is being selected. - * - * @attribute activateEvent - * @type string - * @default 'tap' - */ - activateEvent: 'tap', - - /** - * Set this to true to disallow changing the selection via the - * `activateEvent`. - * - * @attribute notap - * @type boolean - * @default false - */ - notap: false, - - defaultExcludedLocalNames: 'template', - - ready: function() { - this.activateListener = this.activateHandler.bind(this); - this.itemFilter = this.filterItem.bind(this); - this.excludedLocalNamesChanged(); - this.observer = new MutationObserver(this.updateSelected.bind(this)); - if (!this.target) { - this.target = this; - } - }, - - /** - * Returns an array of all items. - * - * @property items - */ - get items() { - if (!this.target) { - return []; - } - var nodes = this.target !== this ? (this.itemsSelector ? - this.target.querySelectorAll(this.itemsSelector) : - this.target.children) : this.$.items.getDistributedNodes(); - return Array.prototype.filter.call(nodes, this.itemFilter); - }, - - filterItem: function(node) { - return !this._excludedNames[node.localName]; - }, - - excludedLocalNamesChanged: function() { - this._excludedNames = {}; - var s = this.defaultExcludedLocalNames; - if (this.excludedLocalNames) { - s += ' ' + this.excludedLocalNames; - } - s.split(/\s+/g).forEach(function(n) { - this._excludedNames[n] = 1; - }, this); - }, - - targetChanged: function(old) { - if (old) { - this.removeListener(old); - this.observer.disconnect(); - this.clearSelection(); - } - if (this.target) { - this.addListener(this.target); - this.observer.observe(this.target, {childList: true}); - this.updateSelected(); - } - }, - - addListener: function(node) { - Polymer.addEventListener(node, this.activateEvent, this.activateListener); - }, - - removeListener: function(node) { - Polymer.removeEventListener(node, this.activateEvent, this.activateListener); - }, - - /** - * Returns the selected item(s). If the `multi` property is true, - * this will return an array, otherwise it will return - * the selected item or undefined if there is no selection. - */ - get selection() { - return this.$.selection.getSelection(); - }, - - selectedChanged: function() { - this.updateSelected(); - }, - - updateSelected: function() { - this.validateSelected(); - if (this.multi) { - this.clearSelection(); - this.selected && this.selected.forEach(function(s) { - this.valueToSelection(s); - }, this); - } else { - this.valueToSelection(this.selected); - } - }, - - validateSelected: function() { - // convert to an array for multi-selection - if (this.multi && !Array.isArray(this.selected) && - this.selected !== null && this.selected !== undefined) { - this.selected = [this.selected]; - } - }, - - clearSelection: function() { - if (this.multi) { - this.selection.slice().forEach(function(s) { - this.$.selection.setItemSelected(s, false); - }, this); - } else { - this.$.selection.setItemSelected(this.selection, false); - } - this.selectedItem = null; - this.$.selection.clear(); - }, - - valueToSelection: function(value) { - var item = (value === null || value === undefined) ? - null : this.items[this.valueToIndex(value)]; - this.$.selection.select(item); - }, - - updateSelectedItem: function() { - this.selectedItem = this.selection; - }, - - selectedItemChanged: function() { - if (this.selectedItem) { - var t = this.selectedItem.templateInstance; - this.selectedModel = t ? t.model : undefined; - } else { - this.selectedModel = null; - } - this.selectedIndex = this.selectedItem ? - parseInt(this.valueToIndex(this.selected)) : -1; - }, - - valueToIndex: function(value) { - // find an item with value == value and return it's index - for (var i=0, items=this.items, c; (c=items[i]); i++) { - if (this.valueForNode(c) == value) { - return i; - } - } - // if no item found, the value itself is probably the index - return value; - }, - - valueForNode: function(node) { - return node[this.valueattr] || node.getAttribute(this.valueattr); - }, - - // events fired from <core-selection> object - selectionSelect: function(e, detail) { - this.updateSelectedItem(); - if (detail.item) { - this.applySelection(detail.item, detail.isSelected); - } - }, - - applySelection: function(item, isSelected) { - if (this.selectedClass) { - item.classList.toggle(this.selectedClass, isSelected); - } - if (this.selectedProperty) { - item[this.selectedProperty] = isSelected; - } - if (this.selectedAttribute && item.setAttribute) { - if (isSelected) { - item.setAttribute(this.selectedAttribute, ''); - } else { - item.removeAttribute(this.selectedAttribute); - } - } - }, - - // event fired from host - activateHandler: function(e) { - if (!this.notap) { - var i = this.findDistributedTarget(e.target, this.items); - if (i >= 0) { - var item = this.items[i]; - var s = this.valueForNode(item) || i; - if (this.multi) { - if (this.selected) { - this.addRemoveSelected(s); - } else { - this.selected = [s]; - } - } else { - this.selected = s; - } - this.asyncFire('core-activate', {item: item}); - } - } - }, - - addRemoveSelected: function(value) { - var i = this.selected.indexOf(value); - if (i >= 0) { - this.selected.splice(i, 1); - } else { - this.selected.push(value); - } - this.valueToSelection(value); - }, - - findDistributedTarget: function(target, nodes) { - // find first ancestor of target (including itself) that - // is in nodes, if any - while (target && target != this) { - var i = Array.prototype.indexOf.call(nodes, target); - if (i >= 0) { - return i; - } - target = target.parentNode; - } - }, - - selectIndex: function(index) { - var item = this.items[index]; - if (item) { - this.selected = this.valueForNode(item) || index; - return item; - } - }, - - /** - * Selects the previous item. This should be used in single selection only. - * - * @method selectPrevious - * @param {boolean} wrap if true and it is already at the first item, wrap to the end - * @returns the previous item or undefined if there is none - */ - selectPrevious: function(wrap) { - var i = wrap && !this.selectedIndex ? this.items.length - 1 : this.selectedIndex - 1; - return this.selectIndex(i); - }, - - /** - * Selects the next item. This should be used in single selection only. - * - * @method selectNext - * @param {boolean} wrap if true and it is already at the last item, wrap to the front - * @returns the next item or undefined if there is none - */ - selectNext: function(wrap) { - var i = wrap && this.selectedIndex >= this.items.length - 1 ? 0 : this.selectedIndex + 1; - return this.selectIndex(i); - } - - }); - </script> -</polymer-element> - -<!-- -Copyright (c) 2014 The Polymer Project Authors. All rights reserved. -This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt -The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt -The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt -Code distributed by Google as part of the polymer project is also -subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt ---> - -<!-- -`paper-tab` is styled to look like a tab. It should be used in conjunction with -`paper-tabs`. - -Example: - - <paper-tabs selected="0"> - <paper-tab>TAB 1</paper-tab> - <paper-tab>TAB 2</paper-tab> - <paper-tab>TAB 3</paper-tab> - </paper-tabs> - -Styling tab: - -To change the ink color: - - .pink paper-tab::shadow #ink { - color: #ff4081; - } - -@group Paper Elements -@element paper-tab -@homepage github.io ---> - - - -<polymer-element name="paper-tab" attributes="noink" role="tab" assetpath="polymer/bower_components/paper-tabs/"> -<template> - - <style>/* -Copyright (c) 2014 The Polymer Project Authors. All rights reserved. -This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt -The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt -The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt -Code distributed by Google as part of the polymer project is also -subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt -*/ - -:host { - display: block; - position: relative; - overflow: hidden; -} - -#tabContainer { - position: absolute; - top: 0; - right: 0; - bottom: 0; - left: 0; -} - -.tab-content { - transition: opacity .1s cubic-bezier(0.4, 0.0, 1, 1), color .1s cubic-bezier(0.4, 0.0, 1, 1); - cursor: default; - pointer-events: none; -} - -:host(:not(.core-selected)) .tab-content { - opacity: 0.6; -} - -#ink { - position: absolute; - top: 0; - right: 0; - bottom: 0; - left: 0; - color: #ffff8d; -} - -:host[noink] #ink { - pointer-events: none; -} - -:host-context(paper-tabs[noink]) #ink { - pointer-events: none; -} -</style> - - <div id="tabContainer" center-justified="" center="" horizontal="" layout=""> - - <div class="tab-content"><content></content></div> - <paper-ripple id="ink" initialopacity="0.95" opacitydecayvelocity="0.98"></paper-ripple> - - </div> - -</template> -<script> - - Polymer('paper-tab', { - - /** - * If true, ink ripple effect is disabled. - * - * @attribute noink - * @type boolean - * @default false - */ - noink: false - - }); - -</script> -</polymer-element> - - -<polymer-element name="paper-tabs" extends="core-selector" attributes="noink nobar" role="tablist" assetpath="polymer/bower_components/paper-tabs/"> -<template> - - <style>/* -Copyright (c) 2014 The Polymer Project Authors. All rights reserved. -This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt -The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt -The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt -Code distributed by Google as part of the polymer project is also -subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt -*/ - -:host { - display: block; - position: relative; - font-size: 14px; - font-weight: 500; - height: 48px; - overflow: hidden; -} - -#tabsContainer { - position: absolute; - top: 0; - right: 0; - bottom: 0; - left: 0; - white-space: nowrap; -} - -#selectionBar { - position: absolute; - height: 2px; - bottom: 0; - left: 0; - width: 0; - background-color: #ffff8d; - transition: width, left; -} - -#selectionBar[hidden] { - display: hidden; -} - -#selectionBar.expand { - transition-duration: 0.15s; - transition-timing-function: cubic-bezier(0.4, 0.0, 1, 1); -} - -#selectionBar.contract { - transition-duration: 0.18s; - transition-timing-function: cubic-bezier(0.0, 0.0, 0.2, 1); -} - -polyfill-next-selector { content: '#tabsContainer > *:not(#selectionBar)'; } -::content > * { - -ms-flex: 1; - -webkit-flex: 1; - flex: 1; -} -</style> - - <div id="tabsContainer" horizontal="" layout=""> - - <shadow></shadow> - <div id="selectionBar" hidden?="{{nobar}}" on-transitionend="{{barTransitionEnd}}"></div> - - </div> - -</template> -<script> - - Polymer('paper-tabs', { - - /** - * If true, ink effect is disabled. - * - * @attribute noink - * @type boolean - * @default false - */ - noink: false, - - /** - * If true, the bottom bar to indicate the selected tab will not be shown. - * - * @attribute nobar - * @type boolean - * @default false - */ - nobar: false, - - activateEvent: 'down', - - nostretch: false, - - selectedIndexChanged: function(old) { - var s = this.$.selectionBar.style; - - if (!this.selectedItem) { - s.width = 0; - s.left = 0; - return; - } - - var w = 100 / this.items.length; - - if (this.nostretch || old === null || old === -1) { - s.width = w + '%'; - s.left = this.selectedIndex * w + '%'; - return; - } - - var m = 5; - this.$.selectionBar.classList.add('expand'); - if (old < this.selectedIndex) { - s.width = w + w * (this.selectedIndex - old) - m + '%'; - this._transitionCounter = 1; - } else { - s.width = w + w * (old - this.selectedIndex) - m + '%'; - s.left = this.selectedIndex * w + m + '%'; - this._transitionCounter = 2; - } - }, - - barTransitionEnd: function(e) { - this._transitionCounter--; - var cl = this.$.selectionBar.classList; - if (cl.contains('expand') && !this._transitionCounter) { - cl.remove('expand'); - cl.add('contract'); - var s = this.$.selectionBar.style; - var w = 100 / this.items.length; - s.width = w + '%'; - s.left = this.selectedIndex * w + '%'; - } else if (cl.contains('contract')) { - cl.remove('contract'); - } - } - - }); - -</script> -</polymer-element> - - - - -<!-- -Copyright (c) 2014 The Polymer Project Authors. All rights reserved. -This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt -The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt -The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt -Code distributed by Google as part of the polymer project is also -subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt ---> - -<!-- -@group Polymer Core Elements - -The `core-ajax` element exposes `XMLHttpRequest` functionality. - - <core-ajax - auto - url="http://gdata.youtube.com/feeds/api/videos/" - params='{"alt":"json", "q":"chrome"}' - handleAs="json" - on-core-response="{{handleResponse}}"></core-ajax> - -With `auto` set to `true`, the element performs a request whenever -its `url` or `params` properties are changed. - -Note: The `params` attribute must be double quoted JSON. - -You can trigger a request explicitly by calling `go` on the -element. - -@element core-ajax -@status beta -@homepage github.io ---> -<!-- -Copyright (c) 2014 The Polymer Project Authors. All rights reserved. -This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt -The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt -The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt -Code distributed by Google as part of the polymer project is also -subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt ---> -<!-- -/** - * @group Polymer Core Elements - * - * core-xhr can be used to perform XMLHttpRequests. - * - * <core-xhr id="xhr"></core-xhr> - * ... - * this.$.xhr.request({url: url, params: params, callback: callback}); - * - * @element core-xhr - */ ---> - - - -<polymer-element name="core-xhr" hidden assetpath="polymer/bower_components/core-ajax/"> - - <script> - - Polymer('core-xhr', { - - /** - * Sends a HTTP request to the server and returns the XHR object. - * - * @method request - * @param {Object} inOptions - * @param {String} inOptions.url The url to which the request is sent. - * @param {String} inOptions.method The HTTP method to use, default is GET. - * @param {boolean} inOptions.sync By default, all requests are sent asynchronously. To send synchronous requests, set to true. - * @param {Object} inOptions.params Data to be sent to the server. - * @param {Object} inOptions.body The content for the request body for POST method. - * @param {Object} inOptions.headers HTTP request headers. - * @param {String} inOptions.responseType The response type. Default is 'text'. - * @param {boolean} inOptions.withCredentials Whether or not to send credentials on the request. Default is false. - * @param {Object} inOptions.callback Called when request is completed. - * @returns {Object} XHR object. - */ - request: function(options) { - var xhr = new XMLHttpRequest(); - var url = options.url; - var method = options.method || 'GET'; - var async = !options.sync; - // - var params = this.toQueryString(options.params); - if (params && method == 'GET') { - url += (url.indexOf('?') > 0 ? '&' : '?') + params; - } - var xhrParams = this.isBodyMethod(method) ? (options.body || params) : null; - // - xhr.open(method, url, async); - if (options.responseType) { - xhr.responseType = options.responseType; - } - if (options.withCredentials) { - xhr.withCredentials = true; - } - this.makeReadyStateHandler(xhr, options.callback); - this.setRequestHeaders(xhr, options.headers); - xhr.send(xhrParams); - if (!async) { - xhr.onreadystatechange(xhr); - } - return xhr; - }, - - toQueryString: function(params) { - var r = []; - for (var n in params) { - var v = params[n]; - n = encodeURIComponent(n); - r.push(v == null ? n : (n + '=' + encodeURIComponent(v))); - } - return r.join('&'); - }, - - isBodyMethod: function(method) { - return this.bodyMethods[(method || '').toUpperCase()]; - }, - - bodyMethods: { - POST: 1, - PUT: 1, - DELETE: 1 - }, - - makeReadyStateHandler: function(xhr, callback) { - xhr.onreadystatechange = function() { - if (xhr.readyState == 4) { - callback && callback.call(null, xhr.response, xhr); - } - }; - }, - - setRequestHeaders: function(xhr, headers) { - if (headers) { - for (var name in headers) { - xhr.setRequestHeader(name, headers[name]); - } - } - } - - }); - - </script> - -</polymer-element> - -<polymer-element name="core-ajax" hidden attributes="url handleAs auto params response error method headers body contentType withCredentials" assetpath="polymer/bower_components/core-ajax/"> -<script> - - Polymer('core-ajax', { - /** - * Fired when a response is received. - * - * @event core-response - */ - - /** - * Fired when an error is received. - * - * @event core-error - */ - - /** - * Fired whenever a response or an error is received. - * - * @event core-complete - */ - - /** - * The URL target of the request. - * - * @attribute url - * @type string - * @default '' - */ - url: '', - - /** - * Specifies what data to store in the `response` property, and - * to deliver as `event.response` in `response` events. - * - * One of: - * - * `text`: uses `XHR.responseText`. - * - * `xml`: uses `XHR.responseXML`. - * - * `json`: uses `XHR.responseText` parsed as JSON. - * - * `arraybuffer`: uses `XHR.response`. - * - * `blob`: uses `XHR.response`. - * - * `document`: uses `XHR.response`. - * - * @attribute handleAs - * @type string - * @default 'text' - */ - handleAs: '', - - /** - * If true, automatically performs an Ajax request when either `url` or `params` changes. - * - * @attribute auto - * @type boolean - * @default false - */ - auto: false, - - /** - * Parameters to send to the specified URL, as JSON. - * - * @attribute params - * @type string (JSON) - * @default '' - */ - params: '', - - /** - * The response for the most recently made request, or null if it hasn't - * completed yet or the request resulted in error. - * - * @attribute response - * @type Object - * @default null - */ - response: null, - - /** - * The error for the most recently made request, or null if it hasn't - * completed yet or the request resulted in success. - * - * @attribute error - * @type Object - * @default null - */ - error: null, - - /** - * The HTTP method to use such as 'GET', 'POST', 'PUT', or 'DELETE'. - * Default is 'GET'. - * - * @attribute method - * @type string - * @default '' - */ - method: '', - - /** - * HTTP request headers to send. - * - * Example: - * - * <core-ajax - * auto - * url="http://somesite.com" - * headers='{"X-Requested-With": "XMLHttpRequest"}' - * handleAs="json" - * on-core-response="{{handleResponse}}"></core-ajax> - * - * @attribute headers - * @type Object - * @default null - */ - headers: null, - - /** - * Optional raw body content to send when method === "POST". - * - * Example: - * - * <core-ajax method="POST" auto url="http://somesite.com" - * body='{"foo":1, "bar":2}'> - * </core-ajax> - * - * @attribute body - * @type Object - * @default null - */ - body: null, - - /** - * Content type to use when sending data. - * - * @attribute contentType - * @type string - * @default 'application/x-www-form-urlencoded' - */ - contentType: 'application/x-www-form-urlencoded', - - /** - * Set the withCredentials flag on the request. - * - * @attribute withCredentials - * @type boolean - * @default false - */ - withCredentials: false, - - /** - * Additional properties to send to core-xhr. - * - * Can be set to an object containing default properties - * to send as arguments to the `core-xhr.request()` method - * which implements the low-level communication. - * - * @property xhrArgs - * @type Object - * @default null - */ - xhrArgs: null, - - ready: function() { - this.xhr = document.createElement('core-xhr'); - }, - - receive: function(response, xhr) { - if (this.isSuccess(xhr)) { - this.processResponse(xhr); - } else { - this.processError(xhr); - } - this.complete(xhr); - }, - - isSuccess: function(xhr) { - var status = xhr.status || 0; - return !status || (status >= 200 && status < 300); - }, - - processResponse: function(xhr) { - var response = this.evalResponse(xhr); - if (xhr === this.activeRequest) { - this.response = response; - } - this.fire('core-response', {response: response, xhr: xhr}); - }, - - processError: function(xhr) { - var response = xhr.status + ': ' + xhr.responseText; - if (xhr === this.activeRequest) { - this.error = response; - } - this.fire('core-error', {response: response, xhr: xhr}); - }, - - complete: function(xhr) { - this.fire('core-complete', {response: xhr.status, xhr: xhr}); - }, - - evalResponse: function(xhr) { - return this[(this.handleAs || 'text') + 'Handler'](xhr); - }, - - xmlHandler: function(xhr) { - return xhr.responseXML; - }, - - textHandler: function(xhr) { - return xhr.responseText; - }, - - jsonHandler: function(xhr) { - var r = xhr.responseText; - try { - return JSON.parse(r); - } catch (x) { - console.warn('core-ajax caught an exception trying to parse response as JSON:'); - console.warn('url:', this.url); - console.warn(x); - return r; - } - }, - - documentHandler: function(xhr) { - return xhr.response; - }, - - blobHandler: function(xhr) { - return xhr.response; - }, - - arraybufferHandler: function(xhr) { - return xhr.response; - }, - - urlChanged: function() { - if (!this.handleAs) { - var ext = String(this.url).split('.').pop(); - switch (ext) { - case 'json': - this.handleAs = 'json'; - break; - } - } - this.autoGo(); - }, - - paramsChanged: function() { - this.autoGo(); - }, - - autoChanged: function() { - this.autoGo(); - }, - - // TODO(sorvell): multiple side-effects could call autoGo - // during one micro-task, use a job to have only one action - // occur - autoGo: function() { - if (this.auto) { - this.goJob = this.job(this.goJob, this.go, 0); - } - }, - - /** - * Performs an Ajax request to the specified URL. - * - * @method go - */ - go: function() { - var args = this.xhrArgs || {}; - // TODO(sjmiles): we may want XHR to default to POST if body is set - args.body = this.body || args.body; - args.params = this.params || args.params; - if (args.params && typeof(args.params) == 'string') { - args.params = JSON.parse(args.params); - } - args.headers = this.headers || args.headers || {}; - if (args.headers && typeof(args.headers) == 'string') { - args.headers = JSON.parse(args.headers); - } - var hasContentType = Object.keys(args.headers).some(function (header) { - return header.toLowerCase() === 'content-type'; - }); - if (!hasContentType && this.contentType) { - args.headers['Content-Type'] = this.contentType; - } - if (this.handleAs === 'arraybuffer' || this.handleAs === 'blob' || - this.handleAs === 'document') { - args.responseType = this.handleAs; - } - args.withCredentials = this.withCredentials; - args.callback = this.receive.bind(this); - args.url = this.url; - args.method = this.method; - - this.response = this.error = null; - this.activeRequest = args.url && this.xhr.request(args); - return this.activeRequest; - } - - }); - -</script> -</polymer-element> - -<!-- -Copyright (c) 2014 The Polymer Project Authors. All rights reserved. -This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt -The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt -The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt -Code distributed by Google as part of the polymer project is also -subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt ---> - -<!-- -`paper-toast` provides lightweight feedback about an operation in a small popup -at the base of the screen on mobile and at the lower left on desktop. Toasts are -above all other elements on screen, including the FAB. - -Toasts automatically disappear after a timeout or after user interaction -elsewhere on the screen, whichever comes first. Toasts can be swiped off -screen. There can be only one on the screen at a time. - -Example: - - <paper-toast text="Your draft has been discarded." onclick="discardDraft(el)"></paper-toast> - - <script> - function discardDraft(el) { - el.show(); - } - </script> - -An action button can be presented in the toast. - -Example (using Polymer's data-binding features): - - <paper-toast id="toast2" text="Connection timed out. Showing limited messages."> - <div style="color: blue;" on-tap="{{retry}}">Retry</div> - </paper-toast> - -Positioning toast: - -A standard toast appears near the lower left of the screen. You can change the -position by overriding bottom and left positions. - - paper-toast { - bottom: 40px; - left: 10px; - } - -To make it fit at the bottom of the screen: - - paper-toast { - bottom: 0; - left: 0; - width: 100%; - } - -When the screen size is smaller than the `responsiveWidth` (default to 480px), -the toast will automatically fits at the bottom of the screen. - -@group Paper Elements -@element paper-toast -@homepage github.io ---> - -<!-- -Copyright (c) 2014 The Polymer Project Authors. All rights reserved. -This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt -The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt -The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt -Code distributed by Google as part of the polymer project is also -subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt ---> - - -<!-- -Copyright (c) 2014 The Polymer Project Authors. All rights reserved. -This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt -The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt -The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt -Code distributed by Google as part of the polymer project is also -subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt ---> - -<!-- - -`<core-transition>` is an abstraction of an animation. It is used to implement pluggable -transitions, for example in `<core-overlay>`. You can extend this class to create a custom -animation, instantiate it, and import it where you need the animation. - -All instances of `<core-transition>` are stored in a single database with `type=transition`. -For more about the database, please see the documentation for `<core-meta>`. - -Each instance of `<core-transition>` objects are shared across all the clients, so you should -not store state information specific to the animated element in the transition. Rather, store -it on the element. - -Example: - -my-transition.html: - - <polymer-element name="my-transition" extends="core-transition"> - <script> - go: function(node) { - node.style.transition = 'opacity 1s ease-out'; - node.style.opacity = 0; - } - </script> - </polymer-element> - - <my-transition id="my-fade-out"></my-transition> - -my-transition-demo.html: - - <link href="components/core-meta/core-meta.html" rel="import"> - <link href="my-transition.html" rel="import"> - - <div id="animate-me"></div> - - <script> - // Get the core-transition - var meta = document.createElement('core-meta'); - meta.type = 'transition'; - var transition = meta.byId('my-fade-out'); - - // Run the animation - var animated = document.getElementById('animate-me'); - transition.go(animated); - </script> - -@group Polymer Core Elements -@element core-transition -@extends core-meta -@status beta -@homepage github.io ---> -<!-- -Fired when the animation finishes. - -@event core-transitionend -@param {Object} detail -@param {Object} detail.node The animated node ---> - - - -<polymer-element name="core-transition" extends="core-meta" assetpath="polymer/bower_components/core-transition/"> - - <script> - Polymer('core-transition', { - - type: 'transition', - - /** - * Run the animation. - * - * @method go - * @param {Node} node The node to apply the animation on - * @param {Object} state State info - */ - go: function(node, state) { - this.complete(node); - }, - - /** - * Set up the animation. This may include injecting a stylesheet, - * applying styles, creating a web animations object, etc.. This - * - * @method setup - * @param {Node} node The animated node - */ - setup: function(node) { - }, - - /** - * Tear down the animation. - * - * @method teardown - * @param {Node} node The animated node - */ - teardown: function(node) { - }, - - /** - * Called when the animation completes. This function also fires the - * `core-transitionend` event. - * - * @method complete - * @param {Node} node The animated node - */ - complete: function(node) { - this.fire('core-transitionend', null, node); - }, - - /** - * Utility function to listen to an event on a node once. - * - * @method listenOnce - * @param {Node} node The animated node - * @param {string} event Name of an event - * @param {Function} fn Event handler - * @param {Array} args Additional arguments to pass to `fn` - */ - listenOnce: function(node, event, fn, args) { - var self = this; - var listener = function() { - fn.apply(self, args); - node.removeEventListener(event, listener, false); - } - node.addEventListener(event, listener, false); - } - - }); - </script> -</polymer-element> -<!-- -Copyright (c) 2014 The Polymer Project Authors. All rights reserved. -This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt -The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt -The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt -Code distributed by Google as part of the polymer project is also -subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt ---> - - - -<polymer-element name="core-key-helper" assetpath="polymer/bower_components/core-overlay/"> - <script> - Polymer('core-key-helper', { - ENTER_KEY: 13, - ESCAPE_KEY: 27 - }); - </script> -</polymer-element> - -<!-- -Copyright (c) 2014 The Polymer Project Authors. All rights reserved. -This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt -The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt -The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt -Code distributed by Google as part of the polymer project is also -subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt ---> - -<polymer-element name="core-overlay-layer" assetpath="polymer/bower_components/core-overlay/"> -<template> - <style> - :host { - position: fixed; - top: 0; - left: 0; - z-index: 1000; - display: none; - } - - :host(.core-opened) { - display: block; - } - </style> - <content></content> -</template> -<script> -(function() { - - Polymer('core-overlay-layer', { - publish: { - opened: false - }, - openedChanged: function() { - this.classList.toggle('core-opened', this.opened); - }, - /** - * Adds an element to the overlay layer - */ - addElement: function(element) { - if (!this.parentNode) { - document.querySelector('body').appendChild(this); - } - if (element.parentNode !== this) { - element.__contents = []; - var ip$ = element.querySelectorAll('content'); - for (var i=0, l=ip$.length, n; (i<l) && (n = ip$[i]); i++) { - this.moveInsertedElements(n); - this.cacheDomLocation(n); - n.parentNode.removeChild(n); - element.__contents.push(n); - } - this.cacheDomLocation(element); - this.updateEventController(element); - var h = this.makeHost(); - h.shadowRoot.appendChild(element); - element.__host = h; - } - }, - makeHost: function() { - var h = document.createElement('overlay-host'); - h.createShadowRoot(); - this.appendChild(h); - return h; - }, - moveInsertedElements: function(insertionPoint) { - var n$ = insertionPoint.getDistributedNodes(); - var parent = insertionPoint.parentNode; - insertionPoint.__contents = []; - for (var i=0, l=n$.length, n; (i<l) && (n=n$[i]); i++) { - this.cacheDomLocation(n); - this.updateEventController(n); - insertionPoint.__contents.push(n); - parent.appendChild(n); - } - }, - updateEventController: function(element) { - element.eventController = this.element.findController(element); - }, - /** - * Removes an element from the overlay layer - */ - removeElement: function(element) { - element.eventController = null; - this.replaceElement(element); - var h = element.__host; - if (h) { - h.parentNode.removeChild(h); - } - }, - replaceElement: function(element) { - if (element.__contents) { - for (var i=0, c$=element.__contents, c; (c=c$[i]); i++) { - this.replaceElement(c); - } - element.__contents = null; - } - if (element.__parentNode) { - var n = element.__nextElementSibling && element.__nextElementSibling - === element.__parentNode ? element.__nextElementSibling : null; - element.__parentNode.insertBefore(element, n); - } - }, - cacheDomLocation: function(element) { - element.__nextElementSibling = element.nextElementSibling; - element.__parentNode = element.parentNode; - } - }); - -})(); -</script> -</polymer-element> - - -<!-- -The `core-overlay` element displays overlayed on top of other content. It starts -out hidden and is displayed by setting its `opened` property to true. -A `core-overlay's` opened state can be toggled by calling the `toggle` -method. - -The `core-overlay` will, by default, show/hide itself when it's opened. The -`target` property may be set to another element to cause that element to -be shown when the overlay is opened. - -It's common to want a `core-overlay` to animate to its opened -position. The `core-overlay` element uses a `core-transition` to handle -animation. The default transition is `core-transition-fade` which -causes the overlay to fade in when displayed. See -<a href="../core-transition/">`core-transition`</a> for more -information about customizing a `core-overlay's` opening animation. The -`backdrop` property can be set to true to show a backdrop behind the overlay -that will darken the rest of the window. - -An element that should close the `core-overlay` will automatically -do so if it's given the `core-overlay-toggle` attribute. This attribute -can be customized with the `closeAttribute` property. You can also use -`closeSelector` if more general matching is needed. - -By default `core-overlay` will close whenever the user taps outside it or -presses the escape key. This behavior can be turned off via the -`autoCloseDisabled` property. - - <core-overlay> - <h2>Dialog</h2> - <input placeholder="say something..." autofocus> - <div>I agree with this wholeheartedly.</div> - <button core-overlay-toggle>OK</button> - </core-overlay> - -`core-overlay` will automatically size and position itself according to the -following rules. The overlay's size is constrained such that it does not -overflow the screen. This is done by setting maxHeight/maxWidth on the -`sizingTarget`. If the `sizingTarget` already has a setting for one of these -properties, it will not be overridden. The overlay should -be positioned via css or imperatively using the `core-overlay-position` event. -If the overlay is not positioned vertically via setting `top` or `bottom`, it -will be centered vertically. The same is true horizontally via a setting to -`left` or `right`. In addition, css `margin` can be used to provide some space -around the overlay. This can be used to ensure -that, for example, a drop shadow is always visible around the overlay. - -@group Core Elements -@element core-overlay -@homepage github.io ---> -<!-- -Fired when the `core-overlay`'s `opened` property changes. - -@event core-overlay-open -@param {Object} detail -@param {Object} detail.opened the opened state ---> -<!-- -Fired when the `core-overlay` has completely opened. - -@event core-overlay-open-completed ---> -<!-- -Fired when the `core-overlay` has completely closed. - -@event core-overlay-close-completed ---> -<!-- -Fired when the `core-overlay` needs to position itself. Optionally, implement -in order to position an overlay via code. If the overlay was not otherwise -positioned, it's important to indicate how the overlay has been positioned by -setting the `dimensions.position` object. For example, if the overlay has been -positioned via setting `right` and `top`, set dimensions.position to an -object like this: `{v: 'top', h: 'right'}`. - -@event core-overlay-position -@param {Object} detail -@param {Object} detail.target the overlay target -@param {Object} detail.sizingTarget the overlay sizing target -@param {Object} detail.opened the opened state ---> -<style> - .core-overlay-backdrop { - position: fixed; - top: 0; - left: 0; - width: 100vw; - height: 100vh; - background-color: black; - opacity: 0; - transition: opacity 0.2s; - } - - .core-overlay-backdrop.core-opened { - opacity: 0.6; - } -</style> - -<polymer-element name="core-overlay" assetpath="polymer/bower_components/core-overlay/"> -<script> -(function() { - - Polymer('core-overlay', { - - publish: { - /** - * The target element that will be shown when the overlay is - * opened. If unspecified, the core-overlay itself is the target. - * - * @attribute target - * @type Object - * @default the overlay element - */ - target: null, - - - /** - * A `core-overlay`'s size is guaranteed to be - * constrained to the window size. To achieve this, the sizingElement - * is sized with a max-height/width. By default this element is the - * target element, but it can be specifically set to a specific element - * inside the target if that is more appropriate. This is useful, for - * example, when a region inside the overlay should scroll if needed. - * - * @attribute sizingTarget - * @type Object - * @default the target element - */ - sizingTarget: null, - - /** - * Set opened to true to show an overlay and to false to hide it. - * A `core-overlay` may be made initially opened by setting its - * `opened` attribute. - * @attribute opened - * @type boolean - * @default false - */ - opened: false, - - /** - * If true, the overlay has a backdrop darkening the rest of the screen. - * The backdrop element is attached to the document body and may be styled - * with the class `core-overlay-backdrop`. When opened the `core-opened` - * class is applied. - * - * @attribute backdrop - * @type boolean - * @default false - */ - backdrop: false, - - /** - * If true, the overlay is guaranteed to display above page content. - * - * @attribute layered - * @type boolean - * @default false - */ - layered: false, - - /** - * By default an overlay will close automatically if the user - * taps outside it or presses the escape key. Disable this - * behavior by setting the `autoCloseDisabled` property to true. - * @attribute autoCloseDisabled - * @type boolean - * @default false - */ - autoCloseDisabled: false, - - /** - * By default an overlay will focus its target or an element inside - * it with the `autoFocus` attribute. Disable this - * behavior by setting the `autoFocusDisabled` property to true. - * @attribute autoFocusDisabled - * @type boolean - * @default false - */ - autoFocusDisabled: false, - - /** - * This property specifies an attribute on elements that should - * close the overlay on tap. Should not set `closeSelector` if this - * is set. - * - * @attribute closeAttribute - * @type string - * @default "core-overlay-toggle" - */ - closeAttribute: 'core-overlay-toggle', - - /** - * This property specifies a selector matching elements that should - * close the overlay on tap. Should not set `closeAttribute` if this - * is set. - * - * @attribute closeSelector - * @type string - * @default "" - */ - closeSelector: '', - - /** - * The transition property specifies a string which identifies a - * <a href="../core-transition/">`core-transition`</a> element that - * will be used to help the overlay open and close. The default - * `core-transition-fade` will cause the overlay to fade in and out. - * - * @attribute transition - * @type string - * @default 'core-transition-fade' - */ - transition: 'core-transition-fade' - - }, - - captureEventName: 'tap', - targetListeners: { - 'tap': 'tapHandler', - 'keydown': 'keydownHandler', - 'core-transitionend': 'transitionend' - }, - - registerCallback: function(element) { - this.layer = document.createElement('core-overlay-layer'); - this.keyHelper = document.createElement('core-key-helper'); - this.meta = document.createElement('core-transition'); - this.scrim = document.createElement('div'); - this.scrim.className = 'core-overlay-backdrop'; - }, - - ready: function() { - this.target = this.target || this; - // flush to ensure styles are installed before paint - Platform.flush(); - }, - - /** - * Toggle the opened state of the overlay. - * @method toggle - */ - toggle: function() { - this.opened = !this.opened; - }, - - /** - * Open the overlay. This is equivalent to setting the `opened` - * property to true. - * @method open - */ - open: function() { - this.opened = true; - }, - - /** - * Close the overlay. This is equivalent to setting the `opened` - * property to false. - * @method close - */ - close: function() { - this.opened = false; - }, - - domReady: function() { - this.ensureTargetSetup(); - }, - - targetChanged: function(old) { - if (this.target) { - // really make sure tabIndex is set - if (this.target.tabIndex < 0) { - this.target.tabIndex = -1; - } - this.addElementListenerList(this.target, this.targetListeners); - this.target.style.display = 'none'; - this.target.__overlaySetup = false; - } - if (old) { - this.removeElementListenerList(old, this.targetListeners); - var transition = this.getTransition(); - if (transition) { - transition.teardown(old); - } else { - old.style.position = ''; - old.style.outline = ''; - } - old.style.display = ''; - } - }, - - transitionChanged: function(old) { - if (!this.target) { - return; - } - if (old) { - this.getTransition(old).teardown(this.target); - } - this.target.__overlaySetup = false; - }, - - // NOTE: wait to call this until we're as sure as possible that target - // is styled. - ensureTargetSetup: function() { - if (!this.target || this.target.__overlaySetup) { - return; - } - if (!this.sizingTarget) { - this.sizingTarget = this.target; - } - this.target.__overlaySetup = true; - this.target.style.display = ''; - var transition = this.getTransition(); - if (transition) { - transition.setup(this.target); - } - var style = this.target.style; - var computed = getComputedStyle(this.target); - if (computed.position === 'static') { - style.position = 'fixed'; - } - style.outline = 'none'; - style.display = 'none'; - }, - - openedChanged: function() { - this.transitioning = true; - this.ensureTargetSetup(); - this.prepareRenderOpened(); - // async here to allow overlay layer to become visible. - this.async(function() { - this.target.style.display = ''; - // force layout to ensure transitions will go - this.target.offsetWidth; - this.renderOpened(); - }); - this.fire('core-overlay-open', this.opened); - }, - - // tasks which must occur before opening; e.g. making the element visible - prepareRenderOpened: function() { - if (this.opened) { - addOverlay(this); - } - this.prepareBackdrop(); - // async so we don't auto-close immediately via a click. - this.async(function() { - if (!this.autoCloseDisabled) { - this.enableElementListener(this.opened, document, - this.captureEventName, 'captureHandler', true); - } - }); - this.enableElementListener(this.opened, window, 'resize', - 'resizeHandler'); - - if (this.opened) { - // force layout so SD Polyfill renders - this.target.offsetHeight; - this.discoverDimensions(); - // if we are showing, then take care when positioning - this.preparePositioning(); - this.positionTarget(); - this.updateTargetDimensions(); - this.finishPositioning(); - if (this.layered) { - this.layer.addElement(this.target); - this.layer.opened = this.opened; - } - } - }, - - // tasks which cause the overlay to actually open; typically play an - // animation - renderOpened: function() { - var transition = this.getTransition(); - if (transition) { - transition.go(this.target, {opened: this.opened}); - } else { - this.transitionend(); - } - this.renderBackdropOpened(); - }, - - // finishing tasks; typically called via a transition - transitionend: function(e) { - // make sure this is our transition event. - if (e && e.target !== this.target) { - return; - } - this.transitioning = false; - if (!this.opened) { - this.resetTargetDimensions(); - this.target.style.display = 'none'; - this.completeBackdrop(); - removeOverlay(this); - if (this.layered) { - if (!currentOverlay()) { - this.layer.opened = this.opened; - } - this.layer.removeElement(this.target); - } - } - this.fire('core-overlay-' + (this.opened ? 'open' : 'close') + - '-completed'); - this.applyFocus(); - }, - - prepareBackdrop: function() { - if (this.backdrop && this.opened) { - if (!this.scrim.parentNode) { - document.body.appendChild(this.scrim); - this.scrim.style.zIndex = currentOverlayZ() - 1; - } - trackBackdrop(this); - } - }, - - renderBackdropOpened: function() { - if (this.backdrop && getBackdrops().length < 2) { - this.scrim.classList.toggle('core-opened', this.opened); - } - }, - - completeBackdrop: function() { - if (this.backdrop) { - trackBackdrop(this); - if (getBackdrops().length === 0) { - this.scrim.parentNode.removeChild(this.scrim); - } - } - }, - - preparePositioning: function() { - this.target.style.transition = this.target.style.webkitTransition = 'none'; - this.target.style.transform = this.target.style.webkitTransform = 'none'; - this.target.style.display = ''; - }, - - discoverDimensions: function() { - if (this.dimensions) { - return; - } - var target = getComputedStyle(this.target); - var sizer = getComputedStyle(this.sizingTarget); - this.dimensions = { - position: { - v: target.top !== 'auto' ? 'top' : (target.bottom !== 'auto' ? - 'bottom' : null), - h: target.left !== 'auto' ? 'left' : (target.right !== 'auto' ? - 'right' : null), - css: target.position - }, - size: { - v: sizer.maxHeight !== 'none', - h: sizer.maxWidth !== 'none' - }, - margin: { - top: parseInt(target.marginTop) || 0, - right: parseInt(target.marginRight) || 0, - bottom: parseInt(target.marginBottom) || 0, - left: parseInt(target.marginLeft) || 0 - } - }; - }, - - finishPositioning: function(target) { - this.target.style.display = 'none'; - this.target.style.transform = this.target.style.webkitTransform = ''; - // force layout to avoid application of transform - this.target.offsetWidth; - this.target.style.transition = this.target.style.webkitTransition = ''; - }, - - getTransition: function(name) { - return this.meta.byId(name || this.transition); - }, - - getFocusNode: function() { - return this.target.querySelector('[autofocus]') || this.target; - }, - - applyFocus: function() { - var focusNode = this.getFocusNode(); - if (this.opened) { - if (!this.autoFocusDisabled) { - focusNode.focus(); - } - } else { - focusNode.blur(); - if (currentOverlay() == this) { - console.warn('Current core-overlay is attempting to focus itself as next! (bug)'); - } else { - focusOverlay(); - } - } - }, - - positionTarget: function() { - // fire positioning event - this.fire('core-overlay-position', {target: this.target, - sizingTarget: this.sizingTarget, opened: this.opened}); - if (!this.dimensions.position.v) { - this.target.style.top = '0px'; - } - if (!this.dimensions.position.h) { - this.target.style.left = '0px'; - } - }, - - updateTargetDimensions: function() { - this.sizeTarget(); - this.repositionTarget(); - }, - - sizeTarget: function() { - this.sizingTarget.style.boxSizing = 'border-box'; - var dims = this.dimensions; - var rect = this.target.getBoundingClientRect(); - if (!dims.size.v) { - this.sizeDimension(rect, dims.position.v, 'top', 'bottom', 'Height'); - } - if (!dims.size.h) { - this.sizeDimension(rect, dims.position.h, 'left', 'right', 'Width'); - } - }, - - sizeDimension: function(rect, positionedBy, start, end, extent) { - var dims = this.dimensions; - var flip = (positionedBy === end); - var m = flip ? start : end; - var ws = window['inner' + extent]; - var o = dims.margin[m] + (flip ? ws - rect[end] : - rect[start]); - var offset = 'offset' + extent; - var o2 = this.target[offset] - this.sizingTarget[offset]; - this.sizingTarget.style['max' + extent] = (ws - o - o2) + 'px'; - }, - - // vertically and horizontally center if not positioned - repositionTarget: function() { - // only center if position fixed. - if (this.dimensions.position.css !== 'fixed') { - return; - } - if (!this.dimensions.position.v) { - var t = (window.innerHeight - this.target.offsetHeight) / 2; - t -= this.dimensions.margin.top; - this.target.style.top = t + 'px'; - } - - if (!this.dimensions.position.h) { - var l = (window.innerWidth - this.target.offsetWidth) / 2; - l -= this.dimensions.margin.left; - this.target.style.left = l + 'px'; - } - }, - - resetTargetDimensions: function() { - if (!this.dimensions.size.v) { - this.sizingTarget.style.maxHeight = ''; - } - if (!this.dimensions.size.h) { - this.sizingTarget.style.maxWidth = ''; - } - this.dimensions = null; - }, - - tapHandler: function(e) { - // closeSelector takes precedence since closeAttribute has a default non-null value. - if (e.target && - (this.closeSelector && e.target.matches(this.closeSelector)) || - (this.closeAttribute && e.target.hasAttribute(this.closeAttribute))) { - this.toggle(); - } else { - if (this.autoCloseJob) { - this.autoCloseJob.stop(); - this.autoCloseJob = null; - } - } - }, - - // We use the traditional approach of capturing events on document - // to to determine if the overlay needs to close. However, due to - // ShadowDOM event retargeting, the event target is not useful. Instead - // of using it, we attempt to close asynchronously and prevent the close - // if a tap event is immediately heard on the target. - // TODO(sorvell): This approach will not work with modal. For - // this we need a scrim. - captureHandler: function(e) { - if (!this.autoCloseDisabled && (currentOverlay() == this)) { - this.autoCloseJob = this.job(this.autoCloseJob, function() { - this.close(); - }); - } - }, - - keydownHandler: function(e) { - if (!this.autoCloseDisabled && (e.keyCode == this.keyHelper.ESCAPE_KEY)) { - this.close(); - e.stopPropagation(); - } - }, - - /** - * Extensions of core-overlay should implement the `resizeHandler` - * method to adjust the size and position of the overlay when the - * browser window resizes. - * @method resizeHandler - */ - resizeHandler: function() { - this.updateTargetDimensions(); - }, - - // TODO(sorvell): these utility methods should not be here. - addElementListenerList: function(node, events) { - for (var i in events) { - this.addElementListener(node, i, events[i]); - } - }, - - removeElementListenerList: function(node, events) { - for (var i in events) { - this.removeElementListener(node, i, events[i]); - } - }, - - enableElementListener: function(enable, node, event, methodName, capture) { - if (enable) { - this.addElementListener(node, event, methodName, capture); - } else { - this.removeElementListener(node, event, methodName, capture); - } - }, - - addElementListener: function(node, event, methodName, capture) { - var fn = this._makeBoundListener(methodName); - if (node && fn) { - Polymer.addEventListener(node, event, fn, capture); - } - }, - - removeElementListener: function(node, event, methodName, capture) { - var fn = this._makeBoundListener(methodName); - if (node && fn) { - Polymer.removeEventListener(node, event, fn, capture); - } - }, - - _makeBoundListener: function(methodName) { - var self = this, method = this[methodName]; - if (!method) { - return; - } - var bound = '_bound' + methodName; - if (!this[bound]) { - this[bound] = function(e) { - method.call(self, e); - }; - } - return this[bound]; - }, - }); - - // TODO(sorvell): This should be an element with private state so it can - // be independent of overlay. - // track overlays for z-index and focus managemant - var overlays = []; - function addOverlay(overlay) { - var z0 = currentOverlayZ(); - overlays.push(overlay); - var z1 = currentOverlayZ(); - if (z1 <= z0) { - applyOverlayZ(overlay, z0); - } - } - - function removeOverlay(overlay) { - var i = overlays.indexOf(overlay); - if (i >= 0) { - overlays.splice(i, 1); - setZ(overlay, ''); - } - } - - function applyOverlayZ(overlay, aboveZ) { - setZ(overlay.target, aboveZ + 2); - } - - function setZ(element, z) { - element.style.zIndex = z; - } - - function currentOverlay() { - return overlays[overlays.length-1]; - } - - var DEFAULT_Z = 10; - - function currentOverlayZ() { - var z; - var current = currentOverlay(); - if (current) { - var z1 = window.getComputedStyle(current.target).zIndex; - if (!isNaN(z1)) { - z = Number(z1); - } - } - return z || DEFAULT_Z; - } - - function focusOverlay() { - var current = currentOverlay(); - // We have to be careful to focus the next overlay _after_ any current - // transitions are complete (due to the state being toggled prior to the - // transition). Otherwise, we risk infinite recursion when a transitioning - // (closed) overlay becomes the current overlay. - // - // NOTE: We make the assumption that any overlay that completes a transition - // will call into focusOverlay to kick the process back off. Currently: - // transitionend -> applyFocus -> focusOverlay. - if (current && !current.transitioning) { - current.applyFocus(); - } - } - - var backdrops = []; - function trackBackdrop(element) { - if (element.opened) { - backdrops.push(element); - } else { - var i = backdrops.indexOf(element); - if (i >= 0) { - backdrops.splice(i, 1); - } - } - } - - function getBackdrops() { - return backdrops; - } -})(); -</script> -</polymer-element> - -<!-- -Copyright (c) 2014 The Polymer Project Authors. All rights reserved. -This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt -The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt -The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt -Code distributed by Google as part of the polymer project is also -subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt ---> - -<!-- - -`<core-transition-css>` implements CSS transitions as `<core-transition>` objects so they can be -reused in a pluggable transition system such as in `<core-overlay>`. Currently this class has -some specific support to animate an element from and to the viewport such as a dialog, but you -can override it for different effects. - -Example: - -my-css-transition.html: - - <polymer-element name="my-css-transition" extends="core-transition-css"> - <template> - <style> - :host(.my-transition) { - opacity: 0; - transition: transform 1s ease-out, opacity 1s ease-out; - } - :host(.my-transition.my-opened) { - opacity: 1; - transform: none; - } - :host(.my-transition-top) { - transform: translateY(-100vh); - } - :host(.my-transition-bottom) { - transform: translateY(100vh); - } - </style> - </template> - <script> - Polymer({ - baseClass: 'my-transition', - openedClass: 'my-opened' - }); - </script> - </polymer-element> - - <my-css-transition id="my-transition-top" transitionType="top"></my-css-transition> - <my-css-transition id="my-transition-bottom" transitionType="bottom"></my-css-transition> - -my-css-transition-demo.html - - <link href="components/core-meta/core-meta.html" rel="import"> - <link href="my-css-transition.html"> - - <div id="animate-me"></div> - - <script> - // Get the core-transition - var meta = document.createElement('core-meta'); - meta.type = 'transition'; - var transition1 = meta.byId('my-transition-top'); - - // Set up the animation - var animated = document.getElementById('animate-me'); - transition1.setup(animated); - transition1.go(animated, {opened: true}); - </script> - -The first element in the template of a `<core-transition-css>` object should be a stylesheet. It -will be injected to the scope of the animated node in the `setup` function. The node is initially -invisible with `opacity: 0`, and you can transition it to an "opened" state by passing -`{opened: true}` to the `go` function. - -All nodes being animated will get the class `my-transition` added in the `setup` function. -Additionally, the class `my-transition-<transitionType>` will be applied. You can use the -`transitionType` attribute to implement several different behaviors with the same -`<core-transition-css>` object. In the above example, `<my-css-transition>` implements both -sliding the node from the top of the viewport and from the bottom of the viewport. - -Available transitions ---------------------- - -`<core-transition-css>` includes several commonly used transitions. - -`core-transition-fade`: Animates from `opacity: 0` to `opacity: 1` when it opens. - -`core-transition-center`: Zooms the node into the final size. - -`core-transition-top`: Slides the node into the final position from the top. - -`core-transition-bottom`: Slides the node into the final position from the bottom. - -`core-transition-left`: Slides the node into the final position from the left. - -`core-transition-right`: Slides the node into the final position from the right. - -@group Polymer Core Elements -@element core-transition-css -@extends core-transition -@status beta -@homepage github.io ---> - - - -<polymer-element name="core-transition-css" extends="core-transition" attributes="transitionType" assetpath="polymer/bower_components/core-transition/"> -<template> - <style no-shim="">/* Copyright (c) 2014 The Polymer Project Authors. All rights reserved. -This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt -The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt -The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt -Code distributed by Google as part of the polymer project is also -subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt */ - -:host(.core-transition) { - outline: none; - overflow: auto; - opacity: 0; - transition: transform 0.2s ease-in-out, opacity 0.2s ease-in; - -webkit-transition: -webkit-transform 0.2s ease-in-out, opacity 0.2s ease-in; -} - - -:host(.core-transition.core-opened) { - opacity: 1; - transform: translateZ(0); - -webkit-transform: translateZ(0); -} - -:host(.core-transition-center) { - transform: scale(0.5); - -webkit-transform: scale(0.5); -} - -:host(.core-transition-top) { - transform: translateY(-200%); - -webkit-transform: translateY(-200%); -} - -:host(.core-transition-bottom) { - transform: translateY(200%); - -webkit-transform: translateY(200%); -} - -:host(.core-transition-left) { - transform: translateX(-200%); - -webkit-transform: translateX(-200%); -} - -:host(.core-transition-right) { - transform: translateX(200%); - -webkit-transform: translateX(200%); -}</style> -</template> -<script> - - Polymer('core-transition-css', { - - /** - * The class that will be applied to all animated nodes. - * - * @attribute baseClass - * @type string - * @default "core-transition" - */ - baseClass: 'core-transition', - - /** - * The class that will be applied to nodes in the opened state. - * - * @attribute openedClass - * @type string - * @default "core-opened" - */ - openedClass: 'core-opened', - - /** - * The class that will be applied to nodes in the closed state. - * - * @attribute closedClass - * @type string - * @default "core-closed" - */ - closedClass: 'core-closed', - - /** - * Event to listen to for animation completion. - * - * @attribute completeEventName - * @type string - * @default "transitionEnd" - */ - completeEventName: 'transitionend', - - publish: { - /** - * A secondary configuration attribute for the animation. The class - * `<baseClass>-<transitionType` is applied to the animated node during - * `setup`. - * - * @attribute transitionType - * @type string - */ - transitionType: null - }, - - registerCallback: function(element) { - this.transitionStyle = element.templateContent().firstElementChild; - }, - - // template is just for loading styles, we don't need a shadowRoot - fetchTemplate: function() { - return null; - }, - - go: function(node, state) { - if (state.opened !== undefined) { - this.transitionOpened(node, state.opened); - } - }, - - setup: function(node) { - if (!node._hasTransitionStyle) { - if (!node.shadowRoot) { - node.createShadowRoot().innerHTML = '<content></content>'; - } - this.installScopeStyle(this.transitionStyle, 'transition', - node.shadowRoot); - node._hasTransitionStyle = true; - } - node.classList.add(this.baseClass); - if (this.transitionType) { - node.classList.add(this.baseClass + '-' + this.transitionType); - } - }, - - teardown: function(node) { - node.classList.remove(this.baseClass); - if (this.transitionType) { - node.classList.remove(this.baseClass + '-' + this.transitionType); - } - }, - - transitionOpened: function(node, opened) { - this.listenOnce(node, this.completeEventName, function() { - node.classList.toggle(this.revealedClass, opened); - if (!opened) { - node.classList.remove(this.closedClass); - } - this.complete(node); - }); - node.classList.toggle(this.openedClass, opened); - node.classList.toggle(this.closedClass, !opened); - } - - }); -</script> -</polymer-element> - -<core-transition-css id="core-transition-fade"></core-transition-css> -<core-transition-css id="core-transition-center" transitiontype="center"></core-transition-css> -<core-transition-css id="core-transition-top" transitiontype="top"></core-transition-css> -<core-transition-css id="core-transition-bottom" transitiontype="bottom"></core-transition-css> -<core-transition-css id="core-transition-left" transitiontype="left"></core-transition-css> -<core-transition-css id="core-transition-right" transitiontype="right"></core-transition-css> - -<!-- -Copyright (c) 2014 The Polymer Project Authors. All rights reserved. -This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt -The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt -The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt -Code distributed by Google as part of the polymer project is also -subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt ---> -<!-- -/** - * @group Polymer Core Elements - * @element core-media-query - * @status beta - * @homepage github.io - * - * core-media-query can be used to data bind to a CSS media query. - * The "query" property is a bare CSS media query. - * The "queryMatches" property will be a boolean representing if the page matches that media query. - * - * core-media-query uses media query listeners to dynamically update the "queryMatches" property. - * A "core-media-change" event also fires when queryMatches changes. - * - * Example: - * - * <core-media-query query="max-width: 640px" queryMatches="{{phoneScreen}}"></core-media-query> - * - */ - - /** - * Fired when the media query state changes - * - * @event core-media-change - */ ---> - - -<polymer-element name="core-media-query" attributes="query queryMatches" assetpath="polymer/bower_components/core-media-query/"> - <template> - <style> - :host { - display: none; - } - </style> - </template> - <script> - Polymer('core-media-query', { - - /** - * The Boolean return value of the media query - * - * @attribute queryMatches - * @type Boolean - * @default false - */ - queryMatches: false, - - /** - * The CSS media query to evaulate - * - * @attribute query - * @type string - * @default '' - */ - query: '', - ready: function() { - this._mqHandler = this.queryHandler.bind(this); - this._mq = null; - }, - queryChanged: function() { - if (this._mq) { - this._mq.removeListener(this._mqHandler); - } - var query = this.query; - if (query[0] !== '(') { - query = '(' + this.query + ')'; - } - this._mq = window.matchMedia(query); - this._mq.addListener(this._mqHandler); - this.queryHandler(this._mq); - }, - queryHandler: function(mq) { - this.queryMatches = mq.matches; - this.asyncFire('core-media-change', mq); - } - }); - </script> -</polymer-element> - - -<polymer-element name="paper-toast" attributes="text duration opened responsiveWidth swipeDisabled" role="status" assetpath="polymer/bower_components/paper-toast/"> - -<template> - - <style>/* -Copyright (c) 2014 The Polymer Project Authors. All rights reserved. -This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt -The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt -The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt -Code distributed by Google as part of the polymer project is also -subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt -*/ - -:host { - display: inline-block; - background: #323232; - color: #f1f1f1; - min-height: 48px; - min-width: 288px; - padding: 16px 24px 12px; - box-sizing: border-box; - -moz-box-sizing: border-box; - box-shadow: 0 2px 5px 0 rgba(0, 0, 0, 0.26); - border-radius: 2px; - bottom: 12px; - left: 12px; - font-size: 14px; - cursor: default; -} - -:host(.capsule) { - border-radius: 24px; -} - -:host(.fit-bottom) { - bottom: 0; - left: 0; - width: 100%; - min-width: 0; - border-radius: 0; -} - -:host(.core-transition.dragging) { - transition: none; -} - -:host(.core-transition.fade-out-down), -:host(.core-transition.fade-out-up), -:host(.core-transition.fade-out-right), -:host(.core-transition.fade-out-left) { - opacity: 0; - transition: -webkit-transform 0.08s ease-in-out, opacity 0.08s ease-in-out; - transition: transform 0.08s ease-in-out, opacity 0.08s ease-in-out; -} - -:host(.core-transition.fade-out-down) { - -webkit-transform: translate(0, 100%); - transform: translate(0, 100%); -} - -:host(.core-transition.fade-out-up) { - -webkit-transform: translate(0, -100%); - transform: translate(0, -100%); -} - -:host(.core-transition.fade-out-right) { - -webkit-transform: translate(100%, 0); - transform: translate(100%, 0); -} - -:host(.core-transition.fade-out-left) { - -webkit-transform: translate(-100%, 0); - transform: translate(-100%, 0); -} - -.toast-container { - overflow: hidden; -} - -.toast-action { - padding-left: 24px; - cursor: pointer; - text-transform: uppercase; -} -</style> - - <core-overlay autofocusdisabled="" opened="{{opened}}" target="{{}}" sizingtarget="{{$.container}}" transition="core-transition-bottom"></core-overlay> - - <div class="toast-container" horizontal="" layout=""> - - <div class="toast-text" flex="">{{text}}</div> - - <div class="toast-text toast-action" on-tap="{{dismiss}}"> - <content></content> - </div> - - </div> - - <core-media-query query="max-width: {{responsiveWidth}}" querymatches="{{narrowMode}}"></core-media-query> - -</template> -<script> - - (function() { - - var currentToast; - - Polymer('paper-toast', { - - /** - * The text shows in a toast. - * - * @attribute text - * @type string - * @default '' - */ - text: '', - - /** - * The duration in milliseconds to show the toast. - * - * @attribute duration - * @type number - * @default 3000 - */ - duration: 3000, - - /** - * Set opened to true to show the toast and to false to hide it. - * - * @attribute opened - * @type boolean - * @default false - */ - opened: false, - - /** - * Min-width when the toast changes to narrow layout. In narrow layout, - * the toast fits at the bottom of the screen when opened. - * - * @attribute responsiveWidth - * @type string - * @default '480px' - */ - responsiveWidth: '480px', - - /** - * If true, the toast can't be swiped. - * - * @attribute swipeDisabled - * @type boolean - * @default false - */ - swipeDisabled: false, - - eventDelegates: { - trackstart: 'trackStart', - track: 'track', - trackend: 'trackEnd', - transitionend: 'transitionEnd' - }, - - narrowModeChanged: function() { - this.classList.toggle('fit-bottom', this.narrowMode); - }, - - openedChanged: function() { - if (this.opened) { - this.dismissJob = this.job(this.dismissJob, this.dismiss, this.duration); - } else { - this.dismissJob && this.dismissJob.stop(); - this.dismiss(); - } - }, - - /** - * Toggle the opened state of the toast. - * @method toggle - */ - toggle: function() { - this.opened = !this.opened; - }, - - /** - * Show the toast for the specified duration - * @method show - */ - show: function() { - if (currentToast) { - currentToast.dismiss(); - } - currentToast = this; - this.opened = true; - }, - - /** - * Dismiss the toast and hide it. - * @method dismiss - */ - dismiss: function() { - if (this.dragging) { - this.shouldDismiss = true; - } else { - this.opened = false; - if (currentToast === this) { - currentToast = null; - } - } - }, - - trackStart: function(e) { - if (!this.swipeDisabled) { - e.preventTap(); - this.vertical = e.yDirection; - this.w = this.offsetWidth; - this.h = this.offsetHeight; - this.dragging = true; - this.classList.add('dragging'); - } - }, - - track: function(e) { - if (this.dragging) { - var s = this.style; - if (this.vertical) { - var y = e.dy; - s.opacity = (this.h - Math.abs(y)) / this.h; - s.webkitTransform = s.transform = 'translate3d(0, ' + y + 'px, 0)'; - } else { - var x = e.dx; - s.opacity = (this.w - Math.abs(x)) / this.w; - s.webkitTransform = s.transform = 'translate3d(' + x + 'px, 0, 0)'; - } - } - }, - - trackEnd: function(e) { - if (this.dragging) { - this.classList.remove('dragging'); - this.style.opacity = null; - this.style.webkitTransform = this.style.transform = null; - var cl = this.classList; - if (this.vertical) { - cl.toggle('fade-out-down', e.yDirection === 1 && e.dy > 0); - cl.toggle('fade-out-up', e.yDirection === -1 && e.dy < 0); - } else { - cl.toggle('fade-out-right', e.xDirection === 1 && e.dx > 0); - cl.toggle('fade-out-left', e.xDirection === -1 && e.dx < 0); - } - this.dragging = false; - } - }, - - transitionEnd: function() { - var cl = this.classList; - if (cl.contains('fade-out-right') || cl.contains('fade-out-left') || - cl.contains('fade-out-down') || cl.contains('fade-out-up')) { - this.dismiss(); - cl.remove('fade-out-right', 'fade-out-left', - 'fade-out-down', 'fade-out-up'); - } else if (this.shouldDismiss) { - this.dismiss(); - } - this.shouldDismiss = false; - } - - }); - - })(); - -</script> -</polymer-element> - - - -<!-- -Copyright (c) 2014 The Polymer Project Authors. All rights reserved. -This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt -The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt -The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt -Code distributed by Google as part of the polymer project is also -subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt ---> - -<!-- -Provides a dialog overlay. - -Child elements that include a `dismissive` attribute are positioned in the lower left corner of the dialog. Elements that use the `affirmative` attribute are positioned in the lower right corner. - -Child elements that include the `dismissive` or `affirmative` attribute will automatically toggle the dialog when clicked. - -One child element should have the `autofocus` attribute so that the Enter key will automatically take action. This is -especially important for screen reader environments. - -Example: - - <paper-dialog heading="Title for dialog"> - <p>Lorem ipsum ....</p> - <p>Id qui scripta ...</p> - <paper-button label="More Info..." dismissive></paper-button> - <paper-button label="Decline" affirmative></paper-button> - <paper-button label="Accept" affirmative autofocus></paper-button> - </paper-dialog> - -#### Transitions - -`<paper-dialog>` can be used with `<paper-transition>` to transition the overlay open and close. - -To use a transition, import `paper-dialog-transition.html` alongside paper-dialog: - - <link rel="import" href="paper-dialog/paper-dialog-transition.html"> - -Then set the `transition` attribute: - - <paper-dialog heading="Title for dialog" transition="paper-dialog-transition-center"> - - <paper-dialog heading="Title for dialog" transition="paper-dialog-transition-bottom"> - -@group Paper Elements -@element paper-dialog -@homepage github.io ---> -<!-- -Fired when the dialog's `opened` property changes. - -@event core-overlay-open -@param {Object} detail -@param {Object} detail.opened the opened state ---> - - - - -<polymer-element name="paper-dialog" attributes="opened heading transition autoCloseDisabled backdrop layered closeSelector" role="dialog" assetpath="polymer/bower_components/paper-dialog/"> - - <template> - - <style>/* - * @license - * Copyright (c) 2014 The Polymer Project Authors. All rights reserved. - * This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt - * The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt - * The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt - * Code distributed by Google as part of the polymer project is also - * subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt - */ - -:host { - background: white; - color: rgba(0, 0, 0, 0.87); -} - -#shadow { - position: absolute; - top: 0; - left: 0; - bottom: 0; - right: 0; - z-index: -1; -} - -#container { - overflow: hidden; -} - -#main { - height: auto; - -webkit-order: 1; - -ms-flex-order: 1; - order: 1; - padding: 24px; - overflow: auto; -} - -h1 { - margin: 0; -} - -#actions { - -webkit-order: 2; - -ms-flex-order: 2; - order: 2; - padding: 4px 16px 20px; -} - -polyfill-next-selector { content: ':host > *'; } -::content > * { - font: inherit; -} -</style> - - <div id="shadow"> - <paper-shadow z="3" hasposition=""></paper-shadow> - </div> - - <core-overlay id="overlay" opened="{{opened}}" autoclosedisabled?="{{autoCloseDisabled}}" backdrop?="{{backdrop}}" layered?="{{layered}}" target="{{}}" sizingtarget="{{$.container}}" closeselector="{{closeSelector}}" transition="{{transition}}" margin="20"></core-overlay> - - <div id="container" layout="" vertical=""> - - <div id="actions" layout="" horizontal=""> - <content select="[dismissive]"></content> - <div flex="" auto=""></div> - <content select="[affirmative]"></content> - </div> - - <div id="main" flex="" auto=""> - <h1>{{heading}}</h1> - <content></content> - </div> - - </div> - - </template> - - <script> - - Polymer('paper-dialog', { - - /** - * Set opened to true to show the dialog and to false to hide it. - * A dialog may be made intially opened by setting its opened attribute. - - * @attribute opened - * @type boolean - * @default false - */ - opened: false, - - /** - * If true, the dialog has a backdrop darkening the rest of the screen. - * The backdrop element is attached to the document body and may be styled - * with the class `core-overlay-backdrop`. When opened the `core-opened` - * class is applied. - * - * @attribute backdrop - * @type boolean - * @default false - */ - backdrop: false, - - /** - * If true, the dialog is guaranteed to display above page content. - * - * @attribute layered - * @type boolean - * @default false - */ - layered: false, - - /** - * By default a dialog will close automatically if the user - * taps outside it or presses the escape key. Disable this - * behavior by setting the `autoCloseDisabled` property to true. - * @attribute autoCloseDisabled - * @type boolean - * @default false - */ - autoCloseDisabled: false, - - /** - * This property specifies a selector matching elements that should - * close the dialog on tap. - * - * @attribute closeSelector - * @type string - * @default "" - */ - closeSelector: '[dismissive],[affirmative]', - - /** - * @attribute heading - * @type string - * @default '' - */ - heading: '', - - /** - * Set this property to the id of a `core-transition` element to specify - * the transition to use when opening/closing this dialog. - * - * @attribute transition - * @type string - * @default '' - */ - transition: '', - - /** - * Toggle the dialog's opened state. - * @method toggle - */ - toggle: function() { - this.$.overlay.toggle(); - }, - - headingChanged: function() { - this.setAttribute('aria-label', this.heading); - } - - }); - - </script> - -</polymer-element> - -<!-- -Copyright (c) 2014 The Polymer Project Authors. All rights reserved. -This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt -The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt -The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt -Code distributed by Google as part of the polymer project is also -subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt ---> - - - -<polymer-element name="paper-dialog-transition" extends="core-transition-css" assetpath="polymer/bower_components/paper-dialog/"> - -<template> - <style no-shim="">/* Copyright (c) 2014 The Polymer Project Authors. All rights reserved. -This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt -The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt -The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt -Code distributed by Google as part of the polymer project is also -subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt */ - -:host(.paper-dialog-transition) { - outline: none; - opacity: 0; - transition: transform 0.2s cubic-bezier(0.4, 0, 0.2, 1), opacity 0.2s cubic-bezier(0.4, 0, 0.2, 1); - -webkit-transition: -webkit-transform 0.2s cubic-bezier(0.4, 0, 0.2, 1), opacity 0.2s cubic-bezier(0.4, 0, 0.2, 1); -} - -:host(.paper-dialog-transition.core-opened) { - opacity: 1; - transform: none; - -webkit-transform: none; -} - -:host(.paper-dialog-transition-bottom) { - transform: scale(0.9) translateY(200%); - -webkit-transform: scale(0.9) translateY(200%); -} -:host(.paper-dialog-transition-center.core-opened) { - animation: paper-dialog-transition-center-keyframes 0.2s cubic-bezier(0.4, 0, 0.2, 1); - -webkit-animation: paper-dialog-transition-center-keyframes 0.2s cubic-bezier(0.4, 0, 0.2, 1); -} +<!-- +Copyright (c) 2014 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--> -@keyframes paper-dialog-transition-center-keyframes { - 0% { - transform: scale(0.5) translateY(0); - -webkit-transform: scale(0.5) translateY(0); - } - 90% { - transform: scale(1) translateY(-10px); - -webkit-transform: scale(1) translateY(-10px); - } - 100% { - transform: scale(1) translateY(0); - -webkit-transform: scale(1) translateY(0); - } -} +<!-- +@group Paper Elements -@-webkit-keyframes paper-dialog-transition-center-keyframes { - 0% { - transform: scale(0.5) translateY(0); - -webkit-transform: scale(0.5) translateY(0); - } - 90% { - transform: scale(1) translateY(-10px); - -webkit-transform: scale(1) translateY(-10px); - } - 100% { - transform: scale(1) translateY(0); - -webkit-transform: scale(1) translateY(0); - } -} -</style> -</template> +`paper-button-base` is the base class for button-like elements with ripple and optional shadow. -<script> - Polymer('paper-dialog-transition',{ - baseClass: 'paper-dialog-transition' - }); -</script> +@element paper-button-base +@extends paper-focusable +@status unstable +--> -</polymer-element> -<paper-dialog-transition id="paper-dialog-transition-bottom" transitiontype="bottom"></paper-dialog-transition> -<paper-dialog-transition id="paper-dialog-transition-center" transitiontype="center"></paper-dialog-transition> <!-- Copyright (c) 2014 The Polymer Project Authors. All rights reserved. This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt @@ -6742,58 +1791,224 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN --> <!-- -@group Paper Elements +/** + * @group Paper Elements + * + * paper-focusable is a base class for paper elements that can be focused. + * + * @element paper-focusable + * @status beta + * @homepage github.io + */ +--> -Material Design: <a href="http://www.google.com/design/spec/components/buttons.html">Buttons</a> -`paper-button` is a button. When the user touches the button, a ripple effect emanates -from the point of contact. It may be flat or raised. A raised button is styled with a -shadow. -Example: +<polymer-element name="paper-focusable" attributes="active focused disabled isToggle" tabindex="0" on-down="{{downAction}}" on-up="{{upAction}}" on-focus="{{focusAction}}" on-blur="{{blurAction}}" on-contextmenu="{{contextMenuAction}}" assetpath="polymer/bower_components/paper-focusable/"> - <paper-button>flat button</paper-button> - <paper-button raised>raised button</paper-button> + <template> + <style> + :host([disabled]) { + pointer-events: none; + } + </style> + <content></content> + </template> -You may use custom DOM in the button body to create a variety of buttons. For example, to -create a button with an icon and some text: + <script> + Polymer('paper-focusable', { - <paper-button> - <core-icon icon="favorite"> - custom button content - </paper-button> + publish: { -Styling -------- + /** + * If true, the button is currently active either because the + * user is holding down the button, or the button is a toggle + * and is currently in the active state. + * + * @attribute active + * @type boolean + * @default false + */ + active: {value: false, reflect: true}, -Style the button with CSS as you would a normal DOM element. + /** + * If true, the element currently has focus due to keyboard + * navigation. + * + * @attribute focused + * @type boolean + * @default false + */ + focused: {value: false, reflect: true}, - /* make #my-button green with yellow text */ - #my-button { - background: green; - color: yellow; - } + /** + * If true, the user is currently holding down the button. + * + * @attribute pressed + * @type boolean + * @default false + */ + pressed: {value: false, reflect: true}, -By default, the ripple is the same color as the foreground at 25% opacity. You may -customize the color using this selector: + /** + * If true, the user cannot interact with this element. + * + * @attribute disabled + * @type boolean + * @default false + */ + disabled: {value: false, reflect: true}, - /* make #my-button use a blue ripple instead of foreground color */ - #my-button::shadow #ripple { - color: blue; - } + /** + * If true, the button toggles the active state with each tap. + * Otherwise, the button becomes active when the user is holding + * it down. + * + * @attribute isToggle + * @type boolean + * @default false + */ + isToggle: {value: false, reflect: false} -The opacity of the ripple is not customizable via CSS. + }, -@element paper-button -@extends paper-button-base -@status unstable ---> + disabledChanged: function() { + if (this.disabled) { + this.removeAttribute('tabindex'); + } else { + this.setAttribute('tabindex', 0); + } + }, + + downAction: function() { + this.pressed = true; + + if (this.isToggle) { + this.active = !this.active; + } else { + this.active = true; + } + }, + + // Pulling up the context menu for an item should focus it; but we need to + // be careful about how we deal with down/up events surrounding context + // menus. The up event typically does not fire until the context menu + // closes: so we focus immediately. + // + // This fires _after_ downAction. + contextMenuAction: function(e) { + // Note that upAction may fire _again_ on the actual up event. + this.upAction(e); + this.focusAction(); + }, + + upAction: function() { + this.pressed = false; + + if (!this.isToggle) { + this.active = false; + } + }, + + focusAction: function() { + if (!this.pressed) { + // Only render the "focused" state if the element gains focus due to + // keyboard navigation. + this.focused = true; + } + }, + + blurAction: function() { + this.focused = false; + } + + }); + + </script> +</polymer-element> + + +<polymer-element name="paper-button-base" extends="paper-focusable" assetpath="polymer/bower_components/paper-button/"> + + <script> + Polymer('paper-button-base',{ + + z: 1, + + activeChanged: function() { + this.super(); + + if (this.active) { + // FIXME: remove when paper-ripple can have a default 'down' state. + if (!this.lastEvent) { + var rect = this.getBoundingClientRect(); + this.lastEvent = { + x: rect.left + rect.width / 2, + y: rect.top + rect.height / 2 + } + } + this.$.ripple.downAction(this.lastEvent); + } else { + this.$.ripple.upAction(); + } + this.adjustZ(); + }, + disabledChanged: function() { + this.super(); + if (this.disabled) { + this.setAttribute('aria-disabled', ''); + } else { + this.removeAttribute('aria-disabled'); + } + this.adjustZ(); + }, + recenteringTouchChanged: function() { + if (this.$.ripple) { + this.$.ripple.classList.toggle('recenteringTouch', this.recenteringTouch); + } + }, + fillChanged: function() { + if (this.$.ripple) { + this.$.ripple.classList.toggle('fill', this.fill); + } + }, + adjustZ: function() { + if (this.active) { + this.z = 2; + } else if (this.disabled) { + this.z = 0; + } else { + this.z = 1; + } + }, + downAction: function(e) { + this.super(e); + this.lastEvent = e; + if (!this.$.ripple) { + var ripple = document.createElement('paper-ripple'); + ripple.setAttribute('id', 'ripple'); + ripple.setAttribute('fit', ''); + if (this.recenteringTouch) { + ripple.classList.add('recenteringTouch'); + } + if (!this.fill) { + ripple.classList.add('circle'); + } + this.$.ripple = ripple; + this.shadowRoot.insertBefore(ripple, this.shadowRoot.firstChild); + // No need to forward the event to the ripple because the ripple + // is triggered in activeChanged + } + } + }); + </script> +</polymer-element> <polymer-element name="paper-button" extends="paper-button-base" attributes="raised recenteringTouch fill" role="button" assetpath="polymer/bower_components/paper-button/"> @@ -6905,8 +2120,8 @@ The opacity of the ripple is not customizable via CSS. }); </script> </polymer-element> - -<!-- +</div> +<div hidden><!-- Copyright (c) 2014 The Polymer Project Authors. All rights reserved. This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE The complete set of authors may be found at http://polymer.github.io/AUTHORS @@ -6963,6 +2178,452 @@ To add custom styling to only some elements, use these selectors: --> +<!-- +Copyright (c) 2014 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--> + + +<!-- +Copyright (c) 2014 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--> + +<!-- +/** + * @group Polymer Core Elements + * + * The `core-iconset-svg` element allows users to define their own icon sets + * that contain svg icons. The svg icon elements should be children of the + * `core-iconset-svg` element. Multiple icons should be given distinct id's. + * + * Using svg elements to create icons has a few advantages over traditional + * bitmap graphics like jpg or png. Icons that use svg are vector based so they + * are resolution independent and should look good on any device. They are + * stylable via css. Icons can be themed, colorized, and even animated. + * + * Example: + * + * <core-iconset-svg id="my-svg-icons" iconSize="24"> + * <svg> + * <defs> + * <g id="shape"> + * <rect x="50" y="50" width="50" height="50" /> + * <circle cx="50" cy="50" r="50" /> + * </g> + * </defs> + * </svg> + * </core-iconset-svg> + * + * This will automatically register the icon set "my-svg-icons" to the iconset + * database. To use these icons from within another element, make a + * `core-iconset` element and call the `byId` method + * to retrieve a given iconset. To apply a particular icon inside an + * element use the `applyIcon` method. For example: + * + * iconset.applyIcon(iconNode, 'car'); + * + * @element core-iconset-svg + * @extends core-meta + * @homepage github.io + */ +--> + + + +<polymer-element name="core-iconset-svg" extends="core-meta" attributes="iconSize" assetpath="polymer/bower_components/core-iconset-svg/"> + + <script> + + Polymer('core-iconset-svg', { + + + /** + * The size of an individual icon. Note that icons must be square. + * + * @attribute iconSize + * @type number + * @default 24 + */ + iconSize: 24, + type: 'iconset', + + created: function() { + this._icons = {}; + }, + + ready: function() { + this.super(); + this.updateIcons(); + }, + + iconById: function(id) { + return this._icons[id] || (this._icons[id] = this.querySelector('#' + id)); + }, + + cloneIcon: function(id) { + var icon = this.iconById(id); + if (icon) { + var content = icon.cloneNode(true); + content.removeAttribute('id'); + var svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg'); + svg.setAttribute('viewBox', '0 0 ' + this.iconSize + ' ' + + this.iconSize); + // NOTE(dfreedm): work around https://crbug.com/370136 + svg.style.pointerEvents = 'none'; + svg.appendChild(content); + return svg; + } + }, + + get iconNames() { + if (!this._iconNames) { + this._iconNames = this.findIconNames(); + } + return this._iconNames; + }, + + findIconNames: function() { + var icons = this.querySelectorAll('[id]').array(); + if (icons.length) { + return icons.map(function(n){ return n.id }); + } + }, + + /** + * Applies an icon to the given element. The svg icon is added to the + * element's shadowRoot if one exists or directly to itself. + * + * @method applyIcon + * @param {Element} element The element to which the icon is + * applied. + * @param {String|Number} icon The name the icon to apply. + * @return {Element} The icon element + */ + applyIcon: function(element, icon) { + var root = element; + // remove old + var old = root.querySelector('svg'); + if (old) { + old.remove(); + } + // install new + var svg = this.cloneIcon(icon); + if (!svg) { + return; + } + svg.setAttribute('height', '100%'); + svg.setAttribute('width', '100%'); + svg.setAttribute('preserveAspectRatio', 'xMidYMid meet'); + svg.style.display = 'block'; + root.insertBefore(svg, root.firstElementChild); + return svg; + }, + + /** + * Tell users of the iconset, that the set has loaded. + * This finds all elements matching the selector argument and calls + * the method argument on them. + * @method updateIcons + * @param selector {string} css selector to identify iconset users, + * defaults to '[icon]' + * @param method {string} method to call on found elements, + * defaults to 'updateIcon' + */ + updateIcons: function(selector, method) { + selector = selector || '[icon]'; + method = method || 'updateIcon'; + var deep = window.ShadowDOMPolyfill ? '' : 'html /deep/ '; + var i$ = document.querySelectorAll(deep + selector); + for (var i=0, e; e=i$[i]; i++) { + if (e[method]) { + e[method].call(e); + } + } + } + + + }); + + </script> + +</polymer-element> + +<core-iconset-svg id="icons" iconsize="24"> +<svg><defs> +<g id="accessibility"><path d="M12,2c1.1,0,2,0.9,2,2s-0.9,2-2,2s-2-0.9-2-2S10.9,2,12,2z M21,9h-6v13h-2v-6h-2v6H9V9H3V7h18V9z"/></g> +<g id="account-balance"><path d="M4,10v7h3v-7H4z M10,10v7h3v-7H10z M2,22h19v-3H2V22z M16,10v7h3v-7H16z M11.5,1L2,6v2h19V6L11.5,1z"/></g> +<g id="account-box"><path d="M3,5l0,14c0,1.1,0.9,2,2,2h14c1.1,0,2-0.9,2-2V5c0-1.1-0.9-2-2-2H5C3.9,3,3,3.9,3,5z M15,9c0,1.7-1.3,3-3,3c-1.7,0-3-1.3-3-3c0-1.7,1.3-3,3-3C13.7,6,15,7.3,15,9z M6,17c0-2,4-3.1,6-3.1s6,1.1,6,3.1v1H6V17z"/></g> +<g id="account-child"><path d="M16.5,12c1.4,0,2.5-1.1,2.5-2.5C19,8.1,17.9,7,16.5,7C15.1,7,14,8.1,14,9.5C14,10.9,15.1,12,16.5,12z M9,11c1.7,0,3-1.3,3-3s-1.3-3-3-3C7.3,5,6,6.3,6,8S7.3,11,9,11z M16.5,14c-1.8,0-5.5,0.9-5.5,2.7V19h11v-2.2C22,14.9,18.3,14,16.5,14z M9,13c-2.3,0-7,1.2-7,3.5V19h7v-2.2c0-0.8,0.3-2.3,2.4-3.5C10.5,13.1,9.7,13,9,13z"/></g> +<g id="account-circle"><path d="M12,2C6.5,2,2,6.5,2,12s4.5,10,10,10c5.5,0,10-4.5,10-10S17.5,2,12,2z M12,5c1.7,0,3,1.3,3,3c0,1.7-1.3,3-3,3c-1.7,0-3-1.3-3-3C9,6.3,10.3,5,12,5z M12,19.2c-2.5,0-4.7-1.3-6-3.2c0-2,4-3.1,6-3.1c2,0,6,1.1,6,3.1C16.7,17.9,14.5,19.2,12,19.2z"/></g> +<g id="add"><path d="M19,13h-6v6h-2v-6H5v-2h6V5h2v6h6V13z"/></g> +<g id="add-box"><path d="M19,3H5C3.9,3,3,3.9,3,5v14c0,1.1,0.9,2,2,2h14c1.1,0,2-0.9,2-2V5C21,3.9,20.1,3,19,3z M17,13h-4v4h-2v-4H7v-2h4V7h2v4h4V13z"/></g> +<g id="add-circle"><path d="M12,2C6.5,2,2,6.5,2,12s4.5,10,10,10c5.5,0,10-4.5,10-10S17.5,2,12,2z M17,13h-4v4h-2v-4H7v-2h4V7h2v4h4V13z"/></g> +<g id="add-circle-outline"><path d="M13,7h-2v4H7v2h4v4h2v-4h4v-2h-4V7z M12,2C6.5,2,2,6.5,2,12s4.5,10,10,10c5.5,0,10-4.5,10-10S17.5,2,12,2z M12,20c-4.4,0-8-3.6-8-8s3.6-8,8-8c4.4,0,8,3.6,8,8S16.4,20,12,20z"/></g> +<g id="add-shopping-cart"><polygon points="18.3,6 18.3,6 15.6,11 "/></g> +<g id="alarm"><path d="M22,5.7l-4.6-3.9l-1.3,1.5l4.6,3.9L22,5.7z M7.9,3.4L6.6,1.9L2,5.7l1.3,1.5L7.9,3.4z M12.5,8H11v6l4.7,2.9l0.8-1.2l-4-2.4V8z M12,4c-5,0-9,4-9,9c0,5,4,9,9,9c5,0,9-4,9-9C21,8,17,4,12,4z M12,20c-3.9,0-7-3.1-7-7c0-3.9,3.1-7,7-7c3.9,0,7,3.1,7,7C19,16.9,15.9,20,12,20z"/></g> +<g id="alarm-add"><path d="M7.9,3.4L6.6,1.9L2,5.7l1.3,1.5L7.9,3.4z M22,5.7l-4.6-3.9l-1.3,1.5l4.6,3.9L22,5.7z M12,4c-5,0-9,4-9,9c0,5,4,9,9,9c5,0,9-4,9-9C21,8,17,4,12,4z M12,20c-3.9,0-7-3.1-7-7c0-3.9,3.1-7,7-7c3.9,0,7,3.1,7,7C19,16.9,15.9,20,12,20z M13,9h-2v3H8v2h3v3h2v-3h3v-2h-3V9z"/></g> +<g id="alarm-off"><path d="M12,6c3.9,0,7,3.1,7,7c0,0.8-0.2,1.6-0.4,2.4l1.5,1.5c0.6-1.2,0.9-2.5,0.9-3.9c0-5-4-9-9-9c-1.4,0-2.7,0.3-3.9,0.9l1.5,1.5C10.4,6.2,11.2,6,12,6z M22,5.7l-4.6-3.9l-1.3,1.5l4.6,3.9L22,5.7z M2.9,2.3L1.6,3.6L3,4.9L1.9,5.8l1.4,1.4l1.1-0.9l0.8,0.8C3.8,8.7,3,10.7,3,13c0,5,4,9,9,9c2.3,0,4.3-0.8,5.9-2.2l2.2,2.2l1.3-1.3L3.9,3.3L2.9,2.3z M16.5,18.4c-1.2,1-2.8,1.6-4.5,1.6c-3.9,0-7-3.1-7-7c0-1.7,0.6-3.3,1.6-4.5L16.5,18.4z M8,3.3L6.6,1.9L5.7,2.6L7.2,4L8,3.3z"/></g> +<g id="alarm-on"><path d="M22,5.7l-4.6-3.9l-1.3,1.5l4.6,3.9L22,5.7z M7.9,3.4L6.6,1.9L2,5.7l1.3,1.5L7.9,3.4z M12,4c-5,0-9,4-9,9c0,5,4,9,9,9c5,0,9-4,9-9C21,8,17,4,12,4z M12,20c-3.9,0-7-3.1-7-7c0-3.9,3.1-7,7-7s7,3.1,7,7C19,16.9,15.9,20,12,20z M10.5,14.5l-2.1-2.1l-1.1,1.1l3.2,3.2l6-6l-1.1-1.1L10.5,14.5z"/></g> +<g id="android"><path d="M6,18c0,0.6,0.4,1,1,1h1v3.5C8,23.3,8.7,24,9.5,24c0.8,0,1.5-0.7,1.5-1.5V19h2v3.5c0,0.8,0.7,1.5,1.5,1.5c0.8,0,1.5-0.7,1.5-1.5V19h1c0.6,0,1-0.4,1-1V8H6V18z M3.5,8C2.7,8,2,8.7,2,9.5v7C2,17.3,2.7,18,3.5,18C4.3,18,5,17.3,5,16.5v-7C5,8.7,4.3,8,3.5,8z M20.5,8C19.7,8,19,8.7,19,9.5v7c0,0.8,0.7,1.5,1.5,1.5c0.8,0,1.5-0.7,1.5-1.5v-7C22,8.7,21.3,8,20.5,8z M15.5,2.2l1.3-1.3c0.2-0.2,0.2-0.5,0-0.7c-0.2-0.2-0.5-0.2-0.7,0l-1.5,1.5C13.9,1.2,13,1,12,1c-1,0-1.9,0.2-2.7,0.6L7.9,0.1C7.7,0,7.3,0,7.1,0.1C7,0.3,7,0.7,7.1,0.9l1.3,1.3C7,3.3,6,5,6,7h12C18,5,17,3.2,15.5,2.2z M10,5H9V4h1V5z M15,5h-1V4h1V5z"/></g> +<g id="announcement"><path d="M20,2H4C2.9,2,2,2.9,2,4l0,18l4-4h14c1.1,0,2-0.9,2-2V4C22,2.9,21.1,2,20,2z M13,11h-2V5h2V11z M13,15h-2v-2h2V15z"/></g> +<g id="apps"><path d="M4,8h4V4H4V8z M10,20h4v-4h-4V20z M4,20h4v-4H4V20z M4,14h4v-4H4V14z M10,14h4v-4h-4V14z M16,4v4h4V4H16z M10,8h4V4h-4V8z M16,14h4v-4h-4V14z M16,20h4v-4h-4V20z"/></g> +<g id="archive"><path d="M20.5,5.2l-1.4-1.7C18.9,3.2,18.5,3,18,3H6C5.5,3,5.1,3.2,4.8,3.5L3.5,5.2C3.2,5.6,3,6,3,6.5V19c0,1.1,0.9,2,2,2h14c1.1,0,2-0.9,2-2V6.5C21,6,20.8,5.6,20.5,5.2z M12,17.5L6.5,12H10v-2h4v2h3.5L12,17.5z M5.1,5l0.8-1h12l0.9,1H5.1z"/></g> +<g id="arrow-back"><path d="M20,11H7.8l5.6-5.6L12,4l-8,8l8,8l1.4-1.4L7.8,13H20V11z"/></g> +<g id="arrow-drop-down"><polygon points="7,10 12,15 17,10 "/></g> +<g id="arrow-drop-down-circle"><path d="M12,2C6.5,2,2,6.5,2,12s4.5,10,10,10c5.5,0,10-4.5,10-10S17.5,2,12,2z M12,14l-4-4h8L12,14z"/></g> +<g id="arrow-drop-up"><polygon points="7,14 12,9 17,14 "/></g> +<g id="arrow-forward"><polygon points="12,4 10.6,5.4 16.2,11 4,11 4,13 16.2,13 10.6,18.6 12,20 20,12 "/></g> +<g id="aspect-ratio"><path d="M19,12h-2v3h-3v2h5V12z M7,9h3V7H5v5h2V9z M21,3H3C1.9,3,1,3.9,1,5v14c0,1.1,0.9,2,2,2h18c1.1,0,2-0.9,2-2V5C23,3.9,22.1,3,21,3z M21,19H3V5h18V19z"/></g> +<g id="assessment"><path d="M19,3H5C3.9,3,3,3.9,3,5v14c0,1.1,0.9,2,2,2h14c1.1,0,2-0.9,2-2V5C21,3.9,20.1,3,19,3z M9,17H7v-7h2V17z M13,17h-2V7h2V17z M17,17h-2v-4h2V17z"/></g> +<g id="assignment"><path d="M19,3h-4.2c-0.4-1.2-1.5-2-2.8-2c-1.3,0-2.4,0.8-2.8,2H5C3.9,3,3,3.9,3,5v14c0,1.1,0.9,2,2,2h14c1.1,0,2-0.9,2-2V5C21,3.9,20.1,3,19,3z M12,3c0.6,0,1,0.4,1,1s-0.4,1-1,1s-1-0.4-1-1S11.4,3,12,3z M14,17H7v-2h7V17z M17,13H7v-2h10V13z M17,9H7V7h10V9z"/></g> +<g id="assignment-ind"><path d="M19,3h-4.2c-0.4-1.2-1.5-2-2.8-2c-1.3,0-2.4,0.8-2.8,2H5C3.9,3,3,3.9,3,5v14c0,1.1,0.9,2,2,2h14c1.1,0,2-0.9,2-2V5C21,3.9,20.1,3,19,3z M12,3c0.6,0,1,0.4,1,1s-0.4,1-1,1s-1-0.4-1-1S11.4,3,12,3z M12,7c1.7,0,3,1.3,3,3c0,1.7-1.3,3-3,3c-1.7,0-3-1.3-3-3C9,8.3,10.3,7,12,7z M18,19H6v-1.4c0-2,4-3.1,6-3.1s6,1.1,6,3.1V19z"/></g> +<g id="assignment-late"><path d="M19,3h-4.2c-0.4-1.2-1.5-2-2.8-2c-1.3,0-2.4,0.8-2.8,2H5C3.9,3,3,3.9,3,5v14c0,1.1,0.9,2,2,2h14c1.1,0,2-0.9,2-2V5C21,3.9,20.1,3,19,3z M12,3c0.6,0,1,0.4,1,1s-0.4,1-1,1s-1-0.4-1-1S11.4,3,12,3z M17,15.6L15.6,17L12,13.4L8.4,17L7,15.6l3.6-3.6L7,8.4L8.4,7l3.6,3.6L15.6,7L17,8.4L13.4,12L17,15.6z"/></g> +<g id="assignment-return"><path d="M19,3h-4.2c-0.4-1.2-1.5-2-2.8-2c-1.3,0-2.4,0.8-2.8,2H5C3.9,3,3,3.9,3,5v14c0,1.1,0.9,2,2,2h14c1.1,0,2-0.9,2-2V5C21,3.9,20.1,3,19,3z M12,3c0.6,0,1,0.4,1,1s-0.4,1-1,1c-0.6,0-1-0.4-1-1S11.4,3,12,3z M16,15h-4v3l-5-5l5-5v3h4V15z"/></g> +<g id="assignment-returned"><path d="M19,3h-4.2c-0.4-1.2-1.5-2-2.8-2c-1.3,0-2.4,0.8-2.8,2H5C3.9,3,3,3.9,3,5v14c0,1.1,0.9,2,2,2h14c1.1,0,2-0.9,2-2V5C21,3.9,20.1,3,19,3z M12,3c0.6,0,1,0.4,1,1s-0.4,1-1,1s-1-0.4-1-1S11.4,3,12,3z M12,18l-5-5h3V9h4v4h3L12,18z"/></g> +<g id="attachment"><path d="M7.5,18c-3,0-5.5-2.5-5.5-5.5S4.5,7,7.5,7H18c2.2,0,4,1.8,4,4s-1.8,4-4,4H9.5C8.1,15,7,13.9,7,12.5S8.1,10,9.5,10H17v1.5H9.5c-0.6,0-1,0.4-1,1s0.4,1,1,1H18c1.4,0,2.5-1.1,2.5-2.5S19.4,8.5,18,8.5H7.5c-2.2,0-4,1.8-4,4s1.8,4,4,4H17V18H7.5z"/></g> +<g id="backspace"><path d="M22,3H7C6.3,3,5.8,3.3,5.4,3.9L0,12l5.4,8.1C5.8,20.6,6.3,21,7,21h15c1.1,0,2-0.9,2-2V5C24,3.9,23.1,3,22,3z M19,15.6L17.6,17L14,13.4L10.4,17L9,15.6l3.6-3.6L9,8.4L10.4,7l3.6,3.6L17.6,7L19,8.4L15.4,12L19,15.6z"/></g> +<g id="backup"><path d="M19.4,10c-0.7-3.4-3.7-6-7.4-6C9.1,4,6.6,5.6,5.4,8C2.3,8.4,0,10.9,0,14c0,3.3,2.7,6,6,6h13c2.8,0,5-2.2,5-5C24,12.4,21.9,10.2,19.4,10z M14,13v4h-4v-4H7l5-5l5,5H14z"/></g> +<g id="block"><path d="M12,2C6.5,2,2,6.5,2,12s4.5,10,10,10c5.5,0,10-4.5,10-10S17.5,2,12,2z M4,12c0-4.4,3.6-8,8-8c1.8,0,3.5,0.6,4.9,1.7L5.7,16.9C4.6,15.5,4,13.8,4,12z M12,20c-1.8,0-3.5-0.6-4.9-1.7L18.3,7.1C19.4,8.5,20,10.2,20,12C20,16.4,16.4,20,12,20z"/></g> +<g id="book"><path d="M18,2H6C4.9,2,4,2.9,4,4v16c0,1.1,0.9,2,2,2h12c1.1,0,2-0.9,2-2V4C20,2.9,19.1,2,18,2z M6,4h5v8l-2.5-1.5L6,12V4z"/></g> +<g id="bookmark"><path d="M17,3H7C5.9,3,5,3.9,5,5l0,16l7-3l7,3V5C19,3.9,18.1,3,17,3z"/></g> +<g id="bookmark-outline"><path d="M17,3H7C5.9,3,5,3.9,5,5l0,16l7-3l7,3V5C19,3.9,18.1,3,17,3z M17,18l-5-2.2L7,18V5h10V18z"/></g> +<g id="bug-report"><path d="M20,8h-2.8c-0.5-0.8-1.1-1.5-1.8-2L17,4.4L15.6,3l-2.2,2.2C13,5.1,12.5,5,12,5s-1,0.1-1.4,0.2L8.4,3L7,4.4L8.6,6C7.9,6.5,7.3,7.2,6.8,8H4v2h2.1C6,10.3,6,10.7,6,11v1H4v2h2v1c0,0.3,0,0.7,0.1,1H4v2h2.8c1,1.8,3,3,5.2,3s4.2-1.2,5.2-3H20v-2h-2.1c0.1-0.3,0.1-0.7,0.1-1v-1h2v-2h-2v-1c0-0.3,0-0.7-0.1-1H20V8z M14,16h-4v-2h4V16z M14,12h-4v-2h4V12z"/></g> +<g id="cached"><path d="M19,8l-4,4h3c0,3.3-2.7,6-6,6c-1,0-2-0.3-2.8-0.7l-1.5,1.5C9,19.5,10.4,20,12,20c4.4,0,8-3.6,8-8h3L19,8z M6,12c0-3.3,2.7-6,6-6c1,0,2,0.3,2.8,0.7l1.5-1.5C15,4.5,13.6,4,12,4c-4.4,0-8,3.6-8,8H1l4,4l4-4H6z"/></g> +<g id="cancel"><path d="M12,2C6.5,2,2,6.5,2,12s4.5,10,10,10c5.5,0,10-4.5,10-10S17.5,2,12,2z M17,15.6L15.6,17L12,13.4L8.4,17L7,15.6l3.6-3.6L7,8.4L8.4,7l3.6,3.6L15.6,7L17,8.4L13.4,12L17,15.6z"/></g> +<g id="check"><polygon points="9,16.2 4.8,12 3.4,13.4 9,19 21,7 19.6,5.6 "/></g> +<g id="check-box"><path d="M19,3H5C3.9,3,3,3.9,3,5v14c0,1.1,0.9,2,2,2h14c1.1,0,2-0.9,2-2V5C21,3.9,20.1,3,19,3z M10,17l-5-5l1.4-1.4l3.6,3.6l7.6-7.6L19,8L10,17z"/></g> +<g id="check-box-blank"><path d="M19,3H5C3.9,3,3,3.9,3,5l0,14c0,1.1,0.9,2,2,2h14c1.1,0,2-0.9,2-2V5C21,3.9,20.1,3,19,3z"/></g> +<g id="check-box-outline"><path d="M7.9,10.1l-1.4,1.4L11,16L21,6l-1.4-1.4L11,13.2L7.9,10.1z M19,19L5,19V5h10V3H5C3.9,3,3,3.9,3,5v14c0,1.1,0.9,2,2,2h14c1.1,0,2-0.9,2-2v-8h-2V19z"/></g> +<g id="check-box-outline-blank"><path d="M19,5v14L5,19V5H19 M19,3H5C3.9,3,3,3.9,3,5v14c0,1.1,0.9,2,2,2h14c1.1,0,2-0.9,2-2V5C21,3.9,20.1,3,19,3L19,3z"/></g> +<g id="check-circle"><path d="M12,2C6.5,2,2,6.5,2,12c0,5.5,4.5,10,10,10c5.5,0,10-4.5,10-10C22,6.5,17.5,2,12,2z M10,17l-5-5l1.4-1.4l3.6,3.6l7.6-7.6L19,8L10,17z"/></g> +<g id="check-circle-blank"><path d="M12,2C6.5,2,2,6.5,2,12c0,5.5,4.5,10,10,10c5.5,0,10-4.5,10-10C22,6.5,17.5,2,12,2z"/></g> +<g id="check-circle-outline"><path d="M7.9,10.1l-1.4,1.4L11,16L21,6l-1.4-1.4L11,13.2L7.9,10.1z M20,12c0,4.4-3.6,8-8,8s-8-3.6-8-8s3.6-8,8-8c0.8,0,1.5,0.1,2.2,0.3l1.6-1.6C14.6,2.3,13.3,2,12,2C6.5,2,2,6.5,2,12s4.5,10,10,10s10-4.5,10-10H20z"/></g> +<g id="check-circle-outline-blank"><path d="M12,2C6.5,2,2,6.5,2,12s4.5,10,10,10c5.5,0,10-4.5,10-10S17.5,2,12,2z M12,20c-4.4,0-8-3.6-8-8s3.6-8,8-8c4.4,0,8,3.6,8,8S16.4,20,12,20z"/></g> +<g id="chevron-left"><polygon points="15.4,7.4 14,6 8,12 14,18 15.4,16.6 10.8,12 "/></g> +<g id="chevron-right"><polygon points="10,6 8.6,7.4 13.2,12 8.6,16.6 10,18 16,12 "/></g> +<g id="class"><path d="M18,2H6C4.9,2,4,2.9,4,4v16c0,1.1,0.9,2,2,2h12c1.1,0,2-0.9,2-2V4C20,2.9,19.1,2,18,2z M6,4h5v8l-2.5-1.5L6,12V4z"/></g> +<g id="clear"><polygon points="19,6.4 17.6,5 12,10.6 6.4,5 5,6.4 10.6,12 5,17.6 6.4,19 12,13.4 17.6,19 19,17.6 13.4,12 "/></g> +<g id="close"><polygon points="19,6.4 17.6,5 12,10.6 6.4,5 5,6.4 10.6,12 5,17.6 6.4,19 12,13.4 17.6,19 19,17.6 13.4,12 "/></g> +<g id="cloud"><path d="M19.4,10c-0.7-3.4-3.7-6-7.4-6C9.1,4,6.6,5.6,5.4,8C2.3,8.4,0,10.9,0,14c0,3.3,2.7,6,6,6h13c2.8,0,5-2.2,5-5C24,12.4,21.9,10.2,19.4,10z"/></g> +<g id="cloud-circle"><path d="M12,2C6.5,2,2,6.5,2,12c0,5.5,4.5,10,10,10c5.5,0,10-4.5,10-10C22,6.5,17.5,2,12,2z M16.5,16c0,0-8.5,0-8.5,0c-1.7,0-3-1.3-3-3s1.3-3,3-3c0,0,0.1,0,0.1,0c0.4-1.7,2-3,3.9-3c2.2,0,4,1.8,4,4h0.5c1.4,0,2.5,1.1,2.5,2.5C19,14.9,17.9,16,16.5,16z"/></g> +<g id="cloud-done"><path d="M19.4,10c-0.7-3.4-3.7-6-7.4-6C9.1,4,6.6,5.6,5.4,8C2.3,8.4,0,10.9,0,14c0,3.3,2.7,6,6,6h13c2.8,0,5-2.2,5-5C24,12.4,21.9,10.2,19.4,10z M10,17l-3.5-3.5l1.4-1.4l2.1,2.1L15.2,9l1.4,1.4L10,17z"/></g> +<g id="cloud-download"><path d="M19.4,10c-0.7-3.4-3.7-6-7.4-6C9.1,4,6.6,5.6,5.4,8C2.3,8.4,0,10.9,0,14c0,3.3,2.7,6,6,6h13c2.8,0,5-2.2,5-5C24,12.4,21.9,10.2,19.4,10z M17,13l-5,5l-5-5h3V9h4v4H17z"/></g> +<g id="cloud-off"><path d="M19.4,10c-0.7-3.4-3.7-6-7.4-6c-1.5,0-2.9,0.4-4,1.2l1.5,1.5C10.2,6.2,11.1,6,12,6c3,0,5.5,2.5,5.5,5.5V12H19c1.7,0,3,1.3,3,3c0,1.1-0.6,2.1-1.6,2.6l1.5,1.5c1.3-0.9,2.1-2.4,2.1-4.1C24,12.4,21.9,10.2,19.4,10z M3,5.3L5.8,8C2.6,8.2,0,10.8,0,14c0,3.3,2.7,6,6,6h11.7l2,2l1.3-1.3L4.3,4L3,5.3z M7.7,10l8,8H6c-2.2,0-4-1.8-4-4c0-2.2,1.8-4,4-4H7.7z"/></g> +<g id="cloud-queue"><path d="M19.4,10c-0.7-3.4-3.7-6-7.4-6C9.1,4,6.6,5.6,5.4,8C2.3,8.4,0,10.9,0,14c0,3.3,2.7,6,6,6h13c2.8,0,5-2.2,5-5C24,12.4,21.9,10.2,19.4,10z M19,18H6c-2.2,0-4-1.8-4-4c0-2.2,1.8-4,4-4h0.7C7.4,7.7,9.5,6,12,6c3,0,5.5,2.5,5.5,5.5V12H19c1.7,0,3,1.3,3,3S20.7,18,19,18z"/></g> +<g id="cloud-upload"><path d="M19.4,10c-0.7-3.4-3.7-6-7.4-6C9.1,4,6.6,5.6,5.4,8C2.3,8.4,0,10.9,0,14c0,3.3,2.7,6,6,6h13c2.8,0,5-2.2,5-5C24,12.4,21.9,10.2,19.4,10z M14,13v4h-4v-4H7l5-5l5,5H14z"/></g> +<g id="content-copy"><path d="M16,1H4C2.9,1,2,1.9,2,3v14h2V3h12V1z M19,5H8C6.9,5,6,5.9,6,7v14c0,1.1,0.9,2,2,2h11c1.1,0,2-0.9,2-2V7C21,5.9,20.1,5,19,5z M19,21H8V7h11V21z"/></g> +<g id="content-cut"><path d="M10,6c0-2.2-1.8-4-4-4S2,3.8,2,6c0,2.2,1.8,4,4,4c0.6,0,1.1-0.1,1.6-0.4L10,12l-2.4,2.4C7.1,14.1,6.6,14,6,14c-2.2,0-4,1.8-4,4c0,2.2,1.8,4,4,4s4-1.8,4-4c0-0.6-0.1-1.1-0.4-1.6L12,14l7,7h4L9.6,7.6C9.9,7.1,10,6.6,10,6z M6,8C4.9,8,4,7.1,4,6s0.9-2,2-2c1.1,0,2,0.9,2,2S7.1,8,6,8z M6,20c-1.1,0-2-0.9-2-2s0.9-2,2-2c1.1,0,2,0.9,2,2S7.1,20,6,20z M12,11.5c0.3,0,0.5,0.2,0.5,0.5c0,0.3-0.2,0.5-0.5,0.5c-0.3,0-0.5-0.2-0.5-0.5C11.5,11.7,11.7,11.5,12,11.5z M23,3h-4l-6,6l2,2L23,3z"/></g> +<g id="content-paste"><path d="M19,2h-4.2c-0.4-1.2-1.5-2-2.8-2c-1.3,0-2.4,0.8-2.8,2H5C3.9,2,3,2.9,3,4v16c0,1.1,0.9,2,2,2h14c1.1,0,2-0.9,2-2V4C21,2.9,20.1,2,19,2z M12,2c0.6,0,1,0.4,1,1s-0.4,1-1,1c-0.6,0-1-0.4-1-1S11.4,2,12,2z M19,20H5V4h2v3h10V4h2V20z"/></g> +<g id="create"><path d="M3,17.2V21h3.8L17.8,9.9l-3.8-3.8L3,17.2z M20.7,7c0.4-0.4,0.4-1,0-1.4l-2.3-2.3c-0.4-0.4-1-0.4-1.4,0l-1.8,1.8l3.8,3.8L20.7,7z"/></g> +<g id="credit-card"><path d="M20,4H4C2.9,4,2,4.9,2,6v12c0,1.1,0.9,2,2,2h16c1.1,0,2-0.9,2-2V6C22,4.9,21.1,4,20,4z M20,18H4v-6h16V18z M20,8H4V6h16V8z"/></g> +<g id="delete"><path d="M6,19c0,1.1,0.9,2,2,2h8c1.1,0,2-0.9,2-2V7H6V19z M19,4h-3.5l-1-1h-5l-1,1H5v2h14V4z"/></g> +<g id="description"><path d="M14,2H6C4.9,2,4,2.9,4,4l0,16c0,1.1,0.9,2,2,2h12c1.1,0,2-0.9,2-2V8L14,2z M16,18H8v-2h8V18z M16,14H8v-2h8V14z M13,9V3.5L18.5,9H13z"/></g> +<g id="developer-mode-tv"><path d="M4,5h16v2h2l0-2c0-1.1-0.9-2-2-2H4C2.9,3,2,3.9,2,5v2h2V5z M7.6,13.8L4.7,11l2.8-2.8L6.1,6.8L1.9,11l4.2,4.2L7.6,13.8z M20,17H4v-2H2v2c0,1.1,0.9,2,2,2h4v2h8v-2h4c1.1,0,2-0.9,2-2l0-2h-2V17z M22,11l-4.2-4.2l-1.4,1.4l2.8,2.8l-2.8,2.8l1.4,1.4L22,11L22,11L22,11L22,11L22,11z"/></g> +<g id="done"><polygon points="9,16.2 4.8,12 3.4,13.4 9,19 21,7 19.6,5.6 "/></g> +<g id="done-all"><path d="M18,7l-1.4-1.4l-6.3,6.3l1.4,1.4L18,7z M22.2,5.6L11.7,16.2L7.5,12l-1.4,1.4l5.6,5.6l12-12L22.2,5.6z M0.4,13.4L6,19l1.4-1.4L1.8,12L0.4,13.4z"/></g> +<g id="drafts"><path d="M22,8c0-0.7-0.4-1.3-0.9-1.7L12,1L2.9,6.3C2.4,6.7,2,7.3,2,8v10c0,1.1,0.9,2,2,2h16c1.1,0,2-0.9,2-2L22,8z M12,13L3.7,7.8L12,3l8.3,4.8L12,13z"/></g> +<g id="drawer"><path d="M12,8c1.1,0,2-0.9,2-2s-0.9-2-2-2c-1.1,0-2,0.9-2,2S10.9,8,12,8z M12,10c-1.1,0-2,0.9-2,2s0.9,2,2,2c1.1,0,2-0.9,2-2S13.1,10,12,10z M12,16c-1.1,0-2,0.9-2,2s0.9,2,2,2c1.1,0,2-0.9,2-2S13.1,16,12,16z"/></g> +<g id="drive"><path d="M22.3,14L15.4,2H8.6l0,0l6.9,12H22.3z M9.7,15l-3.4,6h13.1l3.4-6H9.7z M7.7,3.5L1.2,15l3.4,6l6.6-11.5L7.7,3.5z"/></g> +<g id="drive-archive"><path d="M19,3H5C3.9,3,3,3.9,3,5v14c0,1.1,0.9,2,2,2h14c1.1,0,2-0.9,2-2V5C21,3.9,20.1,3,19,3z M12,18l-4-4h8L12,18z M16,12H8v-2h8V12z M16,8H8V6h8V8z"/></g> +<g id="drive-audio"><path d="M19,3H5C3.9,3,3,3.9,3,5v14c0,1.1,0.9,2,2,2h14c1.1,0,2-0.9,2-2V5C21,3.9,20.1,3,19,3z M7.2,18C6.5,18,6,17.5,6,16.8v-3.6V12c0-3.3,2.7-6,6-6s6,2.7,6,6v1.2v3.6c0,0.7-0.5,1.2-1.2,1.2H14v-4h2v-2c0-2.2-1.8-4-4-4s-4,1.8-4,4v2h2v4H7.2z"/></g> +<g id="drive-chart"><path d="M19,3H5C3.9,3,3,3.9,3,5v14c0,1.1,0.9,2,2,2h14c1.1,0,2-0.9,2-2V5C21,3.9,20.1,3,19,3z M9,17H7v-7h2V17z M13,17h-2V7h2V17z M17,17h-2v-4h2V17z"/></g> +<g id="drive-document"><path d="M19,3H5C3.9,3,3,3.9,3,5v14c0,1.1,0.9,2,2,2h14c1.1,0,2-0.9,2-2V5C21,3.9,20.1,3,19,3z M17,9H7V7h10V9z M17,13H7v-2h10V13z M14,17H7v-2h7V17z"/></g> +<g id="drive-drawing"><path d="M19,3H5C3.9,3,3,3.9,3,5v14c0,1.1,0.9,2,2,2h14c1.1,0,2-0.9,2-2V5C21,3.9,20.1,3,19,3z M18,18h-6v-5.8c-0.7,0.6-1.5,1-2.5,1c-2,0-3.7-1.7-3.7-3.7s1.7-3.7,3.7-3.7c2,0,3.7,1.7,3.7,3.7c0,1-0.4,1.8-1,2.5H18V18z"/></g> +<g id="drive-file"><path d="M6,2C4.9,2,4,2.9,4,4l0,16c0,1.1,0.9,2,2,2h12c1.1,0,2-0.9,2-2V8l-6-6H6z M13,9V3.5L18.5,9H13z"/></g> +<g id="drive-file-move"><path d="M20,6h-8l-2-2H4C2.9,4,2,4.9,2,6v12c0,1.1,0.9,2,2,2h16c1.1,0,2-0.9,2-2V8C22,6.9,21.1,6,20,6z M9,18v-3H5v-4h4V8l5,5L9,18z"/></g> +<g id="drive-file-rename"><path d="M19,3H5C3.9,3,3,3.9,3,5v14c0,1.1,0.9,2,2,2h14c1.1,0,2-0.9,2-2V5C21,3.9,20.1,3,19,3z M6,17v-2.5l7.9-7.9c0.2-0.2,0.5-0.2,0.7,0l1.8,1.8c0.2,0.2,0.2,0.5,0,0.7L8.5,17H6z M18,17h-7.5l2-2H18V17z"/></g> +<g id="drive-form"><path d="M19,3H5C3.9,3,3,3.9,3,5v14c0,1.1,0.9,2,2,2h14c1.1,0,2-0.9,2-2V5C21,3.9,20.1,3,19,3z M9,17H7v-2h2V17z M9,13H7v-2h2V13z M9,9H7V7h2V9z M17,17h-7v-2h7V17z M17,13h-7v-2h7V13z M17,9h-7V7h7V9z"/></g> +<g id="drive-fusiontable"><path d="M19,3H5C3.9,3,3,3.9,3,5v14c0,1.1,0.9,2,2,2h14c1.1,0,2-0.9,2-2V5C21,3.9,20.1,3,19,3z M19,10.2L13,17l-4-4l-4,4v-3l4-4l4,4l6-6.8V10.2z"/></g> +<g id="drive-image"><path d="M21,19V5c0-1.1-0.9-2-2-2H5C3.9,3,3,3.9,3,5v14c0,1.1,0.9,2,2,2h14C20.1,21,21,20.1,21,19z M8.5,13.5l2.5,3l3.5-4.5l4.5,6H5L8.5,13.5z"/></g> +<g id="drive-keep"><path d="M9,21c0,0.6,0.4,1,1,1h4c0.6,0,1-0.4,1-1v-1H9V21z M12,2C8.1,2,5,5.1,5,9c0,2.4,1.2,4.5,3,5.7V17c0,0.6,0.4,1,1,1h6c0.6,0,1-0.4,1-1v-2.3c1.8-1.3,3-3.4,3-5.7C19,5.1,15.9,2,12,2z"/></g> +<g id="drive-ms-excel"><path d="M19,3H5C3.9,3,3,3.9,3,5v14c0,1.1,0.9,2,2,2h14c1.1,0,2-0.9,2-2V5C21,3.9,20.1,3,19,3z M16.2,17h-2L12,13.2L9.8,17h-2l3.2-5L7.8,7h2l2.2,3.8L14.2,7h2L13,12L16.2,17z"/></g> +<g id="drive-ms-powerpoint"><path d="M19,3H5C3.9,3,3,3.9,3,5v14c0,1.1,0.9,2,2,2h14c1.1,0,2-0.9,2-2V5C21,3.9,20.1,3,19,3z M9.8,13.4V17H8V7h4.3c1.5,0,2.2,0.3,2.8,0.9c0.7,0.6,0.9,1.4,0.9,2.3c0,1-0.3,1.8-0.9,2.3c-0.6,0.5-1.3,0.8-2.8,0.8H9.8z"/><path d="M9.8,12V8.4h2.3c0.7,0,1.2,0.2,1.5,0.6c0.3,0.4,0.5,0.7,0.5,1.2c0,0.6-0.2,0.9-0.5,1.3c-0.3,0.3-0.7,0.5-1.4,0.5H9.8z"/></g> +<g id="drive-ms-word"><path d="M19,3H5C3.9,3,3,3.9,3,5v14c0,1.1,0.9,2,2,2h14c1.1,0,2-0.9,2-2V5C21,3.9,20.1,3,19,3z M15.5,17H14l-2-7.5L10,17H8.5L6.1,7h1.7l1.5,7.5l2-7.5h1.4l2,7.5L16.2,7h1.7L15.5,17z"/></g> +<g id="drive-pdf"><path d="M11.3,8.6L11.3,8.6C11.4,8.6,11.4,8.6,11.3,8.6c0.1-0.4,0.2-0.6,0.2-0.9l0-0.2c0.1-0.5,0.1-0.9,0-1c0,0,0,0,0-0.1l-0.1-0.1c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0.1-0.1,0.1C11.1,7,11.1,7.7,11.3,8.6C11.3,8.6,11.3,8.6,11.3,8.6z M8.3,15.5c-0.2,0.1-0.4,0.2-0.5,0.3c-0.7,0.6-1.2,1.3-1.3,1.6c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0C7.1,17.3,7.7,16.7,8.3,15.5C8.4,15.5,8.4,15.5,8.3,15.5C8.4,15.5,8.3,15.5,8.3,15.5z M17.5,14c-0.1-0.1-0.5-0.4-1.9-0.4c-0.1,0-0.1,0-0.2,0c0,0,0,0,0,0c0,0,0,0,0,0.1c0.7,0.3,1.4,0.5,1.9,0.5c0.1,0,0.1,0,0.2,0l0,0c0,0,0.1,0,0.1,0c0,0,0,0,0-0.1c0,0,0,0,0,0C17.6,14.1,17.5,14.1,17.5,14z M19,3H5C3.9,3,3,3.9,3,5v14c0,1.1,0.9,2,2,2h14c1.1,0,2-0.9,2-2V5C21,3.9,20.1,3,19,3z M17.9,14.8C17.7,14.9,17.4,15,17,15c-0.8,0-2-0.2-3-0.7c-1.7,0.2-3,0.4-4,0.8c-0.1,0-0.1,0-0.2,0.1c-1.2,2.1-2.2,3.1-3,3.1c-0.2,0-0.3,0-0.4-0.1l-0.5-0.3l0-0.1c-0.1-0.2-0.1-0.3-0.1-0.5c0.1-0.5,0.7-1.4,1.9-2.1c0.2-0.1,0.5-0.3,0.9-0.5c0.3-0.5,0.6-1.1,1-1.8c0.5-1,0.8-2,1.1-2.9l0,0c-0.4-1.2-0.6-1.9-0.2-3.3c0.1-0.4,0.4-0.8,0.8-0.8l0.2,0c0.2,0,0.4,0.1,0.6,0.2c0.7,0.7,0.4,2.3,0,3.6c0,0.1,0,0.1,0,0.1c0.4,1.1,1,2,1.6,2.6c0.3,0.2,0.5,0.4,0.9,0.6c0.5,0,0.9-0.1,1.3-0.1c1.2,0,2,0.2,2.3,0.7c0.1,0.2,0.1,0.4,0.1,0.6C18.2,14.3,18.1,14.6,17.9,14.8z M11.4,10.9c-0.2,0.7-0.6,1.5-1,2.4c-0.2,0.4-0.4,0.7-0.6,1.1c0,0,0.1,0,0.1,0l0.1,0v0c1.3-0.5,2.5-0.8,3.3-0.9c-0.2-0.1-0.3-0.2-0.4-0.3C12.4,12.6,11.8,11.8,11.4,10.9z"/></g> +<g id="drive-presentation"><path d="M19,3H5C3.9,3,3,3.9,3,5v14c0,1.1,0.9,2,2,2h14c1.1,0,2-0.9,2-2V5C21,3.9,20.1,3,19,3z M19,16H5V8h14V16z"/></g> +<g id="drive-script"><path d="M19,3H5C3.9,3,3,3.9,3,5l0,4h0v6h0l0,4c0,1.1,0.9,2,2,2h14c1.1,0,2-0.9,2-2V5C21,3.9,20.1,3,19,3z M11,17v-3H5v-4h6V7l5,5L11,17z"/></g> +<g id="drive-site"><path d="M19,4H5C3.9,4,3,4.9,3,6l0,12c0,1.1,0.9,2,2,2h14c1.1,0,2-0.9,2-2V6C21,4.9,20.1,4,19,4z M14,18H5v-4h9V18z M14,13H5V9h9V13z M19,18h-4V9h4V18z"/></g> +<g id="drive-spreadsheet"><path d="M19,3H5C3.9,3,3,3.9,3,5l0,3h0v11c0,1.1,0.9,2,2,2h14c1.1,0,2-0.9,2-2V5C21,3.9,20.1,3,19,3z M19,11h-8v8H9v-8H5V9h4V5h2v4h8V11z"/></g> +<g id="drive-text"><path d="M14,2H6C4.9,2,4,2.9,4,4l0,16c0,1.1,0.9,2,2,2h12c1.1,0,2-0.9,2-2V8L14,2z M16,18H8v-2h8V18z M16,14H8v-2h8V14z M13,9V3.5L18.5,9H13z"/></g> +<g id="drive-video"><path d="M18,4l2,4h-3l-2-4h-2l2,4h-3l-2-4H8l2,4H7L5,4H4C2.9,4,2,4.9,2,6l0,12c0,1.1,0.9,2,2,2h16c1.1,0,2-0.9,2-2V4H18z"/></g> +<g id="drive-zip"><path d="M19,3H5C3.9,3,3,3.9,3,5v14c0,1.1,0.9,2,2,2h14c1.1,0,2-0.9,2-2V5C21,3.9,20.1,3,19,3z M14,9h-2v2h2v2h-2v-2h-2V9h2V7h-2V5h2v2h2V9z M14,17h-2v-2h-2v-2h2v2h2V17z"/></g> +<g id="due-date"><path d="M17,12h-5v5h5V12z M16,1v2H8V1H6v2H5C3.9,3,3,3.9,3,5l0,14c0,1.1,0.9,2,2,2h14c1.1,0,2-0.9,2-2V5c0-1.1-0.9-2-2-2h-1V1H16z M19,19H5V8h14V19z"/></g> +<g id="error"><path d="M12,2C6.5,2,2,6.5,2,12s4.5,10,10,10c5.5,0,10-4.5,10-10S17.5,2,12,2z M13,17h-2v-2h2V17z M13,13h-2V7h2V13z"/></g> +<g id="event"><path d="M17,12h-5v5h5V12z M16,1v2H8V1H6v2H5C3.9,3,3,3.9,3,5l0,14c0,1.1,0.9,2,2,2h14c1.1,0,2-0.9,2-2V5c0-1.1-0.9-2-2-2h-1V1H16z M19,19H5V8h14V19z"/></g> +<g id="exit-to-app"><path d="M10.1,15.6l1.4,1.4l5-5l-5-5l-1.4,1.4l2.6,2.6H3v2h9.7L10.1,15.6z M19,3H5C3.9,3,3,3.9,3,5v4h2V5h14v14H5v-4H3v4c0,1.1,0.9,2,2,2h14c1.1,0,2-0.9,2-2V5C21,3.9,20.1,3,19,3z"/></g> +<g id="expand-less"><polygon points="12,8 6,14 7.4,15.4 12,10.8 16.6,15.4 18,14 "/></g> +<g id="expand-more"><polygon points="16.6,8.6 12,13.2 7.4,8.6 6,10 12,16 18,10 "/></g> +<g id="explore"><path d="M12,10.9c-0.6,0-1.1,0.5-1.1,1.1s0.5,1.1,1.1,1.1c0.6,0,1.1-0.5,1.1-1.1S12.6,10.9,12,10.9z M12,2C6.5,2,2,6.5,2,12c0,5.5,4.5,10,10,10c5.5,0,10-4.5,10-10C22,6.5,17.5,2,12,2z M14.2,14.2L6,18l3.8-8.2L18,6L14.2,14.2z"/></g> +<g id="extension"><path d="M20.5,11H19V7c0-1.1-0.9-2-2-2h-4V3.5C13,2.1,11.9,1,10.5,1C9.1,1,8,2.1,8,3.5V5H4C2.9,5,2,5.9,2,7l0,3.8h1.5c1.5,0,2.7,1.2,2.7,2.7S5,16.2,3.5,16.2H2L2,20c0,1.1,0.9,2,2,2h3.8v-1.5c0-1.5,1.2-2.7,2.7-2.7c1.5,0,2.7,1.2,2.7,2.7V22H17c1.1,0,2-0.9,2-2v-4h1.5c1.4,0,2.5-1.1,2.5-2.5S21.9,11,20.5,11z"/></g> +<g id="favorite"><path d="M12,21.4L10.6,20C5.4,15.4,2,12.3,2,8.5C2,5.4,4.4,3,7.5,3c1.7,0,3.4,0.8,4.5,2.1C13.1,3.8,14.8,3,16.5,3C19.6,3,22,5.4,22,8.5c0,3.8-3.4,6.9-8.6,11.5L12,21.4z"/></g> +<g id="favorite-outline"><path d="M16.5,3c-1.7,0-3.4,0.8-4.5,2.1C10.9,3.8,9.2,3,7.5,3C4.4,3,2,5.4,2,8.5c0,3.8,3.4,6.9,8.6,11.5l1.4,1.3l1.4-1.3c5.1-4.7,8.6-7.8,8.6-11.5C22,5.4,19.6,3,16.5,3z M12.1,18.6L12,18.6l-0.1-0.1C7.1,14.2,4,11.4,4,8.5C4,6.5,5.5,5,7.5,5c1.5,0,3,1,3.6,2.4h1.9C13.5,6,15,5,16.5,5c2,0,3.5,1.5,3.5,3.5C20,11.4,16.9,14.2,12.1,18.6z"/></g> +<g id="file-download"><path d="M19,9h-4V3H9v6H5l7,7L19,9z M5,18v2h14v-2H5z"/></g> +<g id="file-map"><path d="M12,6.5c-0.8,0-1.5,0.7-1.5,1.5s0.7,1.5,1.5,1.5c0.8,0,1.5-0.7,1.5-1.5S12.8,6.5,12,6.5z M19,1H5C3.9,1,3,1.9,3,3v14c0,1.1,0.9,2,2,2h14c1.1,0,2-0.9,2-2V3C21,1.9,20.1,1,19,1z M12.5,17h-1c-1-4.1-4-5.8-4-9c0-2.5,2-4.5,4.5-4.5c2.5,0,4.5,2,4.5,4.5C16.5,11.2,13.5,12.9,12.5,17z"/></g> +<g id="file-upload"><polygon points="9,16 15,16 15,10 19,10 12,3 5,10 9,10 "/></g> +<g id="filter"><path d="M10,18h4v-2h-4V18z M3,6v2h18V6H3z M6,13h12v-2H6V13z"/></g> +<g id="flag"><polygon points="14.4,6 14,4 5,4 5,21 7,21 7,14 12.6,14 13,16 20,16 20,6 "/></g> +<g id="flip-to-back"><path d="M9,7H7l0,2h2V7z M9,11H7v2h2V11z M9,3C7.9,3,7,3.9,7,5h2V3z M13,15h-2v2h2V15z M19,3v2h2C21,3.9,20.1,3,19,3z M13,3h-2v2h2V3z M9,17v-2H7C7,16.1,7.9,17,9,17z M19,13h2v-2h-2V13z M19,9h2V7h-2V9z M19,17c1.1,0,2-0.9,2-2h-2V17z M5,7H3v2h0l0,10c0,1.1,0.9,2,2,2h12v-2H5V7z M15,5h2V3h-2V5z M15,17h2v-2h-2V17z"/></g> +<g id="flip-to-front"><path d="M3,13h2v-2H3L3,13z M3,17h2v-2H3V17z M5,21v-2H3C3,20.1,3.9,21,5,21z M3,9h2V7H3V9z M15,21h2v-2h-2V21z M19,3H9C7.9,3,7,3.9,7,5v2h0v2v6c0,1.1,0.9,2,2,2h5h4h1c1.1,0,2-0.9,2-2V5C21,3.9,20.1,3,19,3z M19,15H9V5h10V15z M11,21h2v-2h-2V21z M7,21h2v-2H7V21z"/></g> +<g id="folder"><path d="M10,4H4C2.9,4,2,4.9,2,6l0,12c0,1.1,0.9,2,2,2h16c1.1,0,2-0.9,2-2V8c0-1.1-0.9-2-2-2h-8L10,4z"/></g> +<g id="folder-mydrive"><path d="M20,6h-8l-2-2H4C2.9,4,2,4.9,2,6l0,12c0,1.1,0.9,2,2,2h16c1.1,0,2-0.9,2-2V8C22,6.9,21.1,6,20,6z M11.5,17l-1.1-2.1l2.8-5l1.5,2.7L12.3,17H11.5z M18.3,17h-5.5l1.4-2.5h5.1l0.3,0.5L18.3,17z M13.8,9h2.4l2.8,5H16l-2.6-4.5L13.8,9z"/></g> +<g id="folder-open"><path d="M20,6h-8l-2-2H4C2.9,4,2,4.9,2,6l0,12c0,1.1,0.9,2,2,2h16c1.1,0,2-0.9,2-2V8C22,6.9,21.1,6,20,6z M20,18H4V8h16V18z"/></g> +<g id="folder-shared"><path d="M20,6h-8l-2-2H4C2.9,4,2,4.9,2,6l0,12c0,1.1,0.9,2,2,2h16c1.1,0,2-0.9,2-2V8C22,6.9,21.1,6,20,6z M15,9c1.1,0,2,0.9,2,2c0,1.1-0.9,2-2,2c-1.1,0-2-0.9-2-2C13,9.9,13.9,9,15,9z M19,17h-8v-1c0-1.3,2.7-2,4-2c1.3,0,4,0.7,4,2V17z"/></g> +<g id="forward"><polygon points="12,8 12,4 20,12 12,20 12,16 4,16 4,8 "/></g> +<g id="fullscreen"><path d="M7,14H5v5h5v-2H7V14z M5,10h2V7h3V5H5V10z M17,17h-3v2h5v-5h-2V17z M14,5v2h3v3h2V5H14z"/></g> +<g id="fullscreen-exit"><path d="M5,16h3v3h2v-5H5V16z M8,8H5v2h5V5H8V8z M14,19h2v-3h3v-2h-5V19z M16,8V5h-2v5h5V8H16z"/></g> +<g id="gesture"><path d="M4.6,6.9C5.3,6.2,6,5.5,6.3,5.7c0.5,0.2,0,1-0.3,1.5c-0.3,0.4-2.9,3.9-2.9,6.3c0,1.3,0.5,2.3,1.3,3c0.8,0.6,1.7,0.7,2.6,0.5c1.1-0.3,1.9-1.4,3.1-2.8c1.2-1.5,2.8-3.4,4.1-3.4c1.6,0,1.6,1,1.8,1.8c-3.8,0.6-5.4,3.7-5.4,5.4c0,1.7,1.4,3.1,3.2,3.1c1.6,0,4.3-1.3,4.7-6.1H21v-2.5h-2.5c-0.2-1.6-1.1-4.2-4-4.2c-2.2,0-4.2,1.9-4.9,2.8c-0.6,0.7-2.1,2.5-2.3,2.7c-0.3,0.3-0.7,0.8-1.1,0.8c-0.4,0-0.7-0.8-0.4-1.9c0.4-1.1,1.4-2.9,1.9-3.5C8.4,8,8.9,7.2,8.9,5.9C8.9,3.7,7.3,3,6.4,3C5.1,3,4,4,3.7,4.3C3.4,4.6,3.1,4.9,2.8,5.2L4.6,6.9z M13.9,18.6c-0.3,0-0.7-0.3-0.7-0.7c0-0.6,0.7-2.2,2.9-2.8C15.7,17.8,14.6,18.6,13.9,18.6z"/></g> +<g id="get-app"><path d="M19,9h-4V3H9v6H5l7,7L19,9z M5,18v2h14v-2H5z"/></g> +<g id="google"><path d="M16.3,13.4l-1.1-0.8c-0.4-0.3-0.8-0.7-0.8-1.4c0-0.7,0.5-1.3,1-1.6c1.3-1,2.6-2.1,2.6-4.3c0-2.1-1.3-3.3-2-3.9h1.7L18.9,0h-6.2C8.3,0,6.1,2.8,6.1,5.8c0,2.3,1.8,4.8,5,4.8h0.8c-0.1,0.3-0.4,0.8-0.4,1.3c0,1,0.4,1.4,0.9,2c-1.4,0.1-4,0.4-5.9,1.6c-1.8,1.1-2.3,2.6-2.3,3.7c0,2.3,2.1,4.5,6.6,4.5c5.4,0,8-3,8-5.9C18.8,15.7,17.7,14.6,16.3,13.4z M8.7,4.3c0-2.2,1.3-3.2,2.7-3.2c2.6,0,4,3.5,4,5.5c0,2.6-2.1,3.1-2.9,3.1C10,9.7,8.7,6.6,8.7,4.3z M12.3,22.3c-3.3,0-5.4-1.5-5.4-3.7c0-2.2,2-2.9,2.6-3.2c1.3-0.4,3-0.5,3.3-0.5c0.3,0,0.5,0,0.7,0c2.4,1.7,3.4,2.4,3.4,4C16.9,20.8,15,22.3,12.3,22.3z"/></g> +<g id="google-plus"><path d="M21,10V7h-2v3h-3v2h3v3h2v-3h3v-2H21z M13.3,13.4l-1.1-0.8c-0.4-0.3-0.8-0.7-0.8-1.4c0-0.7,0.5-1.3,1-1.6c1.3-1,2.6-2.1,2.6-4.3c0-2.1-1.3-3.3-2-3.9h1.7L15.9,0H9.7C5.3,0,3.1,2.8,3.1,5.8c0,2.3,1.8,4.8,5,4.8h0.8c-0.1,0.3-0.4,0.8-0.4,1.3c0,1,0.4,1.4,0.9,2c-1.4,0.1-4,0.4-5.9,1.6c-1.8,1.1-2.3,2.6-2.3,3.7c0,2.3,2.1,4.5,6.6,4.5c5.4,0,8-3,8-5.9C15.8,15.7,14.7,14.6,13.3,13.4z M5.7,4.3c0-2.2,1.3-3.2,2.7-3.2c2.6,0,4,3.5,4,5.5c0,2.6-2.1,3.1-2.9,3.1C7,9.7,5.7,6.6,5.7,4.3z M9.3,22.3c-3.3,0-5.4-1.5-5.4-3.7c0-2.2,2-2.9,2.6-3.2c1.3-0.4,3-0.5,3.3-0.5c0.3,0,0.5,0,0.7,0c2.4,1.7,3.4,2.4,3.4,4C13.9,20.8,12,22.3,9.3,22.3z"/></g> +<g id="grade"><polygon points="12,17.3 18.2,21 16.5,14 22,9.2 14.8,8.6 12,2 9.2,8.6 2,9.2 7.5,14 5.8,21 "/></g> +<g id="group-work"><path d="M12,2C6.5,2,2,6.5,2,12c0,5.5,4.5,10,10,10c5.5,0,10-4.5,10-10C22,6.5,17.5,2,12,2z M8,17.5c-1.4,0-2.5-1.1-2.5-2.5s1.1-2.5,2.5-2.5s2.5,1.1,2.5,2.5S9.4,17.5,8,17.5z M9.5,8c0-1.4,1.1-2.5,2.5-2.5s2.5,1.1,2.5,2.5s-1.1,2.5-2.5,2.5S9.5,9.4,9.5,8z M16,17.5c-1.4,0-2.5-1.1-2.5-2.5s1.1-2.5,2.5-2.5s2.5,1.1,2.5,2.5S17.4,17.5,16,17.5z"/></g> +<g id="help"><path d="M12,2C6.5,2,2,6.5,2,12s4.5,10,10,10c5.5,0,10-4.5,10-10S17.5,2,12,2z M13,19h-2v-2h2V19z M15.1,11.3l-0.9,0.9C13.4,12.9,13,13.5,13,15h-2v-0.5c0-1.1,0.4-2.1,1.2-2.8l1.2-1.3C13.8,10.1,14,9.6,14,9c0-1.1-0.9-2-2-2c-1.1,0-2,0.9-2,2H8c0-2.2,1.8-4,4-4c2.2,0,4,1.8,4,4C16,9.9,15.6,10.7,15.1,11.3z"/></g> +<g id="highlight-remove"><path d="M14.6,8L12,10.6L9.4,8L8,9.4l2.6,2.6L8,14.6L9.4,16l2.6-2.6l2.6,2.6l1.4-1.4L13.4,12L16,9.4L14.6,8z M12,2C6.5,2,2,6.5,2,12s4.5,10,10,10c5.5,0,10-4.5,10-10S17.5,2,12,2z M12,20c-4.4,0-8-3.6-8-8s3.6-8,8-8s8,3.6,8,8S16.4,20,12,20z"/></g> +<g id="history"><path opacity="0.9" d="M13,3c-5,0-9,4-9,9H1l3.9,3.9c0,0,0,0.1,0.1,0.1l4-4H6c0-3.9,3.1-7,7-7c3.9,0,7,3.1,7,7s-3.1,7-7,7c-1.9,0-3.7-0.8-4.9-2.1l-1.4,1.4C8.3,20,10.5,21,13,21c5,0,9-4,9-9S18,3,13,3z M12,8v5l4.3,2.5l0.7-1.2l-3.5-2.1V8H12z"/></g> +<g id="home"><polygon points="10,20 10,14 14,14 14,20 19,20 19,12 22,12 12,3 2,12 5,12 5,20 "/></g> +<g id="https"><path d="M18,8h-1V6c0-2.8-2.2-5-5-5C9.2,1,7,3.2,7,6v2H6c-1.1,0-2,0.9-2,2v10c0,1.1,0.9,2,2,2h12c1.1,0,2-0.9,2-2V10C20,8.9,19.1,8,18,8z M12,17c-1.1,0-2-0.9-2-2s0.9-2,2-2c1.1,0,2,0.9,2,2S13.1,17,12,17z M15.1,8H8.9V6c0-1.7,1.4-3.1,3.1-3.1c1.7,0,3.1,1.4,3.1,3.1V8z"/></g> +<g id="inbox"><path d="M19,3H5C3.9,3,3,3.9,3,5l0,14c0,1.1,0.9,2,2,2h14c1.1,0,2-0.9,2-2V5C21,3.9,20.1,3,19,3z M19,15h-4c0,1.7-1.3,3-3,3c-1.7,0-3-1.3-3-3H5V5h14V15z M16,10h-2V7h-4v3H8l4,4L16,10z"/></g> +<g id="info"><path d="M12,2C6.5,2,2,6.5,2,12s4.5,10,10,10c5.5,0,10-4.5,10-10S17.5,2,12,2z M13,17h-2v-6h2V17z M13,9h-2V7h2V9z"/></g> +<g id="info-outline"><path d="M11,17h2v-6h-2V17z M12,2C6.5,2,2,6.5,2,12s4.5,10,10,10c5.5,0,10-4.5,10-10S17.5,2,12,2z M12,20c-4.4,0-8-3.6-8-8s3.6-8,8-8c4.4,0,8,3.6,8,8S16.4,20,12,20z M11,9h2V7h-2V9z"/></g> +<g id="input"><path d="M21,3H3C1.9,3,1,3.9,1,5v4h2V5h18v14H3v-4H1v4c0,1.1,0.9,2,2,2h18c1.1,0,2-0.9,2-2V5C23,3.9,22.1,3,21,3z M11,16l4-4l-4-4v3H1v2h10V16z"/></g> +<g id="invert-colors"><path d="M17.7,7.9L12,2.3l0,0v0L6.3,7.9c-3.1,3.1-3.1,8.2,0,11.3c1.6,1.6,3.6,2.3,5.7,2.3c2,0,4.1-0.8,5.7-2.3C20.8,16.1,20.8,11.1,17.7,7.9z M12,19.6L12,19.6c-1.6,0-3.1-0.6-4.2-1.8C6.6,16.7,6,15.2,6,13.6c0-1.6,0.6-3.1,1.8-4.2L12,5.1L12,19.6z"/></g> +<g id="keep"><path d="M16,12V4h1V2H7v2h1v8l-2,2v2h5.2v6h1.6v-6H18v-2L16,12z"/></g> +<g id="label"><path d="M17.6,5.8C17.3,5.3,16.7,5,16,5L5,5C3.9,5,3,5.9,3,7v10c0,1.1,0.9,2,2,2l11,0c0.7,0,1.3-0.3,1.6-0.8L22,12L17.6,5.8z"/></g> +<g id="label-outline"><path d="M17.6,5.8C17.3,5.3,16.7,5,16,5L5,5C3.9,5,3,5.9,3,7v10c0,1.1,0.9,2,2,2l11,0c0.7,0,1.3-0.3,1.6-0.8L22,12L17.6,5.8z M16,17H5V7h11l3.5,5L16,17z"/></g> +<g id="language"><path d="M12,2C6.5,2,2,6.5,2,12s4.5,10,10,10c5.5,0,10-4.5,10-10S17.5,2,12,2z M18.9,8H16c-0.3-1.3-0.8-2.4-1.4-3.6C16.4,5.1,18,6.3,18.9,8z M12,4c0.8,1.2,1.5,2.5,1.9,4h-3.8C10.5,6.6,11.2,5.2,12,4z M4.3,14C4.1,13.4,4,12.7,4,12s0.1-1.4,0.3-2h3.4c-0.1,0.7-0.1,1.3-0.1,2s0.1,1.3,0.1,2H4.3z M5.1,16H8c0.3,1.3,0.8,2.4,1.4,3.6C7.6,18.9,6,17.7,5.1,16z M8,8H5.1c1-1.7,2.5-2.9,4.3-3.6C8.8,5.6,8.3,6.7,8,8z M12,20c-0.8-1.2-1.5-2.5-1.9-4h3.8C13.5,17.4,12.8,18.8,12,20z M14.3,14H9.7c-0.1-0.7-0.2-1.3-0.2-2s0.1-1.3,0.2-2h4.7c0.1,0.7,0.2,1.3,0.2,2S14.4,13.3,14.3,14z M14.6,19.6c0.6-1.1,1.1-2.3,1.4-3.6h2.9C18,17.7,16.4,18.9,14.6,19.6z M16.4,14c0.1-0.7,0.1-1.3,0.1-2s-0.1-1.3-0.1-2h3.4c0.2,0.6,0.3,1.3,0.3,2s-0.1,1.4-0.3,2H16.4z"/></g> +<g id="launch"><path d="M19,19H5V5h7V3H5C3.9,3,3,3.9,3,5v14c0,1.1,0.9,2,2,2h14c1.1,0,2-0.9,2-2v-7h-2V19z M14,3v2h3.6l-9.8,9.8l1.4,1.4L19,6.4V10h2V3H14z"/></g> +<g id="link"><path d="M3.9,12c0-1.7,1.4-3.1,3.1-3.1h4V7H7c-2.8,0-5,2.2-5,5s2.2,5,5,5h4v-1.9H7C5.3,15.1,3.9,13.7,3.9,12z M8,13h8v-2H8V13z M17,7h-4v1.9h4c1.7,0,3.1,1.4,3.1,3.1s-1.4,3.1-3.1,3.1h-4V17h4c2.8,0,5-2.2,5-5S19.8,7,17,7z"/></g> +<g id="list"><path d="M3,13h2v-2H3V13z M3,17h2v-2H3V17z M3,9h2V7H3V9z M7,13h14v-2H7V13z M7,17h14v-2H7V17z M7,7v2h14V7H7z"/></g> +<g id="lock"><path d="M18,8h-1V6c0-2.8-2.2-5-5-5C9.2,1,7,3.2,7,6v2H6c-1.1,0-2,0.9-2,2v10c0,1.1,0.9,2,2,2h12c1.1,0,2-0.9,2-2V10C20,8.9,19.1,8,18,8z M12,17c-1.1,0-2-0.9-2-2s0.9-2,2-2c1.1,0,2,0.9,2,2S13.1,17,12,17z M15.1,8H8.9V6c0-1.7,1.4-3.1,3.1-3.1c1.7,0,3.1,1.4,3.1,3.1V8z"/></g> +<g id="lock-open"><path d="M12,17c1.1,0,2-0.9,2-2s-0.9-2-2-2c-1.1,0-2,0.9-2,2S10.9,17,12,17z M18,8h-1V6c0-2.8-2.2-5-5-5C9.2,1,7,3.2,7,6h1.9c0-1.7,1.4-3.1,3.1-3.1c1.7,0,3.1,1.4,3.1,3.1v2H6c-1.1,0-2,0.9-2,2v10c0,1.1,0.9,2,2,2h12c1.1,0,2-0.9,2-2V10C20,8.9,19.1,8,18,8z M18,20H6V10h12V20z"/></g> +<g id="lock-outline"><path d="M18,8h-1V6c0-2.8-2.2-5-5-5C9.2,1,7,3.2,7,6v2H6c-1.1,0-2,0.9-2,2v10c0,1.1,0.9,2,2,2h12c1.1,0,2-0.9,2-2V10C20,8.9,19.1,8,18,8z M12,2.9c1.7,0,3.1,1.4,3.1,3.1v2H9V6H8.9C8.9,4.3,10.3,2.9,12,2.9z M18,20H6V10h12V20z M12,17c1.1,0,2-0.9,2-2s-0.9-2-2-2c-1.1,0-2,0.9-2,2S10.9,17,12,17z"/></g> +<g id="loyalty"><path d="M21.4,11.6l-9-9C12.1,2.2,11.6,2,11,2H4C2.9,2,2,2.9,2,4v7c0,0.6,0.2,1.1,0.6,1.4l9,9c0.4,0.4,0.9,0.6,1.4,0.6c0.6,0,1.1-0.2,1.4-0.6l7-7c0.4-0.4,0.6-0.9,0.6-1.4C22,12.4,21.8,11.9,21.4,11.6z M5.5,7C4.7,7,4,6.3,4,5.5S4.7,4,5.5,4S7,4.7,7,5.5S6.3,7,5.5,7z M17.3,15.3L13,19.5l-4.3-4.3l0,0C8.3,14.8,8,14.2,8,13.5c0-1.4,1.1-2.5,2.5-2.5c0.7,0,1.3,0.3,1.8,0.7l0.7,0.7l0.7-0.7c0.5-0.5,1.1-0.7,1.8-0.7c1.4,0,2.5,1.1,2.5,2.5C18,14.2,17.7,14.8,17.3,15.3L17.3,15.3z"/></g> +<g id="mail"><path d="M20,4H4C2.9,4,2,4.9,2,6l0,12c0,1.1,0.9,2,2,2h16c1.1,0,2-0.9,2-2V6C22,4.9,21.1,4,20,4z M20,8l-8,5L4,8V6l8,5l8-5V8z"/></g> +<g id="markunread"><path d="M20,6H10v6H8V4h6V0H6v6H4C2.9,6,2,6.9,2,8l0,12c0,1.1,0.9,2,2,2h16c1.1,0,2-0.9,2-2V8C22,6.9,21.1,6,20,6z"/></g> +<g id="markunread"><path d="M22,6l2-2l-2-2l-2,2l-2-2l-2,2l-2-2l-2,2l-2-2L8,4L6,2L4,4L2,2L0,4l2,2L0,8l2,2l-2,2l2,2l-2,2l2,2l-2,2l2,2l2-2l2,2l2-2l2,2l2-2l2,2l2-2l2,2l2-2l2,2l2-2l-2-2l2-2l-2-2l2-2l-2-2l2-2L22,6z M20,8l-8,5L4,8V6l8,5l8-5V8z"/></g> +<g id="menu"><path d="M3,18h18v-2H3V18z M3,13h18v-2H3V13z M3,6v2h18V6H3z"/></g> +<g id="more-horiz"><path d="M6,10c-1.1,0-2,0.9-2,2s0.9,2,2,2c1.1,0,2-0.9,2-2S7.1,10,6,10z M18,10c-1.1,0-2,0.9-2,2s0.9,2,2,2c1.1,0,2-0.9,2-2S19.1,10,18,10z M12,10c-1.1,0-2,0.9-2,2s0.9,2,2,2c1.1,0,2-0.9,2-2S13.1,10,12,10z"/></g> +<g id="more-vert"><path d="M12,8c1.1,0,2-0.9,2-2s-0.9-2-2-2c-1.1,0-2,0.9-2,2S10.9,8,12,8z M12,10c-1.1,0-2,0.9-2,2s0.9,2,2,2c1.1,0,2-0.9,2-2S13.1,10,12,10z M12,16c-1.1,0-2,0.9-2,2s0.9,2,2,2c1.1,0,2-0.9,2-2S13.1,16,12,16z"/></g> +<g id="note-add"><path d="M14,2H6C4.9,2,4,2.9,4,4l0,16c0,1.1,0.9,2,2,2h12c1.1,0,2-0.9,2-2V8L14,2z M16,16h-3v3h-2v-3H8v-2h3v-3h2v3h3V16z M13,9V3.5L18.5,9H13z"/></g> +<g id="open-in-browser"><path d="M19,4H5C3.9,4,3,4.9,3,6v12c0,1.1,0.9,2,2,2h3v-2H5V8h14v10h-3v2h3c1.1,0,2-0.9,2-2V6C21,4.9,20.1,4,19,4z M12,10l-5,5h3v5h4v-5h3L12,10z"/></g> +<g id="open-in-new"><path d="M19,19H5V5h7V3H5C3.9,3,3,3.9,3,5v14c0,1.1,0.9,2,2,2h14c1.1,0,2-0.9,2-2v-7h-2V19z M14,3v2h3.6l-9.8,9.8l1.4,1.4L19,6.4V10h2V3H14z"/></g> +<g id="open-with"><path d="M10,9h4V6h3l-5-5L7,6h3V9z M9,10H6V7l-5,5l5,5v-3h3V10z M23,12l-5-5v3h-3v4h3v3L23,12z M14,15h-4v3H7l5,5l5-5h-3V15z"/></g> +<g id="payment"><path d="M20,4H4C2.9,4,2,4.9,2,6l0,12c0,1.1,0.9,2,2,2h16c1.1,0,2-0.9,2-2V6C22,4.9,21.1,4,20,4z M20,18H4v-6h16V18z M20,8H4V6h16V8z"/></g> +<g id="perm-camera-mic"><path d="M20,5h-3.2L15,3H9L7.2,5H4C2.9,5,2,5.9,2,7v12c0,1.1,0.9,2,2,2h7v-2.1C8.2,18.4,6,16,6,13h2c0,2.2,1.8,4,4,4s4-1.8,4-4h2c0,3-2.2,5.4-5,5.9V21h7c1.1,0,2-0.9,2-2V7C22,5.9,21.1,5,20,5z M14,13c0,1.1-0.9,2-2,2s-2-0.9-2-2V9c0-1.1,0.9-2,2-2s2,0.9,2,2V13z"/></g> +<g id="perm-contact-cal"><path d="M19,3h-1V1h-2v2H8V1H6v2H5C3.9,3,3,3.9,3,5l0,14c0,1.1,0.9,2,2,2h14c1.1,0,2-0.9,2-2V5C21,3.9,20.1,3,19,3z M12,6c1.7,0,3,1.3,3,3c0,1.7-1.3,3-3,3s-3-1.3-3-3C9,7.3,10.3,6,12,6z M18,18H6v-1c0-2,4-3.1,6-3.1s6,1.1,6,3.1V18z"/></g> +<g id="perm-data-setting"><path d="M19,11.5c0.3,0,0.7,0,1,0.1V0L0,20h11.6c0-0.3-0.1-0.7-0.1-1C11.5,14.9,14.9,11.5,19,11.5z M22.7,19.5c0-0.2,0-0.3,0-0.5c0-0.2,0-0.3,0-0.5l1.1-0.8c0.1-0.1,0.1-0.2,0.1-0.3l-1-1.7c-0.1-0.1-0.2-0.2-0.3-0.1L21.3,16c-0.3-0.2-0.5-0.4-0.8-0.5l-0.2-1.3c0-0.1-0.1-0.2-0.2-0.2h-2c-0.1,0-0.2,0.1-0.2,0.2l-0.2,1.3c-0.3,0.1-0.6,0.3-0.8,0.5l-1.2-0.5c-0.1,0-0.2,0-0.3,0.1l-1,1.7c-0.1,0.1,0,0.2,0.1,0.3l1.1,0.8c0,0.2,0,0.3,0,0.5c0,0.2,0,0.3,0,0.5l-1.1,0.8c-0.1,0.1-0.1,0.2-0.1,0.3l1,1.7c0.1,0.1,0.2,0.2,0.3,0.1l1.2-0.5c0.3,0.2,0.5,0.4,0.8,0.5l0.2,1.3c0,0.1,0.1,0.2,0.2,0.2h2c0.1,0,0.2-0.1,0.2-0.2l0.2-1.3c0.3-0.1,0.6-0.3,0.8-0.5l1.2,0.5c0.1,0,0.2,0,0.3-0.1l1-1.7c0.1-0.1,0-0.2-0.1-0.3L22.7,19.5z M19,20.5c-0.8,0-1.5-0.7-1.5-1.5s0.7-1.5,1.5-1.5s1.5,0.7,1.5,1.5S19.8,20.5,19,20.5z"/></g> +<g id="perm-device-info"><path d="M13,7h-2v2h2V7z M13,11h-2v6h2V11z M17,1L7,1C5.9,1,5,1.9,5,3v18c0,1.1,0.9,2,2,2h10c1.1,0,2-0.9,2-2V3C19,1.9,18.1,1,17,1z M17,19H7V5h10V19z"/></g> +<g id="perm-identity"><path d="M12,5.9c1.2,0,2.1,0.9,2.1,2.1s-0.9,2.1-2.1,2.1S9.9,9.2,9.9,8S10.8,5.9,12,5.9 M12,14.9c3,0,6.1,1.5,6.1,2.1v1.1H5.9V17C5.9,16.4,9,14.9,12,14.9 M12,4C9.8,4,8,5.8,8,8c0,2.2,1.8,4,4,4c2.2,0,4-1.8,4-4C16,5.8,14.2,4,12,4L12,4z M12,13c-2.7,0-8,1.3-8,4v3h16v-3C20,14.3,14.7,13,12,13L12,13z"/></g> +<g id="perm-media"><path d="M2,6H0v5h0l0,9c0,1.1,0.9,2,2,2h18v-2H2V6z M22,4h-8l-2-2H6C4.9,2,4,2.9,4,4l0,12c0,1.1,0.9,2,2,2h16c1.1,0,2-0.9,2-2V6C24,4.9,23.1,4,22,4z M7,15l4.5-6l3.5,4.5l2.5-3L21,15H7z"/></g> +<g id="perm-phone-msg"><path d="M20,15.5c-1.2,0-2.4-0.2-3.6-0.6c-0.3-0.1-0.7,0-1,0.2l-2.2,2.2c-2.8-1.4-5.1-3.8-6.6-6.6l2.2-2.2c0.3-0.3,0.4-0.7,0.2-1C8.7,6.4,8.5,5.2,8.5,4c0-0.6-0.4-1-1-1H4C3.5,3,3,3.4,3,4c0,9.4,7.6,17,17,17c0.6,0,1-0.4,1-1v-3.5C21,15.9,20.6,15.5,20,15.5z M12,3v10l3-3h6V3H12z"/></g> +<g id="perm-scan-wifi"><path d="M12,3C7,3,3.2,4.9,0,7.2L12,22L24,7.3C20.9,4.9,17.1,3,12,3z M13,16h-2v-6h2V16z M11,8V6h2v2H11z"/></g> +<g id="picture-in-picture"><path d="M19,7h-8v6h8V7z M21,3H3C1.9,3,1,3.9,1,5v14c0,1.1,0.9,2,2,2h18c1.1,0,2-0.9,2-2V5C23,3.9,22.1,3,21,3z M21,19H3V5h18V19z"/></g> +<g id="polymer"><polygon points="19,4 15,4 7.1,16.6 4.5,12 9,4 5,4 0.5,12 5,20 9,20 16.9,7.4 19.5,12 15,20 19,20 23.5,12 "/></g> +<g id="print"><path d="M19,8H5c-1.7,0-3,1.3-3,3v6h4v4h12v-4h4v-6C22,9.3,20.7,8,19,8z M16,19H8v-5h8V19z M19,12c-0.6,0-1-0.4-1-1s0.4-1,1-1c0.6,0,1,0.4,1,1S19.6,12,19,12z M18,3H6v4h12V3z"/></g> +<g id="query-builder"><path d="M12,2C6.5,2,2,6.5,2,12s4.5,10,10,10c5.5,0,10-4.5,10-10S17.5,2,12,2z M12,20c-4.4,0-8-3.6-8-8s3.6-8,8-8c4.4,0,8,3.6,8,8S16.4,20,12,20z"/><polygon points="12.5,7 11,7 11,13 16.2,16.2 17,14.9 12.5,12.3 "/></g> +<g id="question-answer"><path d="M21,6h-2v9H6v2c0,0.6,0.4,1,1,1h11l4,4V7C22,6.4,21.6,6,21,6z M17,12V3c0-0.6-0.4-1-1-1H3C2.4,2,2,2.4,2,3v14l4-4h10C16.6,13,17,12.6,17,12z"/></g> +<g id="radio-button-off"><path d="M12,2C6.5,2,2,6.5,2,12s4.5,10,10,10c5.5,0,10-4.5,10-10S17.5,2,12,2z M12,20c-4.4,0-8-3.6-8-8s3.6-8,8-8c4.4,0,8,3.6,8,8S16.4,20,12,20z"/></g> +<g id="radio-button-on"><path d="M12,7c-2.8,0-5,2.2-5,5s2.2,5,5,5c2.8,0,5-2.2,5-5S14.8,7,12,7z M12,2C6.5,2,2,6.5,2,12s4.5,10,10,10c5.5,0,10-4.5,10-10S17.5,2,12,2z M12,20c-4.4,0-8-3.6-8-8s3.6-8,8-8c4.4,0,8,3.6,8,8S16.4,20,12,20z"/></g> +<g id="receipt"><path d="M18,17H6v-2h12V17z M18,13H6v-2h12V13z M18,9H6V7h12V9z M3,22l1.5-1.5L6,22l1.5-1.5L9,22l1.5-1.5L12,22l1.5-1.5L15,22l1.5-1.5L18,22l1.5-1.5L21,22V2l-1.5,1.5L18,2l-1.5,1.5L15,2l-1.5,1.5L12,2l-1.5,1.5L9,2L7.5,3.5L6,2L4.5,3.5L3,2V22z"/></g> +<g id="redeem"><path d="M20,6h-2.2C17.9,5.7,18,5.4,18,5c0-1.7-1.3-3-3-3c-1,0-2,0.5-2.5,1.3l0,0L12,4l-0.5-0.7l0,0C11,2.5,10.1,2,9,2C7.4,2,6,3.3,6,5c0,0.4,0.1,0.7,0.2,1H4C2.9,6,2,6.9,2,8l0,11c0,1.1,0.9,2,2,2h16c1.1,0,2-0.9,2-2V8C22,6.9,21.1,6,20,6z M15,4c0.6,0,1,0.4,1,1s-0.4,1-1,1s-1-0.4-1-1S14.5,4,15,4z M9,4c0.6,0,1,0.4,1,1S9.6,6,9,6S8,5.6,8,5S8.5,4,9,4z M20,19H4v-2h16V19z M20,14H4V8h5.1L7,10.8L8.6,12L11,8.8l1-1.4l1,1.4l2.4,3.2l1.6-1.2L14.9,8H20V14z"/></g> +<g id="refresh"><path d="M17.6,6.4C16.2,4.9,14.2,4,12,4c-4.4,0-8,3.6-8,8s3.6,8,8,8c3.7,0,6.8-2.6,7.7-6h-2.1c-0.8,2.3-3,4-5.6,4c-3.3,0-6-2.7-6-6s2.7-6,6-6c1.7,0,3.1,0.7,4.2,1.8L13,11h7V4L17.6,6.4z"/></g> +<g id="reminder"><path d="M16.9,13c1.3-1.3,2.1-3,2.1-5c0-3.9-3.1-7-7-7C8.1,1,5,4.1,5,8c0,2,0.8,3.7,2.1,5l0,0l3.5,3.5L6,21.1l1.4,1.4L16.9,13z M15.5,11.5L15.5,11.5L12,15.1l-3.5-3.5l0,0l0,0C7.6,10.6,7,9.4,7,8c0-2.8,2.2-5,5-5c2.8,0,5,2.2,5,5C17,9.4,16.4,10.6,15.5,11.5L15.5,11.5z M13.4,19.3l3.2,3.2l1.4-1.4l-3.2-3.2L13.4,19.3z"/></g> +<g id="remove"><path d="M19,13H5v-2h14V13z"/></g> +<g id="remove-circle"><path d="M12,2C6.5,2,2,6.5,2,12s4.5,10,10,10c5.5,0,10-4.5,10-10S17.5,2,12,2z M17,13H7v-2h10V13z"/></g> +<g id="remove-circle-outline"><path d="M7,11v2h10v-2H7z M12,2C6.5,2,2,6.5,2,12s4.5,10,10,10c5.5,0,10-4.5,10-10S17.5,2,12,2z M12,20c-4.4,0-8-3.6-8-8s3.6-8,8-8c4.4,0,8,3.6,8,8S16.4,20,12,20z"/></g> +<g id="reorder"><path d="M4,16h16v-2H4V16z M4,9v2h16V9H4z"/></g> +<g id="reply"><path d="M10,9V5l-7,7l7,7v-4.1c5,0,8.5,1.6,11,5.1C20,15,17,10,10,9z"/></g> +<g id="reply-all"><path d="M7,8V5l-7,7l7,7v-3l-4-4L7,8z M13,9V5l-7,7l7,7v-4.1c5,0,8.5,1.6,11,5.1C23,15,20,10,13,9z"/></g> +<g id="report"><path d="M15.7,3H8.3L3,8.3v7.5L8.3,21h7.5l5.3-5.3V8.3L15.7,3z M12,17.3c-0.7,0-1.3-0.6-1.3-1.3c0-0.7,0.6-1.3,1.3-1.3c0.7,0,1.3,0.6,1.3,1.3C13.3,16.7,12.7,17.3,12,17.3z M13,13h-2V7h2V13z"/></g> +<g id="report-problem"><path d="M1,21h22L12,2L1,21z M13,18h-2v-2h2V18z M13,14h-2v-4h2V14z"/></g> +<g id="restore"><path d="M13,3c-5,0-9,4-9,9H1l3.9,3.9c0,0,0,0.1,0.1,0.1l4-4H6c0-3.9,3.1-7,7-7c3.9,0,7,3.1,7,7s-3.1,7-7,7c-1.9,0-3.7-0.8-4.9-2.1l-1.4,1.4C8.3,20,10.5,21,13,21c5,0,9-4,9-9S18,3,13,3z M12,8v5l4.3,2.5l0.7-1.2l-3.5-2.1V8H12z"/></g> +<g id="room"><path d="M12,2C8.1,2,5,5.1,5,9c0,5.2,7,13,7,13s7-7.8,7-13C19,5.1,15.9,2,12,2z M12,11.5c-1.4,0-2.5-1.1-2.5-2.5s1.1-2.5,2.5-2.5c1.4,0,2.5,1.1,2.5,2.5S13.4,11.5,12,11.5z"/></g> +<g id="rotate-left"><path d="M7.1,8.5L5.7,7.1C4.8,8.3,4.2,9.6,4.1,11h2C6.2,10.1,6.6,9.3,7.1,8.5z M6.1,13h-2c0.2,1.4,0.7,2.7,1.6,3.9l1.4-1.4C6.6,14.7,6.2,13.9,6.1,13z M7.1,18.3c1.2,0.9,2.5,1.4,3.9,1.6v-2c-0.9-0.1-1.7-0.5-2.5-1L7.1,18.3z M13,4.1V1L8.5,5.5L13,10V6.1c2.8,0.5,5,2.9,5,5.9s-2.2,5.4-5,5.9v2c3.9-0.5,7-3.9,7-7.9S16.9,4.6,13,4.1z"/></g> +<g id="rotate-right"><path d="M15.5,5.5L11,1v3.1C7.1,4.6,4,7.9,4,12s3.1,7.4,7,7.9v-2C8.2,17.4,6,15,6,12s2.2-5.4,5-5.9V10L15.5,5.5z M19.9,11c-0.2-1.4-0.7-2.7-1.6-3.9l-1.4,1.4c0.5,0.8,0.9,1.6,1,2.5H19.9z M13,17.9v2c1.4-0.2,2.7-0.7,3.9-1.6l-1.4-1.4C14.7,17.4,13.9,17.8,13,17.9z M16.9,15.5l1.4,1.4c0.9-1.2,1.5-2.5,1.6-3.9h-2C17.8,13.9,17.4,14.7,16.9,15.5z"/></g> +<g id="rotation-3d"><path d="M11,14v-1c0-0.6-0.4-1-1-1c0.6,0,1-0.4,1-1v-1c0-1.1-0.9-2-2-2H6v2h3v1H7v2h2v1l0,0l0,0v0h0H6v2h3C10.1,16,11,15.1,11,14z M15,8h-3v8h3c1.7,0,3-1.3,3-3v-2C18,9.3,16.7,8,15,8z M16,13c0,0.6-0.4,1-1,1h-1v-4h1c0.6,0,1,0.4,1,1V13z M12,0c-0.2,0-0.4,0-0.7,0l3.8,3.8l1.3-1.3c3.3,1.5,5.6,4.7,6,8.5h1.5C23.4,4.8,18.3,0,12,0z M7.5,21.5c-3.3-1.5-5.6-4.7-6-8.5H0.1C0.6,19.2,5.7,24,12,24c0.2,0,0.4,0,0.7,0l-3.8-3.8L7.5,21.5z"/></g> +<g id="save"><path d="M17,3H5C3.9,3,3,3.9,3,5l0,14c0,1.1,0.9,2,2,2h14c1.1,0,2-0.9,2-2V7L17,3z M12,19c-1.7,0-3-1.3-3-3s1.3-3,3-3c1.7,0,3,1.3,3,3S13.7,19,12,19z M15,9H5V5h10V9z"/></g> +<g id="schedule"><path fill-opacity="0.9" d="M12,2C6.5,2,2,6.5,2,12s4.5,10,10,10c5.5,0,10-4.5,10-10S17.5,2,12,2z M12,20c-4.4,0-8-3.6-8-8s3.6-8,8-8c4.4,0,8,3.6,8,8S16.4,20,12,20z"/><polygon fill-opacity="0.9" points="12.5,7 11,7 11,13 16.2,16.2 17,14.9 12.5,12.2 "/></g> +<g id="search"><path d="M15.5,14h-0.8l-0.3-0.3c1-1.1,1.6-2.6,1.6-4.2C16,5.9,13.1,3,9.5,3C5.9,3,3,5.9,3,9.5S5.9,16,9.5,16c1.6,0,3.1-0.6,4.2-1.6l0.3,0.3v0.8l5,5l1.5-1.5L15.5,14z M9.5,14C7,14,5,12,5,9.5S7,5,9.5,5C12,5,14,7,14,9.5S12,14,9.5,14z"/></g> +<g id="select-all"><path d="M3,5h2V3C3.9,3,3,3.9,3,5z M3,13h2v-2H3V13z M7,21h2v-2H7V21z M3,9h2V7H3V9z M13,3h-2v2h2V3z M19,3v2h2C21,3.9,20.1,3,19,3z M5,21v-2H3C3,20.1,3.9,21,5,21z M3,17h2v-2H3V17z M9,3H7v2h2V3z M11,21h2v-2h-2V21z M19,13h2v-2h-2V13z M19,21c1.1,0,2-0.9,2-2h-2V21z M19,9h2V7h-2V9z M19,17h2v-2h-2V17z M15,21h2v-2h-2V21z M15,5h2V3h-2V5z M7,17h10V7H7V17z M9,9h6v6H9V9z"/></g> +<g id="send"><polygon points="2,21 23,12 2,3 2,10 17,12 2,14 "/></g> +<g id="send-money"><path d="M2,12c0-2.6,1.7-4.8,4-5.7V4.3c-3.4,0.9-6,4-6,7.7s2.6,6.8,6,7.7v-2.1C3.7,16.8,2,14.6,2,12z M24,12l-4-4v3h-7v2h7v3L24,12z M14,18c-3.3,0-6-2.7-6-6s2.7-6,6-6c1.7,0,3.2,0.7,4.2,1.8l1.4-1.4C18.2,4.9,16.2,4,14,4c-4.4,0-8,3.6-8,8s3.6,8,8,8c2.2,0,4.2-0.9,5.7-2.3l-1.4-1.4C17.2,17.3,15.7,18,14,18z"/></g> +<g id="settings"><path d="M19.4,13c0-0.3,0.1-0.6,0.1-1s0-0.7-0.1-1l2.1-1.7c0.2-0.2,0.2-0.4,0.1-0.6l-2-3.5C19.5,5.1,19.3,5,19,5.1l-2.5,1c-0.5-0.4-1.1-0.7-1.7-1l-0.4-2.6C14.5,2.2,14.2,2,14,2h-4C9.8,2,9.5,2.2,9.5,2.4L9.1,5.1C8.5,5.3,8,5.7,7.4,6.1L5,5.1C4.7,5,4.5,5.1,4.3,5.3l-2,3.5C2.2,8.9,2.3,9.2,2.5,9.4L4.6,11c0,0.3-0.1,0.6-0.1,1s0,0.7,0.1,1l-2.1,1.7c-0.2,0.2-0.2,0.4-0.1,0.6l2,3.5C4.5,18.9,4.7,19,5,18.9l2.5-1c0.5,0.4,1.1,0.7,1.7,1l0.4,2.6c0,0.2,0.2,0.4,0.5,0.4h4c0.2,0,0.5-0.2,0.5-0.4l0.4-2.6c0.6-0.3,1.2-0.6,1.7-1l2.5,1c0.2,0.1,0.5,0,0.6-0.2l2-3.5c0.1-0.2,0.1-0.5-0.1-0.6L19.4,13z M12,15.5c-1.9,0-3.5-1.6-3.5-3.5s1.6-3.5,3.5-3.5s3.5,1.6,3.5,3.5S13.9,15.5,12,15.5z"/></g> +<g id="settings-applications"><path d="M12,10c-1.1,0-2,0.9-2,2s0.9,2,2,2s2-0.9,2-2S13.1,10,12,10z M19,3H5C3.9,3,3,3.9,3,5v14c0,1.1,0.9,2,2,2h14c1.1,0,2-0.9,2-2V5C21,3.9,20.1,3,19,3z M17.2,12c0,0.2,0,0.5,0,0.7l1.5,1.2c0.1,0.1,0.2,0.3,0.1,0.4l-1.4,2.4c-0.1,0.2-0.3,0.2-0.4,0.2l-1.7-0.7c-0.4,0.3-0.8,0.5-1.2,0.7l-0.3,1.9c0,0.2-0.2,0.3-0.3,0.3h-2.8c-0.2,0-0.3-0.1-0.3-0.3L10,16.9c-0.4-0.2-0.8-0.4-1.2-0.7l-1.7,0.7c-0.2,0.1-0.3,0-0.4-0.2l-1.4-2.4c-0.1-0.2,0-0.3,0.1-0.4l1.5-1.2c0-0.2,0-0.5,0-0.7s0-0.5,0-0.7l-1.5-1.2c-0.1-0.1-0.2-0.3-0.1-0.4l1.4-2.4c0.1-0.2,0.3-0.2,0.4-0.2l1.7,0.7C9.2,7.6,9.6,7.3,10,7.1l0.3-1.9c0-0.2,0.2-0.3,0.3-0.3h2.8c0.2,0,0.3,0.1,0.3,0.3L14,7.1c0.4,0.2,0.8,0.4,1.2,0.7l1.7-0.7c0.2-0.1,0.3,0,0.4,0.2l1.4,2.4c0.1,0.2,0,0.3-0.1,0.4l-1.5,1.2C17.2,11.5,17.2,11.8,17.2,12z"/></g> +<g id="settings-backup-restore"><path d="M14,12c0-1.1-0.9-2-2-2s-2,0.9-2,2s0.9,2,2,2S14,13.1,14,12z M12,3c-5,0-9,4-9,9H0l4,4l4-4H5c0-3.9,3.1-7,7-7s7,3.1,7,7s-3.1,7-7,7c-1.5,0-2.9-0.5-4.1-1.3l-1.4,1.4C8,20.3,9.9,21,12,21c5,0,9-4,9-9S17,3,12,3z"/></g> +<g id="settings-bluetooth"><path d="M11,24h2v-2h-2V24z M7,24h2v-2H7V24z M15,24h2v-2h-2V24z M17.7,5.7L12,0h-1v7.6L6.4,3L5,4.4l5.6,5.6L5,15.6L6.4,17l4.6-4.6V20h1l5.7-5.7L13.4,10L17.7,5.7z M13,3.8l1.9,1.9L13,7.6V3.8z M14.9,14.3L13,16.2v-3.8L14.9,14.3z"/></g> +<g id="settings-cell"><path d="M7,24h2v-2H7V24z M11,24h2v-2h-2V24z M15,24h2v-2h-2V24z M16,0L8,0C6.9,0,6,0.9,6,2v16c0,1.1,0.9,2,2,2h8c1.1,0,2-0.9,2-2V2C18,0.9,17.1,0,16,0z M16,16H8V4h8V16z"/></g> +<g id="settings-display"><path d="M21,19H3V5h18V19z M21,3H3C1.9,3,1,3.9,1,5v14c0,1.1,0.9,2,2,2h18c1.1,0,2-0.9,2-2V5C23,3.9,22.1,3,21,3L21,3z"/><path d="M10,12c0-1.1,0.9-2,2-2V8c0.3,0,0.7,0.1,1,0.1V6h-2v2.1c-0.4,0.1-0.7,0.2-1,0.4L8.5,7.1L7.1,8.5L8.6,10c-0.2,0.3-0.3,0.7-0.4,1H6v2h2.1c0.1,0.4,0.2,0.7,0.4,1l-1.5,1.5l1.4,1.4l1.5-1.5c0.3,0.2,0.7,0.3,1,0.4V18h2v-2.1c-0.3,0.1-0.7,0.1-1,0.1v-2C10.9,14,10,13.1,10,12z M15.4,10l1.5-1.5l-1.4-1.4L14,8.6C14.6,8.9,15.1,9.4,15.4,10z M14,15.4l1.5,1.5l1.4-1.4L15.4,14C15.1,14.6,14.6,15.1,14,15.4z M12,10v4c1.1,0,2-0.9,2-2C14,10.9,13.1,10,12,10z M15.9,11c0.1,0.3,0.1,0.7,0.1,1s-0.1,0.7-0.1,1H18v-2H15.9z"/></g> +<g id="settings-ethernet"><path d="M7.8,6.8L6.2,5.5L0.8,12l5.4,6.5l1.5-1.3L3.4,12L7.8,6.8z M7,13h2v-2H7V13z M17,11h-2v2h2V11z M11,13h2v-2h-2V13z M17.8,5.5l-1.5,1.3l4.3,5.2l-4.3,5.2l1.5,1.3l5.4-6.5L17.8,5.5z"/></g> +<g id="settings-input-antenna"><path d="M12,5c-3.9,0-7,3.1-7,7h2c0-2.8,2.2-5,5-5s5,2.2,5,5h2C19,8.1,15.9,5,12,5z M13,14.3c0.9-0.4,1.5-1.3,1.5-2.3c0-1.4-1.1-2.5-2.5-2.5S9.5,10.6,9.5,12c0,1,0.6,1.9,1.5,2.3v3.3L7.6,21L9,22.4l3-3l3,3l1.4-1.4L13,17.6V14.3z M12,1C5.9,1,1,5.9,1,12h2c0-5,4-9,9-9s9,4,9,9h2C23,5.9,18.1,1,12,1z"/></g> +<g id="settings-input-component"><path d="M5,2c0-0.6-0.4-1-1-1S3,1.4,3,2v4H1v6h6V6H5V2z M9,16c0,1.3,0.8,2.4,2,2.8V23h2v-4.2c1.2-0.4,2-1.5,2-2.8v-2H9V16z M1,16c0,1.3,0.8,2.4,2,2.8V23h2v-4.2c1.2-0.4,2-1.5,2-2.8v-2H1V16z M21,6V2c0-0.6-0.4-1-1-1s-1,0.4-1,1v4h-2v6h6V6H21z M13,2c0-0.6-0.4-1-1-1s-1,0.4-1,1v4H9v6h6V6h-2V2z M17,16c0,1.3,0.8,2.4,2,2.8V23h2v-4.2c1.2-0.4,2-1.5,2-2.8v-2h-6V16z"/></g> +<g id="settings-input-composite"><path d="M5,2c0-0.6-0.4-1-1-1S3,1.4,3,2v4H1v6h6V6H5V2z M9,16c0,1.3,0.8,2.4,2,2.8V23h2v-4.2c1.2-0.4,2-1.5,2-2.8v-2H9V16z M1,16c0,1.3,0.8,2.4,2,2.8V23h2v-4.2c1.2-0.4,2-1.5,2-2.8v-2H1V16z M21,6V2c0-0.6-0.4-1-1-1s-1,0.4-1,1v4h-2v6h6V6H21z M13,2c0-0.6-0.4-1-1-1s-1,0.4-1,1v4H9v6h6V6h-2V2z M17,16c0,1.3,0.8,2.4,2,2.8V23h2v-4.2c1.2-0.4,2-1.5,2-2.8v-2h-6V16z"/></g> +<g id="settings-input-hdmi"><path d="M18,7V4c0-1.1-0.9-2-2-2H8C6.9,2,6,2.9,6,4v3H5v6l3,6v3h8v-3l3-6V7H18z M8,4h8v3h-2V5h-1v2h-2V5h-1v2H8V4z"/></g> +<g id="settings-input-svideo"><path d="M8,11.5C8,10.7,7.3,10,6.5,10S5,10.7,5,11.5S5.7,13,6.5,13S8,12.3,8,11.5z M15,6.5C15,5.7,14.3,5,13.5,5h-3C9.7,5,9,5.7,9,6.5S9.7,8,10.5,8h3C14.3,8,15,7.3,15,6.5z M8.5,15C7.7,15,7,15.7,7,16.5S7.7,18,8.5,18s1.5-0.7,1.5-1.5S9.3,15,8.5,15z M12,1C5.9,1,1,5.9,1,12s4.9,11,11,11s11-4.9,11-11S18.1,1,12,1z M12,21c-5,0-9-4-9-9s4-9,9-9s9,4,9,9S17,21,12,21z M17.5,10c-0.8,0-1.5,0.7-1.5,1.5s0.7,1.5,1.5,1.5s1.5-0.7,1.5-1.5S18.3,10,17.5,10z M15.5,15c-0.8,0-1.5,0.7-1.5,1.5s0.7,1.5,1.5,1.5s1.5-0.7,1.5-1.5S16.3,15,15.5,15z"/></g> +<g id="settings-overscan"><path d="M12,5.5L10,8h4L12,5.5z M18,10v4l2.5-2L18,10z M6,10l-2.5,2L6,14V10z M14,16h-4l2,2.5L14,16z M21,3H3C1.9,3,1,3.9,1,5v14c0,1.1,0.9,2,2,2h18c1.1,0,2-0.9,2-2V5C23,3.9,22.1,3,21,3z M21,19H3V5h18V19z"/></g> +<g id="settings-phone"><path d="M13,9h-2v2h2V9z M17,9h-2v2h2V9z M20,15.5c-1.2,0-2.4-0.2-3.6-0.6c-0.3-0.1-0.7,0-1,0.2l-2.2,2.2c-2.8-1.4-5.1-3.8-6.6-6.6l2.2-2.2c0.3-0.3,0.4-0.7,0.2-1C8.7,6.4,8.5,5.2,8.5,4c0-0.6-0.4-1-1-1H4C3.4,3,3,3.4,3,4c0,9.4,7.6,17,17,17c0.6,0,1-0.4,1-1v-3.5C21,15.9,20.6,15.5,20,15.5z M19,9v2h2V9H19z"/></g> +<g id="settings-power"><path d="M7,24h2v-2H7V24z M11,24h2v-2h-2V24z M13,2h-2v10h2V2z M16.6,4.4l-1.4,1.4C16.8,6.9,18,8.8,18,11c0,3.3-2.7,6-6,6c-3.3,0-6-2.7-6-6c0-2.2,1.2-4.1,2.9-5.1L7.4,4.4C5.4,5.9,4,8.3,4,11c0,4.4,3.6,8,8,8c4.4,0,8-3.6,8-8C20,8.3,18.6,5.9,16.6,4.4z M15,24h2v-2h-2V24z"/></g> +<g id="settings-remote"><path d="M15,9H9c-0.6,0-1,0.4-1,1v12c0,0.6,0.4,1,1,1h6c0.6,0,1-0.4,1-1V10C16,9.4,15.6,9,15,9z M12,15c-1.1,0-2-0.9-2-2s0.9-2,2-2s2,0.9,2,2S13.1,15,12,15z M7.1,6.1l1.4,1.4C9.4,6.6,10.6,6,12,6s2.6,0.6,3.5,1.5l1.4-1.4C15.7,4.8,13.9,4,12,4S8.3,4.8,7.1,6.1z M12,0C9,0,6.2,1.2,4.2,3.2l1.4,1.4C7.3,3,9.5,2,12,2s4.7,1,6.4,2.6l1.4-1.4C17.8,1.2,15,0,12,0z"/></g> +<g id="settings-voice"><path d="M7,24h2v-2H7V24z M12,13c1.7,0,3-1.3,3-3l0-6c0-1.7-1.3-3-3-3c-1.7,0-3,1.3-3,3v6C9,11.7,10.3,13,12,13z M11,24h2v-2h-2V24z M15,24h2v-2h-2V24z M19,10h-1.7c0,3-2.5,5.1-5.3,5.1c-2.8,0-5.3-2.1-5.3-5.1H5c0,3.4,2.7,6.2,6,6.7V20h2v-3.3C16.3,16.2,19,13.4,19,10z"/></g> +<g id="shop"><path d="M16,6V4l-2-2h-4L8,4v2H2v13c0,1.1,0.9,2,2,2h16c1.1,0,2-0.9,2-2V6H16z M10,4h4v2h-4V4z M9,18V9l7.5,4L9,18z"/></g> +<g id="shop-two"><path d="M18,5V3l-2-2h-4l-2,2v2H5v11c0,1.1,0.9,2,2,2h14c1.1,0,2-0.9,2-2V5H18z M12,3h4v2h-4V3z M12,15V8l5.5,3L12,15z M3,9H1v11c0,1.1,0.9,2,2,2h14c1.1,0,2-0.9,2-2H3V9z"/></g> +<g id="shopping-basket"><path d="M17.2,9l-4.4-6.6C12.6,2.2,12.3,2,12,2c-0.3,0-0.6,0.1-0.8,0.4L6.8,9H2c-0.6,0-1,0.4-1,1c0,0.1,0,0.2,0,0.3l2.5,9.3c0.2,0.8,1,1.5,1.9,1.5h13c0.9,0,1.7-0.6,1.9-1.5l2.5-9.3c0-0.1,0-0.2,0-0.3c0-0.6-0.4-1-1-1H17.2z M9,9l3-4.4L15,9H9z M12,17c-1.1,0-2-0.9-2-2s0.9-2,2-2c1.1,0,2,0.9,2,2S13.1,17,12,17z"/></g> +<g id="shopping-cart"><path d="M7,18c-1.1,0-2,0.9-2,2s0.9,2,2,2c1.1,0,2-0.9,2-2S8.1,18,7,18z M1,2v2h2l3.6,7.6L5.2,14C5.1,14.3,5,14.7,5,15c0,1.1,0.9,2,2,2h12v-2H7.4c-0.1,0-0.2-0.1-0.2-0.2c0,0,0-0.1,0-0.1L8.1,13h7.4c0.8,0,1.4-0.4,1.7-1l3.6-6.5C21,5.3,21,5.2,21,5c0-0.6-0.4-1-1-1H5.2L4.3,2H1z M17,18c-1.1,0-2,0.9-2,2s0.9,2,2,2c1.1,0,2-0.9,2-2S18.1,18,17,18z"/></g> +<g id="sort"><path d="M3,18h6v-2H3V18z M3,6v2h18V6H3z M3,13h12v-2H3V13z"/></g> +<g id="star"><polygon points="12,17.273 18.18,21 16.545,13.971 22,9.244 14.809,8.627 12,2 9.191,8.627 2,9.244 7.455,13.971 5.82,21 "/></g> +<g id="star-half"><path d="M22,9.744l-7.191-0.617L12,2.5L9.191,9.127L2,9.744v0l0,0l5.455,4.727L5.82,21.5L12,17.772l0,0l6.18,3.727l-1.635-7.029L22,9.744z M12,15.896V6.595l1.71,4.036l4.38,0.376l-3.322,2.878l0.996,4.281L12,15.896z"/></g> +<g id="star-outline"><path d="M22,9.244l-7.191-0.617L12,2L9.191,8.627L2,9.244l5.455,4.727L5.82,21L12,17.272L18.18,21l-1.635-7.029L22,9.244z M12,15.396l-3.763,2.27l0.996-4.281L5.91,10.507l4.38-0.376L12,6.095l1.71,4.036l4.38,0.376l-3.322,2.878l0.996,4.281L12,15.396z"/></g> +<g id="star-rate"><polygon points="12,14.3 15.7,17 14.3,12.6 18,10 13.5,10 12,5.5 10.5,10 6,10 9.7,12.6 8.3,17 "/></g> +<g id="stars"><path d="M12,2C6.5,2,2,6.5,2,12s4.5,10,10,10c5.5,0,10-4.5,10-10S17.5,2,12,2z M16.2,18L12,15.4L7.8,18l1.1-4.8L5.2,10l4.9-0.4L12,5l1.9,4.5l4.9,0.4l-3.7,3.2L16.2,18z"/></g> +<g id="store"><path d="M20,4H4v2h16V4z M21,14v-2l-1-5H4l-1,5v2h1v6h10v-6h4v6h2v-6H21z M12,18H6v-4h6V18z"/></g> +<g id="subject"><path d="M14,17H4v2h10V17z M20,9H4v2h16V9z M4,15h16v-2H4V15z M4,5v2h16V5H4z"/></g> +<g id="swap-driving-apps"><circle cx="6.5" cy="15.5" r="1.5"/><circle cx="17.5" cy="15.5" r="1.5"/><path d="M18.9,7c-0.2-0.6-0.8-1-1.4-1H16H6V4L3,7l2,2l1,1V8h11.7l1.3,4H3v9c0,0.6,0.4,1,1,1h1c0.6,0,1-0.4,1-1v-1h12v1c0,0.6,0.4,1,1,1h1c0.6,0,1-0.4,1-1v-8L18.9,7z M6.5,17C5.7,17,5,16.3,5,15.5S5.7,14,6.5,14C7.3,14,8,14.7,8,15.5S7.3,17,6.5,17z M17.5,17c-0.8,0-1.5-0.7-1.5-1.5s0.7-1.5,1.5-1.5c0.8,0,1.5,0.7,1.5,1.5S18.3,17,17.5,17z M16,0v2H8v2h8v2l3-3L16,0z"/></g> +<g id="swap-driving-apps-wheel"><path d="M14.4,6.1c-0.5-0.2-1.1,0-1.3,0.6L11.7,10c-1,0.1-1.7,1-1.7,2c0,1.1,0.9,2,2,2s2-0.9,2-2c0-0.5-0.2-0.9-0.4-1.2l1.4-3.4C15.1,6.9,14.9,6.3,14.4,6.1z M7,9c-0.6,0-1,0.4-1,1c0,0.6,0.4,1,1,1s1-0.4,1-1C8,9.4,7.6,9,7,9z M11,7c0-0.6-0.4-1-1-1S9,6.4,9,7c0,0.6,0.4,1,1,1S11,7.6,11,7z M17,9c-0.6,0-1,0.4-1,1c0,0.6,0.4,1,1,1s1-0.4,1-1C18,9.4,17.6,9,17,9z M12,2C6.5,2,2,6.5,2,12s4.5,10,10,10s10-4.5,10-10S17.5,2,12,2z M17.3,18c-1.4-1.2-3.2-2-5.3-2s-3.9,0.8-5.3,2C5.1,16.5,4,14.4,4,12c0-4.4,3.6-8,8-8s8,3.6,8,8C20,14.4,18.9,16.5,17.3,18z"/></g> +<g id="swap-horiz"><path d="M7,11l-4,4l4,4v-3h7v-2H7V11z M21,9l-4-4v3h-7v2h7v3L21,9z"/></g> +<g id="swap-vert"><path d="M16,17v-7h-2v7h-3l4,4l4-4H16z M9,3L5,7h3v7h2V7h3L9,3z"/></g> +<g id="swap-vert-circle"><path d="M12,2C6.5,2,2,6.5,2,12s4.5,10,10,10c5.5,0,10-4.5,10-10S17.5,2,12,2z M6.5,9L10,5.5L13.5,9H11v4H9V9H6.5z M17.5,15L14,18.5L10.5,15H13v-4h2v4H17.5z"/></g> +<g id="system-update-tv"><path d="M12,15l4-4h-3V3h-2v8H8L12,15z M20,3h-5v2h5v12H4V5h5V3H4C2.9,3,2,3.9,2,5v12c0,1.1,0.9,2,2,2h4v2h8v-2h4c1.1,0,2-0.9,2-2l0-12C22,3.9,21.1,3,20,3z"/></g> +<g id="tab"><path d="M21,3H3C1.9,3,1,3.9,1,5v14c0,1.1,0.9,2,2,2h18c1.1,0,2-0.9,2-2V5C23,3.9,22.1,3,21,3z M21,19L3,19V5h10v4h8V19z"/></g> +<g id="tab-unselected"><path d="M1,9h2V7H1V9z M1,13h2v-2H1V13z M1,5h2V3C1.9,3,1,3.9,1,5z M9,21h2v-2l-2,0V21z M1,17h2v-2H1V17z M3,21v-2H1C1,20.1,1.9,21,3,21z M21,3h-8v6h10V5C23,3.9,22.1,3,21,3z M21,17h2v-2h-2V17z M9,5h2V3H9V5z M5,21h2v-2l-2,0V21z M5,5h2V3H5V5z M21,21c1.1,0,2-0.9,2-2h-2V21z M21,13h2v-2h-2V13z M13,21h2v-2l-2,0V21z M17,21h2v-2l-2,0V21z"/></g> +<g id="text-format"><path d="M5,17v2h14v-2H5z M9.5,12.8h5l0.9,2.2h2.1L12.8,4h-1.5L6.5,15h2.1L9.5,12.8z M12,6l1.9,5h-3.7L12,6z"/></g> +<g id="theaters"><path d="M18,3v2h-2V3H8v2H6V3H4v18h2v-2h2v2h8v-2h2v2h2V3H18z M8,17H6v-2h2V17z M8,13H6v-2h2V13z M8,9H6V7h2V9z M18,17h-2v-2h2V17z M18,13h-2v-2h2V13z M18,9h-2V7h2V9z"/></g> +<g id="thumb-down"><path d="M15,3H6C5.2,3,4.5,3.5,4.2,4.2l-3,7.1C1.1,11.5,1,11.7,1,12v1.9l0,0c0,0,0,0.1,0,0.1c0,1.1,0.9,2,2,2h6.3l-1,4.6c0,0.1,0,0.2,0,0.3c0,0.4,0.2,0.8,0.4,1.1L9.8,23l6.6-6.6c0.4-0.4,0.6-0.9,0.6-1.4V5C17,3.9,16.1,3,15,3z M19,3v12h4V3H19z"/></g> +<g id="thumb-up"><path d="M1,21h4V9H1V21z M23,10c0-1.1-0.9-2-2-2h-6.3l1-4.6c0-0.1,0-0.2,0-0.3c0-0.4-0.2-0.8-0.4-1.1L14.2,1L7.6,7.6C7.2,7.9,7,8.4,7,9v10c0,1.1,0.9,2,2,2h9c0.8,0,1.5-0.5,1.8-1.2l3-7.1c0.1-0.2,0.1-0.5,0.1-0.7V10L23,10C23,10.1,23,10,23,10z"/></g> +<g id="toc"><path d="M3,9h14V7H3V9z M3,13h14v-2H3V13z M3,17h14v-2H3V17z M19,17h2v-2h-2V17z M19,7v2h2V7H19z M19,13h2v-2h-2V13z"/></g> +<g id="today"><path d="M19,3h-1V1h-2v2H8V1H6v2H5C3.9,3,3,3.9,3,5l0,14c0,1.1,0.9,2,2,2h14c1.1,0,2-0.9,2-2V5C21,3.9,20.1,3,19,3z M19,19H5V8h14V19z"/><rect x="7" y="10" width="5" height="5"/></g> +<g id="translate"><path d="M12.9,15.1l-2.5-2.5l0,0c1.7-1.9,3-4.2,3.7-6.5H17V4h-7V2H8v2H1v2l11.2,0c-0.7,1.9-1.7,3.8-3.2,5.4c-0.9-1-1.7-2.2-2.3-3.4h-2c0.7,1.6,1.7,3.2,3,4.6l-5.1,5L4,19l5-5l3.1,3.1L12.9,15.1z M18.5,10h-2L12,22h2l1.1-3h4.8l1.1,3h2L18.5,10z M15.9,17l1.6-4.3l1.6,4.3H15.9z"/></g> +<g id="trending-down"><polygon points="16,18 18.3,15.7 13.4,10.8 9.4,14.8 2,7.4 3.4,6 9.4,12 13.4,8 19.7,14.3 22,12 22,18 "/></g> +<g id="trending-neutral"><polygon points="22,12 18,8 18,11 3,11 3,13 18,13 18,16 "/></g> +<g id="trending-up"><polygon points="16,6 18.3,8.3 13.4,13.2 9.4,9.2 2,16.6 3.4,18 9.4,12 13.4,16 19.7,9.7 22,12 22,6 "/></g> +<g id="turned-in"><path d="M17,3H7C5.9,3,5,3.9,5,5l0,16l7-3l7,3V5C19,3.9,18.1,3,17,3z"/></g> +<g id="turned-in-not"><path d="M17,3H7C5.9,3,5,3.9,5,5l0,16l7-3l7,3V5C19,3.9,18.1,3,17,3z M17,18l-5-2.2L7,18V5h10V18z"/></g> +<g id="undo"><path d="M12,5V1.5l-5,5l5,5V7c3.3,0,6,2.7,6,6s-2.7,6-6,6c-3.3,0-6-2.7-6-6H4c0,4.4,3.6,8,8,8c4.4,0,8-3.6,8-8S16.4,5,12,5z"/></g> +<g id="unfold-less"><path d="M7.4,18.6L8.8,20l3.2-3.2l3.2,3.2l1.4-1.4L12,14L7.4,18.6z M16.6,5.4L15.2,4L12,7.2L8.8,4L7.4,5.4L12,10L16.6,5.4z"/></g> +<g id="unfold-more"><path d="M12,5.8L15.2,9l1.4-1.4L12,3L7.4,7.6L8.8,9L12,5.8z M12,18.2L8.8,15l-1.4,1.4L12,21l4.6-4.6L15.2,15L12,18.2z"/></g> +<g id="view-array"><path d="M4,18h3V5H4V18z M18,5v13h3V5H18z M8,18h9V5H8V18z"/></g> +<g id="view-column"><path d="M10,18h5V5h-5V18z M4,18h5V5H4V18z M16,5v13h5V5H16z"/></g> +<g id="view-headline"><path d="M4,15h17v-2H4V15z M4,19h17v-2H4V19z M4,11h17V9H4V11z M4,5v2h17V5H4z"/></g> +<g id="view-list"><path d="M4,14h4v-4H4V14z M4,19h4v-4H4V19z M4,9h4V5H4V9z M9,14h12v-4H9V14z M9,19h12v-4H9V19z M9,5v4h12V5H9z"/></g> +<g id="view-module"><path d="M4,11h5V5H4V11z M4,18h5v-6H4V18z M10,18h5v-6h-5V18z M16,18h5v-6h-5V18z M10,11h5V5h-5V11z M16,5v6h5V5H16z"/></g> +<g id="view-quilt"><path d="M10,18h5v-6h-5V18z M4,18h5V5H4V18z M16,18h5v-6h-5V18z M10,5v6h11V5H10z"/></g> +<g id="view-stream"><path d="M4,18h17v-6H4V18z M4,5v6h17V5H4z"/></g> +<g id="visibility"><path d="M12,4.5C7,4.5,2.7,7.6,1,12c1.7,4.4,6,7.5,11,7.5c5,0,9.3-3.1,11-7.5C21.3,7.6,17,4.5,12,4.5z M12,17c-2.8,0-5-2.2-5-5s2.2-5,5-5c2.8,0,5,2.2,5,5S14.8,17,12,17z M12,9c-1.7,0-3,1.3-3,3s1.3,3,3,3c1.7,0,3-1.3,3-3S13.7,9,12,9z"/></g> +<g id="visibility-off"><path d="M12,7c2.8,0,5,2.2,5,5c0,0.6-0.1,1.3-0.4,1.8l2.9,2.9c1.5-1.3,2.7-2.9,3.4-4.7c-1.7-4.4-6-7.5-11-7.5c-1.4,0-2.7,0.3-4,0.7l2.2,2.2C10.7,7.1,11.4,7,12,7z M2,4.3l2.3,2.3L4.7,7c-1.7,1.3-3,3-3.7,5c1.7,4.4,6,7.5,11,7.5c1.5,0,3-0.3,4.4-0.8l0.4,0.4l2.9,2.9l1.3-1.3L3.3,3L2,4.3z M7.5,9.8l1.5,1.5C9,11.6,9,11.8,9,12c0,1.7,1.3,3,3,3c0.2,0,0.4,0,0.7-0.1l1.5,1.5C13.5,16.8,12.8,17,12,17c-2.8,0-5-2.2-5-5C7,11.2,7.2,10.5,7.5,9.8z M11.8,9l3.1,3.1c0-0.1,0-0.1,0-0.2c0-1.7-1.3-3-3-3C11.9,9,11.9,9,11.8,9z"/></g> +<g id="wallet-giftcard"><path d="M20,6h-2.2C17.9,5.7,18,5.4,18,5c0-1.7-1.3-3-3-3c-1,0-2,0.5-2.5,1.3l0,0L12,4l-0.5-0.7l0,0C11,2.5,10,2,9,2C7.3,2,6,3.3,6,5c0,0.4,0.1,0.7,0.2,1H4C2.9,6,2,6.9,2,8l0,11c0,1.1,0.9,2,2,2h16c1.1,0,2-0.9,2-2V8C22,6.9,21.1,6,20,6z M15,4c0.6,0,1,0.4,1,1s-0.4,1-1,1s-1-0.4-1-1S14.4,4,15,4z M9,4c0.6,0,1,0.4,1,1S9.6,6,9,6S8,5.6,8,5S8.4,4,9,4z M20,19H4v-2h16V19z M20,14H4V8h5.1L7,10.8L8.6,12L11,8.8l1-1.4l1,1.4l2.4,3.2l1.6-1.2L14.9,8H20V14z"/></g> +<g id="wallet-membership"><path d="M20,2H4C2.9,2,2,2.9,2,4v11c0,1.1,0.9,2,2,2h4v5l4-2l4,2v-5h4c1.1,0,2-0.9,2-2V4C22,2.9,21.1,2,20,2z M20,15H4v-2h16V15z M20,10H4V4h16V10z"/></g> +<g id="wallet-travel"><path d="M20,6h-3V4l-2-2H9L7,4v2H4C2.9,6,2,6.9,2,8v11c0,1.1,0.9,2,2,2h16c1.1,0,2-0.9,2-2V8C22,6.9,21.1,6,20,6z M9,4h6v2H9V4z M20,19H4v-2h16V19z M20,14H4V8h3v4h2V8h6v4h2V8h3V14z"/></g> +<g id="warning"><path d="M1,21h22L12,2L1,21z M13,18h-2v-2h2V18z M13,14h-2v-4h2V14z"/></g> +<g id="work"><path d="M20,6h-4V4l-2-2h-4L8,4v2H4C2.9,6,2,6.9,2,8l0,11c0,1.1,0.9,2,2,2h16c1.1,0,2-0.9,2-2V8C22,6.9,21.1,6,20,6z M14,6h-4V4h4V6z"/></g> +</defs></svg> +</core-iconset-svg> <!-- Copyright (c) 2014 The Polymer Project Authors. All rights reserved. @@ -7896,5019 +3557,9689 @@ Polymer('core-style', { }); -})(); -</script> -</polymer-element> +})(); +</script> +</polymer-element> + + +<core-style id="paper-input"> + +:host([focused]) .floated-label { + color: {{g.paperInput.focusedColor}}; +} + +.focused-underline, +.cursor { + background-color: {{g.paperInput.focusedColor}}; +} + + +:host(.invalid[focused]) .floated-label, +:host([focused]) .error-text, +:host([focused]) .error-icon { + color: {{g.paperInput.invalidColor}}; +} + +:host(.invalid) .focused-underline, +:host(.invalid) .cursor { + background-color: {{g.paperInput.invalidColor}}; +} + +</core-style> + +<polymer-element name="paper-input" extends="core-input" layout="" vertical="" attributes="label floatingLabel maxRows error" on-transitionend="{{transitionEndAction}}" on-webkittransitionend="{{transitionEndAction}}" assetpath="polymer/bower_components/paper-input/"> + + <template> + + <!-- + Input tests: + + - set value to integer 0 + - various html5 input types + - sizing: + - single-line: size with CSS + - single-line: can fit to container + - multi-line: size with CSS + - multi-line: size with rows + - multi-line: can fit to container + - multi-line: grows with typing + - multi-line: max rows + - multi-line: max rows, scrolls after + --> + + <style>/* + * @license + * Copyright (c) 2014 The Polymer Project Authors. All rights reserved. + * This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt + * The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt + * The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt + * Code distributed by Google as part of the polymer project is also + * subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt + */ + +:host { + display: inline-block; + outline: none; + text-align: inherit; + color: #757575; + padding: 0.75em 0; +} + +:host /deep/ input, +:host /deep/ textarea { + font: inherit; + color: #000; + padding: 0; + margin: 0; + background-color: transparent; + border: none; + outline: none; + /* see comments in template */ + width: 100%; + height: 100%; +} + +input:invalid, +textarea:invalid { + box-shadow: none; +} + +textarea { + resize: none; +} + +[invisible] { + visibility: hidden; +} + +[animated] { + visibility: visible !important; + -webkit-transition: -webkit-transform 0.2s cubic-bezier(0.4, 0, 0.2, 1), opacity 0.2s cubic-bezier(0.4, 0, 0.2, 1); + transition: transform 0.2s cubic-bezier(0.4, 0, 0.2, 1), opacity 0.2s cubic-bezier(0.4, 0, 0.2, 1); +} + +.floated-label { + font-size: 0.75em; + background: transparent; + white-space: nowrap; +} + +.mirror-text { + padding: 0.5em 0 0.25em; + max-width: 100%; + white-space: nowrap; +} + +:host([multiline]) .mirror-text { + white-space: pre-wrap; + word-wrap: break-word; +} + +.label { + padding: 0.5em 0 0.25em; + background: transparent; + pointer-events: none; +} + +.label-text { + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + display: inline-block; + max-width: 100%; + -moz-transform-origin: 0% 0%; + -webkit-transform-origin: 0% 0%; + transform-origin: 0% 0%; +} + +.cursor { + position: absolute; + top: 0.4em; + left: 0; + width: 1px; + height: 1.4em; + opacity: 0.4; + -moz-transform-origin: 0%; + -webkit-transform-origin: 0%; + transform-origin: 0%; + -webkit-transform: none; + transform: none; +} + +.cursor[invisible] { + opacity: 0.75; + -webkit-transform: translate3d(3em,0,0) scale3d(50,1,1); + transform: translate3d(3em,0,0) scale3d(50,1,1); +} + +.input-container { + position: absolute; + /* simulate padding so the input/textarea can use 100% width/height */ + top: 0.5em; + right: 0; + bottom: 0.25em; + left: 0; +} + +.underline { + height: 0px; + overflow: visible; +} + +:host([disabled]) .underline { + border-bottom: 1px dashed; +} + +.unfocused-underline { + height: 1px; + background: #757575; + border-bottom-color: #757575; +} + +.focused-underline { + height: 2px; + -webkit-transform: none; + transform: none; +} + +.focused-underline[invisible] { + -webkit-transform: scale3d(0,1,1); + transform: scale3d(0,1,1); +} + +.error-text { + font-size: 0.75em; + padding: 0.5em 0; +} + +.error-icon { + height: 20px; + width: 20px; +} +</style> + <core-style ref="paper-input"></core-style> + + <div class="floated-label" aria-hidden="true" hidden?="{{!floatingLabel}}" invisible?="{{!inputValue && !(type === 'number' && !validity.valid) || labelAnimated}}"> + <!-- needed for floating label animation measurement --> + <span id="floatedLabelText" class="label-text">{{label}}</span> + </div> + + <!-- <div class="input-body" flex auto relative on-down="{{downAction}}" on-up="{{upAction}}"> --> + <div class="input-body" flex="" auto="" relative=""> + + <!-- the mirror sizes the input/textarea so it grows with typing --> + <div id="mirror" class="mirror-text" invisible="" aria-hidden="true"></div> + + <div class="label" fit="" aria-hidden="true"> + <!-- needed for floating label animation measurement --> + <span id="labelText" class="label-text" invisible?="{{inputValue || !inputValue && type === 'number' && !validity.valid}}" animated?="{{labelAnimated}}">{{label}}</span> + </div> + + <div class="cursor" invisible?="{{!cursorAnimated}}" animated?="{{cursorAnimated}}"></div> + + <!-- size the input/textarea with a div, because the textarea has intrinsic size in ff --> + <div class="input-container" on-down="{{downAction}}" on-up="{{upAction}}"> + <shadow></shadow> + </div> + + </div> + + <div id="underline" class="underline" relative=""> + <div class="unfocused-underline" fit="" invisible?="{{disabled}}"></div> + <div id="focusedUnderline" class="focused-underline" fit="" invisible?="{{!focused}}" animated?="{{underlineAnimated}}"></div> + </div> + + <div layout="" horizontal="" center="" hidden?="{{!invalid}}"> + <div class="error-text" flex="" auto="" role="alert" aria-hidden="{{!invalid}}">{{error || validationMessage}}</div> + <core-icon class="error-icon" icon="warning"></core-icon> + </div> + + </template> + + <script> + + (function() { + + var paperInput = CoreStyle.g.paperInput = CoreStyle.g.paperInput || {}; + paperInput.focusedColor = '#4059a9'; + paperInput.invalidColor = '#d34336'; + + Polymer('paper-input', { + + publish: { + /** + * The label for this input. It normally appears as grey text inside + * the text input and disappears once the user enters text. + * + * @attribute label + * @type string + * @default '' + */ + label: '', + + /** + * If true, the label will "float" above the text input once the + * user enters text instead of disappearing. + * + * @attribute floatingLabel + * @type boolean + * @default false + */ + floatingLabel: false, + + /** + * (multiline only) If set to a non-zero value, the height of this + * text input will grow with the value changes until it is maxRows + * rows tall. If the maximum size does not fit the value, the text + * input will scroll internally. + * + * @attribute maxRows + * @type number + * @default 0 + */ + maxRows: 0, + + /** + * The message to display if the input value fails validation. If this + * is unset or the empty string, a default message is displayed depending + * on the type of validation error. + * + * @attribute error + * @type string + */ + error: '', + + focused: {value: false, reflect: true} + + }, + + get inputValueForMirror() { + var tokens = this.inputValue ? String(this.inputValue).replace(/&/gm, '&').replace(/"/gm, '"').replace(/'/gm, ''').replace(/</gm, '<').replace(/>/gm, '>').split('\n') : ['']; + + // Enforce the min and max heights for a multiline input here to + // avoid measurement + if (this.multiline) { + if (this.maxRows && tokens.length > this.maxRows) { + tokens = tokens.slice(0, this.maxRows); + } + while (this.rows && tokens.length < this.rows) { + tokens.push(''); + } + } + + return tokens.join('<br>') + ' '; + }, + + get inputHasValue() { + // if type = number, the input value is the empty string until a valid number + // is entered so we must do some hacks here + return this.inputValue || (this.type === 'number' && !this.validity.valid); + }, + + syncInputValueToMirror: function() { + this.$.mirror.innerHTML = this.inputValueForMirror; + }, + + ready: function() { + this.syncInputValueToMirror(); + }, + + prepareLabelTransform: function() { + var toRect = this.$.floatedLabelText.getBoundingClientRect(); + var fromRect = this.$.labelText.getBoundingClientRect(); + if (toRect.width !== 0) { + var sy = toRect.height / fromRect.height; + this.$.labelText.cachedTransform = + 'scale3d(' + (toRect.width / fromRect.width) + ',' + sy + ',1) ' + + 'translate3d(0,' + (toRect.top - fromRect.top) / sy + 'px,0)'; + } + }, + + animateFloatingLabel: function() { + if (!this.floatingLabel || this.labelAnimated) { + return; + } + + if (!this.$.labelText.cachedTransform) { + this.prepareLabelTransform(); + } + + // If there's still no cached transform, the input is invisible so don't + // do the animation. + if (!this.$.labelText.cachedTransform) { + return; + } + + this.labelAnimated = true; + // Handle interrupted animation + this.async(function() { + this.transitionEndAction(); + }, null, 250); + + if (this.inputHasValue) { + this.$.labelText.style.webkitTransform = this.$.labelText.cachedTransform; + this.$.labelText.style.transform = this.$.labelText.cachedTransform; + } else { + // Handle if the label started out floating + if (!this.$.labelText.style.webkitTransform && !this.$.labelText.style.transform) { + this.$.labelText.style.webkitTransform = this.$.labelText.cachedTransform; + this.$.labelText.style.transform = this.$.labelText.cachedTransform; + this.$.labelText.offsetTop; + } + this.$.labelText.style.webkitTransform = ''; + this.$.labelText.style.transform = ''; + } + }, + + inputValueChanged: function(old) { + this.super(); + + this.syncInputValueToMirror(); + if (old && !this.inputValue || !old && this.inputValue) { + this.animateFloatingLabel(); + } + }, + + placeholderChanged: function() { + this.label = this.placeholder; + }, + + inputFocusAction: function() { + this.super(arguments); + this.focused = true; + }, + + inputBlurAction: function(e) { + this.super(arguments); + this.focused = false; + }, + + downAction: function(e) { + if (this.disabled) { + return; + } + + if (this.focused) { + return; + } + + // The underline spills from the tap location + var rect = this.$.underline.getBoundingClientRect(); + var right = e.x - rect.left; + this.$.focusedUnderline.style.mozTransformOrigin = right + 'px'; + this.$.focusedUnderline.style.webkitTransformOrigin = right + 'px '; + this.$.focusedUnderline.style.transformOriginX = right + 'px'; + + // Animations only run when the user interacts with the input + this.underlineAnimated = true; + + // Cursor animation only runs if the input is empty + if (!this.inputHasValue) { + this.cursorAnimated = true; + } + // Handle interrupted animation + this.async(function() { + this.transitionEndAction(); + }, null, 250); + }, + + keydownAction: function() { + this.super(); + + // more type = number hacks. see core-input for more info + if (this.type === 'number') { + var valid = !this.inputValue && this.validity.valid; + this.async(function() { + if (valid !== (!this.inputValue && this.validity.valid)) { + this.animateFloatingLabel(); + } + }); + } + }, + + transitionEndAction: function() { + this.underlineAnimated = false; + this.cursorAnimated = false; + this.labelAnimated = false; + } + + }); + + }()); + + </script> + +</polymer-element> +</div> + +<div hidden><!-- +Copyright (c) 2014 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--> + +<!-- +`core-header-panel` contains a header section and a content panel section. + +__Important:__ The `core-header-panel` will not display if its parent does not have a height. + +Using [layout attributes](http://www.polymer-project.org/docs/polymer/layout-attrs.html), you can easily make the `core-header-panel` fill the screen + + <body fullbleed layout vertical> + <core-header-panel flex> + <core-toolbar> + <div>Hello World!</div> + </core-toolbar> + </core-header-panel> + </body> + +or, if you would prefer to do it in CSS, just give `html`, `body`, and `core-header-panel` a height of 100%: + + html, body { + height: 100%; + margin: 0; + } + core-header-panel { + height: 100%; + } + +Special support is provided for scrolling modes when one uses a core-toolbar or equivalent +for the header section. + +Example: + + <core-header-panel> + <core-toolbar>Header</core-toolbar> + <div>Content goes here...</div> + </core-header-panel> + +If you want to use other than `core-toolbar` for the header, add +`core-header` class to that element. + +Example: + + <core-header-panel> + <div class="core-header">Header</div> + <div>Content goes here...</div> + </core-header-panel> + +To have the content fits to the main area, use `fit` attribute. + + <core-header-panel> + <div class="core-header">standard</div> + <div class="content" fit>content fits 100% below the header</div> + </core-header-panel> + +Use `mode` to control the header and scrolling behavior. + +@group Polymer Core Elements +@element core-header-panel +@homepage github.io +--> + + + +<polymer-element name="core-header-panel" assetpath="polymer/bower_components/core-header-panel/"> +<template> + + <style>/* +Copyright (c) 2014 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +*/ + +:host { + display: block; + position: relative; +} + +#outerContainer { + position: absolute; + top: 0; + right: 0; + bottom: 0; + left: 0; +} + +#mainPanel { + position: relative; +} + +#mainContainer { + position: relative; + overflow-y: auto; + overflow-x: hidden; + -webkit-overflow-scrolling: touch; +} + +#dropShadow { + position: absolute; + top: 0; + left: 0; + right: 0; + height: 6px; + box-shadow: inset 0px 5px 6px -3px rgba(0, 0, 0, 0.4); +} + +#dropShadow.hidden { + display: none; +} + +/* +mode: scroll +*/ +:host([mode=scroll]) #mainContainer { + overflow: visible; +} + +:host([mode=scroll]) #outerContainer { + overflow-y: auto; + overflow-x: hidden; + -webkit-overflow-scrolling: touch; +} + +/* +mode: cover +*/ +:host([mode=cover]) #mainPanel { + position: static; +} + +:host([mode=cover]) #mainContainer { + position: absolute; + top: 0; + right: 0; + bottom: 0; + left: 0; +} + +:host([mode=cover]) #dropShadow { + position: static; + width: 100%; +} +</style> + + <div id="outerContainer" vertical="" layout=""> + + <content id="headerContent" select="core-toolbar, .core-header"></content> + + <div id="mainPanel" flex="" vertical="" layout=""> + + <div id="mainContainer" flex?="{{mode !== 'cover'}}"> + <content id="mainContent" select="*"></content> + </div> + + <div id="dropShadow"></div> + + </div> + + </div> + +</template> +<script> + + Polymer('core-header-panel', { + + /** + * Fired when the content has been scrolled. `event.detail.target` returns + * the scrollable element which you can use to access scroll info such as + * `scrollTop`. + * + * <core-header-panel on-scroll="{{scrollHandler}}"> + * ... + * </core-header-panel> + * + * + * scrollHandler: function(event) { + * var scroller = event.detail.target; + * console.log(scroller.scrollTop); + * } + * + * @event scroll + */ + + publish: { + /** + * Controls header and scrolling behavior. Options are + * `standard`, `seamed`, `waterfall`, `waterfall-tall`, `scroll` and + * `cover`. Default is `standard`. + * + * `standard`: The header is a step above the panel. The header will consume the + * panel at the point of entry, preventing it from passing through to the + * opposite side. + * + * `seamed`: The header is presented as seamed with the panel. + * + * `waterfall`: Similar to standard mode, but header is initially presented as + * seamed with panel, but then separates to form the step. + * + * `waterfall-tall`: The header is initially taller (`tall` class is added to + * the header). As the user scrolls, the header separates (forming an edge) + * while condensing (`tall` class is removed from the header). + * + * `scroll`: The header keeps its seam with the panel, and is pushed off screen. + * + * `cover`: The panel covers the whole `core-header-panel` including the + * header. This allows user to style the panel in such a way that the panel is + * partially covering the header. + * + * <style> + * core-header-panel[mode=cover]::shadow #mainContainer { + * left: 80px; + * } + * .content { + * margin: 60px 60px 60px 0; + * } + * </style> + * + * <core-header-panel mode="cover"> + * <core-appbar class="tall"> + * <core-icon-button icon="menu"></core-icon-button> + * </core-appbar> + * <div class="content"></div> + * </core-header-panel> + * + * @attribute mode + * @type string + * @default '' + */ + mode: {value: '', reflect: true}, + + /** + * The class used in waterfall-tall mode. Change this if the header + * accepts a different class for toggling height, e.g. "medium-tall" + * + * @attribute tallClass + * @type string + * @default 'tall' + */ + tallClass: 'tall', + + /** + * If true, the drop-shadow is always shown no matter what mode is set to. + * + * @attribute shadow + * @type boolean + * @default false + */ + shadow: false + }, + + animateDuration: 200, + + modeConfigs: { + shadowMode: {'waterfall': 1, 'waterfall-tall': 1}, + noShadow: {'seamed': 1, 'cover': 1, 'scroll': 1}, + tallMode: {'waterfall-tall': 1}, + outerScroll: {'scroll': 1} + }, + + ready: function() { + this.scrollHandler = this.scroll.bind(this); + this.addListener(); + }, + + detached: function() { + this.removeListener(this.mode); + }, + + addListener: function() { + this.scroller.addEventListener('scroll', this.scrollHandler); + }, + + removeListener: function(mode) { + var s = this.getScrollerForMode(mode); + s.removeEventListener('scroll', this.scrollHandler); + }, + + domReady: function() { + this.async('scroll'); + }, + + modeChanged: function(old) { + var header = this.header; + if (header) { + var configs = this.modeConfigs; + // in tallMode it may add tallClass to the header; so do the cleanup + // when mode is changed from tallMode to not tallMode + if (configs.tallMode[old] && !configs.tallMode[this.mode]) { + header.classList.remove(this.tallClass); + this.async(function() { + header.classList.remove('animate'); + }, null, this.animateDuration); + } else { + header.classList.toggle('animate', configs.tallMode[this.mode]); + } + } + if (configs.outerScroll[this.mode] || configs.outerScroll[old]) { + this.removeListener(old); + this.addListener(); + } + this.scroll(); + }, + + get header() { + return this.$.headerContent.getDistributedNodes()[0]; + }, + + getScrollerForMode: function(mode) { + return this.modeConfigs.outerScroll[mode] ? + this.$.outerContainer : this.$.mainContainer; + }, + + /** + * Returns the scrollable element. + * + * @property scroller + * @type Object + */ + get scroller() { + return this.getScrollerForMode(this.mode); + }, + + scroll: function() { + var configs = this.modeConfigs; + var main = this.$.mainContainer; + var header = this.header; + + var sTop = main.scrollTop; + var atTop = sTop === 0; + + this.$.dropShadow.classList.toggle('hidden', !this.shadow && + (atTop && configs.shadowMode[this.mode] || configs.noShadow[this.mode])); + + if (header && configs.tallMode[this.mode]) { + header.classList.toggle(this.tallClass, atTop || + header.classList.contains(this.tallClass) && + main.scrollHeight < this.$.outerContainer.offsetHeight); + } + + this.fire('scroll', {target: this.scroller}, this, false); + } + + }); + +</script> +</polymer-element> + +<!-- +Copyright (c) 2014 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--> + +<!-- +`core-toolbar` is a horizontal bar containing elements that can be used for +label, navigation, search and actions. + + <core-toolbar> + <core-icon-button icon="menu" on-tap="{{menuAction}}"></core-icon-button> + <div flex>Title</div> + <core-icon-button icon="more" on-tap="{{moreAction}}"></core-icon-button> + </core-toolbar> + +`core-toolbar` has a standard height, but can made be taller by setting `tall` +class on the `core-toolbar`. This will make the toolbar 3x the normal height. + + <core-toolbar class="tall"> + <core-icon-button icon="menu"></core-icon-button> + </core-toolbar> + +Apply `medium-tall` class to make the toolbar medium tall. This will make the +toolbar 2x the normal height. + + <core-toolbar class="medium-tall"> + <core-icon-button icon="menu"></core-icon-button> + </core-toolbar> + +When taller, elements can pin to either the top (default), middle or bottom. + + <core-toolbar class="tall"> + <core-icon-button icon="menu"></core-icon-button> + <div class="middle indent">Middle Title</div> + <div class="bottom indent">Bottom Title</div> + </core-toolbar> + +To make an element completely fit at the bottom of the toolbar, use `fit` along +with `bottom`. + + <core-toolbar class="tall"> + <div id="progressBar" class="bottom fit"></div> + </core-toolbar> + +`core-toolbar` adapts to mobile/narrow layout when there is a `core-narrow` class set +on itself or any of its ancestors. + +@group Polymer Core Elements +@element core-toolbar +@homepage github.io +--> + + + +<polymer-element name="core-toolbar" assetpath="polymer/bower_components/core-toolbar/"> +<template> + + <style>/* +Copyright (c) 2014 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +*/ + +:host { + /* technical */ + display: block; + position: relative; + box-sizing: border-box; + -moz-box-sizing: border-box; + /* size */ + height: 64px; + /* typography */ + font-size: 1.3em; + /* background */ + background-color: #CFD8DC; +} + +:host(.animate) { + /* transition */ + transition: height 0.18s ease-in; +} + +:host(.medium-tall) { + height: 128px; +} + +:host(.tall) { + height: 192px; +} + +.toolbar-tools { + position: relative; + height: 64px; + padding: 0 8px; + pointer-events: none; +} + +/* narrow layout */ +:host(.core-narrow), +:host-context(.core-narrow) { + height: 56px; +} + +polyfill-next-selector { content: ':host.core-narrow.medium-tall, .core-narrow :host.medium-tall'; } +:host(.core-narrow.medium-tall), +:host-context(.core-narrow):host(.medium-tall) { + height: 112px; +} + +polyfill-next-selector { content: ':host.core-narrow.tall, .core-narrow :host.tall'; } +:host(.core-narrow.tall), +:host-context(.core-narrow):host(.tall) { + height: 168px; +} + +polyfill-next-selector { content: ':host.core-narrow .toolbar-tools, .core-narrow :host .toolbar-tools'; } +:host(.core-narrow) .toolbar-tools, +:host-context(.core-narrow) .toolbar-tools { + height: 56px; + padding: 0; +} + +/* middle bar */ +#middleBar { + position: absolute; + top: 0; + right: 0; + left: 0; +} + +:host(.tall, .medium-tall) #middleBar { + -webkit-transform: translateY(100%); + transform: translateY(100%); +} + +/* bottom bar */ +#bottomBar { + position: absolute; + right: 0; + bottom: 0; + left: 0; +} + +/* make elements (e.g. buttons) respond to mouse/touch events */ +polyfill-next-selector { content: '.toolbar-tools > *'; } +::content > * { + pointer-events: auto; +} + +/* elements spacing */ +polyfill-next-selector { content: '.toolbar-tools > *'; } +::content > * { + margin: 0 8px; +} + +/* misc helpers */ +polyfill-next-selector { content: '.toolbar-tools > .fit'; } +::content > .fit { + position: absolute; + top: auto; + right: 0; + bottom: 0; + left: 0; + width: auto; + margin: 0; +} + +polyfill-next-selector { content: ':host .indent'; } +::content > .indent { + margin-left: 60px; +} +</style> + + <div id="bottomBar" class="toolbar-tools" center="" horizontal="" layout=""> + <content select=".bottom"></content> + </div> + + <div id="middleBar" class="toolbar-tools" center="" horizontal="" layout=""> + <content select=".middle"></content> + </div> + + <div id="topBar" class="toolbar-tools" center="" horizontal="" layout=""> + <content></content> + </div> + +</template> +<script>Polymer('core-toolbar');</script></polymer-element> + +<!-- +Copyright (c) 2014 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--> + +<!-- +`core-icon-button` is an icon with button behaviors. + + <core-icon-button src="star.png"></core-icon-button> + +`core-icon-button` includes a default icon set. Use `icon` to specify +which icon from the icon set to use. + + <core-icon-button icon="menu"></core-icon-button> + +See [`core-iconset`](#core-iconset) for more information about +how to use a custom icon set. + +@group Polymer Core Elements +@element core-icon-button +@homepage github.io +--> + + + + +<polymer-element name="core-icon-button" attributes="src icon active" assetpath="polymer/bower_components/core-icon-button/"> + + <template> + <style>/* +Copyright (c) 2014 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE +The complete set of authors may be found at http://polymer.github.io/AUTHORS +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS +*/ + +:host { + display: inline-block; + box-sizing: border-box; + -moz-box-sizing: border-box; + user-select: none; + -moz-user-select: none; + -webkit-user-select: none; + border-radius: 2px; + padding: 7px; + margin: 2px; + vertical-align: middle; + font-size: 1rem; + cursor: pointer; +} + +:host([disabled]) { + opacity: 0.6; + pointer-events: none; +} + +:host(.outline) { + box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.1); +} + +:host(:hover:not([disabled])) { + box-shadow: 0 1px 0 0 rgba(0, 0, 0, 0.12), 0 0 0 1px rgba(0, 0, 0, 0.1); +} + +:host(.selected:not([disabled])) { + background-color: rgba(0, 0, 0, 0.05); + box-shadow: inset 0 1px 0 0 rgba(0, 0, 0, 0.05), 0 0 0 1px rgba(0, 0, 0, 0.12); +} + +:host(:active:not([disabled]), .selected:active:not([disabled])) { + background-color: rgba(0, 0, 0, 0.05); + box-shadow: inset 0 1px 0 0 rgba(0, 0, 0, 0.1), 0 0 0 1px rgba(0, 0, 0, 0.12); +} + +:host(.core-dark-theme.outline) { + background-color: rgba(200, 200, 200, 0.05); + box-shadow: 0 0 0 1px rgba(200, 200, 200, 0.1); +} + +:host(.core-dark-theme:hover) { + background-color: rgba(200, 200, 200, 0.05); + box-shadow: 0 1px 0 0 rgba(200, 200, 200, 0.12), 0 0 0 1px rgba(200, 200, 200, 0.1); +} + +:host(.core-dark-theme.selected) { + background-color: rgba(220, 220, 220, 0.05); + box-shadow: inset 0 1px 0 0 rgba(200, 200, 200, 0.05), 0 0 0 1px rgba(200, 200, 200, 0.12); +} + +:host(.core-dark-theme:active, .core-dark-theme.selected:active) { + background-color: rgba(200, 200, 200, 0.05); + box-shadow: inset 0 1px 0 0 rgba(200, 200, 200, 0.1), 0 0 0 1px rgba(200, 200, 200, 0.12); +} + +core-icon { + pointer-events: none; +} + +/* note: this is a polyfill aware selector */ +:host ::content > :not(core-icon) { + margin-left: 4px; +} +</style> + <core-icon src="{{src}}" icon="{{icon}}"></core-icon><content></content> + </template> + + <script> + + Polymer('core-icon-button', { + + /** + * The URL of an image for the icon. Should not use `icon` property + * if you are using this property. + * + * @attribute src + * @type string + * @default '' + */ + src: '', + + /** + * If true, border is placed around the button to indicate it's + * active state. + * + * @attribute active + * @type boolean + * @default false + */ + active: false, + + /** + * Specifies the icon name or index in the set of icons available in + * the icon set. Should not use `src` property if you are using this + * property. + * + * @attribute icon + * @type string + * @default '' + */ + icon: '', + + activeChanged: function() { + this.classList.toggle('selected', this.active); + } + + }); + + </script> + +</polymer-element> + +<!-- +Copyright (c) 2014 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--> + +<!-- +@group Paper Elements + +Material Design: <a href="https://spec.googleplex.com/quantum/components/buttons.html">Button</a> + +`paper-fab` is a floating action button. It contains an image placed in the center and +comes in two sizes: regular size and a smaller size by applying the class `mini`. When +the user touches the button, a ripple effect emanates from the center of the button. + +You may import `core-icons` to use with this element, or provide an URL to a custom icon. +See `core-iconset` for more information about how to use a custom icon set. + +Example: + + <link href="path/to/core-icons/core-icons.html" rel="import"> + + <paper-fab icon="add"></paper-fab> + <paper-fab mini icon="favorite"></paper-fab> + <paper-fab src="star.png"></paper-fab> + +Styling +------- + +Style the button with CSS as you would a normal DOM element. If you are using the icons +provided by `core-icons`, the icon will inherit the foreground color of the button. + + /* make a blue "cloud" button */ + <paper-fab icon="cloud" style="color: blue;"></paper-fab> + +By default, the ripple is the same color as the foreground at 25% opacity. You may +customize the color using this selector: + + /* make #my-button use a blue ripple instead of foreground color */ + #my-button::shadow #ripple { + color: blue; + } + +The opacity of the ripple is not customizable via CSS. + +Accessibility +------------- + +The button is accessible by default if you use the `icon` property. By default, the +`aria-label` attribute will be set to the `icon` property. If you use a custom icon, +you should ensure that the `aria-label` attribute is set. + + <paper-fab src="star.png" aria-label="star"></paper-fab> + +@element paper-fab +@extends paper-button-base +@status unstable +--> + + + + + + +<polymer-element name="paper-fab" extends="paper-button-base" attributes="src icon mini" role="button" assetpath="polymer/bower_components/paper-fab/"> + + <template> + + <style> + :host { + display: inline-block; + position: relative; + outline: none; + -webkit-user-select: none; + user-select: none; + cursor: pointer; + z-index: 0; + + box-sizing: border-box; + width: 56px; + height: 56px; + background: #d23f31; + color: #fff; + border-radius: 50%; + padding: 16px; + } + + :host([mini]) { + width: 40px; + height: 40px; + padding: 8px; + } + + :host([disabled]) { + color: #c9c9c9; + pointer-events: none; + cursor: auto; + } + + #ripple { + pointer-events: none; + z-index: -1; + } + </style> + + <template if="{{raised}}"> + <paper-shadow id="shadow" z="{{z}}" animated=""></paper-shadow> + </template> + + <!-- to position to ripple behind the icon --> + <core-icon relative="" id="icon" src="{{src}}" icon="{{icon}}"></core-icon> + + </template> + + <script> + Polymer('paper-fab',{ + + publish: { + + /** + * The URL of an image for the icon. If the src property is specified, + * the icon property should not be. + * + * @attribute src + * @type string + * @default '' + */ + src: '', + + /** + * Specifies the icon name or index in the set of icons available in + * the icon's icon set. If the icon property is specified, + * the src property should not be. + * + * @attribute icon + * @type string + * @default '' + */ + icon: '', + + /** + * Set this to true to style this is a "mini" FAB. + * + * @attribute mini + * @type boolean + * @default false + */ + mini: false, + + raised: true, + recenteringTouch: false, + fill: true + + }, + + iconChanged: function(oldIcon) { + this.setAttribute('aria-label', this.icon); + } + + }); + + </script> +</polymer-element> + +<!-- +Copyright (c) 2014 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--> + +<!-- +`paper-tabs` is a `core-selector` styled to look like tabs. Tabs make it easy to +explore and switch between different views or functional aspects of an app, or +to browse categorized data sets. + +Use `selected` property to get or set the selected tab. + +Example: + + <paper-tabs selected="0"> + <paper-tab>TAB 1</paper-tab> + <paper-tab>TAB 2</paper-tab> + <paper-tab>TAB 3</paper-tab> + </paper-tabs> + +See <a href="#paper-tab">paper-tab</a> for more information about +`paper-tab`. + +Styling tabs: + +To change the sliding bar color: + + paper-tabs.pink::shadow #selectionBar { + background-color: #ff4081; + } + +@group Paper Elements +@element paper-tabs +@extends core-selector +@homepage github.io +--> + +<!-- +Copyright (c) 2014 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--> + +<!-- +@group Polymer Core Elements + +`<core-selector>` is used to manage a list of elements that can be selected. + +The attribute `selected` indicates which item element is being selected. +The attribute `multi` indicates if multiple items can be selected at once. +Tapping on the item element would fire `core-activate` event. Use +`core-select` event to listen for selection changes. + +Example: + + <core-selector selected="0"> + <div>Item 1</div> + <div>Item 2</div> + <div>Item 3</div> + </core-selector> + +`<core-selector>` is not styled. Use the `core-selected` CSS class to style the selected element. + + <style> + .item.core-selected { + background: #eee; + } + </style> + ... + <core-selector> + <div class="item">Item 1</div> + <div class="item">Item 2</div> + <div class="item">Item 3</div> + </core-selector> + +@element core-selector +@status stable +@homepage github.io +--> + +<!-- +Fired when an item's selection state is changed. This event is fired both +when an item is selected or deselected. The `isSelected` detail property +contains the selection state. + +@event core-select +@param {Object} detail + @param {boolean} detail.isSelected true for selection and false for deselection + @param {Object} detail.item the item element +--> +<!-- +Fired when an item element is tapped. + +@event core-activate +@param {Object} detail + @param {Object} detail.item the item element +--> + + +<!-- +Copyright (c) 2014 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--> +<!-- +@group Polymer Core Elements + +The `<core-selection>` element is used to manage selection state. It has no +visual appearance and is typically used in conjunction with another element. +For example, [core-selector](#core-selector) +use a `<core-selection>` to manage selection. + +To mark an item as selected, call the `select(item)` method on +`<core-selection>`. The item itself is an argument to this method. + +The `<core-selection>`element manages selection state for any given set of +items. When an item is selected, the `core-select` event is fired. + +The attribute `multi` indicates if multiple items can be selected at once. + +Example: + + <polymer-element name="selection-example"> + <template> + <style> + polyfill-next-selector { content: ':host > .selected'; } + ::content > .selected { + font-weight: bold; + font-style: italic; + } + </style> + <ul on-tap="{{itemTapAction}}"> + <content></content> + </ul> + <core-selection id="selection" multi + on-core-select="{{selectAction}}"></core-selection> + </template> + <script> + Polymer('selection-example', { + itemTapAction: function(e, detail, sender) { + this.$.selection.select(e.target); + }, + selectAction: function(e, detail, sender) { + detail.item.classList.toggle('selected', detail.isSelected); + } + }); + </script> + </polymer-element> + + <selection-example> + <li>Red</li> + <li>Green</li> + <li>Blue</li> + </selection-example> + +@element core-selection +--> + +<!-- +Fired when an item's selection state is changed. This event is fired both +when an item is selected or deselected. The `isSelected` detail property +contains the selection state. + +@event core-select +@param {Object} detail + @param {boolean} detail.isSelected true for selection and false for de-selection + @param {Object} detail.item the item element +--> + + +<polymer-element name="core-selection" attributes="multi" hidden assetpath="polymer/bower_components/core-selection/"> + <script> + Polymer('core-selection', { + /** + * If true, multiple selections are allowed. + * + * @attribute multi + * @type boolean + * @default false + */ + multi: false, + ready: function() { + this.clear(); + }, + clear: function() { + this.selection = []; + }, + /** + * Retrieves the selected item(s). + * @method getSelection + * @returns Returns the selected item(s). If the multi property is true, + * getSelection will return an array, otherwise it will return + * the selected item or undefined if there is no selection. + */ + getSelection: function() { + return this.multi ? this.selection : this.selection[0]; + }, + /** + * Indicates if a given item is selected. + * @method isSelected + * @param {any} item The item whose selection state should be checked. + * @returns Returns true if `item` is selected. + */ + isSelected: function(item) { + return this.selection.indexOf(item) >= 0; + }, + setItemSelected: function(item, isSelected) { + if (item !== undefined && item !== null) { + if (isSelected) { + this.selection.push(item); + } else { + var i = this.selection.indexOf(item); + if (i >= 0) { + this.selection.splice(i, 1); + } + } + this.fire("core-select", {isSelected: isSelected, item: item}); + } + }, + /** + * Set the selection state for a given `item`. If the multi property + * is true, then the selected state of `item` will be toggled; otherwise + * the `item` will be selected. + * @method select + * @param {any} item: The item to select. + */ + select: function(item) { + if (this.multi) { + this.toggle(item); + } else if (this.getSelection() !== item) { + this.setItemSelected(this.getSelection(), false); + this.setItemSelected(item, true); + } + }, + /** + * Toggles the selection state for `item`. + * @method toggle + * @param {any} item: The item to toggle. + */ + toggle: function(item) { + this.setItemSelected(item, !this.isSelected(item)); + } + }); + </script> +</polymer-element> + + +<polymer-element name="core-selector" attributes="selected multi valueattr selectedClass selectedProperty selectedAttribute selectedItem selectedModel selectedIndex notap excludedLocalNames target itemsSelector activateEvent" assetpath="polymer/bower_components/core-selector/"> + + <template> + <core-selection id="selection" multi="{{multi}}" on-core-select="{{selectionSelect}}"></core-selection> + <content id="items" select="*"></content> + </template> + + <script> + + Polymer('core-selector', { + + /** + * Gets or sets the selected element. Default to use the index + * of the item element. + * + * If you want a specific attribute value of the element to be + * used instead of index, set "valueattr" to that attribute name. + * + * Example: + * + * <core-selector valueattr="label" selected="foo"> + * <div label="foo"></div> + * <div label="bar"></div> + * <div label="zot"></div> + * </core-selector> + * + * In multi-selection this should be an array of values. + * + * Example: + * + * <core-selector id="selector" valueattr="label" multi> + * <div label="foo"></div> + * <div label="bar"></div> + * <div label="zot"></div> + * </core-selector> + * + * this.$.selector.selected = ['foo', 'zot']; + * + * @attribute selected + * @type Object + * @default null + */ + selected: null, + + /** + * If true, multiple selections are allowed. + * + * @attribute multi + * @type boolean + * @default false + */ + multi: false, + + /** + * Specifies the attribute to be used for "selected" attribute. + * + * @attribute valueattr + * @type string + * @default 'name' + */ + valueattr: 'name', + + /** + * Specifies the CSS class to be used to add to the selected element. + * + * @attribute selectedClass + * @type string + * @default 'core-selected' + */ + selectedClass: 'core-selected', + + /** + * Specifies the property to be used to set on the selected element + * to indicate its active state. + * + * @attribute selectedProperty + * @type string + * @default '' + */ + selectedProperty: '', + + /** + * Specifies the attribute to set on the selected element to indicate + * its active state. + * + * @attribute selectedAttribute + * @type string + * @default 'active' + */ + selectedAttribute: 'active', + + /** + * Returns the currently selected element. In multi-selection this returns + * an array of selected elements. + * Note that you should not use this to set the selection. Instead use + * `selected`. + * + * @attribute selectedItem + * @type Object + * @default null + */ + selectedItem: null, + + /** + * In single selection, this returns the model associated with the + * selected element. + * Note that you should not use this to set the selection. Instead use + * `selected`. + * + * @attribute selectedModel + * @type Object + * @default null + */ + selectedModel: null, + + /** + * In single selection, this returns the selected index. + * Note that you should not use this to set the selection. Instead use + * `selected`. + * + * @attribute selectedIndex + * @type number + * @default -1 + */ + selectedIndex: -1, + + /** + * Nodes with local name that are in the list will not be included + * in the selection items. In the following example, `items` returns four + * `core-item`'s and doesn't include `h3` and `hr`. + * + * <core-selector excludedLocalNames="h3 hr"> + * <h3>Header</h3> + * <core-item>Item1</core-item> + * <core-item>Item2</core-item> + * <hr> + * <core-item>Item3</core-item> + * <core-item>Item4</core-item> + * </core-selector> + * + * @attribute excludedLocalNames + * @type string + * @default '' + */ + excludedLocalNames: '', + + /** + * The target element that contains items. If this is not set + * core-selector is the container. + * + * @attribute target + * @type Object + * @default null + */ + target: null, + + /** + * This can be used to query nodes from the target node to be used for + * selection items. Note this only works if `target` is set + * and is not `core-selector` itself. + * + * Example: + * + * <core-selector target="{{$.myForm}}" itemsSelector="input[type=radio]"></core-selector> + * <form id="myForm"> + * <label><input type="radio" name="color" value="red"> Red</label> <br> + * <label><input type="radio" name="color" value="green"> Green</label> <br> + * <label><input type="radio" name="color" value="blue"> Blue</label> <br> + * <p>color = {{color}}</p> + * </form> + * + * @attribute itemsSelector + * @type string + * @default '' + */ + itemsSelector: '', + + /** + * The event that would be fired from the item element to indicate + * it is being selected. + * + * @attribute activateEvent + * @type string + * @default 'tap' + */ + activateEvent: 'tap', + + /** + * Set this to true to disallow changing the selection via the + * `activateEvent`. + * + * @attribute notap + * @type boolean + * @default false + */ + notap: false, + + defaultExcludedLocalNames: 'template', + + ready: function() { + this.activateListener = this.activateHandler.bind(this); + this.itemFilter = this.filterItem.bind(this); + this.excludedLocalNamesChanged(); + this.observer = new MutationObserver(this.updateSelected.bind(this)); + if (!this.target) { + this.target = this; + } + }, + + /** + * Returns an array of all items. + * + * @property items + */ + get items() { + if (!this.target) { + return []; + } + var nodes = this.target !== this ? (this.itemsSelector ? + this.target.querySelectorAll(this.itemsSelector) : + this.target.children) : this.$.items.getDistributedNodes(); + return Array.prototype.filter.call(nodes, this.itemFilter); + }, + + filterItem: function(node) { + return !this._excludedNames[node.localName]; + }, + + excludedLocalNamesChanged: function() { + this._excludedNames = {}; + var s = this.defaultExcludedLocalNames; + if (this.excludedLocalNames) { + s += ' ' + this.excludedLocalNames; + } + s.split(/\s+/g).forEach(function(n) { + this._excludedNames[n] = 1; + }, this); + }, + + targetChanged: function(old) { + if (old) { + this.removeListener(old); + this.observer.disconnect(); + this.clearSelection(); + } + if (this.target) { + this.addListener(this.target); + this.observer.observe(this.target, {childList: true}); + this.updateSelected(); + } + }, + + addListener: function(node) { + Polymer.addEventListener(node, this.activateEvent, this.activateListener); + }, + + removeListener: function(node) { + Polymer.removeEventListener(node, this.activateEvent, this.activateListener); + }, + + /** + * Returns the selected item(s). If the `multi` property is true, + * this will return an array, otherwise it will return + * the selected item or undefined if there is no selection. + */ + get selection() { + return this.$.selection.getSelection(); + }, + + selectedChanged: function() { + this.updateSelected(); + }, + + updateSelected: function() { + this.validateSelected(); + if (this.multi) { + this.clearSelection(); + this.selected && this.selected.forEach(function(s) { + this.valueToSelection(s); + }, this); + } else { + this.valueToSelection(this.selected); + } + }, + + validateSelected: function() { + // convert to an array for multi-selection + if (this.multi && !Array.isArray(this.selected) && + this.selected !== null && this.selected !== undefined) { + this.selected = [this.selected]; + } + }, + + clearSelection: function() { + if (this.multi) { + this.selection.slice().forEach(function(s) { + this.$.selection.setItemSelected(s, false); + }, this); + } else { + this.$.selection.setItemSelected(this.selection, false); + } + this.selectedItem = null; + this.$.selection.clear(); + }, + + valueToSelection: function(value) { + var item = (value === null || value === undefined) ? + null : this.items[this.valueToIndex(value)]; + this.$.selection.select(item); + }, + + updateSelectedItem: function() { + this.selectedItem = this.selection; + }, + + selectedItemChanged: function() { + if (this.selectedItem) { + var t = this.selectedItem.templateInstance; + this.selectedModel = t ? t.model : undefined; + } else { + this.selectedModel = null; + } + this.selectedIndex = this.selectedItem ? + parseInt(this.valueToIndex(this.selected)) : -1; + }, + + valueToIndex: function(value) { + // find an item with value == value and return it's index + for (var i=0, items=this.items, c; (c=items[i]); i++) { + if (this.valueForNode(c) == value) { + return i; + } + } + // if no item found, the value itself is probably the index + return value; + }, + + valueForNode: function(node) { + return node[this.valueattr] || node.getAttribute(this.valueattr); + }, + + // events fired from <core-selection> object + selectionSelect: function(e, detail) { + this.updateSelectedItem(); + if (detail.item) { + this.applySelection(detail.item, detail.isSelected); + } + }, + + applySelection: function(item, isSelected) { + if (this.selectedClass) { + item.classList.toggle(this.selectedClass, isSelected); + } + if (this.selectedProperty) { + item[this.selectedProperty] = isSelected; + } + if (this.selectedAttribute && item.setAttribute) { + if (isSelected) { + item.setAttribute(this.selectedAttribute, ''); + } else { + item.removeAttribute(this.selectedAttribute); + } + } + }, + + // event fired from host + activateHandler: function(e) { + if (!this.notap) { + var i = this.findDistributedTarget(e.target, this.items); + if (i >= 0) { + var item = this.items[i]; + var s = this.valueForNode(item) || i; + if (this.multi) { + if (this.selected) { + this.addRemoveSelected(s); + } else { + this.selected = [s]; + } + } else { + this.selected = s; + } + this.asyncFire('core-activate', {item: item}); + } + } + }, + + addRemoveSelected: function(value) { + var i = this.selected.indexOf(value); + if (i >= 0) { + this.selected.splice(i, 1); + } else { + this.selected.push(value); + } + this.valueToSelection(value); + }, + + findDistributedTarget: function(target, nodes) { + // find first ancestor of target (including itself) that + // is in nodes, if any + while (target && target != this) { + var i = Array.prototype.indexOf.call(nodes, target); + if (i >= 0) { + return i; + } + target = target.parentNode; + } + }, + + selectIndex: function(index) { + var item = this.items[index]; + if (item) { + this.selected = this.valueForNode(item) || index; + return item; + } + }, + + /** + * Selects the previous item. This should be used in single selection only. + * + * @method selectPrevious + * @param {boolean} wrap if true and it is already at the first item, wrap to the end + * @returns the previous item or undefined if there is none + */ + selectPrevious: function(wrap) { + var i = wrap && !this.selectedIndex ? this.items.length - 1 : this.selectedIndex - 1; + return this.selectIndex(i); + }, + + /** + * Selects the next item. This should be used in single selection only. + * + * @method selectNext + * @param {boolean} wrap if true and it is already at the last item, wrap to the front + * @returns the next item or undefined if there is none + */ + selectNext: function(wrap) { + var i = wrap && this.selectedIndex >= this.items.length - 1 ? 0 : this.selectedIndex + 1; + return this.selectIndex(i); + } + + }); + </script> +</polymer-element> + +<!-- +Copyright (c) 2014 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--> + +<!-- +`paper-tab` is styled to look like a tab. It should be used in conjunction with +`paper-tabs`. + +Example: + + <paper-tabs selected="0"> + <paper-tab>TAB 1</paper-tab> + <paper-tab>TAB 2</paper-tab> + <paper-tab>TAB 3</paper-tab> + </paper-tabs> + +Styling tab: + +To change the ink color: + + .pink paper-tab::shadow #ink { + color: #ff4081; + } + +@group Paper Elements +@element paper-tab +@homepage github.io +--> + + + +<polymer-element name="paper-tab" attributes="noink" role="tab" assetpath="polymer/bower_components/paper-tabs/"> +<template> + + <style>/* +Copyright (c) 2014 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +*/ + +:host { + display: block; + position: relative; + overflow: hidden; +} + +#tabContainer { + position: absolute; + top: 0; + right: 0; + bottom: 0; + left: 0; +} + +.tab-content { + transition: opacity .1s cubic-bezier(0.4, 0.0, 1, 1), color .1s cubic-bezier(0.4, 0.0, 1, 1); + cursor: default; + pointer-events: none; +} + +:host(:not(.core-selected)) .tab-content { + opacity: 0.6; +} + +#ink { + position: absolute; + top: 0; + right: 0; + bottom: 0; + left: 0; + color: #ffff8d; +} + +:host[noink] #ink { + pointer-events: none; +} + +:host-context(paper-tabs[noink]) #ink { + pointer-events: none; +} +</style> + + <div id="tabContainer" center-justified="" center="" horizontal="" layout=""> + + <div class="tab-content"><content></content></div> + <paper-ripple id="ink" initialopacity="0.95" opacitydecayvelocity="0.98"></paper-ripple> + + </div> + +</template> +<script> + + Polymer('paper-tab', { + + /** + * If true, ink ripple effect is disabled. + * + * @attribute noink + * @type boolean + * @default false + */ + noink: false + + }); + +</script> +</polymer-element> + + +<polymer-element name="paper-tabs" extends="core-selector" attributes="noink nobar" role="tablist" assetpath="polymer/bower_components/paper-tabs/"> +<template> + + <style>/* +Copyright (c) 2014 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +*/ + +:host { + display: block; + position: relative; + font-size: 14px; + font-weight: 500; + height: 48px; + overflow: hidden; +} + +#tabsContainer { + position: absolute; + top: 0; + right: 0; + bottom: 0; + left: 0; + white-space: nowrap; +} + +#selectionBar { + position: absolute; + height: 2px; + bottom: 0; + left: 0; + width: 0; + background-color: #ffff8d; + transition: width, left; +} + +#selectionBar[hidden] { + display: hidden; +} + +#selectionBar.expand { + transition-duration: 0.15s; + transition-timing-function: cubic-bezier(0.4, 0.0, 1, 1); +} + +#selectionBar.contract { + transition-duration: 0.18s; + transition-timing-function: cubic-bezier(0.0, 0.0, 0.2, 1); +} + +polyfill-next-selector { content: '#tabsContainer > *:not(#selectionBar)'; } +::content > * { + -ms-flex: 1; + -webkit-flex: 1; + flex: 1; +} +</style> + + <div id="tabsContainer" horizontal="" layout=""> + + <shadow></shadow> + <div id="selectionBar" hidden?="{{nobar}}" on-transitionend="{{barTransitionEnd}}"></div> + + </div> + +</template> +<script> + + Polymer('paper-tabs', { + + /** + * If true, ink effect is disabled. + * + * @attribute noink + * @type boolean + * @default false + */ + noink: false, + + /** + * If true, the bottom bar to indicate the selected tab will not be shown. + * + * @attribute nobar + * @type boolean + * @default false + */ + nobar: false, + + activateEvent: 'down', + + nostretch: false, + + selectedIndexChanged: function(old) { + var s = this.$.selectionBar.style; + + if (!this.selectedItem) { + s.width = 0; + s.left = 0; + return; + } + + var w = 100 / this.items.length; + + if (this.nostretch || old === null || old === -1) { + s.width = w + '%'; + s.left = this.selectedIndex * w + '%'; + return; + } + + var m = 5; + this.$.selectionBar.classList.add('expand'); + if (old < this.selectedIndex) { + s.width = w + w * (this.selectedIndex - old) - m + '%'; + this._transitionCounter = 1; + } else { + s.width = w + w * (old - this.selectedIndex) - m + '%'; + s.left = this.selectedIndex * w + m + '%'; + this._transitionCounter = 2; + } + }, + + barTransitionEnd: function(e) { + this._transitionCounter--; + var cl = this.$.selectionBar.classList; + if (cl.contains('expand') && !this._transitionCounter) { + cl.remove('expand'); + cl.add('contract'); + var s = this.$.selectionBar.style; + var w = 100 / this.items.length; + s.width = w + '%'; + s.left = this.selectedIndex * w + '%'; + } else if (cl.contains('contract')) { + cl.remove('contract'); + } + } + + }); + +</script> +</polymer-element> + + + + +<script>//! moment.js +//! version : 2.8.3 +//! authors : Tim Wood, Iskren Chernev, Moment.js contributors +//! license : MIT +//! momentjs.com + +(function (undefined) { + /************************************ + Constants + ************************************/ + + var moment, + VERSION = '2.8.3', + // the global-scope this is NOT the global object in Node.js + globalScope = typeof global !== 'undefined' ? global : this, + oldGlobalMoment, + round = Math.round, + hasOwnProperty = Object.prototype.hasOwnProperty, + i, + + YEAR = 0, + MONTH = 1, + DATE = 2, + HOUR = 3, + MINUTE = 4, + SECOND = 5, + MILLISECOND = 6, + + // internal storage for locale config files + locales = {}, + + // extra moment internal properties (plugins register props here) + momentProperties = [], + + // check for nodeJS + hasModule = (typeof module !== 'undefined' && module.exports), + + // ASP.NET json date format regex + aspNetJsonRegex = /^\/?Date\((\-?\d+)/i, + aspNetTimeSpanJsonRegex = /(\-)?(?:(\d*)\.)?(\d+)\:(\d+)(?:\:(\d+)\.?(\d{3})?)?/, + + // from http://docs.closure-library.googlecode.com/git/closure_goog_date_date.js.source.html + // somewhat more in line with 4.4.3.2 2004 spec, but allows decimal anywhere + isoDurationRegex = /^(-)?P(?:(?:([0-9,.]*)Y)?(?:([0-9,.]*)M)?(?:([0-9,.]*)D)?(?:T(?:([0-9,.]*)H)?(?:([0-9,.]*)M)?(?:([0-9,.]*)S)?)?|([0-9,.]*)W)$/, + + // format tokens + formattingTokens = /(\[[^\[]*\])|(\\)?(Mo|MM?M?M?|Do|DDDo|DD?D?D?|ddd?d?|do?|w[o|w]?|W[o|W]?|Q|YYYYYY|YYYYY|YYYY|YY|gg(ggg?)?|GG(GGG?)?|e|E|a|A|hh?|HH?|mm?|ss?|S{1,4}|X|zz?|ZZ?|.)/g, + localFormattingTokens = /(\[[^\[]*\])|(\\)?(LT|LL?L?L?|l{1,4})/g, + + // parsing token regexes + parseTokenOneOrTwoDigits = /\d\d?/, // 0 - 99 + parseTokenOneToThreeDigits = /\d{1,3}/, // 0 - 999 + parseTokenOneToFourDigits = /\d{1,4}/, // 0 - 9999 + parseTokenOneToSixDigits = /[+\-]?\d{1,6}/, // -999,999 - 999,999 + parseTokenDigits = /\d+/, // nonzero number of digits + parseTokenWord = /[0-9]*['a-z\u00A0-\u05FF\u0700-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]+|[\u0600-\u06FF\/]+(\s*?[\u0600-\u06FF]+){1,2}/i, // any word (or two) characters or numbers including two/three word month in arabic. + parseTokenTimezone = /Z|[\+\-]\d\d:?\d\d/gi, // +00:00 -00:00 +0000 -0000 or Z + parseTokenT = /T/i, // T (ISO separator) + parseTokenTimestampMs = /[\+\-]?\d+(\.\d{1,3})?/, // 123456789 123456789.123 + parseTokenOrdinal = /\d{1,2}/, + + //strict parsing regexes + parseTokenOneDigit = /\d/, // 0 - 9 + parseTokenTwoDigits = /\d\d/, // 00 - 99 + parseTokenThreeDigits = /\d{3}/, // 000 - 999 + parseTokenFourDigits = /\d{4}/, // 0000 - 9999 + parseTokenSixDigits = /[+-]?\d{6}/, // -999,999 - 999,999 + parseTokenSignedNumber = /[+-]?\d+/, // -inf - inf + + // iso 8601 regex + // 0000-00-00 0000-W00 or 0000-W00-0 + T + 00 or 00:00 or 00:00:00 or 00:00:00.000 + +00:00 or +0000 or +00) + isoRegex = /^\s*(?:[+-]\d{6}|\d{4})-(?:(\d\d-\d\d)|(W\d\d$)|(W\d\d-\d)|(\d\d\d))((T| )(\d\d(:\d\d(:\d\d(\.\d+)?)?)?)?([\+\-]\d\d(?::?\d\d)?|\s*Z)?)?$/, + + isoFormat = 'YYYY-MM-DDTHH:mm:ssZ', + + isoDates = [ + ['YYYYYY-MM-DD', /[+-]\d{6}-\d{2}-\d{2}/], + ['YYYY-MM-DD', /\d{4}-\d{2}-\d{2}/], + ['GGGG-[W]WW-E', /\d{4}-W\d{2}-\d/], + ['GGGG-[W]WW', /\d{4}-W\d{2}/], + ['YYYY-DDD', /\d{4}-\d{3}/] + ], + + // iso time formats and regexes + isoTimes = [ + ['HH:mm:ss.SSSS', /(T| )\d\d:\d\d:\d\d\.\d+/], + ['HH:mm:ss', /(T| )\d\d:\d\d:\d\d/], + ['HH:mm', /(T| )\d\d:\d\d/], + ['HH', /(T| )\d\d/] + ], + + // timezone chunker '+10:00' > ['10', '00'] or '-1530' > ['-15', '30'] + parseTimezoneChunker = /([\+\-]|\d\d)/gi, + + // getter and setter names + proxyGettersAndSetters = 'Date|Hours|Minutes|Seconds|Milliseconds'.split('|'), + unitMillisecondFactors = { + 'Milliseconds' : 1, + 'Seconds' : 1e3, + 'Minutes' : 6e4, + 'Hours' : 36e5, + 'Days' : 864e5, + 'Months' : 2592e6, + 'Years' : 31536e6 + }, + + unitAliases = { + ms : 'millisecond', + s : 'second', + m : 'minute', + h : 'hour', + d : 'day', + D : 'date', + w : 'week', + W : 'isoWeek', + M : 'month', + Q : 'quarter', + y : 'year', + DDD : 'dayOfYear', + e : 'weekday', + E : 'isoWeekday', + gg: 'weekYear', + GG: 'isoWeekYear' + }, + + camelFunctions = { + dayofyear : 'dayOfYear', + isoweekday : 'isoWeekday', + isoweek : 'isoWeek', + weekyear : 'weekYear', + isoweekyear : 'isoWeekYear' + }, + + // format function strings + formatFunctions = {}, + + // default relative time thresholds + relativeTimeThresholds = { + s: 45, // seconds to minute + m: 45, // minutes to hour + h: 22, // hours to day + d: 26, // days to month + M: 11 // months to year + }, + + // tokens to ordinalize and pad + ordinalizeTokens = 'DDD w W M D d'.split(' '), + paddedTokens = 'M D H h m s w W'.split(' '), + + formatTokenFunctions = { + M : function () { + return this.month() + 1; + }, + MMM : function (format) { + return this.localeData().monthsShort(this, format); + }, + MMMM : function (format) { + return this.localeData().months(this, format); + }, + D : function () { + return this.date(); + }, + DDD : function () { + return this.dayOfYear(); + }, + d : function () { + return this.day(); + }, + dd : function (format) { + return this.localeData().weekdaysMin(this, format); + }, + ddd : function (format) { + return this.localeData().weekdaysShort(this, format); + }, + dddd : function (format) { + return this.localeData().weekdays(this, format); + }, + w : function () { + return this.week(); + }, + W : function () { + return this.isoWeek(); + }, + YY : function () { + return leftZeroFill(this.year() % 100, 2); + }, + YYYY : function () { + return leftZeroFill(this.year(), 4); + }, + YYYYY : function () { + return leftZeroFill(this.year(), 5); + }, + YYYYYY : function () { + var y = this.year(), sign = y >= 0 ? '+' : '-'; + return sign + leftZeroFill(Math.abs(y), 6); + }, + gg : function () { + return leftZeroFill(this.weekYear() % 100, 2); + }, + gggg : function () { + return leftZeroFill(this.weekYear(), 4); + }, + ggggg : function () { + return leftZeroFill(this.weekYear(), 5); + }, + GG : function () { + return leftZeroFill(this.isoWeekYear() % 100, 2); + }, + GGGG : function () { + return leftZeroFill(this.isoWeekYear(), 4); + }, + GGGGG : function () { + return leftZeroFill(this.isoWeekYear(), 5); + }, + e : function () { + return this.weekday(); + }, + E : function () { + return this.isoWeekday(); + }, + a : function () { + return this.localeData().meridiem(this.hours(), this.minutes(), true); + }, + A : function () { + return this.localeData().meridiem(this.hours(), this.minutes(), false); + }, + H : function () { + return this.hours(); + }, + h : function () { + return this.hours() % 12 || 12; + }, + m : function () { + return this.minutes(); + }, + s : function () { + return this.seconds(); + }, + S : function () { + return toInt(this.milliseconds() / 100); + }, + SS : function () { + return leftZeroFill(toInt(this.milliseconds() / 10), 2); + }, + SSS : function () { + return leftZeroFill(this.milliseconds(), 3); + }, + SSSS : function () { + return leftZeroFill(this.milliseconds(), 3); + }, + Z : function () { + var a = -this.zone(), + b = '+'; + if (a < 0) { + a = -a; + b = '-'; + } + return b + leftZeroFill(toInt(a / 60), 2) + ':' + leftZeroFill(toInt(a) % 60, 2); + }, + ZZ : function () { + var a = -this.zone(), + b = '+'; + if (a < 0) { + a = -a; + b = '-'; + } + return b + leftZeroFill(toInt(a / 60), 2) + leftZeroFill(toInt(a) % 60, 2); + }, + z : function () { + return this.zoneAbbr(); + }, + zz : function () { + return this.zoneName(); + }, + X : function () { + return this.unix(); + }, + Q : function () { + return this.quarter(); + } + }, + + deprecations = {}, + + lists = ['months', 'monthsShort', 'weekdays', 'weekdaysShort', 'weekdaysMin']; + + // Pick the first defined of two or three arguments. dfl comes from + // default. + function dfl(a, b, c) { + switch (arguments.length) { + case 2: return a != null ? a : b; + case 3: return a != null ? a : b != null ? b : c; + default: throw new Error('Implement me'); + } + } + + function hasOwnProp(a, b) { + return hasOwnProperty.call(a, b); + } + + function defaultParsingFlags() { + // We need to deep clone this object, and es5 standard is not very + // helpful. + return { + empty : false, + unusedTokens : [], + unusedInput : [], + overflow : -2, + charsLeftOver : 0, + nullInput : false, + invalidMonth : null, + invalidFormat : false, + userInvalidated : false, + iso: false + }; + } + + function printMsg(msg) { + if (moment.suppressDeprecationWarnings === false && + typeof console !== 'undefined' && console.warn) { + console.warn('Deprecation warning: ' + msg); + } + } + + function deprecate(msg, fn) { + var firstTime = true; + return extend(function () { + if (firstTime) { + printMsg(msg); + firstTime = false; + } + return fn.apply(this, arguments); + }, fn); + } + + function deprecateSimple(name, msg) { + if (!deprecations[name]) { + printMsg(msg); + deprecations[name] = true; + } + } + + function padToken(func, count) { + return function (a) { + return leftZeroFill(func.call(this, a), count); + }; + } + function ordinalizeToken(func, period) { + return function (a) { + return this.localeData().ordinal(func.call(this, a), period); + }; + } + + while (ordinalizeTokens.length) { + i = ordinalizeTokens.pop(); + formatTokenFunctions[i + 'o'] = ordinalizeToken(formatTokenFunctions[i], i); + } + while (paddedTokens.length) { + i = paddedTokens.pop(); + formatTokenFunctions[i + i] = padToken(formatTokenFunctions[i], 2); + } + formatTokenFunctions.DDDD = padToken(formatTokenFunctions.DDD, 3); + + + /************************************ + Constructors + ************************************/ + + function Locale() { + } + + // Moment prototype object + function Moment(config, skipOverflow) { + if (skipOverflow !== false) { + checkOverflow(config); + } + copyConfig(this, config); + this._d = new Date(+config._d); + } + + // Duration Constructor + function Duration(duration) { + var normalizedInput = normalizeObjectUnits(duration), + years = normalizedInput.year || 0, + quarters = normalizedInput.quarter || 0, + months = normalizedInput.month || 0, + weeks = normalizedInput.week || 0, + days = normalizedInput.day || 0, + hours = normalizedInput.hour || 0, + minutes = normalizedInput.minute || 0, + seconds = normalizedInput.second || 0, + milliseconds = normalizedInput.millisecond || 0; + + // representation for dateAddRemove + this._milliseconds = +milliseconds + + seconds * 1e3 + // 1000 + minutes * 6e4 + // 1000 * 60 + hours * 36e5; // 1000 * 60 * 60 + // Because of dateAddRemove treats 24 hours as different from a + // day when working around DST, we need to store them separately + this._days = +days + + weeks * 7; + // It is impossible translate months into days without knowing + // which months you are are talking about, so we have to store + // it separately. + this._months = +months + + quarters * 3 + + years * 12; + + this._data = {}; + + this._locale = moment.localeData(); + + this._bubble(); + } + + /************************************ + Helpers + ************************************/ + + + function extend(a, b) { + for (var i in b) { + if (hasOwnProp(b, i)) { + a[i] = b[i]; + } + } + + if (hasOwnProp(b, 'toString')) { + a.toString = b.toString; + } + + if (hasOwnProp(b, 'valueOf')) { + a.valueOf = b.valueOf; + } + + return a; + } + + function copyConfig(to, from) { + var i, prop, val; + + if (typeof from._isAMomentObject !== 'undefined') { + to._isAMomentObject = from._isAMomentObject; + } + if (typeof from._i !== 'undefined') { + to._i = from._i; + } + if (typeof from._f !== 'undefined') { + to._f = from._f; + } + if (typeof from._l !== 'undefined') { + to._l = from._l; + } + if (typeof from._strict !== 'undefined') { + to._strict = from._strict; + } + if (typeof from._tzm !== 'undefined') { + to._tzm = from._tzm; + } + if (typeof from._isUTC !== 'undefined') { + to._isUTC = from._isUTC; + } + if (typeof from._offset !== 'undefined') { + to._offset = from._offset; + } + if (typeof from._pf !== 'undefined') { + to._pf = from._pf; + } + if (typeof from._locale !== 'undefined') { + to._locale = from._locale; + } + + if (momentProperties.length > 0) { + for (i in momentProperties) { + prop = momentProperties[i]; + val = from[prop]; + if (typeof val !== 'undefined') { + to[prop] = val; + } + } + } + + return to; + } + + function absRound(number) { + if (number < 0) { + return Math.ceil(number); + } else { + return Math.floor(number); + } + } + + // left zero fill a number + // see http://jsperf.com/left-zero-filling for performance comparison + function leftZeroFill(number, targetLength, forceSign) { + var output = '' + Math.abs(number), + sign = number >= 0; + + while (output.length < targetLength) { + output = '0' + output; + } + return (sign ? (forceSign ? '+' : '') : '-') + output; + } + + function positiveMomentsDifference(base, other) { + var res = {milliseconds: 0, months: 0}; + + res.months = other.month() - base.month() + + (other.year() - base.year()) * 12; + if (base.clone().add(res.months, 'M').isAfter(other)) { + --res.months; + } + + res.milliseconds = +other - +(base.clone().add(res.months, 'M')); + + return res; + } + + function momentsDifference(base, other) { + var res; + other = makeAs(other, base); + if (base.isBefore(other)) { + res = positiveMomentsDifference(base, other); + } else { + res = positiveMomentsDifference(other, base); + res.milliseconds = -res.milliseconds; + res.months = -res.months; + } + + return res; + } + + // TODO: remove 'name' arg after deprecation is removed + function createAdder(direction, name) { + return function (val, period) { + var dur, tmp; + //invert the arguments, but complain about it + if (period !== null && !isNaN(+period)) { + deprecateSimple(name, 'moment().' + name + '(period, number) is deprecated. Please use moment().' + name + '(number, period).'); + tmp = val; val = period; period = tmp; + } + + val = typeof val === 'string' ? +val : val; + dur = moment.duration(val, period); + addOrSubtractDurationFromMoment(this, dur, direction); + return this; + }; + } + + function addOrSubtractDurationFromMoment(mom, duration, isAdding, updateOffset) { + var milliseconds = duration._milliseconds, + days = duration._days, + months = duration._months; + updateOffset = updateOffset == null ? true : updateOffset; + + if (milliseconds) { + mom._d.setTime(+mom._d + milliseconds * isAdding); + } + if (days) { + rawSetter(mom, 'Date', rawGetter(mom, 'Date') + days * isAdding); + } + if (months) { + rawMonthSetter(mom, rawGetter(mom, 'Month') + months * isAdding); + } + if (updateOffset) { + moment.updateOffset(mom, days || months); + } + } + + // check if is an array + function isArray(input) { + return Object.prototype.toString.call(input) === '[object Array]'; + } + + function isDate(input) { + return Object.prototype.toString.call(input) === '[object Date]' || + input instanceof Date; + } + + // compare two arrays, return the number of differences + function compareArrays(array1, array2, dontConvert) { + var len = Math.min(array1.length, array2.length), + lengthDiff = Math.abs(array1.length - array2.length), + diffs = 0, + i; + for (i = 0; i < len; i++) { + if ((dontConvert && array1[i] !== array2[i]) || + (!dontConvert && toInt(array1[i]) !== toInt(array2[i]))) { + diffs++; + } + } + return diffs + lengthDiff; + } + + function normalizeUnits(units) { + if (units) { + var lowered = units.toLowerCase().replace(/(.)s$/, '$1'); + units = unitAliases[units] || camelFunctions[lowered] || lowered; + } + return units; + } + + function normalizeObjectUnits(inputObject) { + var normalizedInput = {}, + normalizedProp, + prop; + + for (prop in inputObject) { + if (hasOwnProp(inputObject, prop)) { + normalizedProp = normalizeUnits(prop); + if (normalizedProp) { + normalizedInput[normalizedProp] = inputObject[prop]; + } + } + } + + return normalizedInput; + } + + function makeList(field) { + var count, setter; + + if (field.indexOf('week') === 0) { + count = 7; + setter = 'day'; + } + else if (field.indexOf('month') === 0) { + count = 12; + setter = 'month'; + } + else { + return; + } + + moment[field] = function (format, index) { + var i, getter, + method = moment._locale[field], + results = []; + + if (typeof format === 'number') { + index = format; + format = undefined; + } + + getter = function (i) { + var m = moment().utc().set(setter, i); + return method.call(moment._locale, m, format || ''); + }; + + if (index != null) { + return getter(index); + } + else { + for (i = 0; i < count; i++) { + results.push(getter(i)); + } + return results; + } + }; + } + + function toInt(argumentForCoercion) { + var coercedNumber = +argumentForCoercion, + value = 0; + + if (coercedNumber !== 0 && isFinite(coercedNumber)) { + if (coercedNumber >= 0) { + value = Math.floor(coercedNumber); + } else { + value = Math.ceil(coercedNumber); + } + } + + return value; + } + + function daysInMonth(year, month) { + return new Date(Date.UTC(year, month + 1, 0)).getUTCDate(); + } + + function weeksInYear(year, dow, doy) { + return weekOfYear(moment([year, 11, 31 + dow - doy]), dow, doy).week; + } + + function daysInYear(year) { + return isLeapYear(year) ? 366 : 365; + } + + function isLeapYear(year) { + return (year % 4 === 0 && year % 100 !== 0) || year % 400 === 0; + } + + function checkOverflow(m) { + var overflow; + if (m._a && m._pf.overflow === -2) { + overflow = + m._a[MONTH] < 0 || m._a[MONTH] > 11 ? MONTH : + m._a[DATE] < 1 || m._a[DATE] > daysInMonth(m._a[YEAR], m._a[MONTH]) ? DATE : + m._a[HOUR] < 0 || m._a[HOUR] > 23 ? HOUR : + m._a[MINUTE] < 0 || m._a[MINUTE] > 59 ? MINUTE : + m._a[SECOND] < 0 || m._a[SECOND] > 59 ? SECOND : + m._a[MILLISECOND] < 0 || m._a[MILLISECOND] > 999 ? MILLISECOND : + -1; + + if (m._pf._overflowDayOfYear && (overflow < YEAR || overflow > DATE)) { + overflow = DATE; + } + + m._pf.overflow = overflow; + } + } + + function isValid(m) { + if (m._isValid == null) { + m._isValid = !isNaN(m._d.getTime()) && + m._pf.overflow < 0 && + !m._pf.empty && + !m._pf.invalidMonth && + !m._pf.nullInput && + !m._pf.invalidFormat && + !m._pf.userInvalidated; + + if (m._strict) { + m._isValid = m._isValid && + m._pf.charsLeftOver === 0 && + m._pf.unusedTokens.length === 0; + } + } + return m._isValid; + } + + function normalizeLocale(key) { + return key ? key.toLowerCase().replace('_', '-') : key; + } + + // pick the locale from the array + // try ['en-au', 'en-gb'] as 'en-au', 'en-gb', 'en', as in move through the list trying each + // substring from most specific to least, but move to the next array item if it's a more specific variant than the current root + function chooseLocale(names) { + var i = 0, j, next, locale, split; + + while (i < names.length) { + split = normalizeLocale(names[i]).split('-'); + j = split.length; + next = normalizeLocale(names[i + 1]); + next = next ? next.split('-') : null; + while (j > 0) { + locale = loadLocale(split.slice(0, j).join('-')); + if (locale) { + return locale; + } + if (next && next.length >= j && compareArrays(split, next, true) >= j - 1) { + //the next array item is better than a shallower substring of this one + break; + } + j--; + } + i++; + } + return null; + } + + function loadLocale(name) { + var oldLocale = null; + if (!locales[name] && hasModule) { + try { + oldLocale = moment.locale(); + require('./locale/' + name); + // because defineLocale currently also sets the global locale, we want to undo that for lazy loaded locales + moment.locale(oldLocale); + } catch (e) { } + } + return locales[name]; + } + + // Return a moment from input, that is local/utc/zone equivalent to model. + function makeAs(input, model) { + return model._isUTC ? moment(input).zone(model._offset || 0) : + moment(input).local(); + } + + /************************************ + Locale + ************************************/ + + + extend(Locale.prototype, { + + set : function (config) { + var prop, i; + for (i in config) { + prop = config[i]; + if (typeof prop === 'function') { + this[i] = prop; + } else { + this['_' + i] = prop; + } + } + }, + + _months : 'January_February_March_April_May_June_July_August_September_October_November_December'.split('_'), + months : function (m) { + return this._months[m.month()]; + }, + _monthsShort : 'Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec'.split('_'), + monthsShort : function (m) { + return this._monthsShort[m.month()]; + }, -<core-style id="paper-input"> + monthsParse : function (monthName) { + var i, mom, regex; -:host([focused]) .floated-label { - color: {{g.paperInput.focusedColor}}; -} + if (!this._monthsParse) { + this._monthsParse = []; + } -.focused-underline, -.cursor { - background-color: {{g.paperInput.focusedColor}}; -} + for (i = 0; i < 12; i++) { + // make the regex if we don't have it already + if (!this._monthsParse[i]) { + mom = moment.utc([2000, i]); + regex = '^' + this.months(mom, '') + '|^' + this.monthsShort(mom, ''); + this._monthsParse[i] = new RegExp(regex.replace('.', ''), 'i'); + } + // test the regex + if (this._monthsParse[i].test(monthName)) { + return i; + } + } + }, + _weekdays : 'Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday'.split('_'), + weekdays : function (m) { + return this._weekdays[m.day()]; + }, -:host(.invalid[focused]) .floated-label, -:host([focused]) .error-text, -:host([focused]) .error-icon { - color: {{g.paperInput.invalidColor}}; -} + _weekdaysShort : 'Sun_Mon_Tue_Wed_Thu_Fri_Sat'.split('_'), + weekdaysShort : function (m) { + return this._weekdaysShort[m.day()]; + }, -:host(.invalid) .focused-underline, -:host(.invalid) .cursor { - background-color: {{g.paperInput.invalidColor}}; -} + _weekdaysMin : 'Su_Mo_Tu_We_Th_Fr_Sa'.split('_'), + weekdaysMin : function (m) { + return this._weekdaysMin[m.day()]; + }, -</core-style> + weekdaysParse : function (weekdayName) { + var i, mom, regex; -<polymer-element name="paper-input" extends="core-input" layout="" vertical="" attributes="label floatingLabel maxRows error" on-transitionend="{{transitionEndAction}}" on-webkittransitionend="{{transitionEndAction}}" assetpath="polymer/bower_components/paper-input/"> + if (!this._weekdaysParse) { + this._weekdaysParse = []; + } - <template> + for (i = 0; i < 7; i++) { + // make the regex if we don't have it already + if (!this._weekdaysParse[i]) { + mom = moment([2000, 1]).day(i); + regex = '^' + this.weekdays(mom, '') + '|^' + this.weekdaysShort(mom, '') + '|^' + this.weekdaysMin(mom, ''); + this._weekdaysParse[i] = new RegExp(regex.replace('.', ''), 'i'); + } + // test the regex + if (this._weekdaysParse[i].test(weekdayName)) { + return i; + } + } + }, - <!-- - Input tests: + _longDateFormat : { + LT : 'h:mm A', + L : 'MM/DD/YYYY', + LL : 'MMMM D, YYYY', + LLL : 'MMMM D, YYYY LT', + LLLL : 'dddd, MMMM D, YYYY LT' + }, + longDateFormat : function (key) { + var output = this._longDateFormat[key]; + if (!output && this._longDateFormat[key.toUpperCase()]) { + output = this._longDateFormat[key.toUpperCase()].replace(/MMMM|MM|DD|dddd/g, function (val) { + return val.slice(1); + }); + this._longDateFormat[key] = output; + } + return output; + }, - - set value to integer 0 - - various html5 input types - - sizing: - - single-line: size with CSS - - single-line: can fit to container - - multi-line: size with CSS - - multi-line: size with rows - - multi-line: can fit to container - - multi-line: grows with typing - - multi-line: max rows - - multi-line: max rows, scrolls after - --> + isPM : function (input) { + // IE8 Quirks Mode & IE7 Standards Mode do not allow accessing strings like arrays + // Using charAt should be more compatible. + return ((input + '').toLowerCase().charAt(0) === 'p'); + }, - <style>/* - * @license - * Copyright (c) 2014 The Polymer Project Authors. All rights reserved. - * This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt - * The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt - * The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt - * Code distributed by Google as part of the polymer project is also - * subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt - */ + _meridiemParse : /[ap]\.?m?\.?/i, + meridiem : function (hours, minutes, isLower) { + if (hours > 11) { + return isLower ? 'pm' : 'PM'; + } else { + return isLower ? 'am' : 'AM'; + } + }, -:host { - display: inline-block; - outline: none; - text-align: inherit; - color: #757575; - padding: 0.75em 0; -} + _calendar : { + sameDay : '[Today at] LT', + nextDay : '[Tomorrow at] LT', + nextWeek : 'dddd [at] LT', + lastDay : '[Yesterday at] LT', + lastWeek : '[Last] dddd [at] LT', + sameElse : 'L' + }, + calendar : function (key, mom) { + var output = this._calendar[key]; + return typeof output === 'function' ? output.apply(mom) : output; + }, -:host /deep/ input, -:host /deep/ textarea { - font: inherit; - color: #000; - padding: 0; - margin: 0; - background-color: transparent; - border: none; - outline: none; - /* see comments in template */ - width: 100%; - height: 100%; -} + _relativeTime : { + future : 'in %s', + past : '%s ago', + s : 'a few seconds', + m : 'a minute', + mm : '%d minutes', + h : 'an hour', + hh : '%d hours', + d : 'a day', + dd : '%d days', + M : 'a month', + MM : '%d months', + y : 'a year', + yy : '%d years' + }, -input:invalid, -textarea:invalid { - box-shadow: none; -} + relativeTime : function (number, withoutSuffix, string, isFuture) { + var output = this._relativeTime[string]; + return (typeof output === 'function') ? + output(number, withoutSuffix, string, isFuture) : + output.replace(/%d/i, number); + }, -textarea { - resize: none; -} + pastFuture : function (diff, output) { + var format = this._relativeTime[diff > 0 ? 'future' : 'past']; + return typeof format === 'function' ? format(output) : format.replace(/%s/i, output); + }, -[invisible] { - visibility: hidden; -} + ordinal : function (number) { + return this._ordinal.replace('%d', number); + }, + _ordinal : '%d', -[animated] { - visibility: visible !important; - -webkit-transition: -webkit-transform 0.2s cubic-bezier(0.4, 0, 0.2, 1), opacity 0.2s cubic-bezier(0.4, 0, 0.2, 1); - transition: transform 0.2s cubic-bezier(0.4, 0, 0.2, 1), opacity 0.2s cubic-bezier(0.4, 0, 0.2, 1); -} + preparse : function (string) { + return string; + }, + + postformat : function (string) { + return string; + }, + + week : function (mom) { + return weekOfYear(mom, this._week.dow, this._week.doy).week; + }, + + _week : { + dow : 0, // Sunday is the first day of the week. + doy : 6 // The week that contains Jan 1st is the first week of the year. + }, + + _invalidDate: 'Invalid date', + invalidDate: function () { + return this._invalidDate; + } + }); + + /************************************ + Formatting + ************************************/ + + + function removeFormattingTokens(input) { + if (input.match(/\[[\s\S]/)) { + return input.replace(/^\[|\]$/g, ''); + } + return input.replace(/\\/g, ''); + } + + function makeFormatFunction(format) { + var array = format.match(formattingTokens), i, length; + + for (i = 0, length = array.length; i < length; i++) { + if (formatTokenFunctions[array[i]]) { + array[i] = formatTokenFunctions[array[i]]; + } else { + array[i] = removeFormattingTokens(array[i]); + } + } + + return function (mom) { + var output = ''; + for (i = 0; i < length; i++) { + output += array[i] instanceof Function ? array[i].call(mom, format) : array[i]; + } + return output; + }; + } -.floated-label { - font-size: 0.75em; - background: transparent; - white-space: nowrap; -} + // format date using native date object + function formatMoment(m, format) { + if (!m.isValid()) { + return m.localeData().invalidDate(); + } -.mirror-text { - padding: 0.5em 0 0.25em; - max-width: 100%; - white-space: nowrap; -} + format = expandFormat(format, m.localeData()); -:host([multiline]) .mirror-text { - white-space: pre-wrap; - word-wrap: break-word; -} + if (!formatFunctions[format]) { + formatFunctions[format] = makeFormatFunction(format); + } -.label { - padding: 0.5em 0 0.25em; - background: transparent; - pointer-events: none; -} + return formatFunctions[format](m); + } -.label-text { - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; - display: inline-block; - max-width: 100%; - -moz-transform-origin: 0% 0%; - -webkit-transform-origin: 0% 0%; - transform-origin: 0% 0%; -} + function expandFormat(format, locale) { + var i = 5; -.cursor { - position: absolute; - top: 0.4em; - left: 0; - width: 1px; - height: 1.4em; - opacity: 0.4; - -moz-transform-origin: 0%; - -webkit-transform-origin: 0%; - transform-origin: 0%; - -webkit-transform: none; - transform: none; -} + function replaceLongDateFormatTokens(input) { + return locale.longDateFormat(input) || input; + } -.cursor[invisible] { - opacity: 0.75; - -webkit-transform: translate3d(3em,0,0) scale3d(50,1,1); - transform: translate3d(3em,0,0) scale3d(50,1,1); -} + localFormattingTokens.lastIndex = 0; + while (i >= 0 && localFormattingTokens.test(format)) { + format = format.replace(localFormattingTokens, replaceLongDateFormatTokens); + localFormattingTokens.lastIndex = 0; + i -= 1; + } -.input-container { - position: absolute; - /* simulate padding so the input/textarea can use 100% width/height */ - top: 0.5em; - right: 0; - bottom: 0.25em; - left: 0; -} + return format; + } -.underline { - height: 0px; - overflow: visible; -} -:host([disabled]) .underline { - border-bottom: 1px dashed; -} + /************************************ + Parsing + ************************************/ -.unfocused-underline { - height: 1px; - background: #757575; - border-bottom-color: #757575; -} -.focused-underline { - height: 2px; - -webkit-transform: none; - transform: none; -} + // get the regex to find the next token + function getParseRegexForToken(token, config) { + var a, strict = config._strict; + switch (token) { + case 'Q': + return parseTokenOneDigit; + case 'DDDD': + return parseTokenThreeDigits; + case 'YYYY': + case 'GGGG': + case 'gggg': + return strict ? parseTokenFourDigits : parseTokenOneToFourDigits; + case 'Y': + case 'G': + case 'g': + return parseTokenSignedNumber; + case 'YYYYYY': + case 'YYYYY': + case 'GGGGG': + case 'ggggg': + return strict ? parseTokenSixDigits : parseTokenOneToSixDigits; + case 'S': + if (strict) { + return parseTokenOneDigit; + } + /* falls through */ + case 'SS': + if (strict) { + return parseTokenTwoDigits; + } + /* falls through */ + case 'SSS': + if (strict) { + return parseTokenThreeDigits; + } + /* falls through */ + case 'DDD': + return parseTokenOneToThreeDigits; + case 'MMM': + case 'MMMM': + case 'dd': + case 'ddd': + case 'dddd': + return parseTokenWord; + case 'a': + case 'A': + return config._locale._meridiemParse; + case 'X': + return parseTokenTimestampMs; + case 'Z': + case 'ZZ': + return parseTokenTimezone; + case 'T': + return parseTokenT; + case 'SSSS': + return parseTokenDigits; + case 'MM': + case 'DD': + case 'YY': + case 'GG': + case 'gg': + case 'HH': + case 'hh': + case 'mm': + case 'ss': + case 'ww': + case 'WW': + return strict ? parseTokenTwoDigits : parseTokenOneOrTwoDigits; + case 'M': + case 'D': + case 'd': + case 'H': + case 'h': + case 'm': + case 's': + case 'w': + case 'W': + case 'e': + case 'E': + return parseTokenOneOrTwoDigits; + case 'Do': + return parseTokenOrdinal; + default : + a = new RegExp(regexpEscape(unescapeFormat(token.replace('\\', '')), 'i')); + return a; + } + } -.focused-underline[invisible] { - -webkit-transform: scale3d(0,1,1); - transform: scale3d(0,1,1); -} + function timezoneMinutesFromString(string) { + string = string || ''; + var possibleTzMatches = (string.match(parseTokenTimezone) || []), + tzChunk = possibleTzMatches[possibleTzMatches.length - 1] || [], + parts = (tzChunk + '').match(parseTimezoneChunker) || ['-', 0, 0], + minutes = +(parts[1] * 60) + toInt(parts[2]); -.error-text { - font-size: 0.75em; - padding: 0.5em 0; -} + return parts[0] === '+' ? -minutes : minutes; + } -.error-icon { - height: 20px; - width: 20px; -} -</style> - <core-style ref="paper-input"></core-style> + // function to convert string input to date + function addTimeToArrayFromToken(token, input, config) { + var a, datePartArray = config._a; + + switch (token) { + // QUARTER + case 'Q': + if (input != null) { + datePartArray[MONTH] = (toInt(input) - 1) * 3; + } + break; + // MONTH + case 'M' : // fall through to MM + case 'MM' : + if (input != null) { + datePartArray[MONTH] = toInt(input) - 1; + } + break; + case 'MMM' : // fall through to MMMM + case 'MMMM' : + a = config._locale.monthsParse(input); + // if we didn't find a month name, mark the date as invalid. + if (a != null) { + datePartArray[MONTH] = a; + } else { + config._pf.invalidMonth = input; + } + break; + // DAY OF MONTH + case 'D' : // fall through to DD + case 'DD' : + if (input != null) { + datePartArray[DATE] = toInt(input); + } + break; + case 'Do' : + if (input != null) { + datePartArray[DATE] = toInt(parseInt(input, 10)); + } + break; + // DAY OF YEAR + case 'DDD' : // fall through to DDDD + case 'DDDD' : + if (input != null) { + config._dayOfYear = toInt(input); + } - <div class="floated-label" aria-hidden="true" hidden?="{{!floatingLabel}}" invisible?="{{!inputValue && !(type === 'number' && !validity.valid) || labelAnimated}}"> - <!-- needed for floating label animation measurement --> - <span id="floatedLabelText" class="label-text">{{label}}</span> - </div> + break; + // YEAR + case 'YY' : + datePartArray[YEAR] = moment.parseTwoDigitYear(input); + break; + case 'YYYY' : + case 'YYYYY' : + case 'YYYYYY' : + datePartArray[YEAR] = toInt(input); + break; + // AM / PM + case 'a' : // fall through to A + case 'A' : + config._isPm = config._locale.isPM(input); + break; + // 24 HOUR + case 'H' : // fall through to hh + case 'HH' : // fall through to hh + case 'h' : // fall through to hh + case 'hh' : + datePartArray[HOUR] = toInt(input); + break; + // MINUTE + case 'm' : // fall through to mm + case 'mm' : + datePartArray[MINUTE] = toInt(input); + break; + // SECOND + case 's' : // fall through to ss + case 'ss' : + datePartArray[SECOND] = toInt(input); + break; + // MILLISECOND + case 'S' : + case 'SS' : + case 'SSS' : + case 'SSSS' : + datePartArray[MILLISECOND] = toInt(('0.' + input) * 1000); + break; + // UNIX TIMESTAMP WITH MS + case 'X': + config._d = new Date(parseFloat(input) * 1000); + break; + // TIMEZONE + case 'Z' : // fall through to ZZ + case 'ZZ' : + config._useUTC = true; + config._tzm = timezoneMinutesFromString(input); + break; + // WEEKDAY - human + case 'dd': + case 'ddd': + case 'dddd': + a = config._locale.weekdaysParse(input); + // if we didn't get a weekday name, mark the date as invalid + if (a != null) { + config._w = config._w || {}; + config._w['d'] = a; + } else { + config._pf.invalidWeekday = input; + } + break; + // WEEK, WEEK DAY - numeric + case 'w': + case 'ww': + case 'W': + case 'WW': + case 'd': + case 'e': + case 'E': + token = token.substr(0, 1); + /* falls through */ + case 'gggg': + case 'GGGG': + case 'GGGGG': + token = token.substr(0, 2); + if (input) { + config._w = config._w || {}; + config._w[token] = toInt(input); + } + break; + case 'gg': + case 'GG': + config._w = config._w || {}; + config._w[token] = moment.parseTwoDigitYear(input); + } + } - <!-- <div class="input-body" flex auto relative on-down="{{downAction}}" on-up="{{upAction}}"> --> - <div class="input-body" flex="" auto="" relative=""> + function dayOfYearFromWeekInfo(config) { + var w, weekYear, week, weekday, dow, doy, temp; - <!-- the mirror sizes the input/textarea so it grows with typing --> - <div id="mirror" class="mirror-text" invisible="" aria-hidden="true"></div> + w = config._w; + if (w.GG != null || w.W != null || w.E != null) { + dow = 1; + doy = 4; - <div class="label" fit="" aria-hidden="true"> - <!-- needed for floating label animation measurement --> - <span id="labelText" class="label-text" invisible?="{{inputValue || !inputValue && type === 'number' && !validity.valid}}" animated?="{{labelAnimated}}">{{label}}</span> - </div> + // TODO: We need to take the current isoWeekYear, but that depends on + // how we interpret now (local, utc, fixed offset). So create + // a now version of current config (take local/utc/offset flags, and + // create now). + weekYear = dfl(w.GG, config._a[YEAR], weekOfYear(moment(), 1, 4).year); + week = dfl(w.W, 1); + weekday = dfl(w.E, 1); + } else { + dow = config._locale._week.dow; + doy = config._locale._week.doy; - <div class="cursor" invisible?="{{!cursorAnimated}}" animated?="{{cursorAnimated}}"></div> + weekYear = dfl(w.gg, config._a[YEAR], weekOfYear(moment(), dow, doy).year); + week = dfl(w.w, 1); - <!-- size the input/textarea with a div, because the textarea has intrinsic size in ff --> - <div class="input-container" on-down="{{downAction}}" on-up="{{upAction}}"> - <shadow></shadow> - </div> + if (w.d != null) { + // weekday -- low day numbers are considered next week + weekday = w.d; + if (weekday < dow) { + ++week; + } + } else if (w.e != null) { + // local weekday -- counting starts from begining of week + weekday = w.e + dow; + } else { + // default to begining of week + weekday = dow; + } + } + temp = dayOfYearFromWeeks(weekYear, week, weekday, doy, dow); - </div> + config._a[YEAR] = temp.year; + config._dayOfYear = temp.dayOfYear; + } - <div id="underline" class="underline" relative=""> - <div class="unfocused-underline" fit="" invisible?="{{disabled}}"></div> - <div id="focusedUnderline" class="focused-underline" fit="" invisible?="{{!focused}}" animated?="{{underlineAnimated}}"></div> - </div> + // convert an array to a date. + // the array should mirror the parameters below + // note: all values past the year are optional and will default to the lowest possible value. + // [year, month, day , hour, minute, second, millisecond] + function dateFromConfig(config) { + var i, date, input = [], currentDate, yearToUse; - <div layout="" horizontal="" center="" hidden?="{{!invalid}}"> - <div class="error-text" flex="" auto="" role="alert" aria-hidden="{{!invalid}}">{{error || validationMessage}}</div> - <core-icon class="error-icon" icon="warning"></core-icon> - </div> + if (config._d) { + return; + } - </template> + currentDate = currentDateArray(config); - <script> + //compute day of the year from weeks and weekdays + if (config._w && config._a[DATE] == null && config._a[MONTH] == null) { + dayOfYearFromWeekInfo(config); + } - (function() { + //if the day of the year is set, figure out what it is + if (config._dayOfYear) { + yearToUse = dfl(config._a[YEAR], currentDate[YEAR]); - var paperInput = CoreStyle.g.paperInput = CoreStyle.g.paperInput || {}; - paperInput.focusedColor = '#4059a9'; - paperInput.invalidColor = '#d34336'; + if (config._dayOfYear > daysInYear(yearToUse)) { + config._pf._overflowDayOfYear = true; + } - Polymer('paper-input', { + date = makeUTCDate(yearToUse, 0, config._dayOfYear); + config._a[MONTH] = date.getUTCMonth(); + config._a[DATE] = date.getUTCDate(); + } - publish: { - /** - * The label for this input. It normally appears as grey text inside - * the text input and disappears once the user enters text. - * - * @attribute label - * @type string - * @default '' - */ - label: '', + // Default to current date. + // * if no year, month, day of month are given, default to today + // * if day of month is given, default month and year + // * if month is given, default only year + // * if year is given, don't default anything + for (i = 0; i < 3 && config._a[i] == null; ++i) { + config._a[i] = input[i] = currentDate[i]; + } - /** - * If true, the label will "float" above the text input once the - * user enters text instead of disappearing. - * - * @attribute floatingLabel - * @type boolean - * @default false - */ - floatingLabel: false, + // Zero out whatever was not defaulted, including time + for (; i < 7; i++) { + config._a[i] = input[i] = (config._a[i] == null) ? (i === 2 ? 1 : 0) : config._a[i]; + } - /** - * (multiline only) If set to a non-zero value, the height of this - * text input will grow with the value changes until it is maxRows - * rows tall. If the maximum size does not fit the value, the text - * input will scroll internally. - * - * @attribute maxRows - * @type number - * @default 0 - */ - maxRows: 0, + config._d = (config._useUTC ? makeUTCDate : makeDate).apply(null, input); + // Apply timezone offset from input. The actual zone can be changed + // with parseZone. + if (config._tzm != null) { + config._d.setUTCMinutes(config._d.getUTCMinutes() + config._tzm); + } + } - /** - * The message to display if the input value fails validation. If this - * is unset or the empty string, a default message is displayed depending - * on the type of validation error. - * - * @attribute error - * @type string - */ - error: '', + function dateFromObject(config) { + var normalizedInput; - focused: {value: false, reflect: true} + if (config._d) { + return; + } - }, + normalizedInput = normalizeObjectUnits(config._i); + config._a = [ + normalizedInput.year, + normalizedInput.month, + normalizedInput.day, + normalizedInput.hour, + normalizedInput.minute, + normalizedInput.second, + normalizedInput.millisecond + ]; - get inputValueForMirror() { - var tokens = this.inputValue ? String(this.inputValue).replace(/&/gm, '&').replace(/"/gm, '"').replace(/'/gm, ''').replace(/</gm, '<').replace(/>/gm, '>').split('\n') : ['']; + dateFromConfig(config); + } - // Enforce the min and max heights for a multiline input here to - // avoid measurement - if (this.multiline) { - if (this.maxRows && tokens.length > this.maxRows) { - tokens = tokens.slice(0, this.maxRows); - } - while (this.rows && tokens.length < this.rows) { - tokens.push(''); - } + function currentDateArray(config) { + var now = new Date(); + if (config._useUTC) { + return [ + now.getUTCFullYear(), + now.getUTCMonth(), + now.getUTCDate() + ]; + } else { + return [now.getFullYear(), now.getMonth(), now.getDate()]; } + } - return tokens.join('<br>') + ' '; - }, + // date from string and format string + function makeDateFromStringAndFormat(config) { + if (config._f === moment.ISO_8601) { + parseISO(config); + return; + } - get inputHasValue() { - // if type = number, the input value is the empty string until a valid number - // is entered so we must do some hacks here - return this.inputValue || (this.type === 'number' && !this.validity.valid); - }, + config._a = []; + config._pf.empty = true; - syncInputValueToMirror: function() { - this.$.mirror.innerHTML = this.inputValueForMirror; - }, + // This array is used to make a Date, either with `new Date` or `Date.UTC` + var string = '' + config._i, + i, parsedInput, tokens, token, skipped, + stringLength = string.length, + totalParsedInputLength = 0; - ready: function() { - this.syncInputValueToMirror(); - }, + tokens = expandFormat(config._f, config._locale).match(formattingTokens) || []; - prepareLabelTransform: function() { - var toRect = this.$.floatedLabelText.getBoundingClientRect(); - var fromRect = this.$.labelText.getBoundingClientRect(); - if (toRect.width !== 0) { - var sy = toRect.height / fromRect.height; - this.$.labelText.cachedTransform = - 'scale3d(' + (toRect.width / fromRect.width) + ',' + sy + ',1) ' + - 'translate3d(0,' + (toRect.top - fromRect.top) / sy + 'px,0)'; + for (i = 0; i < tokens.length; i++) { + token = tokens[i]; + parsedInput = (string.match(getParseRegexForToken(token, config)) || [])[0]; + if (parsedInput) { + skipped = string.substr(0, string.indexOf(parsedInput)); + if (skipped.length > 0) { + config._pf.unusedInput.push(skipped); + } + string = string.slice(string.indexOf(parsedInput) + parsedInput.length); + totalParsedInputLength += parsedInput.length; + } + // don't parse if it's not a known token + if (formatTokenFunctions[token]) { + if (parsedInput) { + config._pf.empty = false; + } + else { + config._pf.unusedTokens.push(token); + } + addTimeToArrayFromToken(token, parsedInput, config); + } + else if (config._strict && !parsedInput) { + config._pf.unusedTokens.push(token); + } } - }, - animateFloatingLabel: function() { - if (!this.floatingLabel || this.labelAnimated) { - return; + // add remaining unparsed input length to the string + config._pf.charsLeftOver = stringLength - totalParsedInputLength; + if (string.length > 0) { + config._pf.unusedInput.push(string); } - if (!this.$.labelText.cachedTransform) { - this.prepareLabelTransform(); + // handle am pm + if (config._isPm && config._a[HOUR] < 12) { + config._a[HOUR] += 12; } - - // If there's still no cached transform, the input is invisible so don't - // do the animation. - if (!this.$.labelText.cachedTransform) { - return; + // if is 12 am, change hours to 0 + if (config._isPm === false && config._a[HOUR] === 12) { + config._a[HOUR] = 0; } - this.labelAnimated = true; - // Handle interrupted animation - this.async(function() { - this.transitionEndAction(); - }, null, 250); + dateFromConfig(config); + checkOverflow(config); + } - if (this.inputHasValue) { - this.$.labelText.style.webkitTransform = this.$.labelText.cachedTransform; - this.$.labelText.style.transform = this.$.labelText.cachedTransform; - } else { - // Handle if the label started out floating - if (!this.$.labelText.style.webkitTransform && !this.$.labelText.style.transform) { - this.$.labelText.style.webkitTransform = this.$.labelText.cachedTransform; - this.$.labelText.style.transform = this.$.labelText.cachedTransform; - this.$.labelText.offsetTop; - } - this.$.labelText.style.webkitTransform = ''; - this.$.labelText.style.transform = ''; + function unescapeFormat(s) { + return s.replace(/\\(\[)|\\(\])|\[([^\]\[]*)\]|\\(.)/g, function (matched, p1, p2, p3, p4) { + return p1 || p2 || p3 || p4; + }); + } + + // Code from http://stackoverflow.com/questions/3561493/is-there-a-regexp-escape-function-in-javascript + function regexpEscape(s) { + return s.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&'); + } + + // date from string and array of format strings + function makeDateFromStringAndArray(config) { + var tempConfig, + bestMoment, + + scoreToBeat, + i, + currentScore; + + if (config._f.length === 0) { + config._pf.invalidFormat = true; + config._d = new Date(NaN); + return; } - }, - inputValueChanged: function(old) { - this.super(); + for (i = 0; i < config._f.length; i++) { + currentScore = 0; + tempConfig = copyConfig({}, config); + if (config._useUTC != null) { + tempConfig._useUTC = config._useUTC; + } + tempConfig._pf = defaultParsingFlags(); + tempConfig._f = config._f[i]; + makeDateFromStringAndFormat(tempConfig); - this.syncInputValueToMirror(); - if (old && !this.inputValue || !old && this.inputValue) { - this.animateFloatingLabel(); + if (!isValid(tempConfig)) { + continue; + } + + // if there is any input that was not parsed add a penalty for that format + currentScore += tempConfig._pf.charsLeftOver; + + //or tokens + currentScore += tempConfig._pf.unusedTokens.length * 10; + + tempConfig._pf.score = currentScore; + + if (scoreToBeat == null || currentScore < scoreToBeat) { + scoreToBeat = currentScore; + bestMoment = tempConfig; + } } - }, - placeholderChanged: function() { - this.label = this.placeholder; - }, + extend(config, bestMoment || tempConfig); + } - inputFocusAction: function() { - this.super(arguments); - this.focused = true; - }, + // date from iso format + function parseISO(config) { + var i, l, + string = config._i, + match = isoRegex.exec(string); - inputBlurAction: function(e) { - this.super(arguments); - this.focused = false; - }, + if (match) { + config._pf.iso = true; + for (i = 0, l = isoDates.length; i < l; i++) { + if (isoDates[i][1].exec(string)) { + // match[5] should be 'T' or undefined + config._f = isoDates[i][0] + (match[6] || ' '); + break; + } + } + for (i = 0, l = isoTimes.length; i < l; i++) { + if (isoTimes[i][1].exec(string)) { + config._f += isoTimes[i][0]; + break; + } + } + if (string.match(parseTokenTimezone)) { + config._f += 'Z'; + } + makeDateFromStringAndFormat(config); + } else { + config._isValid = false; + } + } - downAction: function(e) { - if (this.disabled) { - return; + // date from iso format or fallback + function makeDateFromString(config) { + parseISO(config); + if (config._isValid === false) { + delete config._isValid; + moment.createFromInputFallback(config); } + } - if (this.focused) { - return; + function map(arr, fn) { + var res = [], i; + for (i = 0; i < arr.length; ++i) { + res.push(fn(arr[i], i)); + } + return res; + } + + function makeDateFromInput(config) { + var input = config._i, matched; + if (input === undefined) { + config._d = new Date(); + } else if (isDate(input)) { + config._d = new Date(+input); + } else if ((matched = aspNetJsonRegex.exec(input)) !== null) { + config._d = new Date(+matched[1]); + } else if (typeof input === 'string') { + makeDateFromString(config); + } else if (isArray(input)) { + config._a = map(input.slice(0), function (obj) { + return parseInt(obj, 10); + }); + dateFromConfig(config); + } else if (typeof(input) === 'object') { + dateFromObject(config); + } else if (typeof(input) === 'number') { + // from milliseconds + config._d = new Date(input); + } else { + moment.createFromInputFallback(config); } + } - // The underline spills from the tap location - var rect = this.$.underline.getBoundingClientRect(); - var right = e.x - rect.left; - this.$.focusedUnderline.style.mozTransformOrigin = right + 'px'; - this.$.focusedUnderline.style.webkitTransformOrigin = right + 'px '; - this.$.focusedUnderline.style.transformOriginX = right + 'px'; - - // Animations only run when the user interacts with the input - this.underlineAnimated = true; + function makeDate(y, m, d, h, M, s, ms) { + //can't just apply() to create a date: + //http://stackoverflow.com/questions/181348/instantiating-a-javascript-object-by-calling-prototype-constructor-apply + var date = new Date(y, m, d, h, M, s, ms); - // Cursor animation only runs if the input is empty - if (!this.inputHasValue) { - this.cursorAnimated = true; + //the date constructor doesn't accept years < 1970 + if (y < 1970) { + date.setFullYear(y); } - // Handle interrupted animation - this.async(function() { - this.transitionEndAction(); - }, null, 250); - }, + return date; + } - keydownAction: function() { - this.super(); + function makeUTCDate(y) { + var date = new Date(Date.UTC.apply(null, arguments)); + if (y < 1970) { + date.setUTCFullYear(y); + } + return date; + } - // more type = number hacks. see core-input for more info - if (this.type === 'number') { - var valid = !this.inputValue && this.validity.valid; - this.async(function() { - if (valid !== (!this.inputValue && this.validity.valid)) { - this.animateFloatingLabel(); + function parseWeekday(input, locale) { + if (typeof input === 'string') { + if (!isNaN(input)) { + input = parseInt(input, 10); + } + else { + input = locale.weekdaysParse(input); + if (typeof input !== 'number') { + return null; + } } - }); } - }, - - transitionEndAction: function() { - this.underlineAnimated = false; - this.cursorAnimated = false; - this.labelAnimated = false; - } - - }); - - }()); - - </script> - -</polymer-element> - - + return input; + } + /************************************ + Relative Time + ************************************/ -<polymer-element name="events-list" attributes="api cbEventClicked" assetpath="polymer/"> - <template> - <style> - :host { - display: block; - } - .eventContainer { - font-size: 1rem; + // helper function for moment.fn.from, moment.fn.fromNow, and moment.duration.fn.humanize + function substituteTimeAgo(string, number, withoutSuffix, isFuture, locale) { + return locale.relativeTime(number || 1, !!withoutSuffix, string, isFuture); } - </style> + function relativeTime(posNegDuration, withoutSuffix, locale) { + var duration = moment.duration(posNegDuration).abs(), + seconds = round(duration.as('s')), + minutes = round(duration.as('m')), + hours = round(duration.as('h')), + days = round(duration.as('d')), + months = round(duration.as('M')), + years = round(duration.as('y')), - <template if="{{cbEventClicked}}"> - <style> - a { - text-decoration: underline; - cursor: pointer; - } - </style> - </template> + args = seconds < relativeTimeThresholds.s && ['s', seconds] || + minutes === 1 && ['m'] || + minutes < relativeTimeThresholds.m && ['mm', minutes] || + hours === 1 && ['h'] || + hours < relativeTimeThresholds.h && ['hh', hours] || + days === 1 && ['d'] || + days < relativeTimeThresholds.d && ['dd', days] || + months === 1 && ['M'] || + months < relativeTimeThresholds.M && ['MM', months] || + years === 1 && ['y'] || ['yy', years]; - <div> - <template repeat="{{event in events}}"> - <div class="eventContainer"> - <a on-click="{{handleClick}}">{{event.event}}</a> - ({{event.listener_count}} listeners) - </div> - </template> + args[2] = withoutSuffix; + args[3] = +posNegDuration > 0; + args[4] = locale; + return substituteTimeAgo.apply({}, args); + } - </div> - </template> - <script> - Polymer('events-list',{ - cbEventClicked: null, - events: [], - domReady: function() { - this.events = this.api.events + /************************************ + Week of Year + ************************************/ - this.api.addEventListener('events-updated', this.eventsUpdated.bind(this)) - }, - eventsUpdated: function() { - this.events = this.api.events; - }, + // firstDayOfWeek 0 = sun, 6 = sat + // the day of the week that starts the week + // (usually sunday or monday) + // firstDayOfWeekOfYear 0 = sun, 6 = sat + // the first week is the week that contains the first + // of this day of the week + // (eg. ISO weeks use thursday (4)) + function weekOfYear(mom, firstDayOfWeek, firstDayOfWeekOfYear) { + var end = firstDayOfWeekOfYear - firstDayOfWeek, + daysToDayOfWeek = firstDayOfWeekOfYear - mom.day(), + adjustedMoment; - handleClick: function(ev) { - if(this.cbEventClicked) { - this.cbEventClicked(ev.path[0].innerHTML); - } - }, - }); - </script> -</polymer-element> + if (daysToDayOfWeek > end) { + daysToDayOfWeek -= 7; + } + if (daysToDayOfWeek < end - 7) { + daysToDayOfWeek += 7; + } -<polymer-element name="event-fire-dialog" attributes="api" assetpath="polymer/"> - <template> - <style> - paper-input:first-child { - padding-top: 0; + adjustedMoment = moment(mom).add(daysToDayOfWeek, 'd'); + return { + week: Math.ceil(adjustedMoment.dayOfYear() / 7), + year: adjustedMoment.year() + }; } - .eventContainer { - margin-left: 30px; - } + //http://en.wikipedia.org/wiki/ISO_week_date#Calculating_a_date_given_the_year.2C_week_number_and_weekday + function dayOfYearFromWeeks(year, week, weekday, firstDayOfWeekOfYear, firstDayOfWeek) { + var d = makeUTCDate(year, 0, 1).getUTCDay(), daysToAdd, dayOfYear; - @media all and (max-width: 620px) { - .eventContainer { - display: none; - } + d = d === 0 ? 7 : d; + weekday = weekday != null ? weekday : firstDayOfWeek; + daysToAdd = firstDayOfWeek - d + (d > firstDayOfWeekOfYear ? 7 : 0) - (d < firstDayOfWeek ? 7 : 0); + dayOfYear = 7 * (week - 1) + (weekday - firstDayOfWeek) + daysToAdd + 1; + + return { + year: dayOfYear > 0 ? year : year - 1, + dayOfYear: dayOfYear > 0 ? dayOfYear : daysInYear(year - 1) + dayOfYear + }; } - </style> + /************************************ + Top Level Functions + ************************************/ - <paper-dialog id="dialog" heading="Fire Event" transition="paper-dialog-transition-bottom" backdrop="true"> - <div layout="" horizontal=""> - <div> - <paper-input id="inputType" label="Event Type" floatinglabel="true" autofocus required></paper-input> - <paper-input id="inputData" label="Event Data (JSON, optional)" floatinglabel="true" multiline=""></paper-input> - </div> - <div class="eventContainer"> - <b>Available events:</b> - <events-list api="{{api}}" cbeventclicked="{{eventSelected}}"> - </events-list></div> - </div> - <paper-button dismissive="">Cancel</paper-button> - <paper-button affirmative="" on-click="{{clickFireEvent}}">Fire Event</paper-button> - </paper-dialog> + function makeMoment(config) { + var input = config._i, + format = config._f; - </template> - <script> - Polymer('event-fire-dialog',{ - ready: function() { - // to ensure callback methods work.. - this.eventSelected = this.eventSelected.bind(this) - }, + config._locale = config._locale || moment.localeData(config._l); - show: function(eventType, eventData) { - this.setEventType(eventType); - this.setEventData(eventData); + if (input === null || (format === undefined && input === '')) { + return moment.invalid({nullInput: true}); + } - this.$.dialog.toggle(); - }, + if (typeof input === 'string') { + config._i = input = config._locale.preparse(input); + } - setEventType: function(eventType) { - this.$.inputType.value = eventType; - }, + if (moment.isMoment(input)) { + return new Moment(input, true); + } else if (format) { + if (isArray(format)) { + makeDateFromStringAndArray(config); + } else { + makeDateFromStringAndFormat(config); + } + } else { + makeDateFromInput(config); + } - setEventData: function(eventData) { - this.$.inputData.value = eventData; - }, + return new Moment(config); + } - eventSelected: function(eventType) { - this.setEventType(eventType); - }, + moment = function (input, format, locale, strict) { + var c; - clickFireEvent: function() { - this.api.fire_event( - this.$.inputType.value, - this.$.inputData.value - ) - } - }); - </script> -</polymer-element> + if (typeof(locale) === 'boolean') { + strict = locale; + locale = undefined; + } + // object construction must be done this way. + // https://github.com/moment/moment/issues/1423 + c = {}; + c._isAMomentObject = true; + c._i = input; + c._f = format; + c._l = locale; + c._strict = strict; + c._isUTC = false; + c._pf = defaultParsingFlags(); + return makeMoment(c); + }; + moment.suppressDeprecationWarnings = false; + moment.createFromInputFallback = deprecate( + 'moment construction falls back to js Date. This is ' + + 'discouraged and will be removed in upcoming major ' + + 'release. Please refer to ' + + 'https://github.com/moment/moment/issues/1407 for more info.', + function (config) { + config._d = new Date(config._i); + } + ); + // Pick a moment m from moments so that m[fn](other) is true for all + // other. This relies on the function fn to be transitive. + // + // moments should either be an array of moment objects or an array, whose + // first element is an array of moment objects. + function pickBy(fn, moments) { + var res, i; + if (moments.length === 1 && isArray(moments[0])) { + moments = moments[0]; + } + if (!moments.length) { + return moment(); + } + res = moments[0]; + for (i = 1; i < moments.length; ++i) { + if (moments[i][fn](res)) { + res = moments[i]; + } + } + return res; + } + moment.min = function () { + var args = [].slice.call(arguments, 0); + return pickBy('isBefore', args); + }; + moment.max = function () { + var args = [].slice.call(arguments, 0); -<!-- -Copyright (c) 2014 The Polymer Project Authors. All rights reserved. -This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt -The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt -The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt -Code distributed by Google as part of the polymer project is also -subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt ---> + return pickBy('isAfter', args); + }; -<!-- -`core-menu` is a selector which styles to looks like a menu. + // creating with utc + moment.utc = function (input, format, locale, strict) { + var c; - <core-menu selected="0"> - <core-item icon="settings" label="Settings"></core-item> - <core-item icon="dialog" label="Dialog"></core-item> - <core-item icon="search" label="Search"></core-item> - </core-menu> - -When an item is selected the `core-selected` class is added to it. The user can -use the class to add more stylings to the selected item. + if (typeof(locale) === 'boolean') { + strict = locale; + locale = undefined; + } + // object construction must be done this way. + // https://github.com/moment/moment/issues/1423 + c = {}; + c._isAMomentObject = true; + c._useUTC = true; + c._isUTC = true; + c._l = locale; + c._i = input; + c._f = format; + c._strict = strict; + c._pf = defaultParsingFlags(); - core-item.core-selected { - color: red; - } + return makeMoment(c).utc(); + }; -The `selectedItem` property references the selected item. + // creating with unix timestamp (in seconds) + moment.unix = function (input) { + return moment(input * 1000); + }; - <core-menu selected="0" selectedItem="{{item}}"> - <core-item icon="settings" label="Settings"></core-item> - <core-item icon="dialog" label="Dialog"></core-item> - <core-item icon="search" label="Search"></core-item> - </core-menu> + // duration + moment.duration = function (input, key) { + var duration = input, + // matching against regexp is expensive, do it on demand + match = null, + sign, + ret, + parseIso, + diffRes; - <div>selected label: {{item.label}}</div> + if (moment.isDuration(input)) { + duration = { + ms: input._milliseconds, + d: input._days, + M: input._months + }; + } else if (typeof input === 'number') { + duration = {}; + if (key) { + duration[key] = input; + } else { + duration.milliseconds = input; + } + } else if (!!(match = aspNetTimeSpanJsonRegex.exec(input))) { + sign = (match[1] === '-') ? -1 : 1; + duration = { + y: 0, + d: toInt(match[DATE]) * sign, + h: toInt(match[HOUR]) * sign, + m: toInt(match[MINUTE]) * sign, + s: toInt(match[SECOND]) * sign, + ms: toInt(match[MILLISECOND]) * sign + }; + } else if (!!(match = isoDurationRegex.exec(input))) { + sign = (match[1] === '-') ? -1 : 1; + parseIso = function (inp) { + // We'd normally use ~~inp for this, but unfortunately it also + // converts floats to ints. + // inp may be undefined, so careful calling replace on it. + var res = inp && parseFloat(inp.replace(',', '.')); + // apply sign while we're at it + return (isNaN(res) ? 0 : res) * sign; + }; + duration = { + y: parseIso(match[2]), + M: parseIso(match[3]), + d: parseIso(match[4]), + h: parseIso(match[5]), + m: parseIso(match[6]), + s: parseIso(match[7]), + w: parseIso(match[8]) + }; + } else if (typeof duration === 'object' && + ('from' in duration || 'to' in duration)) { + diffRes = momentsDifference(moment(duration.from), moment(duration.to)); -The `core-select` event signals selection change. + duration = {}; + duration.ms = diffRes.milliseconds; + duration.M = diffRes.months; + } - <core-menu selected="0" on-core-select="{{selectAction}}"> - <core-item icon="settings" label="Settings"></core-item> - <core-item icon="dialog" label="Dialog"></core-item> - <core-item icon="search" label="Search"></core-item> - </core-menu> + ret = new Duration(duration); - ... + if (moment.isDuration(input) && hasOwnProp(input, '_locale')) { + ret._locale = input._locale; + } - selectAction: function(e, detail) { - if (detail.isSelected) { - var selectedItem = detail.item; - ... - } - } + return ret; + }; -@group Polymer Core Elements -@element core-menu -@extends core-selector ---> + // version number + moment.version = VERSION; + // default format + moment.defaultFormat = isoFormat; + // constant that refers to the ISO standard + moment.ISO_8601 = function () {}; -<polymer-element name="core-menu" extends="core-selector" assetpath="polymer/bower_components/core-menu/"> -<template> + // Plugins that add properties should also add the key here (null value), + // so we can properly clone ourselves. + moment.momentProperties = momentProperties; - <style>/* -Copyright (c) 2014 The Polymer Project Authors. All rights reserved. -This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt -The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt -The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt -Code distributed by Google as part of the polymer project is also -subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt -*/ + // This function will be called whenever a moment is mutated. + // It is intended to keep the offset in sync with the timezone. + moment.updateOffset = function () {}; -:host { - display: block; - margin: 12px; -} + // This function allows you to set a threshold for relative time strings + moment.relativeTimeThreshold = function (threshold, limit) { + if (relativeTimeThresholds[threshold] === undefined) { + return false; + } + if (limit === undefined) { + return relativeTimeThresholds[threshold]; + } + relativeTimeThresholds[threshold] = limit; + return true; + }; -polyfill-next-selector { content: ':host > core-item'; } -::content > core-item { - cursor: default; -} -</style> - - <shadow></shadow> - -</template> -<script>Polymer('core-menu');</script></polymer-element> + moment.lang = deprecate( + 'moment.lang is deprecated. Use moment.locale instead.', + function (key, value) { + return moment.locale(key, value); + } + ); -<!-- -Copyright (c) 2014 The Polymer Project Authors. All rights reserved. -This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE -The complete set of authors may be found at http://polymer.github.io/AUTHORS -The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS -Code distributed by Google as part of the polymer project is also -subject to an additional IP rights grant found at http://polymer.github.io/PATENTS ---> + // This function will load locale and then set the global locale. If + // no arguments are passed in, it will simply return the current global + // locale key. + moment.locale = function (key, values) { + var data; + if (key) { + if (typeof(values) !== 'undefined') { + data = moment.defineLocale(key, values); + } + else { + data = moment.localeData(key); + } -<!-- -Use to create nested menus inside of `core-menu` elements. + if (data) { + moment.duration._locale = moment._locale = data; + } + } - <core-menu selected="0"> - - <core-submenu icon="settings" label="Topics"> - <core-item label="Topic 1"></core-item> - <core-item label="Topic 2"></core-item> - </core-submenu> - - <core-submenu icon="settings" label="Favorites"> - <core-item label="Favorite 1"></core-item> - <core-item label="Favorite 2"></core-item> - <core-item label="Favorite 3"></core-item> - </core-submenu> - - </core-menu> - -There is a margin set on the submenu to indent the items. -You can override the margin by doing: + return moment._locale._abbr; + }; - core-submenu::shadow #submenu { - margin-left: 20px; - } + moment.defineLocale = function (name, values) { + if (values !== null) { + values.abbr = name; + if (!locales[name]) { + locales[name] = new Locale(); + } + locales[name].set(values); -To style the item for the submenu, do something like this: + // backwards compat for now: also set the locale + moment.locale(name); - core-submenu::shadow > #submenuItem { - color: blue; - } - -To style all the `core-item`s in the light DOM: + return locales[name]; + } else { + // useful for testing + delete locales[name]; + return null; + } + }; - polyfill-next-selector { content: 'core-submenu > #submenu > core-item'; } - core-submenu > core-item { - color: red; - } - -The above will style `Topic1` and `Topic2` to have font color red. + moment.langData = deprecate( + 'moment.langData is deprecated. Use moment.localeData instead.', + function (key) { + return moment.localeData(key); + } + ); - <core-submenu icon="settings" label="Topics"> - <core-item label="Topic1"></core-item> - <core-item label="Topic2"></core-item> - </core-submenu> - -@group Polymer Core Elements -@element core-submenu -@extends core-item ---> + // returns locale data + moment.localeData = function (key) { + var locale; -<!-- -Copyright (c) 2014 The Polymer Project Authors. All rights reserved. -This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt -The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt -The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt -Code distributed by Google as part of the polymer project is also -subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt ---> + if (key && key._locale && key._locale._abbr) { + key = key._locale._abbr; + } -<!-- -`core-item` is a simple line-item object: a label and/or an icon that can also -act as a link. + if (!key) { + return moment._locale; + } -Example: + if (!isArray(key)) { + //short-circuit everything else + locale = loadLocale(key); + if (locale) { + return locale; + } + key = [key]; + } - <core-item icon="settings" label="Settings"></core-item> - -To use as a link, put <a> element in the item. + return chooseLocale(key); + }; -Example: + // compare moment object + moment.isMoment = function (obj) { + return obj instanceof Moment || + (obj != null && hasOwnProp(obj, '_isAMomentObject')); + }; - <core-item icon="settings" label="Settings"> - <a href="#settings" target="_self"></a> - </core-item> + // for typechecking Duration objects + moment.isDuration = function (obj) { + return obj instanceof Duration; + }; -@group Polymer Core Elements -@element core-item -@homepage github.io ---> + for (i = lists.length - 1; i >= 0; --i) { + makeList(lists[i]); + } + moment.normalizeUnits = function (units) { + return normalizeUnits(units); + }; + moment.invalid = function (flags) { + var m = moment.utc(NaN); + if (flags != null) { + extend(m._pf, flags); + } + else { + m._pf.userInvalidated = true; + } -<polymer-element name="core-item" attributes="label icon src" horizontal="" center="" layout="" assetpath="polymer/bower_components/core-item/"> -<template> - <style>/* -Copyright (c) 2014 The Polymer Project Authors. All rights reserved. -This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt -The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt -The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt -Code distributed by Google as part of the polymer project is also -subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt -*/ + return m; + }; -:host { - display: block; - position: relative; - min-height: 40px; - white-space: nowrap; -} + moment.parseZone = function () { + return moment.apply(null, arguments).parseZone(); + }; -:host(.font-scalable) { - min-height: 2.5em; -} + moment.parseTwoDigitYear = function (input) { + return toInt(input) + (toInt(input) > 68 ? 1900 : 2000); + }; -:host(.core-selected) { - font-weight: bold; -} + /************************************ + Moment Prototype + ************************************/ -#icon { - margin: 0 16px 0 4px; -} -:host(.font-scalable) #icon { - margin: 0 1em 0 0.25em; - height: 1.5em; - width: 1.5em; -} + extend(moment.fn = Moment.prototype, { -polyfill-next-selector { content: ':host > a'; } -::content > a { - position: absolute; - top: 0; - right: 0; - bottom: 0; - left: 0; - /* IE10 styling to ensure link is clickable. Cannot be completely - transparent or minifiers change it to `transparent` which does not work. */ - background-color: rgba(0, 0, 0, 0.000001); -} -</style> - <template if="{{icon || src}}"> - <core-icon src="{{src}}" id="icon" icon="{{icon}}" hidden?="{{!src && !icon}}"></core-icon> - </template> - <div id="label">{{label}}</div> - <content></content> -</template> -<script> + clone : function () { + return moment(this); + }, - Polymer('core-item', { - - /** - * The URL of an image for the icon. - * - * @attribute src - * @type string - * @default '' - */ + valueOf : function () { + return +this._d + ((this._offset || 0) * 60000); + }, - /** - * Specifies the icon from the Polymer icon set. - * - * @attribute icon - * @type string - * @default '' - */ + unix : function () { + return Math.floor(+this / 1000); + }, - /** - * Specifies the label for the menu item. - * - * @attribute label - * @type string - * @default '' - */ + toString : function () { + return this.clone().locale('en').format('ddd MMM DD YYYY HH:mm:ss [GMT]ZZ'); + }, - }); + toDate : function () { + return this._offset ? new Date(+this) : this._d; + }, -</script> -</polymer-element> + toISOString : function () { + var m = moment(this).utc(); + if (0 < m.year() && m.year() <= 9999) { + return formatMoment(m, 'YYYY-MM-DD[T]HH:mm:ss.SSS[Z]'); + } else { + return formatMoment(m, 'YYYYYY-MM-DD[T]HH:mm:ss.SSS[Z]'); + } + }, + toArray : function () { + var m = this; + return [ + m.year(), + m.month(), + m.date(), + m.hours(), + m.minutes(), + m.seconds(), + m.milliseconds() + ]; + }, -<!-- -Copyright (c) 2014 The Polymer Project Authors. All rights reserved. -This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt -The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt -The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt -Code distributed by Google as part of the polymer project is also -subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt ---> + isValid : function () { + return isValid(this); + }, -<!-- -`core-collapse` creates a collapsible block of content. By default, the content -will be collapsed. Use `opened` to show/hide the content. + isDSTShifted : function () { + if (this._a) { + return this.isValid() && compareArrays(this._a, (this._isUTC ? moment.utc(this._a) : moment(this._a)).toArray()) > 0; + } - <button on-click="{{toggle}}">toggle collapse</button> - - <core-collapse id="collapse"> - ... - </core-collapse> - - ... + return false; + }, - toggle: function() { - this.$.collapse.toggle(); - } + parsingFlags : function () { + return extend({}, this._pf); + }, -@group Polymer Core Elements -@element core-collapse ---> + invalidAt: function () { + return this._pf.overflow; + }, + utc : function (keepLocalTime) { + return this.zone(0, keepLocalTime); + }, + local : function (keepLocalTime) { + if (this._isUTC) { + this.zone(0, keepLocalTime); + this._isUTC = false; -<style shim-shadowdom="">/* -Copyright (c) 2014 The Polymer Project Authors. All rights reserved. -This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt -The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt -The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt -Code distributed by Google as part of the polymer project is also -subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt -*/ + if (keepLocalTime) { + this.add(this._dateTzOffset(), 'm'); + } + } + return this; + }, -html /deep/ core-collapse { - display: block; -} + format : function (inputString) { + var output = formatMoment(this, inputString || moment.defaultFormat); + return this.localeData().postformat(output); + }, -html /deep/ .core-collapse-closed { - display: none; -} -</style> + add : createAdder(1, 'add'), -<polymer-element name="core-collapse" attributes="target horizontal opened duration fixedSize" assetpath="polymer/bower_components/core-collapse/"> -<template> + subtract : createAdder(-1, 'subtract'), - <content></content> + diff : function (input, units, asFloat) { + var that = makeAs(input, this), + zoneDiff = (this.zone() - that.zone()) * 6e4, + diff, output, daysAdjust; -</template> -<script> + units = normalizeUnits(units); - Polymer('core-collapse', { + if (units === 'year' || units === 'month') { + // average number of days in the months in the given dates + diff = (this.daysInMonth() + that.daysInMonth()) * 432e5; // 24 * 60 * 60 * 1000 / 2 + // difference in months + output = ((this.year() - that.year()) * 12) + (this.month() - that.month()); + // adjust by taking difference in days, average number of days + // and dst in the given months. + daysAdjust = (this - moment(this).startOf('month')) - + (that - moment(that).startOf('month')); + // same as above but with zones, to negate all dst + daysAdjust -= ((this.zone() - moment(this).startOf('month').zone()) - + (that.zone() - moment(that).startOf('month').zone())) * 6e4; + output += daysAdjust / diff; + if (units === 'year') { + output = output / 12; + } + } else { + diff = (this - that); + output = units === 'second' ? diff / 1e3 : // 1000 + units === 'minute' ? diff / 6e4 : // 1000 * 60 + units === 'hour' ? diff / 36e5 : // 1000 * 60 * 60 + units === 'day' ? (diff - zoneDiff) / 864e5 : // 1000 * 60 * 60 * 24, negate dst + units === 'week' ? (diff - zoneDiff) / 6048e5 : // 1000 * 60 * 60 * 24 * 7, negate dst + diff; + } + return asFloat ? output : absRound(output); + }, - /** - * Fired when the `core-collapse`'s `opened` property changes. - * - * @event core-collapse-open - */ + from : function (time, withoutSuffix) { + return moment.duration({to: this, from: time}).locale(this.locale()).humanize(!withoutSuffix); + }, - /** - * Fired when the target element has been resized as a result of the opened - * state changing. - * - * @event core-resize - */ + fromNow : function (withoutSuffix) { + return this.from(moment(), withoutSuffix); + }, - /** - * The target element. - * - * @attribute target - * @type object - * @default null - */ - target: null, + calendar : function (time) { + // We want to compare the start of today, vs this. + // Getting start-of-today depends on whether we're zone'd or not. + var now = time || moment(), + sod = makeAs(now, this).startOf('day'), + diff = this.diff(sod, 'days', true), + format = diff < -6 ? 'sameElse' : + diff < -1 ? 'lastWeek' : + diff < 0 ? 'lastDay' : + diff < 1 ? 'sameDay' : + diff < 2 ? 'nextDay' : + diff < 7 ? 'nextWeek' : 'sameElse'; + return this.format(this.localeData().calendar(format, this)); + }, - /** - * If true, the orientation is horizontal; otherwise is vertical. - * - * @attribute horizontal - * @type boolean - * @default false - */ - horizontal: false, + isLeapYear : function () { + return isLeapYear(this.year()); + }, - /** - * Set opened to true to show the collapse element and to false to hide it. - * - * @attribute opened - * @type boolean - * @default false - */ - opened: false, + isDST : function () { + return (this.zone() < this.clone().month(0).zone() || + this.zone() < this.clone().month(5).zone()); + }, - /** - * Collapsing/expanding animation duration in second. - * - * @attribute duration - * @type number - * @default 0.33 - */ - duration: 0.33, + day : function (input) { + var day = this._isUTC ? this._d.getUTCDay() : this._d.getDay(); + if (input != null) { + input = parseWeekday(input, this.localeData()); + return this.add(input - day, 'd'); + } else { + return day; + } + }, - /** - * If true, the size of the target element is fixed and is set - * on the element. Otherwise it will try to - * use auto to determine the natural size to use - * for collapsing/expanding. - * - * @attribute fixedSize - * @type boolean - * @default false - */ - fixedSize: false, + month : makeAccessor('Month', true), + + startOf : function (units) { + units = normalizeUnits(units); + // the following switch intentionally omits break keywords + // to utilize falling through the cases. + switch (units) { + case 'year': + this.month(0); + /* falls through */ + case 'quarter': + case 'month': + this.date(1); + /* falls through */ + case 'week': + case 'isoWeek': + case 'day': + this.hours(0); + /* falls through */ + case 'hour': + this.minutes(0); + /* falls through */ + case 'minute': + this.seconds(0); + /* falls through */ + case 'second': + this.milliseconds(0); + /* falls through */ + } - created: function() { - this.transitionEndListener = this.transitionEnd.bind(this); - }, - - ready: function() { - this.target = this.target || this; - }, + // weeks are a special case + if (units === 'week') { + this.weekday(0); + } else if (units === 'isoWeek') { + this.isoWeekday(1); + } - domReady: function() { - this.async(function() { - this.afterInitialUpdate = true; - }); - }, + // quarters are also special + if (units === 'quarter') { + this.month(Math.floor(this.month() / 3) * 3); + } - detached: function() { - if (this.target) { - this.removeListeners(this.target); - } - }, + return this; + }, - targetChanged: function(old) { - if (old) { - this.removeListeners(old); - } - if (!this.target) { - return; - } - this.isTargetReady = !!this.target; - this.classList.toggle('core-collapse-closed', this.target !== this); - this.target.style.overflow = 'hidden'; - this.horizontalChanged(); - this.addListeners(this.target); - // set core-collapse-closed class initially to hide the target - this.toggleClosedClass(true); - this.update(); - }, + endOf: function (units) { + units = normalizeUnits(units); + return this.startOf(units).add(1, (units === 'isoWeek' ? 'week' : units)).subtract(1, 'ms'); + }, - addListeners: function(node) { - node.addEventListener('transitionend', this.transitionEndListener); - }, + isAfter: function (input, units) { + units = normalizeUnits(typeof units !== 'undefined' ? units : 'millisecond'); + if (units === 'millisecond') { + input = moment.isMoment(input) ? input : moment(input); + return +this > +input; + } else { + return +this.clone().startOf(units) > +moment(input).startOf(units); + } + }, - removeListeners: function(node) { - node.removeEventListener('transitionend', this.transitionEndListener); - }, + isBefore: function (input, units) { + units = normalizeUnits(typeof units !== 'undefined' ? units : 'millisecond'); + if (units === 'millisecond') { + input = moment.isMoment(input) ? input : moment(input); + return +this < +input; + } else { + return +this.clone().startOf(units) < +moment(input).startOf(units); + } + }, - horizontalChanged: function() { - this.dimension = this.horizontal ? 'width' : 'height'; - }, + isSame: function (input, units) { + units = normalizeUnits(units || 'millisecond'); + if (units === 'millisecond') { + input = moment.isMoment(input) ? input : moment(input); + return +this === +input; + } else { + return +this.clone().startOf(units) === +makeAs(input, this).startOf(units); + } + }, - openedChanged: function() { - this.update(); - this.fire('core-collapse-open', this.opened); - }, + min: deprecate( + 'moment().min is deprecated, use moment.min instead. https://github.com/moment/moment/issues/1548', + function (other) { + other = moment.apply(null, arguments); + return other < this ? this : other; + } + ), - /** - * Toggle the opened state. - * - * @method toggle - */ - toggle: function() { - this.opened = !this.opened; - }, + max: deprecate( + 'moment().max is deprecated, use moment.max instead. https://github.com/moment/moment/issues/1548', + function (other) { + other = moment.apply(null, arguments); + return other > this ? this : other; + } + ), - setTransitionDuration: function(duration) { - var s = this.target.style; - s.transition = duration ? (this.dimension + ' ' + duration + 's') : null; - if (duration === 0) { - this.async('transitionEnd'); - } - }, + // keepLocalTime = true means only change the timezone, without + // affecting the local hour. So 5:31:26 +0300 --[zone(2, true)]--> + // 5:31:26 +0200 It is possible that 5:31:26 doesn't exist int zone + // +0200, so we adjust the time as needed, to be valid. + // + // Keeping the time actually adds/subtracts (one hour) + // from the actual represented time. That is why we call updateOffset + // a second time. In case it wants us to change the offset again + // _changeInProgress == true case, then we have to adjust, because + // there is no such time in the given timezone. + zone : function (input, keepLocalTime) { + var offset = this._offset || 0, + localAdjust; + if (input != null) { + if (typeof input === 'string') { + input = timezoneMinutesFromString(input); + } + if (Math.abs(input) < 16) { + input = input * 60; + } + if (!this._isUTC && keepLocalTime) { + localAdjust = this._dateTzOffset(); + } + this._offset = input; + this._isUTC = true; + if (localAdjust != null) { + this.subtract(localAdjust, 'm'); + } + if (offset !== input) { + if (!keepLocalTime || this._changeInProgress) { + addOrSubtractDurationFromMoment(this, + moment.duration(offset - input, 'm'), 1, false); + } else if (!this._changeInProgress) { + this._changeInProgress = true; + moment.updateOffset(this, true); + this._changeInProgress = null; + } + } + } else { + return this._isUTC ? offset : this._dateTzOffset(); + } + return this; + }, - transitionEnd: function() { - if (this.opened && !this.fixedSize) { - this.updateSize('auto', null); - } - this.setTransitionDuration(null); - this.toggleClosedClass(!this.opened); - this.asyncFire('core-resize', null, this.target); - }, + zoneAbbr : function () { + return this._isUTC ? 'UTC' : ''; + }, - toggleClosedClass: function(closed) { - this.hasClosedClass = closed; - this.target.classList.toggle('core-collapse-closed', closed); - }, + zoneName : function () { + return this._isUTC ? 'Coordinated Universal Time' : ''; + }, - updateSize: function(size, duration, forceEnd) { - this.setTransitionDuration(duration); - this.calcSize(); - var s = this.target.style; - var nochange = s[this.dimension] === size; - s[this.dimension] = size; - // transitonEnd will not be called if the size has not changed - if (forceEnd && nochange) { - this.transitionEnd(); - } - }, + parseZone : function () { + if (this._tzm) { + this.zone(this._tzm); + } else if (typeof this._i === 'string') { + this.zone(this._i); + } + return this; + }, - update: function() { - if (!this.target) { - return; - } - if (!this.isTargetReady) { - this.targetChanged(); - } - this.horizontalChanged(); - this[this.opened ? 'show' : 'hide'](); - }, + hasAlignedHourOffset : function (input) { + if (!input) { + input = 0; + } + else { + input = moment(input).zone(); + } - calcSize: function() { - return this.target.getBoundingClientRect()[this.dimension] + 'px'; - }, + return (this.zone() - input) % 60 === 0; + }, - getComputedSize: function() { - return getComputedStyle(this.target)[this.dimension]; - }, + daysInMonth : function () { + return daysInMonth(this.year(), this.month()); + }, - show: function() { - this.toggleClosedClass(false); - // for initial update, skip the expanding animation to optimize - // performance e.g. skip calcSize - if (!this.afterInitialUpdate) { - this.transitionEnd(); - return; - } - if (!this.fixedSize) { - this.updateSize('auto', null); - var s = this.calcSize(); - if (s == '0px') { - this.transitionEnd(); - return; - } - this.updateSize(0, null); - } - this.async(function() { - this.updateSize(this.size || s, this.duration, true); - }); - }, + dayOfYear : function (input) { + var dayOfYear = round((moment(this).startOf('day') - moment(this).startOf('year')) / 864e5) + 1; + return input == null ? dayOfYear : this.add((input - dayOfYear), 'd'); + }, + + quarter : function (input) { + return input == null ? Math.ceil((this.month() + 1) / 3) : this.month((input - 1) * 3 + this.month() % 3); + }, + + weekYear : function (input) { + var year = weekOfYear(this, this.localeData()._week.dow, this.localeData()._week.doy).year; + return input == null ? year : this.add((input - year), 'y'); + }, - hide: function() { - // don't need to do anything if it's already hidden - if (this.hasClosedClass && !this.fixedSize) { - return; - } - if (this.fixedSize) { - // save the size before hiding it - this.size = this.getComputedSize(); - } else { - this.updateSize(this.calcSize(), null); - } - this.async(function() { - this.updateSize(0, this.duration); - }); - } + isoWeekYear : function (input) { + var year = weekOfYear(this, 1, 4).year; + return input == null ? year : this.add((input - year), 'y'); + }, - }); + week : function (input) { + var week = this.localeData().week(this); + return input == null ? week : this.add((input - week) * 7, 'd'); + }, -</script> -</polymer-element> + isoWeek : function (input) { + var week = weekOfYear(this, 1, 4).week; + return input == null ? week : this.add((input - week) * 7, 'd'); + }, + weekday : function (input) { + var weekday = (this.day() + 7 - this.localeData()._week.dow) % 7; + return input == null ? weekday : this.add(input - weekday, 'd'); + }, -<polymer-element name="core-submenu" attributes="selected selectedItem label icon src valueattr" assetpath="polymer/bower_components/core-menu/"> -<template> + isoWeekday : function (input) { + // behaves the same as moment#day except + // as a getter, returns 7 instead of 0 (1-7 range instead of 0-6) + // as a setter, sunday should belong to the previous week. + return input == null ? this.day() || 7 : this.day(this.day() % 7 ? input : input - 7); + }, - <style>/* -Copyright (c) 2014 The Polymer Project Authors. All rights reserved. -This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE -The complete set of authors may be found at http://polymer.github.io/AUTHORS -The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS -Code distributed by Google as part of the polymer project is also -subject to an additional IP rights grant found at http://polymer.github.io/PATENTS -*/ + isoWeeksInYear : function () { + return weeksInYear(this.year(), 1, 4); + }, -:host { - display: block; - height: auto; -} + weeksInYear : function () { + var weekInfo = this.localeData()._week; + return weeksInYear(this.year(), weekInfo.dow, weekInfo.doy); + }, -:host(.core-selected, [active]) { - font-weight: initial; -} + get : function (units) { + units = normalizeUnits(units); + return this[units](); + }, -core-item { - cursor: default; -} + set : function (units, value) { + units = normalizeUnits(units); + if (typeof this[units] === 'function') { + this[units](value); + } + return this; + }, -::content > core-item { - cursor: default; -} + // If passed a locale key, it will set the locale for this + // instance. Otherwise, it will return the locale configuration + // variables for this instance. + locale : function (key) { + var newLocaleData; -:host(.font-scalable) > core-item { - min-height: 2.5em; -} + if (key === undefined) { + return this._locale._abbr; + } else { + newLocaleData = moment.localeData(key); + if (newLocaleData != null) { + this._locale = newLocaleData; + } + return this; + } + }, -:host(.font-scalable) > core-item::shadow core-icon { - margin: 0 1em 0 0.25em; - height: 1.5em; - width: 1.5em; -} + lang : deprecate( + 'moment().lang() is deprecated. Use moment().localeData() instead.', + function (key) { + if (key === undefined) { + return this.localeData(); + } else { + return this.locale(key); + } + } + ), -#submenu { - margin: 0 0 0 44px; -} + localeData : function () { + return this._locale; + }, -:host(.font-scalable) > #submenu { - margin: 0 0 0 2.75em; -} -</style> + _dateTzOffset : function () { + // On Firefox.24 Date#getTimezoneOffset returns a floating point. + // https://github.com/moment/moment/pull/1871 + return Math.round(this._d.getTimezoneOffset() / 15) * 15; + } + }); - <core-item id="submenuItem" src="{{src}}" label="{{label}}" icon="{{icon}}" class="{{ {'core-selected' : active} | tokenList}}" on-tap="{{activate}}"> - <content select=".item-content"></content> - </core-item> + function rawMonthSetter(mom, value) { + var dayOfMonth; - <core-menu id="submenu" selected="{{selected}}" selecteditem="{{selectedItem}}" valueattr="{{valueattr}}"> - <content></content> - </core-menu> + // TODO: Move this out of here! + if (typeof value === 'string') { + value = mom.localeData().monthsParse(value); + // TODO: Another silent failure? + if (typeof value !== 'number') { + return mom; + } + } - <core-collapse target="{{$.submenu}}" opened="{{opened}}"></core-collapse> + dayOfMonth = Math.min(mom.date(), + daysInMonth(mom.year(), value)); + mom._d['set' + (mom._isUTC ? 'UTC' : '') + 'Month'](value, dayOfMonth); + return mom; + } -</template> -<script> + function rawGetter(mom, unit) { + return mom._d['get' + (mom._isUTC ? 'UTC' : '') + unit](); + } - Polymer('core-submenu', { + function rawSetter(mom, unit, value) { + if (unit === 'Month') { + return rawMonthSetter(mom, value); + } else { + return mom._d['set' + (mom._isUTC ? 'UTC' : '') + unit](value); + } + } - publish: { - active: {value: false, reflect: true} - }, + function makeAccessor(unit, keepTime) { + return function (value) { + if (value != null) { + rawSetter(this, unit, value); + moment.updateOffset(this, keepTime); + return this; + } else { + return rawGetter(this, unit); + } + }; + } - opened: false, + moment.fn.millisecond = moment.fn.milliseconds = makeAccessor('Milliseconds', false); + moment.fn.second = moment.fn.seconds = makeAccessor('Seconds', false); + moment.fn.minute = moment.fn.minutes = makeAccessor('Minutes', false); + // Setting the hour should keep the time, because the user explicitly + // specified which hour he wants. So trying to maintain the same hour (in + // a new timezone) makes sense. Adding/subtracting hours does not follow + // this rule. + moment.fn.hour = moment.fn.hours = makeAccessor('Hours', true); + // moment.fn.month is defined separately + moment.fn.date = makeAccessor('Date', true); + moment.fn.dates = deprecate('dates accessor is deprecated. Use date instead.', makeAccessor('Date', true)); + moment.fn.year = makeAccessor('FullYear', true); + moment.fn.years = deprecate('years accessor is deprecated. Use year instead.', makeAccessor('FullYear', true)); - get items() { - return this.$.submenu.items; - }, + // add plural methods + moment.fn.days = moment.fn.day; + moment.fn.months = moment.fn.month; + moment.fn.weeks = moment.fn.week; + moment.fn.isoWeeks = moment.fn.isoWeek; + moment.fn.quarters = moment.fn.quarter; - hasItems: function() { - return !!this.items.length; - }, + // add aliased format methods + moment.fn.toJSON = moment.fn.toISOString; - unselectAllItems: function() { - this.$.submenu.selected = null; - this.$.submenu.clearSelection(); - }, + /************************************ + Duration Prototype + ************************************/ - activeChanged: function() { - if (this.hasItems()) { - this.opened = this.active; - } - if (!this.active) { - this.unselectAllItems(); - } - }, - - toggle: function() { - this.opened = !this.opened; - }, - activate: function() { - if (this.hasItems() && this.active) { - this.toggle(); - this.unselectAllItems(); - } + function daysToYears (days) { + // 400 years have 146097 days (taking into account leap year rules) + return days * 400 / 146097; } - - }); -</script> -</polymer-element> + function yearsToDays (years) { + // years * 365 + absRound(years / 4) - + // absRound(years / 100) + absRound(years / 400); + return years * 146097 / 400; + } + + extend(moment.duration.fn = Duration.prototype, { + + _bubble : function () { + var milliseconds = this._milliseconds, + days = this._days, + months = this._months, + data = this._data, + seconds, minutes, hours, years = 0; + + // The following code bubbles up values, see the tests for + // examples of what that means. + data.milliseconds = milliseconds % 1000; + + seconds = absRound(milliseconds / 1000); + data.seconds = seconds % 60; + minutes = absRound(seconds / 60); + data.minutes = minutes % 60; + hours = absRound(minutes / 60); + data.hours = hours % 24; -<polymer-element name="services-list" attributes="api cbServiceClicked" assetpath="polymer/"> - <template> - <style> - :host { - display: block; - } + days += absRound(hours / 24); - core-menu { - margin-top: 0; - font-size: 1rem; - } + // Accurately convert days to years, assume start from year 0. + years = absRound(daysToYears(days)); + days -= absRound(yearsToDays(years)); - a { - display: block; - } - </style> + // 30 days to a month + // TODO (iskren): Use anchor date (like 1st Jan) to compute this. + months += absRound(days / 30); + days %= 30; - <template if="{{cbServiceClicked}}"> - <style> - a { - text-decoration: underline; - cursor: pointer; - } - </style> - </template> + // 12 months -> 1 year + years += absRound(months / 12); + months %= 12; - <div> - <core-menu selected="0"> - - <template repeat="{{serv in services}}"> - <core-submenu icon="settings" label="{{serv.domain}}"> - <template repeat="{{service in serv.services}}"> - <a on-click="{{serviceClicked}}" data-domain="{{serv.domain}}">{{service}}</a> - </template> - </core-submenu> - </template> - - </core-menu> + data.days = days; + data.months = months; + data.years = years; + }, - </div> - </template> - <script> - Polymer('services-list',{ - services: [], - cbServiceClicked: null, + abs : function () { + this._milliseconds = Math.abs(this._milliseconds); + this._days = Math.abs(this._days); + this._months = Math.abs(this._months); - domReady: function() { - this.services = this.api.services + this._data.milliseconds = Math.abs(this._data.milliseconds); + this._data.seconds = Math.abs(this._data.seconds); + this._data.minutes = Math.abs(this._data.minutes); + this._data.hours = Math.abs(this._data.hours); + this._data.months = Math.abs(this._data.months); + this._data.years = Math.abs(this._data.years); - this.api.addEventListener('services-updated', this.servicesUpdated.bind(this)) - }, + return this; + }, - servicesUpdated: function() { - this.services = this.api.services; - }, + weeks : function () { + return absRound(this.days() / 7); + }, - serviceClicked: function(ev) { - if(this.cbServiceClicked) { - var target = ev.path[0]; - var domain = target.getAttributeNode("data-domain").value; - var service = target.innerHTML; + valueOf : function () { + return this._milliseconds + + this._days * 864e5 + + (this._months % 12) * 2592e6 + + toInt(this._months / 12) * 31536e6; + }, - this.cbServiceClicked(domain, service); - } - } + humanize : function (withSuffix) { + var output = relativeTime(this, !withSuffix, this.localeData()); - }); - </script> -</polymer-element> + if (withSuffix) { + output = this.localeData().pastFuture(+this, output); + } + return this.localeData().postformat(output); + }, -<polymer-element name="service-call-dialog" attributes="api" assetpath="polymer/"> - <template> - <style> - paper-input:first-child { - padding-top: 0; - } + add : function (input, val) { + // supports only 2.0-style add(1, 's') or add(moment) + var dur = moment.duration(input, val); - .serviceContainer { - margin-left: 30px; - } + this._milliseconds += dur._milliseconds; + this._days += dur._days; + this._months += dur._months; - @media all and (max-width: 620px) { - .serviceContainer { - display: none; - } - } + this._bubble(); - </style> + return this; + }, - <paper-dialog id="dialog" heading="Call Service" transition="paper-dialog-transition-bottom" backdrop="true"> - <div layout="" horizontal=""> - <div> - <paper-input id="inputDomain" label="Domain" floatinglabel="true" autofocus required></paper-input> - <paper-input id="inputService" label="Service" floatinglabel="true" required></paper-input> - <paper-input id="inputData" label="Service Data (JSON, optional)" floatinglabel="true" multiline=""></paper-input> - </div> - <div class="serviceContainer"> - <b>Available services:</b> - <services-list api="{{api}}" cbserviceclicked="{{serviceSelected}}"> - </services-list></div> - </div> - <paper-button dismissive="">Cancel</paper-button> - <paper-button affirmative="" on-click="{{clickCallService}}">Call Service</paper-button> - </paper-dialog> + subtract : function (input, val) { + var dur = moment.duration(input, val); - </template> - <script> - Polymer('service-call-dialog',{ - ready: function() { - // to ensure callback methods work.. - this.serviceSelected = this.serviceSelected.bind(this) - }, + this._milliseconds -= dur._milliseconds; + this._days -= dur._days; + this._months -= dur._months; - show: function(domain, service, serviceData) { - this.setService(domain, service); - this.$.inputData.value = serviceData; - this.$.dialog.toggle(); - }, + this._bubble(); - setService: function(domain, service) { - this.$.inputDomain.value = domain; - this.$.inputService.value = service; - }, + return this; + }, - serviceSelected: function(domain, service) { - this.setService(domain, service); - }, + get : function (units) { + units = normalizeUnits(units); + return this[units.toLowerCase() + 's'](); + }, - clickCallService: function() { - this.api.call_service( - this.$.inputDomain.value, - this.$.inputService.value, - this.$.inputData.value - ) - } - }); - </script> -</polymer-element> + as : function (units) { + var days, months; + units = normalizeUnits(units); + if (units === 'month' || units === 'year') { + days = this._days + this._milliseconds / 864e5; + months = this._months + daysToYears(days) * 12; + return units === 'month' ? months : months / 12; + } else { + // handle milliseconds separately because of floating point math errors (issue #1867) + days = this._days + yearsToDays(this._months / 12); + switch (units) { + case 'week': return days / 7 + this._milliseconds / 6048e5; + case 'day': return days + this._milliseconds / 864e5; + case 'hour': return days * 24 + this._milliseconds / 36e5; + case 'minute': return days * 24 * 60 + this._milliseconds / 6e4; + case 'second': return days * 24 * 60 * 60 + this._milliseconds / 1000; + // Math.floor prevents floating point math errors here + case 'millisecond': return Math.floor(days * 24 * 60 * 60 * 1000) + this._milliseconds; + default: throw new Error('Unknown unit ' + units); + } + } + }, + lang : moment.fn.lang, + locale : moment.fn.locale, + toIsoString : deprecate( + 'toIsoString() is deprecated. Please use toISOString() instead ' + + '(notice the capitals)', + function () { + return this.toISOString(); + } + ), + toISOString : function () { + // inspired by https://github.com/dordille/moment-isoduration/blob/master/moment.isoduration.js + var years = Math.abs(this.years()), + months = Math.abs(this.months()), + days = Math.abs(this.days()), + hours = Math.abs(this.hours()), + minutes = Math.abs(this.minutes()), + seconds = Math.abs(this.seconds() + this.milliseconds() / 1000); + if (!this.asSeconds()) { + // this is the same as C#'s (Noda) and python (isodate)... + // but not other JS (goog.date) + return 'P0D'; + } + return (this.asSeconds() < 0 ? '-' : '') + + 'P' + + (years ? years + 'Y' : '') + + (months ? months + 'M' : '') + + (days ? days + 'D' : '') + + ((hours || minutes || seconds) ? 'T' : '') + + (hours ? hours + 'H' : '') + + (minutes ? minutes + 'M' : '') + + (seconds ? seconds + 'S' : ''); + }, + localeData : function () { + return this._locale; + } + }); + moment.duration.fn.toString = moment.duration.fn.toISOString; -<polymer-element name="entity-list" attributes="api cbEntityClicked" assetpath="polymer/"> - <template> - <style> - :host { - display: block; + function makeDurationGetter(name) { + moment.duration.fn[name] = function () { + return this._data[name]; + }; } - .entityContainer { - font-size: 1rem; + for (i in unitMillisecondFactors) { + if (hasOwnProp(unitMillisecondFactors, i)) { + makeDurationGetter(i.toLowerCase()); + } } - </style> - <template if="{{cbEntityClicked}}"> - <style> - a { - text-decoration: underline; - cursor: pointer; - } - </style> - </template> + moment.duration.fn.asMilliseconds = function () { + return this.as('ms'); + }; + moment.duration.fn.asSeconds = function () { + return this.as('s'); + }; + moment.duration.fn.asMinutes = function () { + return this.as('m'); + }; + moment.duration.fn.asHours = function () { + return this.as('h'); + }; + moment.duration.fn.asDays = function () { + return this.as('d'); + }; + moment.duration.fn.asWeeks = function () { + return this.as('weeks'); + }; + moment.duration.fn.asMonths = function () { + return this.as('M'); + }; + moment.duration.fn.asYears = function () { + return this.as('y'); + }; - <div> - <template repeat="{{state in states}}"> - <div class="eventContainer"> - <a on-click="{{handleClick}}">{{state.entity_id}}</a> - </div> - </template> + /************************************ + Default Locale + ************************************/ - </div> - </template> - <script> - Polymer('entity-list',{ - cbEventClicked: null, - states: [], - domReady: function() { - this.api.addEventListener('states-updated', this.statesUpdated.bind(this)) - this.statesUpdated() - }, + // Set default locale, other locale will inherit from English. + moment.locale('en', { + ordinal : function (number) { + var b = number % 10, + output = (toInt(number % 100 / 10) === 1) ? 'th' : + (b === 1) ? 'st' : + (b === 2) ? 'nd' : + (b === 3) ? 'rd' : 'th'; + return number + output; + } + }); - statesUpdated: function() { - this.states = this.api.states; - }, + /* EMBED_LOCALES */ - handleClick: function(ev) { - if(this.cbEntityClicked) { - this.cbEntityClicked(ev.path[0].innerHTML); - } - }, + /************************************ + Exposing Moment + ************************************/ - }); - </script> -</polymer-element> + function makeGlobal(shouldDeprecate) { + /*global ender:false */ + if (typeof ender !== 'undefined') { + return; + } + oldGlobalMoment = globalScope.moment; + if (shouldDeprecate) { + globalScope.moment = deprecate( + 'Accessing Moment through the global scope is ' + + 'deprecated, and will be removed in an upcoming ' + + 'release.', + moment); + } else { + globalScope.moment = moment; + } + } + // CommonJS module is defined + if (hasModule) { + module.exports = moment; + } else if (typeof define === 'function' && define.amd) { + define('moment', function (require, exports, module) { + if (module.config && module.config() && module.config().noGlobal === true) { + // release the global variable + globalScope.moment = oldGlobalMoment; + } -<polymer-element name="state-set-dialog" attributes="api" assetpath="polymer/"> - <template> - <style> - paper-input:first-child { - padding-top: 0; + return moment; + }); + makeGlobal(true); + } else { + makeGlobal(); } +}).call(this); +</script> + +<!-- +Copyright (c) 2014 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--> - .stateContainer { - margin-left: 30px; - } +<!-- +The `core-tooltip` element creates a hover tooltip centered for the content +it contains. It can be positioned on the top|bottom|left|right of content using +the `position` attribute. - @media all and (max-width: 620px) { - .stateContainer { - display: none; - } - } +To include HTML in the tooltip, include the `tip` attribute on the relevant +content. - </style> +<b>Example</b>: - <paper-dialog id="dialog" heading="Set State" transition="paper-dialog-transition-center" backdrop="true"> - <div layout="" horizontal=""> - <div> - <paper-input id="inputEntityID" label="Entity ID" floatinglabel="true" autofocus required></paper-input> - <paper-input id="inputState" label="State" floatinglabel="true" required></paper-input> - <paper-input id="inputData" label="State attributes (JSON, optional)" floatinglabel="true" multiline=""></paper-input> - </div> - <div class="stateContainer"> - <b>Current entities:</b> - <entity-list api="{{api}}" cbentityclicked="{{entitySelected}}"></entity-list> - </div> - </div> - <paper-button dismissive="">Cancel</paper-button> - <paper-button affirmative="" on-click="{{clickSetState}}">Set State</paper-button> - </paper-dialog> + <core-tooltip label="I'm a tooltip"> + <span>Hover over me.</span> + </core-tooltip> - </template> - <script> - Polymer('state-set-dialog',{ - ready: function() { - // to ensure callback methods work.. - this.entitySelected = this.entitySelected.bind(this) - }, +<b>Example</b> - positioning the tooltip to the right: - show: function(entityId, state, stateData) { - this.setEntityId(entityId); - this.setState(state); - this.setStateData(stateData); + <core-tooltip label="I'm a tooltip to the right" position="right"> + <core-icon-button icon="drawer"></core-icon-button> + </core-tooltip> - this.$.dialog.toggle(); - }, +<b>Example</b> - no arrow and showing by default: - setEntityId: function(entityId) { - this.$.inputEntityID.value = entityId; - }, + <core-tooltip label="Tooltip with no arrow and always on" noarrow show> + <img src="image.jpg"> + </core-tooltip> - setState: function(state) { - this.$.inputState.value = state; - }, +<b>Example</b> - disable the tooltip. - setStateData: function(stateData) { - var value = stateData ? JSON.stringify(stateData, null, ' ') : ""; + <core-tooltip label="Disabled label never shows" disabled> + ... + </core-tooltip> - this.$.inputData.value = value; - }, +<b>Example</b> - rich tooltip using the `tip` attribute: - entitySelected: function(entityId) { - this.setEntityId(entityId); + <core-tooltip> + <div>Example of a rich information tooltip</div> + <div tip> + <img src="profile.jpg">Foo <b>Bar</b> - <a href="#">@baz</a> + </div> + </core-tooltip> - var state = this.api.getState(entityId); - this.setState(state.state); - this.setStateData(state.attributes); - }, +By default, the `tip` attribute specifies the HTML content for a rich tooltip. +You can customize this attribute with the `tipAttribute` attribute: - clickSetState: function() { - this.api.set_state( - this.$.inputEntityID.value, - this.$.inputState.value, - JSON.parse(this.$.inputData.value) - ); - } - }); - </script> -</polymer-element> + <core-tooltip tipAttribute="htmltooltip"> + <div>Example of a rich information tooltip</div> + <div htmltooltip> + ... + </div> + </core-tooltip> +@group Polymer Core Elements +@element core-tooltip +@extends paper-focusable +@homepage http://www.polymer-project.org/components/core-tooltip/index.html +--> -<polymer-element name="home-assistant-api" attributes="auth" assetpath="polymer/"> - <template> - <style> - core-ajax { - display: none; - } - </style> - <paper-toast id="toast" role="alert" text=""></paper-toast> - <event-fire-dialog id="eventDialog" api="{{api}}"></event-fire-dialog> - <service-call-dialog id="serviceDialog" api="{{api}}"></service-call-dialog> - <state-set-dialog id="stateDialog" api="{{api}}"></state-set-dialog> - <core-ajax id="statesAjax" auto="" method="GET" url="/api/states" headers="{{ha_headers}}" on-core-response="{{statesLoaded}}" handleas="json"> - </core-ajax> - <core-ajax id="eventsAjax" auto="" method="GET" url="/api/events" headers="{{ha_headers}}" on-core-response="{{eventsLoaded}}" handleas="json"> - </core-ajax> +<!-- TODO: would be nice to inherit from label to get .htmlFor, and .control, + but the latter is readonly. --> +<!-- TODO: support off center arrows. --> +<!-- TODO: detect mobile and apply the .large class, instead of manual + control. --> +<!-- TODO: possibly reuse core-overlay. --> +<polymer-element name="core-tooltip" extends="paper-focusable" attributes="noarrow position label show tipAttribute" role="tooltip" assetpath="polymer/bower_components/core-tooltip/"> +<template> + + <style>/* Copyright (c) 2014 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt */ - <core-ajax id="servicesAjax" auto="" method="GET" url="/api/services" headers="{{ha_headers}}" on-core-response="{{servicesLoaded}}" handleas="json"> - </core-ajax> +:host { + box-sizing: border-box; + position: relative; + display: inline-block; + outline: none; +} - </template> - <script> - Polymer('home-assistant-api',{ - auth: "not-set", - states: [], - services: {}, - events: {}, - stateUpdateTimeout: null, +:host(:hover:not([disabled])) .core-tooltip { + visibility: visible !important; +} - computed: { - ha_headers: '{"HA-access": auth}' - }, +:host([focused]) .core-tooltip { + visibility: visible !important; +} - created: function() { - this.api = this; +.core-tooltip:not(.show) { + visibility: hidden; +} - // so we can pass these methods safely as callbacks - this.turn_on = this.turn_on.bind(this); - this.turn_off = this.turn_off.bind(this); - }, +.core-tooltip { + position: absolute; + font-size: 10px; + font-family: sans-serif; + padding: 8px; + color: white; + background-color: rgba(0,0,0,0.8); + box-sizing: border-box; + border-radius: 3px; /* TODO: not in spec. */ + white-space: nowrap; + line-height: 6px; + z-index: 1002; /* TODO: this is brittle. */ + -webkit-user-select: none; + user-select: none; +} - _laterFetchStates: function() { - if(this.stateUpdateTimeout) { - clearTimeout(this.stateUpdateTimeout); - } +:host([large]) .core-tooltip { + line-height: 14px; + font-size: 14px; + padding: 16px; +} - // update states in 60 seconds - this.stateUpdateTimeout = setTimeout(this.fetchStates.bind(this), 60000); - }, +.core-tooltip.noarrow::after { + display: none; +} - _sortStates: function(states) { - return states.sort(function(one, two) { - if (one.entity_id > two.entity_id) { - return 1; - } else if (one.entity_id < two.entity_id) { - return -1; - } else { - return 0; - } - }) - }, +.core-tooltip::after { + position: absolute; + border: solid transparent; + content: ''; + height: 0; + width: 0; + border-width: 4px; +} - statesLoaded: function() { - // Make a copy of the loaded data - this.states = this._sortStates(this.$.statesAjax.response.slice(0)); +.top { + margin-bottom: 10px; /* TODO: not specified in spec */ + bottom: 100%; +} - this.fire('states-updated') +.right { + margin-left: 10px; /* TODO: not specified in spec */ + left: 100%; +} - this._laterFetchStates(); - }, +.bottom { + top: 100%; + margin-top: 10px; /* TODO: not specified in spec */ +} - eventsLoaded: function() { - // Make a copy of the loaded data - this.events = this.$.eventsAjax.response; +.left { + margin-right: 10px; /* TODO: not specified in spec */ + right: 100%; +} - this.fire('events-updated') - }, +.core-tooltip.bottom::after { + bottom: 100%; + left: calc(50% - 4px); + border-bottom-color: rgba(0,0,0,0.8); +} - servicesLoaded: function() { - // Make a copy of the loaded data - this.services = this.$.servicesAjax.response; +.core-tooltip.left::after { + left: 100%; + top: calc(50% - 4px); + border-left-color: rgba(0,0,0,0.8); +} - this.fire('services-updated') - }, +.core-tooltip.top::after { + top: 100%; + left: calc(50% - 4px); + border-top-color: rgba(0,0,0,0.8); +} - _pushNewState: function(new_state) { - var state; - var stateFound = false; +.core-tooltip.right::after { + right: 100%; + top: calc(50% - 4px); + border-right-color: rgba(0,0,0,0.8); +} +</style> + <div id="tooltip" hidden?="{{!hasTooltipContent}}" class="core-tooltip {{position}} {{ {noarrow: noarrow, show: show && !disabled} | tokenList}}"> + <content id="c" select="[{{tipAttribute}}]">{{label}}</content> + </div> - for(var i = 0; i < this.states.length; i++) { - if(this.states[i].entity_id == new_state.entity_id) { - state = this.states[i]; - state.attributes = new_state.attributes; - state.last_changed = new_state.last_changed; - state.state = new_state.state; + <content></content> - stateFound = true; - break; - } - } +</template> +<script> - if(!stateFound) { - this.states.push(new_state); - this._sortStates(this.states); - } - }, + Polymer('core-tooltip',{ - fetchState: function(entity_id) { - var successStateUpdate = function(new_state) { - this._pushNewState(new_state); - } + /** + * A simple string label for the tooltip to display. To display a rich + * HTML tooltip instead, omit `label` and include the `tip` attribute + * on a child node of `core-tooltip`. + * + * @attribute label + * @type string + * @default null + */ + label: null, - this.call_api("GET", "states/" + entity_id, null, successStateUpdate.bind(this)); + computed: { + // Indicates whether the tooltip has a set label propety or + // an element with the `tip` attribute. + hasTooltipContent: 'label || !!tipElement' }, - fetchStates: function() { - this.$.statesAjax.go(); - }, + publish: { + /** + * Forces the tooltip to display. If `disabled` is set, this property is ignored. + * + * @attribute show + * @type boolean + * @default false + */ + show: {value: false, reflect: true}, - getState: function(entityId) { - for(var i = 0; i < this.states.length; i++) { - if(this.states[i].entity_id == entityId) { - return this.states[i]; - } - } - }, + /** + * Positions the tooltip to the top, right, bottom, left of its content. + * + * @attribute position + * @type string + * @default 'bottom' + */ + position: {value: 'bottom', reflect: true}, - getCustomGroups: function() { - return this.states.filter(function(state) { - return state.entity_id.lastIndexOf("group.") == 0; - }) + /** + * If true, the tooltip an arrow pointing towards the content. + * + * @attribute noarrow + * @type boolean + * @default false + */ + noarrow: {value: false, reflect: true} }, - turn_on: function(entity_id) { - this.call_service("homeassistant", "turn_on", {entity_id: entity_id}); - }, + /** + * Customizes the attribute used to specify which content + * is the rich HTML tooltip. + * + * @attribute tipAttribute + * @type string + * @default 'tip' + */ + tipAttribute: 'tip', - turn_off: function(entity_id) { - this.call_service("homeassistant", "turn_off", {entity_id: entity_id}) + attached: function() { + this.updatedChildren(); }, - set_state: function(entity_id, state, attributes) { - var payload = {state: state} + updatedChildren: function () { + this.tipElement = null; - if(attributes) { - payload.attributes = attributes; + for (var i = 0, el; el = this.$.c.getDistributedNodes()[i]; ++i) { + if (el.hasAttribute && el.hasAttribute('tip')) { + this.tipElement = el; + break; + } } - var successToast = function(new_state) { - this.showToast("State of "+entity_id+" successful set to "+state+"."); - this._pushNewState(new_state); - } + // Job ensures we're not double calling setPosition() on DOM attach. + this.job('positionJob', this.setPosition); - this.call_api("POST", "states/" + entity_id, - payload, successToast.bind(this)); + // Monitor children to re-position tooltip when light dom changes. + this.onMutation(this, this.updatedChildren); }, - call_service: function(domain, service, parameters) { - var successToast = function() { - this.showToast("Service "+domain+"/"+service+" successful called."); - } + labelChanged: function(oldVal, newVal) { + this.job('positionJob', this.setPosition); + }, - this.call_api("POST", "services/" + domain + "/" + service, - parameters, successToast.bind(this)); + positionChanged: function(oldVal, newVal) { + this.job('positionJob', this.setPosition); }, - fire_event: function(eventType, eventData) { - eventData = eventData ? JSON.parse(eventData) : ""; + setPosition: function() { + var controlWidth = this.clientWidth; + var controlHeight = this.clientHeight; + var toolTipWidth = this.$.tooltip.clientWidth; + var toolTipHeight = this.$.tooltip.clientHeight; - var successToast = function() { - this.showToast("Event "+eventType+" successful fired."); + switch (this.position) { + case 'top': + case 'bottom': + this.$.tooltip.style.left = (controlWidth - toolTipWidth) / 2 + 'px'; + this.$.tooltip.style.top = null; + break; + case 'left': + case 'right': + this.$.tooltip.style.left = null; + this.$.tooltip.style.top = (controlHeight - toolTipHeight) / 2 + 'px'; + break; } + } + }); - this.call_api("POST", "events/" + eventType, - eventData, successToast.bind(this)); - }, +</script> +</polymer-element> + + +<!-- +Copyright (c) 2014 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--> - call_api: function(method, path, parameters, callback) { - var req = new XMLHttpRequest(); - req.open(method, "/api/" + path, true) - req.setRequestHeader("HA-access", this.auth); +<!-- +`paper-toggle-button` provides a ON/OFF switch that user can toggle the state +by tapping or by dragging the swtich. - req.onreadystatechange = function() { +Example: - if(req.readyState == 4 && req.status > 199 && req.status < 300) { + <paper-toggle-button></paper-toggle-button> - if(callback) { - callback(JSON.parse(req.responseText)) - } - // if we targetted an entity id, update state after 2 seconds - if(parameters && parameters.entity_id) { - var updateCallback; - - // if a string, update just that entity, otherwise update all - if(typeof(parameters.entity_id) == "string") { - updateCallback = function() { - this.fetchState(parameters.entity_id); - } +Styling toggle button: - } else { - updateCallback = this.fetchStates(); - } +To change the ink color for checked state: - setTimeout(updateCallback.bind(this), 2000); - } - } - }.bind(this) + paper-toggle-button::shadow paper-radio-button::shadow #ink[checked] { + color: #4285f4; + } + +To change the radio checked color: + + paper-toggle-button::shadow paper-radio-button::shadow #onRadio { + background-color: #4285f4; + } + +To change the bar color for checked state: - if(parameters) { - req.send(JSON.stringify(parameters)); - } else { - req.send(); - } - }, + paper-toggle-button::shadow #toggleBar[checked] { + background-color: #4285f4; + } + +To change the ink color for unchecked state: - showEditStateDialog: function(entityId) { - var state = this.getState(entityId); + paper-toggle-button::shadow paper-radio-button::shadow #ink { + color: #b5b5b5; + } + +To change the radio unchecked color: + + paper-toggle-button::shadow paper-radio-button::shadow #offRadio { + border-color: #b5b5b5; + } - this.showSetStateDialog(entityId, state.state, state.attributes) - }, +To change the bar color for unchecked state: - showSetStateDialog: function(entityId, state, stateAttributes) { - entityId = entityId || ""; - state = state || ""; - stateAttributes = stateAttributes || null; + paper-toggle-button::shadow #toggleBar { + background-color: red; + } - this.$.stateDialog.show(entityId, state, stateAttributes); - }, +@group Paper Elements +@element paper-toggle-button +@homepage github.io +--> - showFireEventDialog: function(eventType, eventData) { - eventType = eventType || ""; - eventData = eventData || ""; +<!-- +Copyright (c) 2014 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--> - this.$.eventDialog.show(eventType, eventData); - }, +<!-- +`paper-radio-button` is a button that can be either checked or unchecked. +User can tap the radio button to check it. But it cannot be unchecked by +tapping once checked. - showCallServiceDialog: function(domain, service, serviceData) { - domain = domain || ""; - service = service || ""; - serviceData = serviceData || ""; +Use `paper-radio-group` to group a set of radio buttons. When radio buttons +are inside a radio group, only one radio button in the group can be checked. - this.$.serviceDialog.show(domain, service, serviceData); - }, +Example: - showToast: function(message) { - this.$.toast.text = message; - this.$.toast.show(); + <paper-radio-button></paper-radio-button> + +Styling radio button: + +To change the ink color for checked state: + + paper-radio-button::shadow #ink[checked] { + color: #4285f4; + } + +To change the radio checked color: + + paper-radio-button::shadow #onRadio { + background-color: #4285f4; } + +To change the ink color for unchecked state: - }); - </script> -</polymer-element> + paper-radio-button::shadow #ink { + color: #b5b5b5; + } + +To change the radio unchecked color: + + paper-radio-button::shadow #offRadio { + border-color: #b5b5b5; + } - -<script>//! moment.js -//! version : 2.8.3 -//! authors : Tim Wood, Iskren Chernev, Moment.js contributors -//! license : MIT -//! momentjs.com +@group Paper Elements +@element paper-radio-button +@homepage github.io +--> -(function (undefined) { - /************************************ - Constants - ************************************/ - var moment, - VERSION = '2.8.3', - // the global-scope this is NOT the global object in Node.js - globalScope = typeof global !== 'undefined' ? global : this, - oldGlobalMoment, - round = Math.round, - hasOwnProperty = Object.prototype.hasOwnProperty, - i, +<!-- + @license + Copyright (c) 2014 The Polymer Project Authors. All rights reserved. + This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt + The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt + The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt + Code distributed by Google as part of the polymer project is also + subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--> - YEAR = 0, - MONTH = 1, - DATE = 2, - HOUR = 3, - MINUTE = 4, - SECOND = 5, - MILLISECOND = 6, +<!-- +`core-a11y-keys` provides a normalized interface for processing keyboard commands that pertain to [WAI-ARIA best +practices](http://www.w3.org/TR/wai-aria-practices/#kbd_general_binding). The element takes care of browser differences +with respect to Keyboard events and uses an expressive syntax to filter key presses. - // internal storage for locale config files - locales = {}, +Use the `keys` attribute to express what combination of keys will trigger the event to fire. - // extra moment internal properties (plugins register props here) - momentProperties = [], +Use the `target` attribute to set up event handlers on a specific node. +The `keys-pressed` event will fire when one of the key combinations set with the `keys` attribute is pressed. - // check for nodeJS - hasModule = (typeof module !== 'undefined' && module.exports), +Example: - // ASP.NET json date format regex - aspNetJsonRegex = /^\/?Date\((\-?\d+)/i, - aspNetTimeSpanJsonRegex = /(\-)?(?:(\d*)\.)?(\d+)\:(\d+)(?:\:(\d+)\.?(\d{3})?)?/, +This element will call `arrowHandler` on all arrow keys: - // from http://docs.closure-library.googlecode.com/git/closure_goog_date_date.js.source.html - // somewhat more in line with 4.4.3.2 2004 spec, but allows decimal anywhere - isoDurationRegex = /^(-)?P(?:(?:([0-9,.]*)Y)?(?:([0-9,.]*)M)?(?:([0-9,.]*)D)?(?:T(?:([0-9,.]*)H)?(?:([0-9,.]*)M)?(?:([0-9,.]*)S)?)?|([0-9,.]*)W)$/, + <core-a11y-keys target="{{}}" keys="up down left right" on-keys-pressed="{{arrowHandler}}"></core-a11y-keys> - // format tokens - formattingTokens = /(\[[^\[]*\])|(\\)?(Mo|MM?M?M?|Do|DDDo|DD?D?D?|ddd?d?|do?|w[o|w]?|W[o|W]?|Q|YYYYYY|YYYYY|YYYY|YY|gg(ggg?)?|GG(GGG?)?|e|E|a|A|hh?|HH?|mm?|ss?|S{1,4}|X|zz?|ZZ?|.)/g, - localFormattingTokens = /(\[[^\[]*\])|(\\)?(LT|LL?L?L?|l{1,4})/g, +Keys Syntax: - // parsing token regexes - parseTokenOneOrTwoDigits = /\d\d?/, // 0 - 99 - parseTokenOneToThreeDigits = /\d{1,3}/, // 0 - 999 - parseTokenOneToFourDigits = /\d{1,4}/, // 0 - 9999 - parseTokenOneToSixDigits = /[+\-]?\d{1,6}/, // -999,999 - 999,999 - parseTokenDigits = /\d+/, // nonzero number of digits - parseTokenWord = /[0-9]*['a-z\u00A0-\u05FF\u0700-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]+|[\u0600-\u06FF\/]+(\s*?[\u0600-\u06FF]+){1,2}/i, // any word (or two) characters or numbers including two/three word month in arabic. - parseTokenTimezone = /Z|[\+\-]\d\d:?\d\d/gi, // +00:00 -00:00 +0000 -0000 or Z - parseTokenT = /T/i, // T (ISO separator) - parseTokenTimestampMs = /[\+\-]?\d+(\.\d{1,3})?/, // 123456789 123456789.123 - parseTokenOrdinal = /\d{1,2}/, +The `keys` attribute can accepts a space seprated, `+` concatenated set of modifier keys and some common keyboard keys. - //strict parsing regexes - parseTokenOneDigit = /\d/, // 0 - 9 - parseTokenTwoDigits = /\d\d/, // 00 - 99 - parseTokenThreeDigits = /\d{3}/, // 000 - 999 - parseTokenFourDigits = /\d{4}/, // 0000 - 9999 - parseTokenSixDigits = /[+-]?\d{6}/, // -999,999 - 999,999 - parseTokenSignedNumber = /[+-]?\d+/, // -inf - inf +The common keys are `a-z`, `0-9` (top row and number pad), `*` (shift 8 and number pad), `F1-F12`, `Page Up`, `Page +Down`, `Left Arrow`, `Right Arrow`, `Down Arrow`, `Up Arrow`, `Home`, `End`, `Escape`, `Space`, `Tab`, and `Enter` keys. + +The modifier keys are `Shift`, `Control`, and `Alt`. + +All keys are expected to be lowercase and shortened: +`Left Arrow` is `left`, `Page Down` is `pagedown`, `Control` is `ctrl`, `F1` is `f1`, `Escape` is `esc` etc. + +Keys Syntax Example: - // iso 8601 regex - // 0000-00-00 0000-W00 or 0000-W00-0 + T + 00 or 00:00 or 00:00:00 or 00:00:00.000 + +00:00 or +0000 or +00) - isoRegex = /^\s*(?:[+-]\d{6}|\d{4})-(?:(\d\d-\d\d)|(W\d\d$)|(W\d\d-\d)|(\d\d\d))((T| )(\d\d(:\d\d(:\d\d(\.\d+)?)?)?)?([\+\-]\d\d(?::?\d\d)?|\s*Z)?)?$/, +Given the `keys` attribute value "ctrl+shift+f7 up pagedown esc space alt+m", the `<core-a11y-keys>` element will send +the `keys-pressed` event if any of the follow key combos are pressed: Control and Shift and F7 keys, Up Arrow key, Page +Down key, Escape key, Space key, Alt and M key. - isoFormat = 'YYYY-MM-DDTHH:mm:ssZ', +Slider Example: - isoDates = [ - ['YYYYYY-MM-DD', /[+-]\d{6}-\d{2}-\d{2}/], - ['YYYY-MM-DD', /\d{4}-\d{2}-\d{2}/], - ['GGGG-[W]WW-E', /\d{4}-W\d{2}-\d/], - ['GGGG-[W]WW', /\d{4}-W\d{2}/], - ['YYYY-DDD', /\d{4}-\d{3}/] - ], +The following is an example of the set of keys that fulfil the WAI-ARIA "slider" role [best +practices](http://www.w3.org/TR/wai-aria-practices/#slider): - // iso time formats and regexes - isoTimes = [ - ['HH:mm:ss.SSSS', /(T| )\d\d:\d\d:\d\d\.\d+/], - ['HH:mm:ss', /(T| )\d\d:\d\d:\d\d/], - ['HH:mm', /(T| )\d\d:\d\d/], - ['HH', /(T| )\d\d/] - ], + <core-a11y-keys target="{{}}" keys="left pagedown down" on-keys-pressed="{{decrement}}"></core-a11y-keys> + <core-a11y-keys target="{{}}" keys="right pageup up" on-keys-pressed="{{increment}}"></core-a11y-keys> + <core-a11y-keys target="{{}}" keys="home" on-keys-pressed="{{setMin}}"></core-a11y-keys> + <core-a11y-keys target="{{}}" keys="end" on-keys-pressed="{{setMax}}"></core-a11y-keys> - // timezone chunker '+10:00' > ['10', '00'] or '-1530' > ['-15', '30'] - parseTimezoneChunker = /([\+\-]|\d\d)/gi, +The `increment` function will move the slider a set amount toward the maximum value. +The `decrement` function will move the slider a set amount toward the minimum value. +The `setMin` function will move the slider to the minimum value. +The `setMax` function will move the slider to the maximum value. - // getter and setter names - proxyGettersAndSetters = 'Date|Hours|Minutes|Seconds|Milliseconds'.split('|'), - unitMillisecondFactors = { - 'Milliseconds' : 1, - 'Seconds' : 1e3, - 'Minutes' : 6e4, - 'Hours' : 36e5, - 'Days' : 864e5, - 'Months' : 2592e6, - 'Years' : 31536e6 - }, +Keys Syntax Grammar: - unitAliases = { - ms : 'millisecond', - s : 'second', - m : 'minute', - h : 'hour', - d : 'day', - D : 'date', - w : 'week', - W : 'isoWeek', - M : 'month', - Q : 'quarter', - y : 'year', - DDD : 'dayOfYear', - e : 'weekday', - E : 'isoWeekday', - gg: 'weekYear', - GG: 'isoWeekYear' - }, +[EBNF](http://en.wikipedia.org/wiki/Extended_Backus%E2%80%93Naur_Form) Grammar of the `keys` attribute. - camelFunctions = { - dayofyear : 'dayOfYear', - isoweekday : 'isoWeekday', - isoweek : 'isoWeek', - weekyear : 'weekYear', - isoweekyear : 'isoWeekYear' - }, + modifier = "shift" | "ctrl" | "alt"; + ascii = ? /[a-z0-9]/ ? ; + fnkey = ? f1 through f12 ? ; + arrow = "up" | "down" | "left" | "right" ; + key = "tab" | "esc" | "space" | "*" | "pageup" | "pagedown" | "home" | "end" | arrow | ascii | fnkey ; + keycombo = { modifier, "+" }, key ; + keys = keycombo, { " ", keycombo } ; - // format function strings - formatFunctions = {}, +@group Core Elements +@element core-a11y-keys +@homepage github.io +--> - // default relative time thresholds - relativeTimeThresholds = { - s: 45, // seconds to minute - m: 45, // minutes to hour - h: 22, // hours to day - d: 26, // days to month - M: 11 // months to year - }, - // tokens to ordinalize and pad - ordinalizeTokens = 'DDD w W M D d'.split(' '), - paddedTokens = 'M D H h m s w W'.split(' '), - formatTokenFunctions = { - M : function () { - return this.month() + 1; - }, - MMM : function (format) { - return this.localeData().monthsShort(this, format); - }, - MMMM : function (format) { - return this.localeData().months(this, format); - }, - D : function () { - return this.date(); - }, - DDD : function () { - return this.dayOfYear(); - }, - d : function () { - return this.day(); - }, - dd : function (format) { - return this.localeData().weekdaysMin(this, format); - }, - ddd : function (format) { - return this.localeData().weekdaysShort(this, format); - }, - dddd : function (format) { - return this.localeData().weekdays(this, format); - }, - w : function () { - return this.week(); - }, - W : function () { - return this.isoWeek(); - }, - YY : function () { - return leftZeroFill(this.year() % 100, 2); - }, - YYYY : function () { - return leftZeroFill(this.year(), 4); - }, - YYYYY : function () { - return leftZeroFill(this.year(), 5); - }, - YYYYYY : function () { - var y = this.year(), sign = y >= 0 ? '+' : '-'; - return sign + leftZeroFill(Math.abs(y), 6); - }, - gg : function () { - return leftZeroFill(this.weekYear() % 100, 2); - }, - gggg : function () { - return leftZeroFill(this.weekYear(), 4); - }, - ggggg : function () { - return leftZeroFill(this.weekYear(), 5); - }, - GG : function () { - return leftZeroFill(this.isoWeekYear() % 100, 2); - }, - GGGG : function () { - return leftZeroFill(this.isoWeekYear(), 4); - }, - GGGGG : function () { - return leftZeroFill(this.isoWeekYear(), 5); - }, - e : function () { - return this.weekday(); - }, - E : function () { - return this.isoWeekday(); - }, - a : function () { - return this.localeData().meridiem(this.hours(), this.minutes(), true); - }, - A : function () { - return this.localeData().meridiem(this.hours(), this.minutes(), false); - }, - H : function () { - return this.hours(); - }, - h : function () { - return this.hours() % 12 || 12; - }, - m : function () { - return this.minutes(); - }, - s : function () { - return this.seconds(); - }, - S : function () { - return toInt(this.milliseconds() / 100); - }, - SS : function () { - return leftZeroFill(toInt(this.milliseconds() / 10), 2); - }, - SSS : function () { - return leftZeroFill(this.milliseconds(), 3); - }, - SSSS : function () { - return leftZeroFill(this.milliseconds(), 3); - }, - Z : function () { - var a = -this.zone(), - b = '+'; - if (a < 0) { - a = -a; - b = '-'; - } - return b + leftZeroFill(toInt(a / 60), 2) + ':' + leftZeroFill(toInt(a) % 60, 2); - }, - ZZ : function () { - var a = -this.zone(), - b = '+'; - if (a < 0) { - a = -a; - b = '-'; - } - return b + leftZeroFill(toInt(a / 60), 2) + leftZeroFill(toInt(a) % 60, 2); - }, - z : function () { - return this.zoneAbbr(); - }, - zz : function () { - return this.zoneName(); - }, - X : function () { - return this.unix(); - }, - Q : function () { - return this.quarter(); - } - }, +<style shim-shadowdom=""> + html /deep/ core-a11y-keys { + display: none; + } +</style> + +<polymer-element name="core-a11y-keys" assetpath="polymer/bower_components/core-a11y-keys/"> +<script> + (function() { + /* + * Chrome uses an older version of DOM Level 3 Keyboard Events + * + * Most keys are labeled as text, but some are Unicode codepoints. + * Values taken from: http://www.w3.org/TR/2007/WD-DOM-Level-3-Events-20071221/keyset.html#KeySet-Set + */ + var KEY_IDENTIFIER = { + 'U+0009': 'tab', + 'U+001B': 'esc', + 'U+0020': 'space', + 'U+002A': '*', + 'U+0030': '0', + 'U+0031': '1', + 'U+0032': '2', + 'U+0033': '3', + 'U+0034': '4', + 'U+0035': '5', + 'U+0036': '6', + 'U+0037': '7', + 'U+0038': '8', + 'U+0039': '9', + 'U+0041': 'a', + 'U+0042': 'b', + 'U+0043': 'c', + 'U+0044': 'd', + 'U+0045': 'e', + 'U+0046': 'f', + 'U+0047': 'g', + 'U+0048': 'h', + 'U+0049': 'i', + 'U+004A': 'j', + 'U+004B': 'k', + 'U+004C': 'l', + 'U+004D': 'm', + 'U+004E': 'n', + 'U+004F': 'o', + 'U+0050': 'p', + 'U+0051': 'q', + 'U+0052': 'r', + 'U+0053': 's', + 'U+0054': 't', + 'U+0055': 'u', + 'U+0056': 'v', + 'U+0057': 'w', + 'U+0058': 'x', + 'U+0059': 'y', + 'U+005A': 'z', + 'U+007F': 'del' + }; - deprecations = {}, + /* + * Special table for KeyboardEvent.keyCode. + * KeyboardEvent.keyIdentifier is better, and KeyBoardEvent.key is even better than that + * + * Values from: https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent.keyCode#Value_of_keyCode + */ + var KEY_CODE = { + 13: 'enter', + 27: 'esc', + 33: 'pageup', + 34: 'pagedown', + 35: 'end', + 36: 'home', + 32: 'space', + 37: 'left', + 38: 'up', + 39: 'right', + 40: 'down', + 46: 'del', + 106: '*' + }; - lists = ['months', 'monthsShort', 'weekdays', 'weekdaysShort', 'weekdaysMin']; + /* + * KeyboardEvent.key is mostly represented by printable character made by the keyboard, with unprintable keys labeled + * nicely. + * + * However, on OS X, Alt+char can make a Unicode character that follows an Apple-specific mapping. In this case, we + * fall back to .keyCode. + */ + var KEY_CHAR = /[a-z0-9*]/; - // Pick the first defined of two or three arguments. dfl comes from - // default. - function dfl(a, b, c) { - switch (arguments.length) { - case 2: return a != null ? a : b; - case 3: return a != null ? a : b != null ? b : c; - default: throw new Error('Implement me'); + function transformKey(key) { + var validKey = ''; + if (key) { + var lKey = key.toLowerCase(); + if (lKey.length == 1) { + if (KEY_CHAR.test(lKey)) { + validKey = lKey; + } + } else if (lKey == 'multiply') { + // numpad '*' can map to Multiply on IE/Windows + validKey = '*'; + } else { + validKey = lKey; } + } + return validKey; } - function hasOwnProp(a, b) { - return hasOwnProperty.call(a, b); + var IDENT_CHAR = /U\+/; + function transformKeyIdentifier(keyIdent) { + var validKey = ''; + if (keyIdent) { + if (IDENT_CHAR.test(keyIdent)) { + validKey = KEY_IDENTIFIER[keyIdent]; + } else { + validKey = keyIdent.toLowerCase(); + } + } + return validKey; } - function defaultParsingFlags() { - // We need to deep clone this object, and es5 standard is not very - // helpful. - return { - empty : false, - unusedTokens : [], - unusedInput : [], - overflow : -2, - charsLeftOver : 0, - nullInput : false, - invalidMonth : null, - invalidFormat : false, - userInvalidated : false, - iso: false - }; + function transformKeyCode(keyCode) { + var validKey = ''; + if (Number(keyCode)) { + if (keyCode >= 65 && keyCode <= 90) { + // ascii a-z + // lowercase is 32 offset from uppercase + validKey = String.fromCharCode(32 + keyCode); + } else if (keyCode >= 112 && keyCode <= 123) { + // function keys f1-f12 + validKey = 'f' + (keyCode - 112); + } else if (keyCode >= 48 && keyCode <= 57) { + // top 0-9 keys + validKey = String(48 - keyCode); + } else if (keyCode >= 96 && keyCode <= 105) { + // num pad 0-9 + validKey = String(96 - keyCode); + } else { + validKey = KEY_CODE[keyCode]; + } + } + return validKey; } - function printMsg(msg) { - if (moment.suppressDeprecationWarnings === false && - typeof console !== 'undefined' && console.warn) { - console.warn('Deprecation warning: ' + msg); + function keyboardEventToKey(ev) { + // fall back from .key, to .keyIdentifier, and then to .keyCode + var normalizedKey = transformKey(ev.key) || transformKeyIdentifier(ev.keyIdentifier) || transformKeyCode(ev.keyCode) || ''; + return { + shift: ev.shiftKey, + ctrl: ev.ctrlKey, + meta: ev.metaKey, + alt: ev.altKey, + key: normalizedKey + }; + } + + /* + * Input: ctrl+shift+f7 => {ctrl: true, shift: true, key: 'f7'} + * ctrl/space => {ctrl: true} || {key: space} + */ + function stringToKey(keyCombo) { + var keys = keyCombo.split('+'); + var keyObj = Object.create(null); + keys.forEach(function(key) { + if (key == 'shift') { + keyObj.shift = true; + } else if (key == 'ctrl') { + keyObj.ctrl = true; + } else if (key == 'alt') { + keyObj.alt = true; + } else { + keyObj.key = key; } + }); + return keyObj; } - function deprecate(msg, fn) { - var firstTime = true; - return extend(function () { - if (firstTime) { - printMsg(msg); - firstTime = false; - } - return fn.apply(this, arguments); - }, fn); + function keyMatches(a, b) { + return Boolean(a.alt) == Boolean(b.alt) && Boolean(a.ctrl) == Boolean(b.ctrl) && Boolean(a.shift) == Boolean(b.shift) && a.key === b.key; } - function deprecateSimple(name, msg) { - if (!deprecations[name]) { - printMsg(msg); - deprecations[name] = true; + /** + * Fired when a keycombo in `keys` is pressed. + * + * @event keys-pressed + */ + function processKeys(ev) { + var current = keyboardEventToKey(ev); + for (var i = 0, dk; i < this._desiredKeys.length; i++) { + dk = this._desiredKeys[i]; + if (keyMatches(dk, current)) { + ev.preventDefault(); + ev.stopPropagation(); + this.fire('keys-pressed', current, this, false); + break; } + } + } + + function listen(node, handler) { + if (node && node.addEventListener) { + node.addEventListener('keydown', handler); + } + } + + function unlisten(node, handler) { + if (node && node.removeEventListener) { + node.removeEventListener('keydown', handler); + } } - function padToken(func, count) { - return function (a) { - return leftZeroFill(func.call(this, a), count); - }; - } - function ordinalizeToken(func, period) { - return function (a) { - return this.localeData().ordinal(func.call(this, a), period); - }; - } + Polymer('core-a11y-keys', { + created: function() { + this._keyHandler = processKeys.bind(this); + }, + attached: function() { + listen(this.target, this._keyHandler); + }, + detached: function() { + unlisten(this.target, this._keyHandler); + }, + publish: { + /** + * The set of key combinations to listen for. + * + * @attribute keys + * @type string (keys syntax) + * @default '' + */ + keys: '', + /** + * The node that will fire keyboard events. + * + * @attribute target + * @type Node + * @default null + */ + target: null + }, + keysChanged: function() { + // * can have multiple mappings: shift+8, * on numpad or Multiply on numpad + var normalized = this.keys.replace('*', '* shift+*'); + this._desiredKeys = normalized.toLowerCase().split(' ').map(stringToKey); + }, + targetChanged: function(oldTarget) { + unlisten(oldTarget, this._keyHandler); + listen(this.target, this._keyHandler); + } + }); + })(); +</script> +</polymer-element> + + +<polymer-element name="paper-radio-button" role="radio" tabindex="0" aria-checked="false" assetpath="polymer/bower_components/paper-radio-button/"> +<template> + + <style>/* +Copyright (c) 2014 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +*/ + +:host { + display: inline-block; + white-space: nowrap; +} - while (ordinalizeTokens.length) { - i = ordinalizeTokens.pop(); - formatTokenFunctions[i + 'o'] = ordinalizeToken(formatTokenFunctions[i], i); - } - while (paddedTokens.length) { - i = paddedTokens.pop(); - formatTokenFunctions[i + i] = padToken(formatTokenFunctions[i], 2); - } - formatTokenFunctions.DDDD = padToken(formatTokenFunctions.DDD, 3); +:host(:focus) { + outline: none; +} +#radioContainer { + position: relative; + width: 16px; + height: 16px; + cursor: pointer; +} - /************************************ - Constructors - ************************************/ +#radioContainer.labeled { + display: inline-block; + vertical-align: middle; +} - function Locale() { - } +#ink { + position: absolute; + top: -16px; + left: -16px; + width: 48px; + height: 48px; + color: #5a5a5a; +} - // Moment prototype object - function Moment(config, skipOverflow) { - if (skipOverflow !== false) { - checkOverflow(config); - } - copyConfig(this, config); - this._d = new Date(+config._d); - } +#ink[checked] { + color: #0f9d58; +} - // Duration Constructor - function Duration(duration) { - var normalizedInput = normalizeObjectUnits(duration), - years = normalizedInput.year || 0, - quarters = normalizedInput.quarter || 0, - months = normalizedInput.month || 0, - weeks = normalizedInput.week || 0, - days = normalizedInput.day || 0, - hours = normalizedInput.hour || 0, - minutes = normalizedInput.minute || 0, - seconds = normalizedInput.second || 0, - milliseconds = normalizedInput.millisecond || 0; +#offRadio { + position: absolute; + top: 0px; + left: 0px; + width: 12px; + height: 12px; + border-radius: 50%; + border: solid 2px; + border-color: #5a5a5a; +} - // representation for dateAddRemove - this._milliseconds = +milliseconds + - seconds * 1e3 + // 1000 - minutes * 6e4 + // 1000 * 60 - hours * 36e5; // 1000 * 60 * 60 - // Because of dateAddRemove treats 24 hours as different from a - // day when working around DST, we need to store them separately - this._days = +days + - weeks * 7; - // It is impossible translate months into days without knowing - // which months you are are talking about, so we have to store - // it separately. - this._months = +months + - quarters * 3 + - years * 12; +#onRadio { + position: absolute; + top: 0; + left: 0; + width: 16px; + height: 16px; + border-radius: 50%; + background-color: #0f9d58; + -webkit-transform: scale(0); + transform: scale(0); + transition: -webkit-transform ease 0.28s; + transition: transform ease 0.28s; +} - this._data = {}; +#onRadio.fill { + -webkit-transform: scale(1.1); + transform: scale(1.1); +} - this._locale = moment.localeData(); +#radioLabel { + position: relative; + display: inline-block; + vertical-align: middle; + margin-left: 10px; + white-space: normal; + pointer-events: none; +} - this._bubble(); - } +#radioLabel[hidden] { + display: none; +} - /************************************ - Helpers - ************************************/ +/* disabled state */ +:host([disabled]) { + pointer-events: none; +} +:host([disabled]) #onRadio { + display: none; +} - function extend(a, b) { - for (var i in b) { - if (hasOwnProp(b, i)) { - a[i] = b[i]; - } - } +:host([disabled]) #offRadio { + opacity: 0.33; + border-color: #5a5a5a; +} - if (hasOwnProp(b, 'toString')) { - a.toString = b.toString; - } +:host([disabled][checked]) #offRadio { + opacity: 0.33; + background-color: #5a5a5a; +} +</style> - if (hasOwnProp(b, 'valueOf')) { - a.valueOf = b.valueOf; - } + <core-a11y-keys target="{{}}" keys="space" on-keys-pressed="{{tap}}"></core-a11y-keys> + + <div id="radioContainer" class="{{ {labeled: label} | tokenList }}"> + + <div id="offRadio"></div> + <div id="onRadio"></div> + + <paper-ripple id="ink" class="circle recenteringTouch" checked?="{{!checked}}"></paper-ripple> + + </div> + + <div id="radioLabel" aria-hidden="true" hidden?="{{!label}}">{{label}}<content></content></div> + +</template> +<script> - return a; + Polymer('paper-radio-button', { + + /** + * Fired when the checked state changes due to user interaction. + * + * @event change + */ + + /** + * Fired when the checked state changes. + * + * @event core-change + */ + + publish: { + /** + * Gets or sets the state, `true` is checked and `false` is unchecked. + * + * @attribute checked + * @type boolean + * @default false + */ + checked: {value: false, reflect: true}, + + /** + * The label for the radio button. + * + * @attribute label + * @type string + * @default '' + */ + label: '', + + /** + * Normally the user cannot uncheck the radio button by tapping once + * checked. Setting this property to `true` makes the radio button + * toggleable from checked to unchecked. + * + * @attribute toggles + * @type boolean + * @default false + */ + toggles: false, + + /** + * If true, the user cannot interact with this element. + * + * @attribute disabled + * @type boolean + * @default false + */ + disabled: {value: false, reflect: true} + }, + + eventDelegates: { + tap: 'tap' + }, + + tap: function() { + var old = this.checked; + this.toggle(); + if (this.checked !== old) { + this.fire('change'); + } + }, + + toggle: function() { + this.checked = !this.toggles || !this.checked; + }, + + checkedChanged: function() { + this.$.onRadio.classList.toggle('fill', this.checked); + this.setAttribute('aria-checked', this.checked ? 'true': 'false'); + this.fire('core-change'); + }, + + labelChanged: function() { + this.setAttribute('aria-label', this.label); } + + }); + +</script> +</polymer-element> - function copyConfig(to, from) { - var i, prop, val; - - if (typeof from._isAMomentObject !== 'undefined') { - to._isAMomentObject = from._isAMomentObject; - } - if (typeof from._i !== 'undefined') { - to._i = from._i; - } - if (typeof from._f !== 'undefined') { - to._f = from._f; - } - if (typeof from._l !== 'undefined') { - to._l = from._l; - } - if (typeof from._strict !== 'undefined') { - to._strict = from._strict; - } - if (typeof from._tzm !== 'undefined') { - to._tzm = from._tzm; - } - if (typeof from._isUTC !== 'undefined') { - to._isUTC = from._isUTC; - } - if (typeof from._offset !== 'undefined') { - to._offset = from._offset; - } - if (typeof from._pf !== 'undefined') { - to._pf = from._pf; - } - if (typeof from._locale !== 'undefined') { - to._locale = from._locale; - } - - if (momentProperties.length > 0) { - for (i in momentProperties) { - prop = momentProperties[i]; - val = from[prop]; - if (typeof val !== 'undefined') { - to[prop] = val; - } - } - } - return to; - } +<polymer-element name="paper-toggle-button" attributes="checked" role="button" aria-pressed="false" tabindex="0" assetpath="polymer/bower_components/paper-toggle-button/"> +<template> - function absRound(number) { - if (number < 0) { - return Math.ceil(number); - } else { - return Math.floor(number); - } - } + <style>/* +Copyright (c) 2014 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +*/ - // left zero fill a number - // see http://jsperf.com/left-zero-filling for performance comparison - function leftZeroFill(number, targetLength, forceSign) { - var output = '' + Math.abs(number), - sign = number >= 0; +:host { + display: inline-block; +} - while (output.length < targetLength) { - output = '0' + output; - } - return (sign ? (forceSign ? '+' : '') : '-') + output; - } +:host(:focus) { + outline: none; +} - function positiveMomentsDifference(base, other) { - var res = {milliseconds: 0, months: 0}; +#toggleContainer { + position: relative; + width: 64px; + height: 16px; +} - res.months = other.month() - base.month() + - (other.year() - base.year()) * 12; - if (base.clone().add(res.months, 'M').isAfter(other)) { - --res.months; - } +#toggleBar { + position: absolute; + top: 8px; + left: 16px; + height: 1px; + width: 32px; + background-color: #5a5a5a; + pointer-events: none; +} - res.milliseconds = +other - +(base.clone().add(res.months, 'M')); +#toggleBar[checked] { + background-color: #0f9d58; +} - return res; - } +#toggleContainer[checked] #checkedBar { + width: 100%; +} - function momentsDifference(base, other) { - var res; - other = makeAs(other, base); - if (base.isBefore(other)) { - res = positiveMomentsDifference(base, other); - } else { - res = positiveMomentsDifference(other, base); - res.milliseconds = -res.milliseconds; - res.months = -res.months; - } +#toggleRadio { + position: absolute; + left: 0; + padding: 8px 48px 8px 0; + margin: -8px -48px -8px 0; + transition: -webkit-transform linear .08s; + transition: transform linear .08s; +} - return res; - } +#toggleRadio[checked] { + -webkit-transform: translate(48px, 0); + transform: translate(48px, 0); + padding: 8px 0 8px 48px; + margin: -8px 0 -8px -48px; +} - // TODO: remove 'name' arg after deprecation is removed - function createAdder(direction, name) { - return function (val, period) { - var dur, tmp; - //invert the arguments, but complain about it - if (period !== null && !isNaN(+period)) { - deprecateSimple(name, 'moment().' + name + '(period, number) is deprecated. Please use moment().' + name + '(number, period).'); - tmp = val; val = period; period = tmp; - } +#toggleRadio.dragging { + -webkit-transition: none; + transition: none; +}</style> - val = typeof val === 'string' ? +val : val; - dur = moment.duration(val, period); - addOrSubtractDurationFromMoment(this, dur, direction); - return this; - }; - } + <div id="toggleContainer"> + + <div id="toggleBar" checked?="{{checked}}"></div> + + <paper-radio-button id="toggleRadio" toggles="" checked="{{checked}}" on-change="{{changeAction}}" on-core-change="{{stopPropagation}}" on-trackstart="{{trackStart}}" on-trackx="{{trackx}}" on-trackend="{{trackEnd}}"></paper-radio-button> + + </div> - function addOrSubtractDurationFromMoment(mom, duration, isAdding, updateOffset) { - var milliseconds = duration._milliseconds, - days = duration._days, - months = duration._months; - updateOffset = updateOffset == null ? true : updateOffset; +</template> +<script> - if (milliseconds) { - mom._d.setTime(+mom._d + milliseconds * isAdding); - } - if (days) { - rawSetter(mom, 'Date', rawGetter(mom, 'Date') + days * isAdding); - } - if (months) { - rawMonthSetter(mom, rawGetter(mom, 'Month') + months * isAdding); - } - if (updateOffset) { - moment.updateOffset(mom, days || months); - } - } + Polymer('paper-toggle-button', { + + /** + * Fired when the checked state changes due to user interaction. + * + * @event change + */ + + /** + * Fired when the checked state changes. + * + * @event core-change + */ - // check if is an array - function isArray(input) { - return Object.prototype.toString.call(input) === '[object Array]'; - } + /** + * Gets or sets the state, `true` is checked and `false` is unchecked. + * + * @attribute checked + * @type boolean + * @default false + */ + checked: false, - function isDate(input) { - return Object.prototype.toString.call(input) === '[object Date]' || - input instanceof Date; - } + trackStart: function(e) { + this._w = this.$.toggleBar.offsetLeft + this.$.toggleBar.offsetWidth; + e.preventTap(); + }, - // compare two arrays, return the number of differences - function compareArrays(array1, array2, dontConvert) { - var len = Math.min(array1.length, array2.length), - lengthDiff = Math.abs(array1.length - array2.length), - diffs = 0, - i; - for (i = 0; i < len; i++) { - if ((dontConvert && array1[i] !== array2[i]) || - (!dontConvert && toInt(array1[i]) !== toInt(array2[i]))) { - diffs++; - } - } - return diffs + lengthDiff; - } + trackx: function(e) { + this._x = Math.min(this._w, + Math.max(0, this.checked ? this._w + e.dx : e.dx)); + this.$.toggleRadio.classList.add('dragging'); + var s = this.$.toggleRadio.style; + s.webkitTransform = s.transform = 'translate3d(' + this._x + 'px,0,0)'; + }, - function normalizeUnits(units) { - if (units) { - var lowered = units.toLowerCase().replace(/(.)s$/, '$1'); - units = unitAliases[units] || camelFunctions[lowered] || lowered; - } - return units; + trackEnd: function() { + var s = this.$.toggleRadio.style; + s.transform = s.webkitTransform = ''; + this.$.toggleRadio.classList.remove('dragging'); + var old = this.checked; + this.checked = Math.abs(this._x) > this._w / 2; + if (this.checked !== old) { + this.fire('change'); + } + }, + + checkedChanged: function() { + this.setAttribute('aria-pressed', Boolean(this.checked)); + this.fire('core-change'); + }, + + changeAction: function(e) { + e.stopPropagation(); + this.fire('change'); + }, + + stopPropagation: function(e) { + e.stopPropagation(); } - function normalizeObjectUnits(inputObject) { - var normalizedInput = {}, - normalizedProp, - prop; - - for (prop in inputObject) { - if (hasOwnProp(inputObject, prop)) { - normalizedProp = normalizeUnits(prop); - if (normalizedProp) { - normalizedInput[normalizedProp] = inputObject[prop]; - } - } - } + }); - return normalizedInput; - } +</script> +</polymer-element> + + - function makeList(field) { - var count, setter; - if (field.indexOf('week') === 0) { - count = 7; - setter = 'day'; - } - else if (field.indexOf('month') === 0) { - count = 12; - setter = 'month'; - } - else { - return; - } - moment[field] = function (format, index) { - var i, getter, - method = moment._locale[field], - results = []; - if (typeof format === 'number') { - index = format; - format = undefined; - } - getter = function (i) { - var m = moment().utc().set(setter, i); - return method.call(moment._locale, m, format || ''); - }; +<!-- +Copyright (c) 2014 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--> - if (index != null) { - return getter(index); - } - else { - for (i = 0; i < count; i++) { - results.push(getter(i)); - } - return results; - } - }; - } - function toInt(argumentForCoercion) { - var coercedNumber = +argumentForCoercion, - value = 0; - if (coercedNumber !== 0 && isFinite(coercedNumber)) { - if (coercedNumber >= 0) { - value = Math.floor(coercedNumber); - } else { - value = Math.ceil(coercedNumber); - } - } +<core-iconset-svg id="device" iconsize="24"> +<svg><defs> +<g id="access-alarm"><path d="M22,5.7l-4.6-3.9l-1.3,1.5l4.6,3.9L22,5.7z M7.9,3.4L6.6,1.9L2,5.7l1.3,1.5L7.9,3.4z M12.5,8H11v6l4.7,2.9l0.8-1.2l-4-2.4V8z M12,4c-5,0-9,4-9,9c0,5,4,9,9,9c5,0,9-4,9-9C21,8,17,4,12,4z M12,20c-3.9,0-7-3.1-7-7c0-3.9,3.1-7,7-7c3.9,0,7,3.1,7,7C19,16.9,15.9,20,12,20z"/></g> +<g id="access-alarms"><path d="M22,5.7l-4.6-3.9l-1.3,1.5l4.6,3.9L22,5.7z M7.9,3.4L6.6,1.9L2,5.7l1.3,1.5L7.9,3.4z M12.5,8H11v6l4.7,2.9l0.8-1.2l-4-2.4V8z M12,4c-5,0-9,4-9,9c0,5,4,9,9,9s9-4,9-9C21,8,17,4,12,4z M12,20c-3.9,0-7-3.1-7-7c0-3.9,3.1-7,7-7c3.9,0,7,3.1,7,7C19,16.9,15.9,20,12,20z"/></g> +<g id="access-time"><path fill-opacity="0.9" d="M12,2C6.5,2,2,6.5,2,12s4.5,10,10,10c5.5,0,10-4.5,10-10S17.5,2,12,2z M12,20c-4.4,0-8-3.6-8-8s3.6-8,8-8c4.4,0,8,3.6,8,8S16.4,20,12,20z"/><polygon fill-opacity="0.9" points="12.5,7 11,7 11,13 16.2,16.2 17,14.9 12.5,12.2 "/></g> +<g id="add-alarm"><path d="M7.9,3.4L6.6,1.9L2,5.7l1.3,1.5L7.9,3.4z M22,5.7l-4.6-3.9l-1.3,1.5l4.6,3.9L22,5.7z M12,4c-5,0-9,4-9,9c0,5,4,9,9,9c5,0,9-4,9-9C21,8,17,4,12,4z M12,20c-3.9,0-7-3.1-7-7c0-3.9,3.1-7,7-7c3.9,0,7,3.1,7,7C19,16.9,15.9,20,12,20z M13,9h-2v3H8v2h3v3h2v-3h3v-2h-3V9z"/></g> +<g id="airplanemode-off"><path d="M13,9V3.5C13,2.7,12.3,2,11.5,2C10.7,2,10,2.7,10,3.5v3.7l7.8,7.8l3.2,1v-2L13,9z M3,5.3l5,5L2,14v2l8-2.5V19l-2,1.5V22l3.5-1l3.5,1v-1.5L13,19v-3.7l5.7,5.7l1.3-1.3L4.3,4L3,5.3z"/></g> +<g id="airplanemode-on"><path d="M21,16v-2l-8-5V3.5C13,2.7,12.3,2,11.5,2C10.7,2,10,2.7,10,3.5V9l-8,5v2l8-2.5V19l-2,1.5V22l3.5-1l3.5,1v-1.5L13,19v-5.5L21,16z"/></g> +<g id="bluetooth"><path d="M17.7,7.7L12,2h-1v7.6L6.4,5L5,6.4l5.6,5.6L5,17.6L6.4,19l4.6-4.6V22h1l5.7-5.7L13.4,12L17.7,7.7z M13,5.8l1.9,1.9L13,9.6V5.8z M14.9,16.3L13,18.2v-3.8L14.9,16.3z"/></g> +<g id="bluetooth-connected"><path d="M7,12l-2-2l-2,2l2,2L7,12z M17.7,7.7L12,2h-1v7.6L6.4,5L5,6.4l5.6,5.6L5,17.6L6.4,19l4.6-4.6V22h1l5.7-5.7L13.4,12L17.7,7.7z M13,5.8l1.9,1.9L13,9.6V5.8z M14.9,16.3L13,18.2v-3.8L14.9,16.3z M19,10l-2,2l2,2l2-2L19,10z"/></g> +<g id="bluetooth-disabled"><path d="M13,5.8l1.9,1.9l-1.6,1.6l1.4,1.4l3-3L12,2h-1v5l2,2V5.8z M5.4,4L4,5.4l6.6,6.6L5,17.6L6.4,19l4.6-4.6V22h1l4.3-4.3l2.3,2.3l1.4-1.4L5.4,4z M13,18.2v-3.8l1.9,1.9L13,18.2z"/></g> +<g id="bluetooth-searching"><path d="M14.2,12l2.3,2.3c0.3-0.7,0.4-1.5,0.4-2.3c0-0.8-0.2-1.6-0.4-2.3L14.2,12z M19.5,6.7L18.3,8c0.6,1.2,1,2.6,1,4s-0.4,2.8-1,4l1.2,1.2c1-1.5,1.5-3.4,1.5-5.3C21,10,20.5,8.2,19.5,6.7z M15.7,7.7L10,2H9v7.6L4.4,5L3,6.4L8.6,12L3,17.6L4.4,19L9,14.4V22h1l5.7-5.7L11.4,12L15.7,7.7z M11,5.8l1.9,1.9L11,9.6V5.8z M12.9,16.3L11,18.2v-3.8L12.9,16.3z"/></g> +<g id="brightness-auto"><path d="M10.9,12.6h2.3L12,9L10.9,12.6z M20,8.7V4h-4.7L12,0.7L8.7,4H4v4.7L0.7,12L4,15.3V20h4.7l3.3,3.3l3.3-3.3H20v-4.7l3.3-3.3L20,8.7z M14.3,16l-0.7-2h-3.2l-0.7,2H7.8L11,7h2l3.2,9H14.3z"/></g> +<g id="brightness-high"><path d="M20,8.7V4h-4.7L12,0.7L8.7,4H4v4.7L0.7,12L4,15.3V20h4.7l3.3,3.3l3.3-3.3H20v-4.7l3.3-3.3L20,8.7z M12,18c-3.3,0-6-2.7-6-6s2.7-6,6-6c3.3,0,6,2.7,6,6S15.3,18,12,18z M12,8c-2.2,0-4,1.8-4,4c0,2.2,1.8,4,4,4s4-1.8,4-4C16,9.8,14.2,8,12,8z"/></g> +<g id="brightness-low"><path d="M20,15.3l3.3-3.3L20,8.7V4h-4.7L12,0.7L8.7,4H4v4.7L0.7,12L4,15.3V20h4.7l3.3,3.3l3.3-3.3H20V15.3z M12,18c-3.3,0-6-2.7-6-6s2.7-6,6-6c3.3,0,6,2.7,6,6S15.3,18,12,18z"/></g> +<g id="brightness-medium"><path d="M20,15.3l3.3-3.3L20,8.7V4h-4.7L12,0.7L8.7,4H4v4.7L0.7,12L4,15.3V20h4.7l3.3,3.3l3.3-3.3H20V15.3z M12,18V6c3.3,0,6,2.7,6,6S15.3,18,12,18z"/></g> +<g id="data-usage"><path d="M13,2.1v3c3.4,0.5,6,3.4,6,6.9c0,0.9-0.2,1.7-0.5,2.5l2.6,1.5c0.6-1.2,0.9-2.6,0.9-4.1C22,6.8,18.1,2.6,13,2.1z M12,19c-3.9,0-7-3.1-7-7c0-3.5,2.6-6.4,6-6.9v-3C5.9,2.5,2,6.8,2,12c0,5.5,4.5,10,10,10c3.3,0,6.2-1.6,8.1-4.1l-2.6-1.5C16.2,18,14.2,19,12,19z"/></g> +<g id="developer-mode"><path d="M7,5h10v2h2V3c0-1.1-0.9-2-2-2L7,1C5.9,1,5,1.9,5,3v4h2V5z M15.4,16.6L20,12l-4.6-4.6L14,8.8l3.2,3.2L14,15.2L15.4,16.6z M10,15.2L6.8,12L10,8.8L8.6,7.4L4,12l4.6,4.6L10,15.2z M17,19H7v-2H5v4c0,1.1,0.9,2,2,2h10c1.1,0,2-0.9,2-2v-4h-2V19z"/></g> +<g id="event-note"><path d="M17,10H7v2h10V10z M13,14H7v2h6V14z M16,1v2H8V1H6v2H5C3.9,3,3,3.9,3,5l0,14c0,1.1,0.9,2,2,2h14c1.1,0,2-0.9,2-2V5c0-1.1-0.9-2-2-2h-1V1H16z M19,19H5V8h14V19z"/></g> +<g id="gps-fixed"><path d="M12,8c-2.2,0-4,1.8-4,4c0,2.2,1.8,4,4,4s4-1.8,4-4C16,9.8,14.2,8,12,8z M20.9,11c-0.5-4.2-3.8-7.5-7.9-7.9V1h-2v2.1C6.8,3.5,3.5,6.8,3.1,11H1v2h2.1c0.5,4.2,3.8,7.5,7.9,7.9V23h2v-2.1c4.2-0.5,7.5-3.8,7.9-7.9H23v-2H20.9z M12,19c-3.9,0-7-3.1-7-7c0-3.9,3.1-7,7-7s7,3.1,7,7C19,15.9,15.9,19,12,19z"/></g> +<g id="gps-not-fixed"><path d="M20.9,11c-0.5-4.2-3.8-7.5-7.9-7.9V1h-2v2.1C6.8,3.5,3.5,6.8,3.1,11H1v2h2.1c0.5,4.2,3.8,7.5,7.9,7.9V23h2v-2.1c4.2-0.5,7.5-3.8,7.9-7.9H23v-2H20.9z M12,19c-3.9,0-7-3.1-7-7c0-3.9,3.1-7,7-7s7,3.1,7,7C19,15.9,15.9,19,12,19z"/></g> +<g id="gps-off"><path d="M20.9,11c-0.5-4.2-3.8-7.5-7.9-7.9V1h-2v2.1C9.9,3.2,8.8,3.5,7.8,4l1.5,1.5C10.2,5.2,11.1,5,12,5c3.9,0,7,3.1,7,7c0,0.9-0.2,1.8-0.5,2.7l1.5,1.5c0.5-1,0.8-2,1-3.2H23v-2H20.9z M3,4.3l2,2C4,7.6,3.3,9.2,3.1,11H1v2h2.1c0.5,4.2,3.8,7.5,7.9,7.9V23h2v-2.1c1.8-0.2,3.4-0.9,4.7-2l2,2l1.3-1.3L4.3,3L3,4.3z M16.3,17.5C15.1,18.5,13.6,19,12,19c-3.9,0-7-3.1-7-7c0-1.6,0.5-3.1,1.5-4.3L16.3,17.5z"/></g> +<g id="location-disabled"><path d="M20.9,11c-0.5-4.2-3.8-7.5-7.9-7.9V1h-2v2.1C9.9,3.2,8.8,3.5,7.8,4l1.5,1.5C10.2,5.2,11.1,5,12,5c3.9,0,7,3.1,7,7c0,0.9-0.2,1.8-0.5,2.7l1.5,1.5c0.5-1,0.8-2,1-3.2H23v-2H20.9z M3,4.3l2,2C4,7.6,3.3,9.2,3.1,11H1v2h2.1c0.5,4.2,3.8,7.5,7.9,7.9V23h2v-2.1c1.8-0.2,3.4-0.9,4.7-2l2,2l1.3-1.3L4.3,3L3,4.3z M16.3,17.5C15.1,18.5,13.6,19,12,19c-3.9,0-7-3.1-7-7c0-1.6,0.5-3.1,1.5-4.3L16.3,17.5z"/></g> +<g id="location-searching"><path d="M20.9,11c-0.5-4.2-3.8-7.5-7.9-7.9V1h-2v2.1C6.8,3.5,3.5,6.8,3.1,11H1v2h2.1c0.5,4.2,3.8,7.5,7.9,7.9V23h2v-2.1c4.2-0.5,7.5-3.8,7.9-7.9H23v-2H20.9z M12,19c-3.9,0-7-3.1-7-7c0-3.9,3.1-7,7-7c3.9,0,7,3.1,7,7C19,15.9,15.9,19,12,19z"/></g> +<g id="network-cell"><path d="M2,22h20V2L2,22z M20,20h-3.3v-9.8L20,6.8V20z"/></g> +<g id="network-wifi"><path d="M12,2C7.5,2,3.3,3.5,0,6l12,16L24,6C20.7,3.5,16.5,2,12,2z M12,7.3C9.4,7.3,7,8,4.9,9.2l-2-2.7C5.6,4.9,8.7,4,12,4c3.3,0,6.4,0.9,9.1,2.5l-2,2.7C17,8,14.6,7.3,12,7.3z"/></g> +<g id="nfc"><path d="M20,2H4C2.9,2,2,2.9,2,4v16c0,1.1,0.9,2,2,2h16c1.1,0,2-0.9,2-2V4C22,2.9,21.1,2,20,2z M20,20H4V4h16V20z M18,6h-5c-1.1,0-2,0.9-2,2v2.3c-0.6,0.3-1,1-1,1.7c0,1.1,0.9,2,2,2c1.1,0,2-0.9,2-2c0-0.7-0.4-1.4-1-1.7V8h3v8H8V8h2V6H8H6v12h12V6z"/></g> +<g id="now-wallpaper"><path d="M4,4h7V2H4C2.9,2,2,2.9,2,4v7h2V4z M10,13l-4,5h12l-3-4l-2,2.7L10,13z M17,8.5C17,7.7,16.3,7,15.5,7S14,7.7,14,8.5s0.7,1.5,1.5,1.5S17,9.3,17,8.5z M20,2h-7v2h7v7h2V4C22,2.9,21.1,2,20,2z M20,20h-7v2h7c1.1,0,2-0.9,2-2v-7h-2V20z M4,13H2v7c0,1.1,0.9,2,2,2h7v-2H4V13z"/></g> +<g id="now-widgets"><path d="M13,13v8h8v-8h-4.3H13z M3,21h8v-8H3V21z M3,3v8h8V7.3V3H3z M16.7,1.7L11,7.3l5.7,5.7l5.7-5.7L16.7,1.7z"/></g> +<g id="screen-lock-landscape"><path d="M21,5H3C1.9,5,1,5.9,1,7v10c0,1.1,0.9,2,2,2h18c1.1,0,2-0.9,2-2V7C23,5.9,22.1,5,21,5z M19,17H5V7h14V17z"/></g> +<g id="screen-lock-portrait"><path d="M17,1H7C5.9,1,5,1.9,5,3v18c0,1.1,0.9,2,2,2h10c1.1,0,2-0.9,2-2V3C19,1.9,18.1,1,17,1z M17,19H7V5h10V19z"/></g> +<g id="screen-lock-rotation"><path d="M23.3,12.8l-2.6-2.6l-1.4,1.4l2.2,2.2l-5.7,5.7L4.5,8.2l5.7-5.7l2.1,2.1l1.4-1.4l-2.4-2.4c-0.6-0.6-1.5-0.6-2.1,0L2.7,7.1c-0.6,0.6-0.6,1.5,0,2.1l12,12c0.6,0.6,1.5,0.6,2.1,0l6.4-6.4C23.8,14.3,23.8,13.4,23.3,12.8z M8.5,20.5c-3.3-1.5-5.6-4.7-6-8.5H1c0.5,6.2,5.7,11,11.9,11c0.2,0,0.4,0,0.7,0l-3.8-3.8L8.5,20.5z M16,9h5c0.6,0,1-0.4,1-1V4c0-0.6-0.4-1-1-1V2.5C21,1.1,19.9,0,18.5,0C17.1,0,16,1.1,16,2.5V3c-0.6,0-1,0.4-1,1v4C15,8.6,15.4,9,16,9z M16.8,2.5c0-0.9,0.8-1.7,1.7-1.7c0.9,0,1.7,0.8,1.7,1.7V3h-3.4V2.5z"/></g> +<g id="screen-rotation"><path d="M16.5,2.5c3.3,1.5,5.6,4.7,6,8.5h1.5C23.4,4.8,18.3,0,12,0c-0.2,0-0.4,0-0.7,0l3.8,3.8L16.5,2.5z M10.2,1.7c-0.6-0.6-1.5-0.6-2.1,0L1.7,8.1c-0.6,0.6-0.6,1.5,0,2.1l12,12c0.6,0.6,1.5,0.6,2.1,0l6.4-6.4c0.6-0.6,0.6-1.5,0-2.1L10.2,1.7z M14.8,21.2l-12-12l6.4-6.4l12,12L14.8,21.2z M7.5,21.5c-3.3-1.5-5.6-4.7-6-8.5H0.1C0.6,19.2,5.7,24,12,24c0.2,0,0.4,0,0.7,0l-3.8-3.8L7.5,21.5z"/></g> +<g id="sd-storage"><path d="M18,2h-8L4,8l0,12c0,1.1,0.9,2,2,2h12c1.1,0,2-0.9,2-2V4C20,2.9,19.1,2,18,2z M12,8h-2V4h2V8z M15,8h-2V4h2V8z M18,8h-2V4h2V8z"/></g> +<g id="signal-cellular-1-bar"><path d="M2,22h20V2L2,22z M20,20h-8.7v-4.5L20,6.8V20z"/></g> +<g id="signal-cellular-2-bar"><path d="M2,22h20V2L2,22z M20,20h-6v-7.2l6-6V20z"/></g> +<g id="signal-cellular-3-bar"><path d="M2,22h20V2L2,22z M20,20h-3.3v-9.8L20,6.8V20z"/></g> +<g id="signal-cellular-4-bar"><polygon points="2,22 22,22 22,2 "/></g> +<g id="signal-wifi-1-bar"><path d="M12,2C7.5,2,3.3,3.5,0,6l12,16L24,6C20.7,3.5,16.5,2,12,2z M12,13.3c-1.2,0-2.4,0.3-3.5,0.7L2.9,6.5C5.6,4.9,8.7,4,12,4c3.3,0,6.4,0.9,9.1,2.5l-5.7,7.6C14.4,13.6,13.2,13.3,12,13.3z"/></g> +<g id="signal-wifi-2-bar"><path d="M12,2C7.5,2,3.3,3.5,0,6l12,16L24,6C20.7,3.5,16.5,2,12,2z M12,10c-2,0-3.8,0.5-5.5,1.3L2.9,6.5C5.6,4.9,8.7,4,12,4c3.3,0,6.4,0.9,9.1,2.5l-3.6,4.9C15.8,10.5,14,10,12,10z"/></g> +<g id="signal-wifi-3-bar"><path d="M12,2C7.5,2,3.3,3.5,0,6l12,16L24,6C20.7,3.5,16.5,2,12,2z M12,7.3C9.4,7.3,7,8,4.9,9.2l-2-2.7C5.6,4.9,8.7,4,12,4c3.3,0,6.4,0.9,9.1,2.5l-2,2.7C17,8,14.6,7.3,12,7.3z"/></g> +<g id="signal-wifi-4-bar"><path d="M12,2C7.5,2,3.3,3.5,0,6l12,16L24,6C20.7,3.5,16.5,2,12,2z"/></g> +<g id="storage"><path d="M2,19h20v-4H2V19z M4,16h2v2H4V16z M2,5v4h20V5H2z M6,8H4V6h2V8z M2,14h20v-4H2V14z M4,11h2v2H4V11z"/></g> +<g id="timer"><path d="M15,1H9v2h6V1z M11,14h2V8h-2V14z M19,7.4L20.5,6C20,5.5,19.5,5,19,4.6L17.6,6c-1.5-1.2-3.5-2-5.6-2c-5,0-9,4-9,9c0,5,4,9,9,9s9-4,9-9C21,10.9,20.3,8.9,19,7.4z M12,20c-3.9,0-7-3.1-7-7c0-3.9,3.1-7,7-7c3.9,0,7,3.1,7,7C19,16.9,15.9,20,12,20z"/></g> +<g id="usb"><path d="M15,7v4h1v2h-3V5h2l-3-4L9,5h2v8H8v-2.1C8.7,10.6,9.2,9.8,9.2,9c0-1.2-1-2.2-2.2-2.2c-1.2,0-2.2,1-2.2,2.2c0,0.8,0.5,1.6,1.2,1.9V13c0,1.1,0.9,2,2,2h3v3.1c-0.7,0.4-1.2,1.1-1.2,1.9c0,1.2,1,2.2,2.2,2.2c1.2,0,2.2-1,2.2-2.2c0-0.9-0.5-1.6-1.2-1.9V15h3c1.1,0,2-0.9,2-2v-2h1V7H15z"/></g> +<g id="wifi-tethering"><path d="M12,11c-1.1,0-2,0.9-2,2c0,1.1,0.9,2,2,2c1.1,0,2-0.9,2-2C14,11.9,13.1,11,12,11z M18,13c0-3.3-2.7-6-6-6c-3.3,0-6,2.7-6,6c0,2.2,1.2,4.1,3,5.2l1-1.7c-1.2-0.7-2-2-2-3.4c0-2.2,1.8-4,4-4s4,1.8,4,4c0,1.5-0.8,2.8-2,3.4l1,1.7C16.8,17.1,18,15.2,18,13z M12,3C6.5,3,2,7.5,2,13c0,3.7,2,6.9,5,8.6l1-1.7c-2.4-1.4-4-4-4-6.9c0-4.4,3.6-8,8-8s8,3.6,8,8c0,3-1.6,5.5-4,6.9l1,1.7c3-1.7,5-5,5-8.6C22,7.5,17.5,3,12,3z"/></g> +</defs></svg> +</core-iconset-svg> - return value; - } +<!-- +Copyright (c) 2014 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--> - function daysInMonth(year, month) { - return new Date(Date.UTC(year, month + 1, 0)).getUTCDate(); - } - function weeksInYear(year, dow, doy) { - return weekOfYear(moment([year, 11, 31 + dow - doy]), dow, doy).week; - } - function daysInYear(year) { - return isLeapYear(year) ? 366 : 365; - } +<core-iconset-svg id="social" iconsize="24"> +<svg><defs> +<g id="cake"><path d="M12,7c1.1,0,2-0.9,2-2c0-0.4-0.1-0.7-0.3-1L12,1l-1.7,3C10.1,4.3,10,4.6,10,5C10,6.1,10.9,7,12,7z M21,21v-4c0-1.1-0.9-2-2-2h-1v-3c0-1.1-0.9-2-2-2h-3V8h-2v2H8c-1.1,0-2,0.9-2,2v3H5c-1.1,0-2,0.9-2,2v4H1v2h22v-2H21z"/></g> +<g id="circles"><path d="M16.7,15c-0.8,2.3-3,4-5.7,4c-3.3,0-6-2.7-6-6c0-2.6,1.7-4.8,4-5.7C9,7.2,9,7.1,9,7c0-1,0.2-2,0.5-2.9C5.3,4.8,2,8.5,2,13c0,5,4,9,9,9c4.5,0,8.2-3.3,8.9-7.5C19,14.8,18,15,17,15C16.9,15,16.8,15,16.7,15z"/><path d="M17,1c-3.3,0-6,2.7-6,6s2.7,6,6,6c3.3,0,6-2.7,6-6S20.3,1,17,1z M17,10c-1.7,0-3-1.3-3-3s1.3-3,3-3c1.7,0,3,1.3,3,3S18.7,10,17,10z"/></g> +<g id="circles-add"><path d="M12,2C6.5,2,2,6.5,2,12c0,5.5,4.5,10,10,10s10-4.5,10-10C22,6.5,17.5,2,12,2z M12,20c-4.4,0-8-3.6-8-8s3.6-8,8-8c4.4,0,8,3.6,8,8S16.4,20,12,20z"/><path d="M13,11V8h-2v3H8v2h3v3h2v-3h3v-2H13z"/></g> +<g id="circles-extended"><path d="M12,10c2.2,0,4-1.8,4-4c0-2.2-1.8-4-4-4C9.8,2,8,3.8,8,6C8,8.2,9.8,10,12,10z M12,4c1.1,0,2,0.9,2,2c0,1.1-0.9,2-2,2c-1.1,0-2-0.9-2-2C10,4.9,10.9,4,12,4z M6,13c-2.2,0-4,1.8-4,4c0,2.2,1.8,4,4,4c2.2,0,4-1.8,4-4C10,14.8,8.2,13,6,13z M6,19c-1.1,0-2-0.9-2-2c0-1.1,0.9-2,2-2c1.1,0,2,0.9,2,2C8,18.1,7.1,19,6,19z M12,11.1c-1,0-1.9,0.9-1.9,1.9s0.9,1.9,1.9,1.9c1,0,1.9-0.9,1.9-1.9S13,11.1,12,11.1z M18,13c-2.2,0-4,1.8-4,4c0,2.2,1.8,4,4,4c2.2,0,4-1.8,4-4C22,14.8,20.2,13,18,13z M18,19c-1.1,0-2-0.9-2-2c0-1.1,0.9-2,2-2c1.1,0,2,0.9,2,2C20,18.1,19.1,19,18,19z"/></g> +<g id="communities"><path d="M9,12c-1.1,0-2,0.9-2,2s0.9,2,2,2c1.1,0,2-0.9,2-2S10.1,12,9,12z M14,9c0-1.1-0.9-2-2-2c-1.1,0-2,0.9-2,2s0.9,2,2,2C13.1,11,14,10.1,14,9z M12,2C6.5,2,2,6.5,2,12c0,5.5,4.5,10,10,10c5.5,0,10-4.5,10-10C22,6.5,17.5,2,12,2z M12,20c-4.4,0-8-3.6-8-8c0-4.4,3.6-8,8-8c4.4,0,8,3.6,8,8C20,16.4,16.4,20,12,20z M15,12c-1.1,0-2,0.9-2,2s0.9,2,2,2c1.1,0,2-0.9,2-2S16.1,12,15,12z"/></g> +<g id="domain"><path d="M12,7V3H2v18h20V7H12z M6,19H4v-2h2V19z M6,15H4v-2h2V15z M6,11H4V9h2V11z M6,7H4V5h2V7z M10,19H8v-2h2V19z M10,15H8v-2h2V15z M10,11H8V9h2V11z M10,7H8V5h2V7z M20,19h-8v-2h2v-2h-2v-2h2v-2h-2V9h8V19z M18,11h-2v2h2V11z M18,15h-2v2h2V15z"/></g> +<g id="group"><path d="M16,11c1.7,0,3-1.3,3-3c0-1.7-1.3-3-3-3c-1.7,0-3,1.3-3,3C13,9.7,14.3,11,16,11z M8,11c1.7,0,3-1.3,3-3c0-1.7-1.3-3-3-3C6.3,5,5,6.3,5,8C5,9.7,6.3,11,8,11z M8,13c-2.3,0-7,1.2-7,3.5V19h14v-2.5C15,14.2,10.3,13,8,13z M16,13c-0.3,0-0.6,0-1,0.1c1.2,0.8,2,2,2,3.4V19h6v-2.5C23,14.2,18.3,13,16,13z"/></g> +<g id="group-add"><path d="M8,10H5V7H3v3H0v2h3v3h2v-3h3V10z M18,11c1.7,0,3-1.3,3-3c0-1.7-1.3-3-3-3c-0.3,0-0.6,0.1-0.9,0.1C17.7,6,18,6.9,18,8s-0.3,2-0.9,2.9C17.4,10.9,17.7,11,18,11z M13,11c1.7,0,3-1.3,3-3c0-1.7-1.3-3-3-3c-1.7,0-3,1.3-3,3C10,9.7,11.3,11,13,11z M19.6,13.2c0.8,0.7,1.4,1.7,1.4,2.8v2h3v-2C24,14.5,21.6,13.5,19.6,13.2z M13,13c-2,0-6,1-6,3v2h12v-2C19,14,15,13,13,13z"/></g> +<g id="location-city"><path d="M15,11V5l-3-3L9,5v2H3v14h18V11H15z M7,19H5v-2h2V19z M7,15H5v-2h2V15z M7,11H5V9h2V11z M13,19h-2v-2h2V19z M13,15h-2v-2h2V15z M13,11h-2V9h2V11z M13,7h-2V5h2V7z M19,19h-2v-2h2V19z M19,15h-2v-2h2V15z"/></g> +<g id="mood"><path d="M12,2C6.5,2,2,6.5,2,12s4.5,10,10,10c5.5,0,10-4.5,10-10S17.5,2,12,2z M12,20c-4.4,0-8-3.6-8-8s3.6-8,8-8c4.4,0,8,3.6,8,8S16.4,20,12,20z M15.5,11c0.8,0,1.5-0.7,1.5-1.5S16.3,8,15.5,8S14,8.7,14,9.5S14.7,11,15.5,11z M8.5,11c0.8,0,1.5-0.7,1.5-1.5S9.3,8,8.5,8S7,8.7,7,9.5S7.7,11,8.5,11z M12,17.5c2.3,0,4.3-1.5,5.1-3.5H6.9C7.7,16,9.7,17.5,12,17.5z"/></g> +<g id="notifications"><path d="M11.5,22c1.1,0,2-0.9,2-2h-4C9.5,21.1,10.4,22,11.5,22z M18,16v-5.5c0-3.1-2.1-5.6-5-6.3V3.5C13,2.7,12.3,2,11.5,2C10.7,2,10,2.7,10,3.5v0.7c-2.9,0.7-5,3.2-5,6.3V16l-2,2v1h17v-1L18,16z"/></g> +<g id="notifications-none"><path d="M11.5,22c1.1,0,2-0.9,2-2h-4C9.5,21.1,10.4,22,11.5,22z M18,16v-5.5c0-3.1-2.1-5.6-5-6.3V3.5C13,2.7,12.3,2,11.5,2C10.7,2,10,2.7,10,3.5v0.7c-2.9,0.7-5,3.2-5,6.3V16l-2,2v1h17v-1L18,16z M16,17H7v-6.5C7,8,9,6,11.5,6C14,6,16,8,16,10.5V17z"/></g> +<g id="notifications-off"><path d="M11.5,22c1.1,0,2-0.9,2-2h-4C9.5,21.1,10.4,22,11.5,22z M18,10.5c0-3.1-2.1-5.6-5-6.3V3.5C13,2.7,12.3,2,11.5,2C10.7,2,10,2.7,10,3.5v0.7C9.5,4.3,9,4.5,8.6,4.7l9.4,9.4V10.5z M17.7,19l2,2l1.3-1.3L4.3,3L3,4.3l2.9,2.9C5.3,8.2,5,9.3,5,10.5V16l-2,2v1H17.7z"/></g> +<g id="notifications-on"><path d="M6.6,3.6L5.2,2.2C2.8,4,1.2,6.8,1,10h2C3.2,7.3,4.5,5,6.6,3.6z M20,10h2c-0.2-3.2-1.7-6-4.1-7.8l-1.4,1.4C18.5,5,19.8,7.3,20,10z M18,10.5c0-3.1-2.1-5.6-5-6.3V3.5C13,2.7,12.3,2,11.5,2C10.7,2,10,2.7,10,3.5v0.7c-2.9,0.7-5,3.2-5,6.3V16l-2,2v1h17v-1l-2-2V10.5z M11.5,22c0.1,0,0.3,0,0.4,0c0.7-0.1,1.2-0.6,1.4-1.2c0.1-0.2,0.2-0.5,0.2-0.8h-4C9.5,21.1,10.4,22,11.5,22z"/></g> +<g id="notifications-paused"><path d="M11.5,22c1.1,0,2-0.9,2-2h-4C9.5,21.1,10.4,22,11.5,22z M18,16v-5.5c0-3.1-2.1-5.6-5-6.3V3.5C13,2.7,12.3,2,11.5,2C10.7,2,10,2.7,10,3.5v0.7c-2.9,0.7-5,3.2-5,6.3V16l-2,2v1h17v-1L18,16z M14,9.8l-2.8,3.4H14V15H9v-1.8l2.8-3.4H9V8h5V9.8z"/></g> +<g id="pages"><path d="M3,5v6h5L7,7l4,1V3H5C3.9,3,3,3.9,3,5z M8,13H3v6c0,1.1,0.9,2,2,2h6v-5l-4,1L8,13z M17,17l-4-1v5h6c1.1,0,2-0.9,2-2v-6l-5,0L17,17z M19,3h-6v5l4-1l-1,4h5V5C21,3.9,20.1,3,19,3z"/></g> +<g id="party-mode"><path d="M20,4h-3.2L15,2H9L7.2,4H4C2.9,4,2,4.9,2,6v12c0,1.1,0.9,2,2,2h16c1.1,0,2-0.9,2-2V6C22,4.9,21.1,4,20,4z M12,7c1.6,0,3.1,0.8,4,2h-4c-1.7,0-3,1.3-3,3c0,0.4,0.1,0.7,0.2,1H7.1C7,12.7,7,12.3,7,12C7,9.2,9.2,7,12,7z M12,17c-1.6,0-3.1-0.8-4-2h4c1.7,0,3-1.3,3-3c0-0.4-0.1-0.7-0.2-1h2.1c0.1,0.3,0.1,0.7,0.1,1C17,14.8,14.8,17,12,17z"/></g> +<g id="people"><path d="M16,11c1.7,0,3-1.3,3-3c0-1.7-1.3-3-3-3c-1.7,0-3,1.3-3,3C13,9.7,14.3,11,16,11z M8,11c1.7,0,3-1.3,3-3c0-1.7-1.3-3-3-3C6.3,5,5,6.3,5,8C5,9.7,6.3,11,8,11z M8,13c-2.3,0-7,1.2-7,3.5V19h14v-2.5C15,14.2,10.3,13,8,13z M16,13c-0.3,0-0.6,0-1,0.1c1.2,0.8,2,2,2,3.4V19h6v-2.5C23,14.2,18.3,13,16,13z"/></g> +<g id="person"><path d="M12,12c2.2,0,4-1.8,4-4c0-2.2-1.8-4-4-4C9.8,4,8,5.8,8,8C8,10.2,9.8,12,12,12z M12,14c-2.7,0-8,1.3-8,4v2h16v-2C20,15.3,14.7,14,12,14z"/></g> +<g id="person-add"><path d="M15,12c2.2,0,4-1.8,4-4c0-2.2-1.8-4-4-4c-2.2,0-4,1.8-4,4C11,10.2,12.8,12,15,12z M6,10V7H4v3H1v2h3v3h2v-3h3v-2H6z M15,14c-2.7,0-8,1.3-8,4v2h16v-2C23,15.3,17.7,14,15,14z"/></g> +<g id="person-outline"><path d="M12,5.9c1.2,0,2.1,0.9,2.1,2.1s-0.9,2.1-2.1,2.1S9.9,9.2,9.9,8S10.8,5.9,12,5.9 M12,14.9c3,0,6.1,1.5,6.1,2.1v1.1H5.9V17C5.9,16.4,9,14.9,12,14.9 M12,4C9.8,4,8,5.8,8,8c0,2.2,1.8,4,4,4c2.2,0,4-1.8,4-4C16,5.8,14.2,4,12,4L12,4z M12,13c-2.7,0-8,1.3-8,4v3h16v-3C20,14.3,14.7,13,12,13L12,13z"/></g> +<g id="plus-one"><polygon points="10,8 8,8 8,12 4,12 4,14 8,14 8,18 10,18 10,14 14,14 14,12 10,12 "/></g> +<g id="poll"><path d="M19,3H5C3.9,3,3,3.9,3,5v14c0,1.1,0.9,2,2,2h14c1.1,0,2-0.9,2-2V5C21,3.9,20.1,3,19,3z M9,17H7v-7h2V17z M13,17h-2V7h2V17z M17,17h-2v-4h2V17z"/></g> +<g id="post-blogger"><path d="M20,2H4C2.9,2,2,2.9,2,4l0,16c0,1.1,0.9,2,2,2h16c1.1,0,2-0.9,2-2V4C22,2.9,21.1,2,20,2z M16,9v1c0,0.6,0.4,1,1,1c0.6,0,1,0.4,1,1v3c0,1.7-1.3,3-3,3H9c-1.7,0-3-1.3-3-3V8c0-1.7,1.3-3,3-3h4c1.7,0,3,1.3,3,3V9z M10,10h2.6c0.6,0,1-0.4,1-1c0-0.6-0.4-1-1-1H10C9.4,8,9,8.4,9,9C9,9.6,9.4,10,10,10z M14,13h-4c-0.6,0-1,0.4-1,1c0,0.6,0.4,1,1,1h4c0.6,0,1-0.4,1-1C15,13.4,14.6,13,14,13z"/></g> +<g id="post-facebook"><path d="M20,2H4C2.9,2,2,2.9,2,4l0,16c0,1.1,0.9,2,2,2h16c1.1,0,2-0.9,2-2V4C22,2.9,21.1,2,20,2z M19,4v3h-2c-0.6,0-1,0.4-1,1v2h3v3h-3v7h-3v-7h-2v-3h2V7.5C13,5.6,14.6,4,16.5,4H19z"/></g> +<g id="post-github"><path d="M7.2 6.6h-.1c-.5 1.4-.2 2.3-.1 2.6-.6.7-1 1.6-1 2.6 0 3.8 2.4 4.6 4.6 4.9-.2 0-.6.2-.8.8-.4.2-1.8.7-2.6-.7 0 0-.5-.8-1.3-.9 0 0-.8 0-.1.5 0 0 .6.3.9 1.3 0 0 .5 1.7 3 1.1v3.1h5v-3.5c0-1-.4-1.5-.8-1.8 2.2-.2 4.6-1 4.6-4.8 0-1.1-.4-2-1-2.6.1-.3.4-1.2-.1-2.6 0 0-.8-.3-2.7 1-.8-.2-1.6-.3-2.5-.3-.8 0-1.7.1-2.5.3-1.4-1-2.2-1-2.6-1zm12.8 15.4h-16c-1.1 0-2-.9-2-2v-16c0-1.1.9-2 2-2h16c1.1 0 2 .9 2 2v16c0 1.1-.9 2-2 2z"/></g> +<g id="post-gplus"><path d="M11.2,8.9c0-1-0.6-3-2.1-3c-0.6,0-1.3,0.4-1.3,1.7c0,1.2,0.6,2.9,2,2.9C9.8,10.5,11.2,10.4,11.2,8.9z M10.6,13.8c-0.1,0-0.2,0-0.3,0h0c-0.3,0-1.2,0.1-1.8,0.3C7.8,14.3,7,14.8,7,15.8c0,1.1,1,2.2,3,2.2c1.5,0,2.4-1,2.4-2C12.4,15.3,11.9,14.8,10.6,13.8z M20,2H4C2.9,2,2,2.9,2,4l0,16c0,1.1,0.9,2,2,2h16c1.1,0,2-0.9,2-2V4C22,2.9,21.1,2,20,2z M9.1,19.2c-2.8,0-4.1-1.6-4.1-3c0-0.5,0.1-1.6,1.5-2.4c0.8-0.5,1.8-0.8,3.1-0.9c-0.2-0.2-0.3-0.5-0.3-1c0-0.2,0-0.3,0.1-0.5H9c-2,0-3.2-1.5-3.2-3c0-1.7,1.3-3.6,4.1-3.6h4.2l-0.3,0.3l-0.7,0.7L13,5.9h-0.7c0.4,0.4,0.9,1.1,0.9,2.2c0,1.4-0.7,2.1-1.6,2.7c-0.2,0.1-0.4,0.4-0.4,0.7c0,0.3,0.2,0.5,0.4,0.6c0.1,0.1,0.3,0.2,0.5,0.3c0.8,0.6,1.9,1.3,1.9,2.9C14,17.1,12.7,19.2,9.1,19.2z M19,12h-2v2h-1v-2h-2v-1h2V9h1v2h2V12z"/></g> +<g id="post-instagram"><path d="M20,2H4C2.9,2,2,2.9,2,4l0,16c0,1.1,0.9,2,2,2h16c1.1,0,2-0.9,2-2V4C22,2.9,21.1,2,20,2z M12,8c2.2,0,4,1.8,4,4s-1.8,4-4,4c-2.2,0-4-1.8-4-4S9.8,8,12,8z M4.5,20C4.2,20,4,19.8,4,19.5V11h2.1C6,11.3,6,11.7,6,12c0,3.3,2.7,6,6,6c3.3,0,6-2.7,6-6c0-0.3,0-0.7-0.1-1H20v8.5c0,0.3-0.2,0.5-0.5,0.5H4.5z M20,6.5C20,6.8,19.8,7,19.5,7h-2C17.2,7,17,6.8,17,6.5v-2C17,4.2,17.2,4,17.5,4h2C19.8,4,20,4.2,20,4.5V6.5z"/></g> +<g id="post-linkedin"><path d="M20,2H4C2.9,2,2,2.9,2,4l0,16c0,1.1,0.9,2,2,2h16c1.1,0,2-0.9,2-2V4C22,2.9,21.1,2,20,2z M8,19H5v-9h3V19z M6.5,8.3c-1,0-1.8-0.8-1.8-1.8s0.8-1.8,1.8-1.8s1.8,0.8,1.8,1.8S7.5,8.3,6.5,8.3z M19,19h-3v-5.3c0-0.8-0.7-1.5-1.5-1.5c-0.8,0-1.5,0.7-1.5,1.5V19h-3v-9h3v1.2c0.5-0.8,1.6-1.4,2.5-1.4c1.9,0,3.5,1.6,3.5,3.5V19z"/></g> +<g id="post-pinterest"><path d="M20,2H4C2.9,2,2,2.9,2,4l0,16c0,1.1,0.9,2,2,2h16c1.1,0,2-0.9,2-2V4C22,2.9,21.1,2,20,2z M13,16.2c-0.8,0-1.6-0.3-2.1-0.9l-1,3.2l-0.1,0.2l0,0c-0.2,0.3-0.5,0.5-0.9,0.5c-0.6,0-1.1-0.5-1.1-1.1c0-0.1,0-0.1,0-0.1l0,0l0.1-0.2l1.8-5.6c0,0-0.2-0.6-0.2-1.5c0-1.7,0.9-2.2,1.7-2.2c0.7,0,1.4,0.3,1.4,1.3c0,1.3-0.9,2-0.9,3c0,0.7,0.6,1.3,1.3,1.3c2.3,0,3.2-1.8,3.2-3.4c0-2.2-1.9-4-4.2-4c-2.3,0-4.2,1.8-4.2,4c0,0.7,0.2,1.3,0.5,1.9c0.1,0.2,0.1,0.3,0.1,0.5c0,0.6-0.4,1-1,1c-0.4,0-0.7-0.2-0.9-0.5c-0.5-0.9-0.8-1.9-0.8-3c0-3.3,2.8-6,6.2-6c3.4,0,6.2,2.7,6.2,6C18.2,13.4,16.6,16.2,13,16.2z"/></g> +<g id="post-tumblr"><path d="M20,2H4C2.9,2,2,2.9,2,4l0,16c0,1.1,0.9,2,2,2h16c1.1,0,2-0.9,2-2V4C22,2.9,21.1,2,20,2z M16,11h-3c0,0,0,3.8,0,3.9c0,0.7,0.1,1.1,1.1,1.1c0.9,0,1.9,0,1.9,0v3c0,0-1,0.1-2.1,0.1c-2.6,0-3.9-1.6-3.9-3.4c0-1.2,0-4.7,0-4.7H8V8.2c2.4-0.2,2.6-2,2.8-3.2H13v3h3V11z"/></g> +<g id="post-twitter"><path d="M20,2H4C2.9,2,2,2.9,2,4l0,16c0,1.1,0.9,2,2,2h16c1.1,0,2-0.9,2-2V4C22,2.9,21.1,2,20,2z M17.7,9.3c-0.1,4.6-3,7.8-7.4,8c-1.8,0.1-3.1-0.5-4.3-1.2c1.3,0.2,3-0.3,3.9-1.1c-1.3-0.1-2.1-0.8-2.5-1.9c0.4,0.1,0.8,0,1.1,0c-1.2-0.4-2-1.1-2.1-2.7c0.3,0.2,0.7,0.3,1.1,0.3c-0.9-0.5-1.5-2.4-0.8-3.6c1.3,1.4,2.9,2.6,5.5,2.8c-0.7-2.8,3.1-4.3,4.6-2.4c0.7-0.1,1.2-0.4,1.7-0.6c-0.2,0.7-0.6,1.1-1.1,1.5c0.5-0.1,1-0.2,1.4-0.4C18.7,8.5,18.2,8.9,17.7,9.3z"/></g> +<g id="public"><path d="M12,2C6.5,2,2,6.5,2,12c0,5.5,4.5,10,10,10c5.5,0,10-4.5,10-10C22,6.5,17.5,2,12,2z M11,19.9c-3.9-0.5-7-3.9-7-7.9c0-0.6,0.1-1.2,0.2-1.8L9,15v1c0,1.1,0.9,2,2,2V19.9z M17.9,17.4c-0.3-0.8-1-1.4-1.9-1.4h-1v-3c0-0.6-0.4-1-1-1H8v-2h2c0.6,0,1-0.4,1-1V7h2c1.1,0,2-0.9,2-2V4.6c2.9,1.2,5,4.1,5,7.4C20,14.1,19.2,16,17.9,17.4z"/></g> +<g id="school"><path d="M5,13.2v4l7,3.8l7-3.8v-4L12,17L5,13.2z M12,3L1,9l11,6l9-4.9V17h2V9L12,3z"/></g> +<g id="share"><path d="M21,11l-7-7v4C7,9,4,14,3,19c2.5-3.5,6-5.1,11-5.1V18L21,11z"/></g> +<g id="share-alt"><path d="M18,16.1c-0.8,0-1.5,0.3-2,0.8l-7.1-4.2C9,12.5,9,12.2,9,12s0-0.5-0.1-0.7L16,7.2C16.5,7.7,17.2,8,18,8c1.7,0,3-1.3,3-3s-1.3-3-3-3s-3,1.3-3,3c0,0.2,0,0.5,0.1,0.7L8,9.8C7.5,9.3,6.8,9,6,9c-1.7,0-2.9,1.2-2.9,2.9c0,1.7,1.3,3,3,3c0.8,0,1.5-0.3,2-0.8l7.1,4.2c-0.1,0.3-0.1,0.5-0.1,0.7c0,1.6,1.3,2.9,2.9,2.9s2.9-1.3,2.9-2.9S19.6,16.1,18,16.1z"/></g> +<g id="whatshot"><path d="M13.5,0.7c0,0,0.7,2.6,0.7,4.8c0,2.1-1.4,3.7-3.4,3.7c-2.1,0-3.6-1.7-3.6-3.7l0-0.4C5.2,7.5,4,10.6,4,14c0,4.4,3.6,8,8,8c4.4,0,8-3.6,8-8C20,8.6,17.4,3.8,13.5,0.7z M11.7,19c-1.8,0-3.2-1.4-3.2-3.1c0-1.6,1-2.8,2.8-3.1c1.8-0.4,3.6-1.2,4.6-2.6c0.4,1.3,0.6,2.6,0.6,4C16.5,16.8,14.4,19,11.7,19z"/></g> +</defs></svg> +</core-iconset-svg> - function isLeapYear(year) { - return (year % 4 === 0 && year % 100 !== 0) || year % 400 === 0; - } +<!-- +Copyright (c) 2014 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--> - function checkOverflow(m) { - var overflow; - if (m._a && m._pf.overflow === -2) { - overflow = - m._a[MONTH] < 0 || m._a[MONTH] > 11 ? MONTH : - m._a[DATE] < 1 || m._a[DATE] > daysInMonth(m._a[YEAR], m._a[MONTH]) ? DATE : - m._a[HOUR] < 0 || m._a[HOUR] > 23 ? HOUR : - m._a[MINUTE] < 0 || m._a[MINUTE] > 59 ? MINUTE : - m._a[SECOND] < 0 || m._a[SECOND] > 59 ? SECOND : - m._a[MILLISECOND] < 0 || m._a[MILLISECOND] > 999 ? MILLISECOND : - -1; - if (m._pf._overflowDayOfYear && (overflow < YEAR || overflow > DATE)) { - overflow = DATE; - } - m._pf.overflow = overflow; - } - } +<core-iconset-svg id="image" iconsize="24"> +<svg><defs> +<g id="add-to-photos"><path d="M4,6H2v14c0,1.1,0.9,2,2,2h14v-2H4V6z M20,2H8C6.9,2,6,2.9,6,4v12c0,1.1,0.9,2,2,2h12c1.1,0,2-0.9,2-2V4C22,2.9,21.1,2,20,2z M19,11h-4v4h-2v-4H9V9h4V5h2v4h4V11z"/></g> +<g id="adjust"><path d="M12,2C6.5,2,2,6.5,2,12s4.5,10,10,10s10-4.5,10-10S17.5,2,12,2z M12,20c-4.4,0-8-3.6-8-8s3.6-8,8-8s8,3.6,8,8S16.4,20,12,20z M15,12c0,1.7-1.3,3-3,3s-3-1.3-3-3s1.3-3,3-3S15,10.3,15,12z"/></g> +<g id="aspect-ratio"><path d="M16,10h-2v2h2V10z M16,14h-2v2h2V14z M8,10H6v2h2V10z M12,10h-2v2h2V10z M20,4H4C2.9,4,2,4.9,2,6v12c0,1.1,0.9,2,2,2h16c1.1,0,2-0.9,2-2V6C22,4.9,21.1,4,20,4z M20,18L4,18V6h16V18z"/></g> +<g id="assistant-photo"><polygon points="14.4,6 14,4 5,4 5,21 7,21 7,14 12.6,14 13,16 20,16 20,6 "/></g> +<g id="auto-awesome"><path d="M19,9l1.2-2.8L23,5l-2.8-1.2L19,1l-1.2,2.8L15,5l2.8,1.2L19,9z M11.5,9.5L9,4L6.5,9.5L1,12l5.5,2.5L9,20l2.5-5.5L17,12L11.5,9.5z M19,15l-1.2,2.7L15,19l2.8,1.2L19,23l1.2-2.8L23,19l-2.8-1.2L19,15z"/></g> +<g id="auto-awesome-mix"><path d="M3,5v14c0,1.1,0.9,2,2,2h6V3H5C3.9,3,3,3.9,3,5z M19,3h-6v8h8V5C21,3.9,20.1,3,19,3z M13,21h6c1.1,0,2-0.9,2-2v-6h-8V21z"/></g> +<g id="auto-awesome-motion"><path d="M14,2H4C2.9,2,2,2.9,2,4v10h2V4h10V2z M18,6H8C6.9,6,6,6.9,6,8v10h2V8h10V6z M20,10h-8c-1.1,0-2,0.9-2,2v8c0,1.1,0.9,2,2,2h8c1.1,0,2-0.9,2-2v-8C22,10.9,21.1,10,20,10z"/></g> +<g id="auto-fix"><polygon points="7.5,5.6 10,7 8.6,4.5 10,2 7.5,3.4 5,2 6.4,4.5 5,7 "/></g> +<g id="auto-fix-high"><polygon points="7.5,5.6 10,7 8.6,4.5 10,2 7.5,3.4 5,2 6.4,4.5 5,7 "/></g> +<g id="auto-fix-normal"><polygon points="22,2 19.5,3.4 17,2 18.4,4.5 17,7 19.5,5.6 22,7 20.6,4.5 "/></g> +<g id="auto-fix-off"><path d="M23,1l-2.5,1.4L18,1l1.4,2.5L18,6l2.5-1.4L23,6l-1.4-2.5L23,1z M14.7,7.2l2.1,2.1l-2.4,2.4l0.8,0.8l2.6-2.6c0.4-0.4,0.4-1,0-1.4l-2.3-2.3c-0.4-0.4-1-0.4-1.4,0l-2.6,2.6l0.8,0.8L14.7,7.2z M13.9,13.9l-3.8-3.8h0L3.3,3.3L2,4.5l6.9,6.9L2.3,18c-0.4,0.4-0.4,1,0,1.4l2.3,2.3c0.4,0.4,1,0.4,1.4,0l6.6-6.6l6.9,6.9l1.3-1.3L13.9,13.9L13.9,13.9z"/></g> +<g id="auto-stories"><path d="M18,1l-5,4v16l5-3.9V1z M1,7v12c0,1.1,0.9,2,2,2h8V5H3C1.9,5,1,5.9,1,7z M21,5h-1v13.1l-0.8,0.6l-3,2.3H21c1.1,0,2-0.9,2-2V7C23,5.9,22.1,5,21,5z"/></g> +<g id="blur-circular"><path d="M10,9c-0.6,0-1,0.4-1,1s0.4,1,1,1s1-0.4,1-1S10.6,9,10,9z M10,13c-0.6,0-1,0.4-1,1s0.4,1,1,1s1-0.4,1-1S10.6,13,10,13z M7,9.5c-0.3,0-0.5,0.2-0.5,0.5s0.2,0.5,0.5,0.5s0.5-0.2,0.5-0.5S7.3,9.5,7,9.5z M10,16.5c-0.3,0-0.5,0.2-0.5,0.5s0.2,0.5,0.5,0.5s0.5-0.2,0.5-0.5S10.3,16.5,10,16.5z M7,13.5c-0.3,0-0.5,0.2-0.5,0.5s0.2,0.5,0.5,0.5s0.5-0.2,0.5-0.5S7.3,13.5,7,13.5z M10,7.5c0.3,0,0.5-0.2,0.5-0.5S10.3,6.5,10,6.5S9.5,6.7,9.5,7S9.7,7.5,10,7.5z M14,9c-0.6,0-1,0.4-1,1s0.4,1,1,1s1-0.4,1-1S14.6,9,14,9z M14,7.5c0.3,0,0.5-0.2,0.5-0.5S14.3,6.5,14,6.5S13.5,6.7,13.5,7S13.7,7.5,14,7.5z M17,13.5c-0.3,0-0.5,0.2-0.5,0.5s0.2,0.5,0.5,0.5s0.5-0.2,0.5-0.5S17.3,13.5,17,13.5z M17,9.5c-0.3,0-0.5,0.2-0.5,0.5s0.2,0.5,0.5,0.5s0.5-0.2,0.5-0.5S17.3,9.5,17,9.5z M12,2C6.5,2,2,6.5,2,12s4.5,10,10,10s10-4.5,10-10S17.5,2,12,2z M12,20c-4.4,0-8-3.6-8-8s3.6-8,8-8s8,3.6,8,8S16.4,20,12,20z M14,16.5c-0.3,0-0.5,0.2-0.5,0.5s0.2,0.5,0.5,0.5s0.5-0.2,0.5-0.5S14.3,16.5,14,16.5z M14,13c-0.6,0-1,0.4-1,1s0.4,1,1,1s1-0.4,1-1S14.6,13,14,13z"/></g> +<g id="blur-linear"><path d="M5,17.5c0.8,0,1.5-0.7,1.5-1.5S5.8,14.5,5,14.5S3.5,15.2,3.5,16S4.2,17.5,5,17.5z M9,13c0.6,0,1-0.4,1-1s-0.4-1-1-1s-1,0.4-1,1S8.4,13,9,13z M9,9c0.6,0,1-0.4,1-1S9.6,7,9,7S8,7.4,8,8S8.4,9,9,9z M3,21h18v-2H3V21z M5,9.5c0.8,0,1.5-0.7,1.5-1.5S5.8,6.5,5,6.5S3.5,7.2,3.5,8S4.2,9.5,5,9.5z M5,13.5c0.8,0,1.5-0.7,1.5-1.5S5.8,10.5,5,10.5S3.5,11.2,3.5,12S4.2,13.5,5,13.5z M9,17c0.6,0,1-0.4,1-1s-0.4-1-1-1s-1,0.4-1,1S8.4,17,9,17z M17,16.5c0.3,0,0.5-0.2,0.5-0.5s-0.2-0.5-0.5-0.5s-0.5,0.2-0.5,0.5S16.7,16.5,17,16.5z M3,3v2h18V3H3z M17,8.5c0.3,0,0.5-0.2,0.5-0.5c0-0.3-0.2-0.5-0.5-0.5S16.5,7.7,16.5,8C16.5,8.3,16.7,8.5,17,8.5z M17,12.5c0.3,0,0.5-0.2,0.5-0.5s-0.2-0.5-0.5-0.5s-0.5,0.2-0.5,0.5S16.7,12.5,17,12.5z M13,9c0.6,0,1-0.4,1-1s-0.4-1-1-1s-1,0.4-1,1S12.4,9,13,9z M13,13c0.6,0,1-0.4,1-1s-0.4-1-1-1s-1,0.4-1,1S12.4,13,13,13z M13,17c0.6,0,1-0.4,1-1s-0.4-1-1-1s-1,0.4-1,1S12.4,17,13,17z"/></g> +<g id="blur-off"><path d="M14,7c0.6,0,1-0.4,1-1s-0.4-1-1-1s-1,0.4-1,1S13.4,7,14,7z M13.8,11.5c0.1,0,0.1,0,0.2,0c0.8,0,1.5-0.7,1.5-1.5S14.8,8.5,14,8.5s-1.5,0.7-1.5,1.5c0,0.1,0,0.1,0,0.2C12.6,10.9,13.1,11.4,13.8,11.5z M14,3.5c0.3,0,0.5-0.2,0.5-0.5S14.3,2.5,14,2.5S13.5,2.7,13.5,3S13.7,3.5,14,3.5z M10,3.5c0.3,0,0.5-0.2,0.5-0.5S10.3,2.5,10,2.5S9.5,2.7,9.5,3S9.7,3.5,10,3.5z M21,10.5c0.3,0,0.5-0.2,0.5-0.5S21.3,9.5,21,9.5s-0.5,0.2-0.5,0.5S20.7,10.5,21,10.5z M10,7c0.6,0,1-0.4,1-1s-0.4-1-1-1S9,5.4,9,6S9.4,7,10,7z M18,15c0.6,0,1-0.4,1-1s-0.4-1-1-1s-1,0.4-1,1S17.4,15,18,15z M18,11c0.6,0,1-0.4,1-1s-0.4-1-1-1s-1,0.4-1,1S17.4,11,18,11z M18,7c0.6,0,1-0.4,1-1s-0.4-1-1-1s-1,0.4-1,1S17.4,7,18,7z M14,20.5c-0.3,0-0.5,0.2-0.5,0.5s0.2,0.5,0.5,0.5s0.5-0.2,0.5-0.5S14.3,20.5,14,20.5z M2.5,5.3l3.8,3.8C6.2,9,6.1,9,6,9c-0.6,0-1,0.4-1,1s0.4,1,1,1s1-0.4,1-1c0-0.1,0-0.2-0.1-0.3l2.8,2.8C9,12.6,8.5,13.3,8.5,14c0,0.8,0.7,1.5,1.5,1.5c0.7,0,1.4-0.5,1.5-1.3l2.8,2.8C14.2,17,14.1,17,14,17c-0.6,0-1,0.4-1,1s0.4,1,1,1s1-0.4,1-1c0-0.1,0-0.2-0.1-0.3l3.8,3.8l1.3-1.3L3.8,4L2.5,5.3z M10,17c-0.6,0-1,0.4-1,1s0.4,1,1,1s1-0.4,1-1S10.6,17,10,17z M21,13.5c-0.3,0-0.5,0.2-0.5,0.5s0.2,0.5,0.5,0.5s0.5-0.2,0.5-0.5S21.3,13.5,21,13.5z M6,13c-0.6,0-1,0.4-1,1s0.4,1,1,1s1-0.4,1-1S6.6,13,6,13z M3,9.5c-0.3,0-0.5,0.2-0.5,0.5s0.2,0.5,0.5,0.5s0.5-0.2,0.5-0.5S3.3,9.5,3,9.5z M10,20.5c-0.3,0-0.5,0.2-0.5,0.5s0.2,0.5,0.5,0.5s0.5-0.2,0.5-0.5S10.3,20.5,10,20.5z M6,17c-0.6,0-1,0.4-1,1s0.4,1,1,1s1-0.4,1-1S6.6,17,6,17z M3,13.5c-0.3,0-0.5,0.2-0.5,0.5s0.2,0.5,0.5,0.5s0.5-0.2,0.5-0.5S3.3,13.5,3,13.5z"/></g> +<g id="blur-on"><path d="M6,13c-0.6,0-1,0.4-1,1s0.4,1,1,1s1-0.4,1-1S6.6,13,6,13z M6,17c-0.6,0-1,0.4-1,1s0.4,1,1,1s1-0.4,1-1S6.6,17,6,17z M6,9c-0.6,0-1,0.4-1,1s0.4,1,1,1s1-0.4,1-1S6.6,9,6,9z M3,9.5c-0.3,0-0.5,0.2-0.5,0.5s0.2,0.5,0.5,0.5s0.5-0.2,0.5-0.5S3.3,9.5,3,9.5z M6,5C5.4,5,5,5.4,5,6s0.4,1,1,1s1-0.4,1-1S6.6,5,6,5z M21,10.5c0.3,0,0.5-0.2,0.5-0.5S21.3,9.5,21,9.5s-0.5,0.2-0.5,0.5S20.7,10.5,21,10.5z M14,7c0.6,0,1-0.4,1-1s-0.4-1-1-1s-1,0.4-1,1S13.4,7,14,7z M14,3.5c0.3,0,0.5-0.2,0.5-0.5S14.3,2.5,14,2.5S13.5,2.7,13.5,3S13.7,3.5,14,3.5z M3,13.5c-0.3,0-0.5,0.2-0.5,0.5s0.2,0.5,0.5,0.5s0.5-0.2,0.5-0.5S3.3,13.5,3,13.5z M10,20.5c-0.3,0-0.5,0.2-0.5,0.5s0.2,0.5,0.5,0.5s0.5-0.2,0.5-0.5S10.3,20.5,10,20.5z M10,3.5c0.3,0,0.5-0.2,0.5-0.5S10.3,2.5,10,2.5S9.5,2.7,9.5,3S9.7,3.5,10,3.5z M10,7c0.6,0,1-0.4,1-1s-0.4-1-1-1S9,5.4,9,6S9.4,7,10,7z M10,12.5c-0.8,0-1.5,0.7-1.5,1.5s0.7,1.5,1.5,1.5s1.5-0.7,1.5-1.5S10.8,12.5,10,12.5z M18,13c-0.6,0-1,0.4-1,1s0.4,1,1,1s1-0.4,1-1S18.6,13,18,13z M18,17c-0.6,0-1,0.4-1,1s0.4,1,1,1s1-0.4,1-1S18.6,17,18,17z M18,9c-0.6,0-1,0.4-1,1s0.4,1,1,1s1-0.4,1-1S18.6,9,18,9z M18,5c-0.6,0-1,0.4-1,1s0.4,1,1,1s1-0.4,1-1S18.6,5,18,5z M21,13.5c-0.3,0-0.5,0.2-0.5,0.5s0.2,0.5,0.5,0.5s0.5-0.2,0.5-0.5S21.3,13.5,21,13.5z M14,17c-0.6,0-1,0.4-1,1s0.4,1,1,1s1-0.4,1-1S14.6,17,14,17z M14,20.5c-0.3,0-0.5,0.2-0.5,0.5s0.2,0.5,0.5,0.5s0.5-0.2,0.5-0.5S14.3,20.5,14,20.5z M10,8.5c-0.8,0-1.5,0.7-1.5,1.5s0.7,1.5,1.5,1.5s1.5-0.7,1.5-1.5S10.8,8.5,10,8.5z M10,17c-0.6,0-1,0.4-1,1s0.4,1,1,1s1-0.4,1-1S10.6,17,10,17z M14,12.5c-0.8,0-1.5,0.7-1.5,1.5s0.7,1.5,1.5,1.5s1.5-0.7,1.5-1.5S14.8,12.5,14,12.5z M14,8.5c-0.8,0-1.5,0.7-1.5,1.5s0.7,1.5,1.5,1.5s1.5-0.7,1.5-1.5S14.8,8.5,14,8.5z"/></g> +<g id="brightness-1"><circle cx="12" cy="12" r="10"/></g> +<g id="brightness-2"><path d="M10,2C8.2,2,6.5,2.5,5,3.3c3,1.7,5,5,5,8.7s-2,6.9-5,8.7c1.5,0.9,3.2,1.3,5,1.3c5.5,0,10-4.5,10-10S15.5,2,10,2z"/></g> +<g id="brightness-3"><path d="M9,2C8,2,6.9,2.2,6,2.5c4.1,1.3,7,5.1,7,9.5s-2.9,8.3-7,9.5C6.9,21.8,8,22,9,22c5.5,0,10-4.5,10-10S14.5,2,9,2z"/></g> +<g id="brightness-4"><path d="M20,8.7V4h-4.7L12,0.7L8.7,4H4v4.7L0.7,12L4,15.3V20h4.7l3.3,3.3l3.3-3.3H20v-4.7l3.3-3.3L20,8.7z M12,18c-0.9,0-1.7-0.2-2.5-0.6c2.1-0.9,3.5-3,3.5-5.4s-1.4-4.5-3.5-5.4C10.3,6.2,11.1,6,12,6c3.3,0,6,2.7,6,6S15.3,18,12,18z"/></g> +<g id="brightness-5"><path d="M20,15.3l3.3-3.3L20,8.7V4h-4.7L12,0.7L8.7,4H4v4.7L0.7,12L4,15.3V20h4.7l3.3,3.3l3.3-3.3H20V15.3z M12,18c-3.3,0-6-2.7-6-6s2.7-6,6-6c3.3,0,6,2.7,6,6S15.3,18,12,18z"/></g> +<g id="brightness-6"><path d="M20,15.3l3.3-3.3L20,8.7V4h-4.7L12,0.7L8.7,4H4v4.7L0.7,12L4,15.3V20h4.7l3.3,3.3l3.3-3.3H20V15.3z M12,18V6c3.3,0,6,2.7,6,6S15.3,18,12,18z"/></g> +<g id="brightness-7"><path d="M20,8.7V4h-4.7L12,0.7L8.7,4H4v4.7L0.7,12L4,15.3V20h4.7l3.3,3.3l3.3-3.3H20v-4.7l3.3-3.3L20,8.7z M12,18c-3.3,0-6-2.7-6-6s2.7-6,6-6c3.3,0,6,2.7,6,6S15.3,18,12,18z M12,8c-2.2,0-4,1.8-4,4c0,2.2,1.8,4,4,4s4-1.8,4-4C16,9.8,14.2,8,12,8z"/></g> +<g id="brush"><path d="M7,14c-1.7,0-3,1.3-3,3c0,1.3-1.2,2-2,2c0.9,1.2,2.5,2,4,2c2.2,0,4-1.8,4-4C10,15.3,8.7,14,7,14z M20.7,4.6l-1.3-1.3c-0.4-0.4-1-0.4-1.4,0l-9,9l2.8,2.8l9-9C21.1,5.7,21.1,5,20.7,4.6z"/></g> +<g id="camera"><path d="M9.4,10.5l4.8-8.3C13.5,2.1,12.7,2,12,2C9.6,2,7.4,2.8,5.7,4.3l3.7,6.3L9.4,10.5z M21.5,9c-0.9-2.9-3.1-5.3-6-6.3L11.9,9H21.5z M21.8,10h-7.5l0.3,0.5l4.8,8.3C21,17,22,14.6,22,12C22,11.3,21.9,10.6,21.8,10z M8.5,12L4.6,5.2C3,7,2,9.4,2,12c0,0.7,0.1,1.4,0.2,2h7.5L8.5,12z M2.5,15c0.9,2.9,3.1,5.3,6,6.3l3.7-6.3H2.5z M13.7,15l-3.9,6.8c0.7,0.2,1.4,0.2,2.2,0.2c2.4,0,4.6-0.8,6.3-2.3l-3.7-6.3L13.7,15z"/></g> +<g id="camera-alt"><circle cx="12" cy="12" r="3.2"/><path d="M9,2L7.2,4H4C2.9,4,2,4.9,2,6v12c0,1.1,0.9,2,2,2h16c1.1,0,2-0.9,2-2V6c0-1.1-0.9-2-2-2h-3.2L15,2H9z M12,17c-2.8,0-5-2.2-5-5s2.2-5,5-5s5,2.2,5,5S14.8,17,12,17z"/></g> +<g id="camera-front"><path d="M12,12c1.7,0,3-1.3,3-3s-1.3-3-3-3c-1.7,0-3,1.3-3,3S10.3,12,12,12z M18,0H6C4.9,0,4,0.9,4,2v20c0,1.1,0.9,2,2,2h12c1.1,0,2-0.9,2-2V2C20,0.9,19.1,0,18,0z M11,1h2v2h-2V1z M13,22v-2H9v-2h4v-2l3,3L13,22z M18,17c0-2-4-3-6-3c-2,0-6,1-6,3V4h12V17z"/></g> +<g id="camera-rear"><path d="M18,0H6C4.9,0,4,0.9,4,2v20c0,1.1,0.9,2,2,2h12c1.1,0,2-0.9,2-2V2C20,0.9,19.1,0,18,0z M12,2c1.1,0,2,0.9,2,2s-0.9,2-2,2s-2-0.9-2-2S10.9,2,12,2z M13,22v-2H9v-2h4v-2l3,3L13,22z"/></g> +<g id="camera-roll"><path d="M14,5c0-1.1-0.9-2-2-2h-1V2c0-0.6-0.4-1-1-1H6C5.4,1,5,1.4,5,2v1H4C2.9,3,2,3.9,2,5v15c0,1.1,0.9,2,2,2h8c1.1,0,2-0.9,2-2h8V5H14z M12,18h-2v-2h2V18z M12,9h-2V7h2V9z M16,18h-2v-2h2V18z M16,9h-2V7h2V9z M20,18h-2v-2h2V18z M20,9h-2V7h2V9z"/></g> +<g id="center-focus-strong"><path d="M12,8c-2.2,0-4,1.8-4,4s1.8,4,4,4s4-1.8,4-4S14.2,8,12,8z M5,15H3v4c0,1.1,0.9,2,2,2h4v-2H5V15z M5,5h4V3H5C3.9,3,3,3.9,3,5v4h2V5z M19,3h-4v2h4v4h2V5C21,3.9,20.1,3,19,3z M19,19h-4v2h4c1.1,0,2-0.9,2-2v-4h-2V19z"/></g> +<g id="center-focus-weak"><path d="M5,15H3v4c0,1.1,0.9,2,2,2h4v-2H5V15z M5,5h4V3H5C3.9,3,3,3.9,3,5v4h2V5z M19,3h-4v2h4v4h2V5C21,3.9,20.1,3,19,3z M19,19h-4v2h4c1.1,0,2-0.9,2-2v-4h-2V19z M12,8c-2.2,0-4,1.8-4,4s1.8,4,4,4s4-1.8,4-4S14.2,8,12,8z M12,14c-1.1,0-2-0.9-2-2s0.9-2,2-2s2,0.9,2,2S13.1,14,12,14z"/></g> +<g id="collections"><path d="M22,16V4c0-1.1-0.9-2-2-2H8C6.9,2,6,2.9,6,4v12c0,1.1,0.9,2,2,2h12C21.1,18,22,17.1,22,16z M11,12l2,2.7l3-3.7l4,5H8L11,12z M2,6v14c0,1.1,0.9,2,2,2h14v-2H4V6H2z"/></g> +<g id="colorize"><path d="M20.7,5.6l-2.3-2.3c-0.4-0.4-1-0.4-1.4,0l-3.1,3.1l-1.9-1.9l-1.4,1.4l1.4,1.4L3,16.3V21h4.8l8.9-8.9l1.4,1.4l1.4-1.4l-1.9-1.9L20.7,7C21.1,6.7,21.1,6,20.7,5.6z M6.9,19L5,17.1L13.1,9l1.9,1.9L6.9,19z"/></g> +<g id="color-lens"><path d="M12,3c-5,0-9,4-9,9s4,9,9,9c0.8,0,1.5-0.7,1.5-1.5c0-0.4-0.1-0.7-0.4-1c-0.2-0.3-0.4-0.6-0.4-1c0-0.8,0.7-1.5,1.5-1.5H16c2.8,0,5-2.2,5-5C21,6.6,17,3,12,3z M6.5,12C5.7,12,5,11.3,5,10.5S5.7,9,6.5,9C7.3,9,8,9.7,8,10.5S7.3,12,6.5,12z M9.5,8C8.7,8,8,7.3,8,6.5S8.7,5,9.5,5C10.3,5,11,5.7,11,6.5S10.3,8,9.5,8z M14.5,8C13.7,8,13,7.3,13,6.5S13.7,5,14.5,5C15.3,5,16,5.7,16,6.5S15.3,8,14.5,8z M17.5,12c-0.8,0-1.5-0.7-1.5-1.5S16.7,9,17.5,9c0.8,0,1.5,0.7,1.5,1.5S18.3,12,17.5,12z"/></g> +<g id="compare"><path d="M10,3H5C3.9,3,3,3.9,3,5v14c0,1.1,0.9,2,2,2h5v2h2V1h-2V3z M10,18H5l5-6V18z M19,3h-5v2h5v13l-5-6v9h5c1.1,0,2-0.9,2-2V5C21,3.9,20.1,3,19,3z"/></g> +<g id="control-point"><path d="M13,7h-2v4H7v2h4v4h2v-4h4v-2h-4V7z M12,2C6.5,2,2,6.5,2,12s4.5,10,10,10s10-4.5,10-10S17.5,2,12,2z M12,20c-4.4,0-8-3.6-8-8s3.6-8,8-8s8,3.6,8,8S16.4,20,12,20z"/></g> +<g id="control-point-duplicate"><polygon points="16,8 14,8 14,11 11,11 11,13 14,13 14,16 16,16 16,13 19,13 19,11 16,11 "/></g> +<g id="crop-16-9"><path d="M19,6H5C3.9,6,3,6.9,3,8v8c0,1.1,0.9,2,2,2h14c1.1,0,2-0.9,2-2V8C21,6.9,20.1,6,19,6z M19,16H5V8h14V16z"/></g> +<g id="crop"><path d="M17,15h2V7c0-1.1-0.9-2-2-2H9v2h8V15z M7,17V1H5v4H1v2h4v10c0,1.1,0.9,2,2,2h10v4h2v-4h4v-2H7z"/></g> +<g id="crop-3-2"><path d="M19,4H5C3.9,4,3,4.9,3,6v12c0,1.1,0.9,2,2,2h14c1.1,0,2-0.9,2-2V6C21,4.9,20.1,4,19,4z M19,18H5V6h14V18z"/></g> +<g id="crop-5-4"><path d="M19,5H5C3.9,5,3,5.9,3,7v10c0,1.1,0.9,2,2,2h14c1.1,0,2-0.9,2-2V7C21,5.9,20.1,5,19,5z M19,17H5V7h14V17z"/></g> +<g id="crop-7-5"><path d="M19,7H5C3.9,7,3,7.9,3,9v6c0,1.1,0.9,2,2,2h14c1.1,0,2-0.9,2-2V9C21,7.9,20.1,7,19,7z M19,15H5V9h14V15z"/></g> +<g id="crop-din"><path d="M19,3H5C3.9,3,3,3.9,3,5v14c0,1.1,0.9,2,2,2h14c1.1,0,2-0.9,2-2V5C21,3.9,20.1,3,19,3z M19,19H5V5h14V19z"/></g> +<g id="crop-free"><path d="M3,5v4h2V5h4V3H5C3.9,3,3,3.9,3,5z M5,15H3v4c0,1.1,0.9,2,2,2h4v-2H5V15z M19,19h-4v2h4c1.1,0,2-0.9,2-2v-4h-2V19z M19,3h-4v2h4v4h2V5C21,3.9,20.1,3,19,3z"/></g> +<g id="crop-landscape"><path d="M19,5H5C3.9,5,3,5.9,3,7v10c0,1.1,0.9,2,2,2h14c1.1,0,2-0.9,2-2V7C21,5.9,20.1,5,19,5z M19,17H5V7h14V17z"/></g> +<g id="crop-original"><path d="M19,3H5C3.9,3,3,3.9,3,5v14c0,1.1,0.9,2,2,2h14c1.1,0,2-0.9,2-2V5C21,3.9,20.1,3,19,3z M19,19H5V5h14V19z M14,12.3l-2.8,3.5l-2-2.4L6.5,17h11L14,12.3z"/></g> +<g id="crop-portrait"><path d="M17,3H7C5.9,3,5,3.9,5,5v14c0,1.1,0.9,2,2,2h10c1.1,0,2-0.9,2-2V5C19,3.9,18.1,3,17,3z M17,19H7V5h10V19z"/></g> +<g id="crop-square"><path d="M18,4H6C4.9,4,4,4.9,4,6v12c0,1.1,0.9,2,2,2h12c1.1,0,2-0.9,2-2V6C20,4.9,19.1,4,18,4z M18,18H6V6h12V18z"/></g> +<g id="dehaze"><path d="M2,15.5v2c6.7-4.4,13.3,4.4,20,0v-2C15.3,19.9,8.7,11.1,2,15.5z M2,10.5v2c6.7-4.4,13.3,4.4,20,0v-2C15.3,14.9,8.7,6.1,2,10.5z M2,5.5v2c6.7-4.4,13.3,4.4,20,0v-2C15.3,9.9,8.7,1.1,2,5.5z"/></g> +<g id="details"><path d="M3,4l9,16l9-16H3z M6.4,6h11.2L12,16L6.4,6z"/></g> +<g id="edit"><path d="M3,17.3V21h3.8L17.8,9.9l-3.8-3.8L3,17.3z M20.7,7c0.4-0.4,0.4-1,0-1.4l-2.3-2.3c-0.4-0.4-1-0.4-1.4,0l-1.8,1.8l3.7,3.8L20.7,7z"/></g> +<g id="exposure"><path d="M19,3H5C3.9,3,3,3.9,3,5v14c0,1.1,0.9,2,2,2h14c1.1,0,2-0.9,2-2V5C21,3.9,20.1,3,19,3z M5.5,7.5h2v-2H9v2h2V9H9v2H7.5V9h-2V7.5z M19,19L5,19L19,5V19z M17,17v-1.5h-5V17H17z"/></g> +<g id="exposure-minus-1"><path d="M4,11v2h8v-2H4z M19,18h-2V7.4l-3,1V6.7L18.7,5H19V18z"/></g> +<g id="exposure-minus-2"><path d="M15,16.3l2.9-3.1c0.4-0.4,0.7-0.8,1-1.2c0.3-0.4,0.6-0.8,0.8-1.2c0.2-0.4,0.4-0.8,0.5-1.2c0.1-0.4,0.2-0.8,0.2-1.2c0-0.5-0.1-1-0.3-1.5S19.8,6.3,19.4,6c-0.3-0.3-0.8-0.5-1.3-0.7C17.7,5.1,17.1,5,16.5,5c-0.7,0-1.3,0.1-1.8,0.3c-0.5,0.2-1,0.5-1.4,0.9c-0.4,0.4-0.7,0.8-0.8,1.3c-0.2,0.5-0.3,1-0.3,1.5h2.1c0-0.3,0-0.6,0.1-0.9c0.1-0.3,0.2-0.5,0.4-0.7C15,7.2,15.2,7,15.5,6.9c0.3-0.1,0.6-0.2,1-0.2c0.3,0,0.6,0.1,0.8,0.2c0.2,0.1,0.4,0.2,0.6,0.4c0.2,0.2,0.3,0.4,0.4,0.6c0.1,0.2,0.1,0.5,0.1,0.8c0,0.2,0,0.4-0.1,0.7c-0.1,0.2-0.2,0.5-0.3,0.7c-0.1,0.2-0.3,0.5-0.6,0.8c-0.2,0.3-0.5,0.6-0.9,1l-4.2,4.6V18H21v-1.7H15z M2,11v2h8v-2H2z"/></g> +<g id="exposure-plus-1"><path d="M10,7H8v4H4v2h4v4h2v-4h4v-2h-4V7z M20,18h-2V7.4l-3,1V6.7L19.7,5H20V18z"/></g> +<g id="exposure-plus-2"><path d="M16,16.3l2.9-3.1c0.4-0.4,0.7-0.8,1-1.2c0.3-0.4,0.6-0.8,0.8-1.2c0.2-0.4,0.4-0.8,0.5-1.2c0.1-0.4,0.2-0.8,0.2-1.2c0-0.5-0.1-1-0.3-1.5S20.8,6.3,20.4,6c-0.3-0.3-0.8-0.5-1.3-0.7C18.7,5.1,18.1,5,17.5,5c-0.7,0-1.3,0.1-1.8,0.3c-0.5,0.2-1,0.5-1.4,0.9c-0.4,0.4-0.7,0.8-0.8,1.3c-0.2,0.5-0.3,1-0.3,1.5h2.1c0-0.3,0-0.6,0.1-0.9c0.1-0.3,0.2-0.5,0.4-0.7C16,7.2,16.2,7,16.5,6.9c0.3-0.1,0.6-0.2,1-0.2c0.3,0,0.6,0.1,0.8,0.2c0.2,0.1,0.4,0.2,0.6,0.4c0.2,0.2,0.3,0.4,0.4,0.6c0.1,0.2,0.1,0.5,0.1,0.8c0,0.2,0,0.4-0.1,0.7c-0.1,0.2-0.2,0.5-0.3,0.7c-0.1,0.2-0.3,0.5-0.6,0.8c-0.2,0.3-0.5,0.6-0.9,1l-4.2,4.6V18H22v-1.7H16z M8,7H6v4H2v2h4v4h2v-4h4v-2H8V7z"/></g> +<g id="exposure-zero"><path d="M16.1,12.5c0,1-0.1,1.9-0.3,2.6c-0.2,0.7-0.5,1.3-0.8,1.7c-0.4,0.4-0.8,0.8-1.3,1S12.6,18,12,18c-0.6,0-1.2-0.1-1.7-0.3s-0.9-0.5-1.3-1c-0.4-0.4-0.6-1-0.8-1.7c-0.2-0.7-0.3-1.5-0.3-2.6v-2c0-1,0.1-1.9,0.3-2.5C8.4,7.2,8.6,6.7,9,6.2c0.4-0.4,0.8-0.7,1.3-0.9C10.8,5.1,11.4,5,12,5c0.6,0,1.2,0.1,1.7,0.3c0.5,0.2,0.9,0.5,1.3,0.9c0.4,0.4,0.6,1,0.8,1.7c0.2,0.7,0.3,1.5,0.3,2.5V12.5z M14,10.1c0-0.6,0-1.2-0.1-1.6c-0.1-0.4-0.2-0.8-0.4-1.1S13.1,7,12.9,6.9c-0.3-0.1-0.5-0.2-0.9-0.2c-0.3,0-0.6,0.1-0.9,0.2c-0.3,0.1-0.5,0.3-0.6,0.6s-0.3,0.6-0.4,1.1C10,9,10,9.5,10,10.1v2.7c0,0.6,0,1.2,0.1,1.6s0.2,0.8,0.4,1.1s0.4,0.5,0.6,0.6s0.5,0.2,0.9,0.2c0.3,0,0.6-0.1,0.9-0.2c0.2-0.1,0.5-0.3,0.6-0.6c0.2-0.3,0.3-0.6,0.4-1.1c0.1-0.4,0.1-1,0.1-1.6V10.1z"/></g> +<g id="filter-1"><path d="M3,5H1v16c0,1.1,0.9,2,2,2h16v-2H3V5z M14,15h2V5h-4v2h2V15z M21,1H7C5.9,1,5,1.9,5,3v14c0,1.1,0.9,2,2,2h14c1.1,0,2-0.9,2-2V3C23,1.9,22.1,1,21,1z M21,17H7V3h14V17z"/></g> +<g id="filter-2"><path d="M3,5H1v16c0,1.1,0.9,2,2,2h16v-2H3V5z M21,1H7C5.9,1,5,1.9,5,3v14c0,1.1,0.9,2,2,2h14c1.1,0,2-0.9,2-2V3C23,1.9,22.1,1,21,1z M21,17H7V3h14V17z M17,13h-4v-2h2c1.1,0,2-0.9,2-2V7c0-1.1-0.9-2-2-2h-4v2h4v2h-2c-1.1,0-2,0.9-2,2v4h6V13z"/></g> +<g id="filter"><path d="M16,10.3l-2.8,3.5l-2-2.4L8.5,15h11L16,10.3z M3,5H1v16c0,1.1,0.9,2,2,2h16v-2H3V5z M21,1H7C5.9,1,5,1.9,5,3v14c0,1.1,0.9,2,2,2h14c1.1,0,2-0.9,2-2V3C23,1.9,22.1,1,21,1z M21,17H7V3h14V17z"/></g> +<g id="filter-3"><path d="M21,1H7C5.9,1,5,1.9,5,3v14c0,1.1,0.9,2,2,2h14c1.1,0,2-0.9,2-2V3C23,1.9,22.1,1,21,1z M21,17H7V3h14V17z M3,5H1v16c0,1.1,0.9,2,2,2h16v-2H3V5z M17,13v-1.5c0-0.8-0.7-1.5-1.5-1.5c0.8,0,1.5-0.7,1.5-1.5V7c0-1.1-0.9-2-2-2h-4v2h4v2h-2v2h2v2h-4v2h4C16.1,15,17,14.1,17,13z"/></g> +<g id="filter-4"><path d="M3,5H1v16c0,1.1,0.9,2,2,2h16v-2H3V5z M15,15h2V5h-2v4h-2V5h-2v6h4V15z M21,1H7C5.9,1,5,1.9,5,3v14c0,1.1,0.9,2,2,2h14c1.1,0,2-0.9,2-2V3C23,1.9,22.1,1,21,1z M21,17H7V3h14V17z"/></g> +<g id="filter-5"><path d="M21,1H7C5.9,1,5,1.9,5,3v14c0,1.1,0.9,2,2,2h14c1.1,0,2-0.9,2-2V3C23,1.9,22.1,1,21,1z M21,17H7V3h14V17z M3,5H1v16c0,1.1,0.9,2,2,2h16v-2H3V5z M17,13v-2c0-1.1-0.9-2-2-2h-2V7h4V5h-6v6h4v2h-4v2h4C16.1,15,17,14.1,17,13z"/></g> +<g id="filter-6"><path d="M3,5H1v16c0,1.1,0.9,2,2,2h16v-2H3V5z M21,1H7C5.9,1,5,1.9,5,3v14c0,1.1,0.9,2,2,2h14c1.1,0,2-0.9,2-2V3C23,1.9,22.1,1,21,1z M21,17H7V3h14V17z M13,15h2c1.1,0,2-0.9,2-2v-2c0-1.1-0.9-2-2-2h-2V7h4V5h-4c-1.1,0-2,0.9-2,2v6C11,14.1,11.9,15,13,15z M13,11h2v2h-2V11z"/></g> +<g id="filter-7"><path d="M3,5H1v16c0,1.1,0.9,2,2,2h16v-2H3V5z M21,1H7C5.9,1,5,1.9,5,3v14c0,1.1,0.9,2,2,2h14c1.1,0,2-0.9,2-2V3C23,1.9,22.1,1,21,1z M21,17H7V3h14V17z M13,15l4-8V5h-6v2h4l-4,8H13z"/></g> +<g id="filter-8"><path d="M3,5H1v16c0,1.1,0.9,2,2,2h16v-2H3V5z M21,1H7C5.9,1,5,1.9,5,3v14c0,1.1,0.9,2,2,2h14c1.1,0,2-0.9,2-2V3C23,1.9,22.1,1,21,1z M21,17H7V3h14V17z M13,15h2c1.1,0,2-0.9,2-2v-1.5c0-0.8-0.7-1.5-1.5-1.5c0.8,0,1.5-0.7,1.5-1.5V7c0-1.1-0.9-2-2-2h-2c-1.1,0-2,0.9-2,2v1.5c0,0.8,0.7,1.5,1.5,1.5c-0.8,0-1.5,0.7-1.5,1.5V13C11,14.1,11.9,15,13,15z M13,7h2v2h-2V7z M13,11h2v2h-2V11z"/></g> +<g id="filter-9"><path d="M3,5H1v16c0,1.1,0.9,2,2,2h16v-2H3V5z M21,1H7C5.9,1,5,1.9,5,3v14c0,1.1,0.9,2,2,2h14c1.1,0,2-0.9,2-2V3C23,1.9,22.1,1,21,1z M21,17H7V3h14V17z"/><path d="M15,5h-2c-1.1,0-2,0.9-2,2v2c0,1.1,0.9,2,2,2h2v2h-4v2h4c1.1,0,2-0.9,2-2V7C17,5.9,16.1,5,15,5z M15,9h-2V7h2V9z"/></g> +<g id="filter-9-plus"><path d="M3,5H1v16c0,1.1,0.9,2,2,2h16v-2H3V5z M14,12V8c0-1.1-0.9-2-2-2h-1C9.9,6,9,6.9,9,8v1c0,1.1,0.9,2,2,2h1v1H9v2h3C13.1,14,14,13.1,14,12z M11,9V8h1v1H11z M21,1H7C5.9,1,5,1.9,5,3v14c0,1.1,0.9,2,2,2h14c1.1,0,2-0.9,2-2V3C23,1.9,22.1,1,21,1z M21,9h-2V7h-2v2h-2v2h2v2h2v-2h2v6H7V3h14V9z"/></g> +<g id="filter-b-and-w"><path d="M19,3H5C3.9,3,3,3.9,3,5v14c0,1.1,0.9,2,2,2h14c1.1,0,2-0.9,2-2V5C21,3.9,20.1,3,19,3z M19,19l-7-8v8H5l7-8V5h7V19z"/></g> +<g id="filter-center-focus"><path d="M5,15H3v4c0,1.1,0.9,2,2,2h4v-2H5V15z M5,5h4V3H5C3.9,3,3,3.9,3,5v4h2V5z M19,3h-4v2h4v4h2V5C21,3.9,20.1,3,19,3z M19,19h-4v2h4c1.1,0,2-0.9,2-2v-4h-2V19z M12,9c-1.7,0-3,1.3-3,3s1.3,3,3,3s3-1.3,3-3S13.7,9,12,9z"/></g> +<g id="filter-drama"><path d="M19.4,10c-0.7-3.4-3.7-6-7.4-6C9.1,4,6.6,5.6,5.4,8C2.3,8.4,0,10.9,0,14c0,3.3,2.7,6,6,6h13c2.8,0,5-2.2,5-5C24,12.4,21.9,10.2,19.4,10z M19,18H6c-2.2,0-4-1.8-4-4s1.8-4,4-4c2.2,0,4,1.8,4,4h2c0-2.8-1.9-5.1-4.4-5.8C8.6,6.9,10.2,6,12,6c3,0,5.5,2.5,5.5,5.5V12H19c1.7,0,3,1.3,3,3S20.7,18,19,18z"/></g> +<g id="filter-frames"><path d="M20,4h-4l-4-4L8,4H4C2.9,4,2,4.9,2,6v14c0,1.1,0.9,2,2,2h16c1.1,0,2-0.9,2-2V6C22,4.9,21.1,4,20,4z M20,20H4V6h4.5L12,2.5L15.5,6H20V20z M18,8H6v10h12"/></g> +<g id="filter-hdr"><path d="M14,6l-3.8,5l2.8,3.8L11.5,16C9.8,13.7,7,10,7,10l-6,8h22L14,6z"/></g> +<g id="filter-none"><path d="M3,5H1v16c0,1.1,0.9,2,2,2h16v-2H3V5z M21,1H7C5.9,1,5,1.9,5,3v14c0,1.1,0.9,2,2,2h14c1.1,0,2-0.9,2-2V3C23,1.9,22.1,1,21,1z M21,17H7V3h14V17z"/></g> +<g id="filter-retrolux"><path d="M13,16.4L19,7l-7-7L5,7l6,9.4v0.1C10.4,16.2,9.7,16,9,16c-2.2,0-4,1.8-4,4s1.8,4,4,4c1.8,0,3.4-1.3,3.9-3l3,3l1.4-1.4L13,18.3V16.4z M11,20c0,1.1-0.9,2-2,2s-2-0.9-2-2s0.9-2,2-2c0.5,0,1,0.2,1.4,0.6l0.6,0.6V20z"/></g> +<g id="filter-tilt-shift"><path d="M11,4.1v-2C9,2.3,7.2,3,5.7,4.3l1.4,1.4C8.2,4.8,9.5,4.3,11,4.1z M18.3,4.3C16.8,3,15,2.3,13,2.1v2c1.5,0.2,2.8,0.8,3.9,1.6L18.3,4.3z M19.9,11h2c-0.2-2-1-3.8-2.2-5.3l-1.4,1.4C19.2,8.2,19.7,9.5,19.9,11z M5.7,7.1L4.3,5.7C3,7.2,2.3,9,2.1,11h2C4.3,9.5,4.8,8.2,5.7,7.1z M4.1,13h-2c0.2,2,1,3.8,2.2,5.3l1.4-1.4C4.8,15.8,4.3,14.5,4.1,13z M15,12c0-1.7-1.3-3-3-3s-3,1.3-3,3s1.3,3,3,3S15,13.7,15,12z M18.3,16.9l1.4,1.4c1.2-1.5,2-3.3,2.2-5.3h-2C19.7,14.5,19.2,15.8,18.3,16.9z M13,19.9v2c2-0.2,3.8-1,5.3-2.2l-1.4-1.4C15.8,19.2,14.5,19.7,13,19.9z M5.7,19.7c1.5,1.2,3.3,2,5.3,2.2v-2c-1.5-0.2-2.8-0.8-3.9-1.6L5.7,19.7z"/></g> +<g id="filter-vintage"><path d="M18.7,12.4c-0.3-0.2-0.6-0.3-0.9-0.4c0.3-0.1,0.6-0.2,0.9-0.4c1.9-1.1,3-3.1,3-5.2c-1.8-1-4.1-1.1-6,0c-0.3,0.2-0.5,0.3-0.8,0.5C15,6.6,15,6.3,15,6c0-2.2-1.2-4.2-3-5.2c-1.8,1-3,3-3,5.2c0,0.3,0,0.6,0.1,0.9C8.8,6.7,8.6,6.6,8.3,6.4c-1.9-1.1-4.2-1-6,0c0,2.1,1.1,4.1,3,5.2c0.3,0.2,0.6,0.3,0.9,0.4c-0.3,0.1-0.6,0.2-0.9,0.4c-1.9,1.1-3,3.1-3,5.2c1.8,1,4.1,1.1,6,0c0.3-0.2,0.5-0.3,0.8-0.5C9,17.4,9,17.7,9,18c0,2.2,1.2,4.2,3,5.2c1.8-1,3-3,3-5.2c0-0.3,0-0.6-0.1-0.9c0.2,0.2,0.5,0.4,0.8,0.5c1.9,1.1,4.2,1,6,0C21.7,15.5,20.6,13.5,18.7,12.4z M12,16c-2.2,0-4-1.8-4-4s1.8-4,4-4c2.2,0,4,1.8,4,4S14.2,16,12,16z"/></g> +<g id="flare"><path d="M7,11H1v2h6V11z M9.2,7.8L7.1,5.6L5.6,7.1l2.1,2.1L9.2,7.8z M13,1h-2v6h2V1z M18.4,7.1l-1.4-1.4l-2.1,2.1l1.4,1.4L18.4,7.1z M17,11v2h6v-2H17z M12,9c-1.7,0-3,1.3-3,3s1.3,3,3,3s3-1.3,3-3S13.7,9,12,9z M14.8,16.2l2.1,2.1l1.4-1.4l-2.1-2.1L14.8,16.2z M5.6,16.9l1.4,1.4l2.1-2.1l-1.4-1.4L5.6,16.9z M11,23h2v-6h-2V23z"/></g> +<g id="flash-auto"><path d="M3,2v12h3v9l7-12H9l4-9H3z M19,2h-2l-3.2,9h1.9l0.7-2h3.2l0.7,2h1.9L19,2z M16.9,7.6L18,4l1.1,3.6H16.9z"/></g> +<g id="flash-off"><path d="M3.3,3L2,4.3l5,5V13h3v9l3.6-6.1l4.1,4.1l1.3-1.3L3.3,3z M17,10h-4l4-8H7v2.2l8.5,8.5L17,10z"/></g> +<g id="flash-on"><polygon points="7,2 7,13 10,13 10,22 17,10 13,10 17,2 "/></g> +<g id="flip"><path d="M15,21h2v-2h-2V21z M19,9h2V7h-2V9z M3,5v14c0,1.1,0.9,2,2,2h4v-2H5V5h4V3H5C3.9,3,3,3.9,3,5z M19,3v2h2C21,3.9,20.1,3,19,3z M11,23h2V1h-2V23z M19,17h2v-2h-2V17z M15,5h2V3h-2V5z M19,13h2v-2h-2V13z M19,21c1.1,0,2-0.9,2-2h-2V21z"/></g> +<g id="gradient"><rect x="11" y="9" width="2" height="2"/><rect x="9" y="11" width="2" height="2"/><rect x="13" y="11" width="2" height="2"/><rect x="15" y="9" width="2" height="2"/><rect x="7" y="9" width="2" height="2"/><path d="M19,3H5C3.9,3,3,3.9,3,5v14c0,1.1,0.9,2,2,2h14c1.1,0,2-0.9,2-2V5C21,3.9,20.1,3,19,3z M9,18H7v-2h2V18z M13,18h-2v-2h2V18z M17,18h-2v-2h2V18z M19,11h-2v2h2v2h-2v-2h-2v2h-2v-2h-2v2H9v-2H7v2H5v-2h2v-2H5V5h14V11z"/></g> +<g id="grain"><path d="M10,12c-1.1,0-2,0.9-2,2c0,1.1,0.9,2,2,2s2-0.9,2-2C12,12.9,11.1,12,10,12z M6,8c-1.1,0-2,0.9-2,2c0,1.1,0.9,2,2,2s2-0.9,2-2C8,8.9,7.1,8,6,8z M6,16c-1.1,0-2,0.9-2,2c0,1.1,0.9,2,2,2s2-0.9,2-2C8,16.9,7.1,16,6,16z M18,8c1.1,0,2-0.9,2-2c0-1.1-0.9-2-2-2s-2,0.9-2,2C16,7.1,16.9,8,18,8z M14,16c-1.1,0-2,0.9-2,2c0,1.1,0.9,2,2,2s2-0.9,2-2C16,16.9,15.1,16,14,16z M18,12c-1.1,0-2,0.9-2,2c0,1.1,0.9,2,2,2s2-0.9,2-2C20,12.9,19.1,12,18,12z M14,8c-1.1,0-2,0.9-2,2c0,1.1,0.9,2,2,2s2-0.9,2-2C16,8.9,15.1,8,14,8z M10,4C8.9,4,8,4.9,8,6c0,1.1,0.9,2,2,2s2-0.9,2-2C12,4.9,11.1,4,10,4z"/></g> +<g id="grid-off"><path d="M8,4v1.5l2,2V4h4v4h-3.5l2,2H14v1.5l2,2V10h4v4h-3.5l2,2H20v1.5l2,2V4c0-1.1-0.9-2-2-2H4.5l2,2H8z M16,4h4v4h-4V4z M21.4,21.4L21.4,21.4L20,20L4,4L2.6,2.6L1.3,1.3L0,2.5l2,2V20c0,1.1,0.9,2,2,2h15.5l2,2l1.3-1.3L21.4,21.4z M10,12.5l1.5,1.5H10V12.5z M4,6.5L5.5,8H4V6.5z M8,20l-4,0v-4h4V20z M8,14H4v-4h3.5L8,10.5V14z M14,20l-4,0v-4h3.5l0.5,0.5V20z M16,20v-1.5l1.5,1.5L16,20z"/></g> +<g id="grid-on"><path d="M20,2H4C2.9,2,2,2.9,2,4v16c0,1.1,0.9,2,2,2h16c1.1,0,2-0.9,2-2V4C22,2.9,21.1,2,20,2z M8,20l-4,0v-4h4V20z M8,14H4v-4h4V14z M8,8H4V4h4V8z M14,20l-4,0v-4h4V20z M14,14h-4v-4h4V14z M14,8h-4V4h4V8z M20,20l-4,0v-4h4V20z M20,14h-4v-4h4V14z M20,8h-4V4h4V8z"/></g> +<g id="hdr-off"><path d="M20.7,11.8c0.2-0.2,0.3-0.6,0.3-1c0-0.2,0-0.4-0.1-0.6c0-0.2-0.1-0.3-0.2-0.4s-0.2-0.2-0.3-0.3c-0.1-0.1-0.3-0.1-0.5-0.1h-1.1v2.7h1.1C20.3,12.2,20.5,12.1,20.7,11.8z"/><path d="M11.6,15.5c0.3,0,0.8,0,1-0.1c0.2-0.1,0.4-0.2,0.5-0.4c0,0,0,0,0,0l-2.3-2.3v2.9H11.6z"/><path d="M15.3,11.8c0-0.6-0.1-1.1-0.3-1.6c-0.2-0.5-0.4-0.9-0.7-1.2c-0.3-0.3-0.7-0.6-1.1-0.7S12.4,8,11.8,8h-0.5l4,4V11.8z M2.5,4.3L6.2,8h-1v3.6H2.8V8H1v9h1.8v-3.9h2.4V17H7V8.8l2,2V17h2.6c0.5,0,1.2-0.1,1.6-0.3c0.4-0.2,0.7-0.4,1-0.7l4.9,4.9l1.3-1.3L3.8,3L2.5,4.3z M10.8,12.6l2.3,2.3c0,0,0,0,0,0c-0.1,0.2-0.3,0.3-0.5,0.4c-0.2,0.1-0.7,0.1-1,0.1h-0.8V12.6z M21.5,13.2c0.2-0.1,0.4-0.2,0.5-0.4c0.2-0.2,0.3-0.3,0.4-0.5c0.1-0.2,0.2-0.4,0.3-0.7c0.1-0.3,0.1-0.6,0.1-0.9c0-0.4-0.1-0.8-0.2-1.2c-0.1-0.3-0.3-0.6-0.6-0.8s-0.5-0.4-0.9-0.5C20.7,8.1,20.3,8,19.9,8H17v5.7l1.8,1.8v-1.8h0.9l1.4,3.3H23v-0.1L21.5,13.2z M20.7,11.8c-0.2,0.2-0.5,0.4-0.8,0.4h-1.1V9.5H20c0.2,0,0.3,0,0.5,0.1c0.1,0.1,0.2,0.2,0.3,0.3s0.1,0.3,0.2,0.4c0,0.2,0.1,0.4,0.1,0.6C21,11.3,20.9,11.6,20.7,11.8z"/></g> +<g id="hdr-on"><path d="M5.2,11.6H2.8V8H1v9h1.8v-3.9h2.4V17H7V8H5.2V11.6z M14.3,9c-0.3-0.3-0.7-0.6-1.1-0.7S12.4,8,11.8,8H9v9h2.6c0.5,0,1.2-0.1,1.6-0.3c0.4-0.2,0.8-0.4,1.1-0.7c0.3-0.3,0.5-0.7,0.7-1.2c0.2-0.5,0.2-1,0.2-1.6v-1.4c0-0.6-0.1-1.1-0.3-1.6C14.9,9.7,14.6,9.3,14.3,9z M13.5,13.2c0,0.4,0,0.8-0.1,1c-0.1,0.3-0.1,0.5-0.3,0.7s-0.3,0.3-0.5,0.4c-0.2,0.1-0.7,0.1-1,0.1h-0.8v-6h1c0.3,0,0.6,0,0.8,0.1c0.2,0.1,0.4,0.2,0.5,0.4c0.1,0.2,0.2,0.4,0.3,0.7c0.1,0.3,0.1,0.6,0.1,1.1V13.2z M21.5,13.2c0.2-0.1,0.4-0.2,0.5-0.4c0.2-0.2,0.3-0.3,0.4-0.5c0.1-0.2,0.2-0.4,0.3-0.7c0.1-0.3,0.1-0.6,0.1-0.9c0-0.4-0.1-0.8-0.2-1.2c-0.1-0.3-0.3-0.6-0.6-0.8s-0.5-0.4-0.9-0.5C20.7,8.1,20.3,8,19.9,8H17v9h1.8v-3.3h0.9l1.4,3.3H23v-0.1L21.5,13.2z M20.7,11.8c-0.2,0.2-0.5,0.4-0.8,0.4h-1.1V9.5H20c0.2,0,0.3,0,0.5,0.1c0.1,0.1,0.2,0.2,0.3,0.3s0.1,0.3,0.2,0.4c0,0.2,0.1,0.4,0.1,0.6C21,11.3,20.9,11.6,20.7,11.8z"/></g> +<g id="hdr-plus-off"><path d="M16.5,16h0.1v-0.1l-1.2-2.9c0.2-0.1,0.3-0.2,0.4-0.3c0.1-0.1,0.2-0.3,0.3-0.4c0.1-0.2,0.2-0.3,0.2-0.5c0-0.2,0.1-0.4,0.1-0.7c0-0.3-0.1-0.7-0.2-0.9c-0.1-0.3-0.2-0.5-0.4-0.7c-0.2-0.2-0.4-0.3-0.7-0.4C14.9,9,14.6,9,14.3,9H12v2.5L16.5,16z M13.4,10.2h0.9c0.1,0,0.3,0,0.4,0.1c0.1,0,0.2,0.1,0.3,0.2c0.1,0.1,0.1,0.2,0.1,0.3c0,0.1,0,0.3,0,0.4c0,0.3-0.1,0.6-0.2,0.8c-0.1,0.2-0.4,0.3-0.6,0.3h-0.9V10.2z M12,14l-1-1l-1.4-1.4l-1.4-1.4L2.3,4.3L1,5.5L4.5,9H3.6v2.8H1.4V9H0v7h1.4v-3h2.2v3H5V9.5l1.1,1.1V16h2c0.4,0,0.9-0.1,1.3-0.2c0.3-0.1,0.6-0.3,0.9-0.6c0.1-0.1,0.1-0.2,0.2-0.2l5,5l1.3-1.3l-3.3-3.3L12,14z M9.3,14.4c-0.1,0.1-0.2,0.2-0.4,0.3c-0.2,0.1-0.5,0.1-0.8,0.1H7.5v-2.8l2,2C9.4,14.2,9.4,14.3,9.3,14.4z M21,12.5v-2h-1.5v2h-2V14h2v2H21v-2h2v-1.5H21z"/></g> +<g id="hdr-plus-on"><path d="M15.9,12.8c0.1-0.1,0.2-0.3,0.3-0.4c0.1-0.2,0.2-0.3,0.2-0.5c0-0.2,0.1-0.4,0.1-0.7c0-0.3-0.1-0.7-0.2-0.9c-0.1-0.3-0.2-0.5-0.4-0.7c-0.2-0.2-0.4-0.3-0.7-0.4C14.9,9,14.6,9,14.3,9H12v7h1.4v-2.6h0.7l1.1,2.6h1.5v-0.1l-1.2-2.9C15.6,13,15.8,12.9,15.9,12.8z M14.9,12c-0.1,0.2-0.4,0.3-0.6,0.3h-0.9v-2.1h0.9c0.1,0,0.3,0,0.4,0.1c0.1,0,0.2,0.1,0.3,0.2c0.1,0.1,0.1,0.2,0.1,0.3c0,0.1,0,0.3,0,0.4C15.1,11.5,15,11.8,14.9,12z M21,12.5v-2h-1.5v2h-2V14h2v2H21v-2h2v-1.5H21z M3.6,11.8H1.4V9H0v7h1.4v-3h2.2v3H5V9H3.6V11.8z M10.3,9.8C10,9.5,9.7,9.3,9.4,9.2S8.7,9,8.3,9H6.1v7h2c0.4,0,0.9-0.1,1.3-0.2c0.3-0.1,0.6-0.3,0.9-0.6c0.2-0.3,0.4-0.6,0.5-0.9c0.1-0.4,0.2-0.8,0.2-1.3V12c0-0.5-0.1-0.9-0.2-1.3S10.5,10,10.3,9.8z M9.6,13c0,0.3,0,0.6-0.1,0.8c0,0.2-0.1,0.4-0.2,0.6c-0.1,0.1-0.2,0.2-0.4,0.3c-0.2,0.1-0.5,0.1-0.8,0.1H7.5v-4.6h0.8c0.2,0,0.4,0,0.6,0.1c0.2,0.1,0.3,0.2,0.4,0.3c0.1,0.1,0.2,0.3,0.2,0.5c0,0.2,0.1,0.5,0.1,0.8V13z"/></g> +<g id="hdr-strong"><path d="M17,6c-3.3,0-6,2.7-6,6s2.7,6,6,6s6-2.7,6-6S20.3,6,17,6z"/><path d="M5,8c-2.2,0-4,1.8-4,4s1.8,4,4,4s4-1.8,4-4S7.2,8,5,8z M5,14c-1.1,0-2-0.9-2-2s0.9-2,2-2s2,0.9,2,2S6.1,14,5,14z"/></g> +<g id="hdr-weak"><path d="M5,8c-2.2,0-4,1.8-4,4s1.8,4,4,4s4-1.8,4-4S7.2,8,5,8z M17,6c-3.3,0-6,2.7-6,6s2.7,6,6,6s6-2.7,6-6S20.3,6,17,6z M17,16c-2.2,0-4-1.8-4-4s1.8-4,4-4c2.2,0,4,1.8,4,4S19.2,16,17,16z"/></g> +<g id="healing"><path d="M17.7,12l4-4c0.4-0.4,0.4-1,0-1.4l-4.3-4.3c-0.4-0.4-1-0.4-1.4,0l-4,4l-4-4C7.8,2.1,7.5,2,7.3,2S6.8,2.1,6.6,2.3L2.3,6.6C1.9,7,1.9,7.7,2.3,8l4,4l-4,4c-0.4,0.4-0.4,1,0,1.4l4.3,4.3c0.4,0.4,1,0.4,1.4,0l4-4l4,4c0.2,0.2,0.5,0.3,0.7,0.3c0.3,0,0.5-0.1,0.7-0.3l4.3-4.3c0.4-0.4,0.4-1,0-1.4L17.7,12z M12,9c0.6,0,1,0.4,1,1s-0.4,1-1,1c-0.6,0-1-0.4-1-1S11.4,9,12,9z M7.3,11L3.7,7.3l3.6-3.6l3.6,3.6L7.3,11z M10,13c-0.6,0-1-0.4-1-1s0.4-1,1-1c0.6,0,1,0.4,1,1S10.6,13,10,13z M12,15c-0.6,0-1-0.4-1-1s0.4-1,1-1c0.6,0,1,0.4,1,1S12.6,15,12,15z M14,11c0.6,0,1,0.4,1,1s-0.4,1-1,1c-0.6,0-1-0.4-1-1S13.4,11,14,11z M16.7,20.3L13,16.7l3.6-3.6l3.6,3.6L16.7,20.3z"/></g> +<g id="image"><path d="M21,19V5c0-1.1-0.9-2-2-2H5C3.9,3,3,3.9,3,5v14c0,1.1,0.9,2,2,2h14C20.1,21,21,20.1,21,19z M8.5,13.5l2.5,3l3.5-4.5l4.5,6H5L8.5,13.5z"/></g> +<g id="iso"><path d="M19,3H5C3.9,3,3,3.9,3,5v14c0,1.1,0.9,2,2,2h14c1.1,0,2-0.9,2-2V5C21,3.9,20.1,3,19,3z M5.5,7.5h2v-2H9v2h2V9H9v2H7.5V9h-2V7.5z M19,19L5,19L19,5V19z M17,17v-1.5h-5V17H17z"/></g> +<g id="landscape"><path d="M14,6l-3.8,5l2.9,3.8L11.5,16C9.8,13.8,7,10,7,10l-6,8h22L14,6z"/></g> +<g id="movie-creation"><path d="M18,4l2,4h-3l-2-4h-2l2,4h-3l-2-4H8l2,4H7L5,4H4C2.9,4,2,4.9,2,6l0,12c0,1.1,0.9,2,2,2h16c1.1,0,2-0.9,2-2V4H18z"/></g> +<g id="palette"><path d="M12,3c-5,0-9,4-9,9s4,9,9,9c0.8,0,1.5-0.7,1.5-1.5c0-0.4-0.1-0.7-0.4-1c-0.2-0.3-0.4-0.6-0.4-1c0-0.8,0.7-1.5,1.5-1.5H16c2.8,0,5-2.2,5-5C21,6.6,17,3,12,3z M6.5,12C5.7,12,5,11.3,5,10.5S5.7,9,6.5,9C7.3,9,8,9.7,8,10.5S7.3,12,6.5,12z M9.5,8C8.7,8,8,7.3,8,6.5S8.7,5,9.5,5C10.3,5,11,5.7,11,6.5S10.3,8,9.5,8z M14.5,8C13.7,8,13,7.3,13,6.5S13.7,5,14.5,5C15.3,5,16,5.7,16,6.5S15.3,8,14.5,8z M17.5,12c-0.8,0-1.5-0.7-1.5-1.5S16.7,9,17.5,9c0.8,0,1.5,0.7,1.5,1.5S18.3,12,17.5,12z"/></g> +<g id="panorama"><polygon points="21,13.5 21,13.5 21,13.5 "/></g> +<g id="panorama-fisheye"><path d="M12,2C6.5,2,2,6.5,2,12s4.5,10,10,10c5.5,0,10-4.5,10-10S17.5,2,12,2z M12,20c-4.4,0-8-3.6-8-8s3.6-8,8-8s8,3.6,8,8S16.4,20,12,20z"/></g> +<g id="panorama-horizontal"><path d="M20,6.5v10.9c-2.6-0.8-5.3-1.2-8-1.2c-2.7,0-5.4,0.4-8,1.2V6.5c2.6,0.8,5.3,1.2,8,1.2C14.7,7.7,17.4,7.3,20,6.5 M21.4,4c-0.1,0-0.2,0-0.3,0.1c-2.9,1.1-6,1.6-9.1,1.6S5.8,5.2,2.9,4.1C2.8,4,2.7,4,2.6,4C2.2,4,2,4.2,2,4.6v14.7C2,19.8,2.2,20,2.6,20c0.1,0,0.2,0,0.3-0.1c2.9-1.1,6-1.6,9.1-1.6s6.2,0.5,9.1,1.6c0.1,0,0.2,0.1,0.3,0.1c0.3,0,0.6-0.2,0.6-0.6V4.6C22,4.2,21.8,4,21.4,4L21.4,4z"/></g> +<g id="panorama-vertical"><path d="M19.9,21.1c-1.1-2.9-1.6-6-1.6-9.1s0.5-6.2,1.6-9.1C20,2.8,20,2.7,20,2.6C20,2.2,19.8,2,19.4,2H4.6C4.2,2,4,2.2,4,2.6c0,0.1,0,0.2,0.1,0.3c1.1,2.9,1.6,6,1.6,9.1s-0.5,6.2-1.6,9.1C4,21.2,4,21.3,4,21.4C4,21.8,4.2,22,4.6,22h14.7c0.4,0,0.6-0.2,0.6-0.6C20,21.3,20,21.2,19.9,21.1z M6.5,20c0.8-2.6,1.2-5.3,1.2-8c0-2.7-0.4-5.4-1.2-8h10.9c-0.8,2.6-1.2,5.3-1.2,8c0,2.7,0.4,5.4,1.2,8H6.5z"/></g> +<g id="panorama-wide-angle"><path d="M12,6c2.4,0,4.7,0.2,7.3,0.6C19.8,8.4,20,10.2,20,12s-0.2,3.6-0.7,5.4C16.7,17.8,14.4,18,12,18s-4.7-0.2-7.3-0.6C4.2,15.6,4,13.8,4,12s0.2-3.6,0.7-5.4C7.3,6.2,9.6,6,12,6 M12,4C9.3,4,6.8,4.2,4,4.7L3.1,4.9L2.9,5.8C2.3,7.9,2,9.9,2,12s0.3,4.1,0.9,6.2l0.3,0.9L4,19.3c2.7,0.5,5.2,0.7,8,0.7s5.2-0.2,8-0.7l0.9-0.2l0.3-0.9c0.6-2.1,0.9-4.1,0.9-6.2s-0.3-4.1-0.9-6.2l-0.3-0.9L20,4.7C17.2,4.2,14.7,4,12,4L12,4z"/></g> +<g id="photo"><path d="M21,19V5c0-1.1-0.9-2-2-2H5C3.9,3,3,3.9,3,5v14c0,1.1,0.9,2,2,2h14C20.1,21,21,20.1,21,19z M8.5,13.5l2.5,3l3.5-4.5l4.5,6H5L8.5,13.5z"/></g> +<g id="photo-album"><path d="M18,2H6C4.9,2,4,2.9,4,4v16c0,1.1,0.9,2,2,2h12c1.1,0,2-0.9,2-2V4C20,2.9,19.1,2,18,2z M6,4h5v8l-2.5-1.5L6,12V4z M6,19l3-3.9l2.1,2.6l3-3.9L18,19H6z"/></g> +<g id="photo-library"><path d="M22,16V4c0-1.1-0.9-2-2-2H8C6.9,2,6,2.9,6,4v12c0,1.1,0.9,2,2,2h12C21.1,18,22,17.1,22,16z M11,12l2,2.7l3-3.7l4,5H8L11,12z M2,6v14c0,1.1,0.9,2,2,2h14v-2H4V6H2z"/></g> +<g id="photosphere"><path d="M22.1,7.6C20.4,3.7,16.5,1,12,1S3.6,3.7,1.9,7.6C1.3,7.9,0.6,8.2,0,8.5v7c0.6,0.3,1.3,0.6,1.9,0.9C3.6,20.3,7.5,23,12,23s8.4-2.7,10.1-6.6c0.7-0.3,1.3-0.6,1.9-0.9v-7C23.4,8.2,22.7,7.9,22.1,7.6z M19.9,6.8c-1.2-0.4-2.5-0.7-3.8-0.9c-0.4-1.1-0.8-2.1-1.3-2.9C16.9,3.6,18.7,5,19.9,6.8z M12,2.5c0.8,0,1.8,1.1,2.5,3.1c-0.8-0.1-1.7-0.1-2.5-0.1s-1.7,0.1-2.5,0.1C10.2,3.6,11.2,2.5,12,2.5z M9.2,2.9c-0.5,0.8-1,1.8-1.3,2.9C6.6,6.1,5.3,6.4,4.1,6.8C5.3,5,7.1,3.6,9.2,2.9z M4.1,17.2c1.2,0.4,2.5,0.7,3.8,0.9c0.4,1.1,0.8,2.1,1.3,2.9C7.1,20.4,5.3,19,4.1,17.2z M12,21.5c-0.8,0-1.8-1.1-2.5-3.1c0.8,0.1,1.7,0.1,2.5,0.1s1.7-0.1,2.5-0.1C13.8,20.4,12.8,21.5,12,21.5z M14.8,21.1c0.5-0.8,1-1.8,1.3-2.9c1.3-0.2,2.5-0.5,3.8-0.9C18.7,19,16.9,20.4,14.8,21.1z M22.5,14.6l-0.3,0.1c-1.1,0.5-2.2,0.9-3.4,1.3L15,11.6L12,15l-4-5l-4.4,5.5C3,15.2,2.4,15,1.8,14.7l-0.3-0.1V9.4l0.3-0.1c6.4-3,14-3,20.4,0l0.3,0.1V14.6z"/></g> +<g id="portrait"><path d="M12,12.2c1.2,0,2.2-1,2.2-2.2c0-1.2-1-2.2-2.2-2.2c-1.2,0-2.2,1-2.2,2.2C9.8,11.2,10.8,12.2,12,12.2z M16.5,16.2c0-1.5-3-2.2-4.5-2.2s-4.5,0.8-4.5,2.2V17h9V16.2z M19,3H5C3.9,3,3,3.9,3,5v14c0,1.1,0.9,2,2,2h14c1.1,0,2-0.9,2-2V5C21,3.9,20.1,3,19,3z M19,19L5,19V5h14V19z"/></g> +<g id="slideshow"><path d="M10,8v8l5-4L10,8z M19,3H5C3.9,3,3,3.9,3,5v14c0,1.1,0.9,2,2,2h14c1.1,0,2-0.9,2-2V5C21,3.9,20.1,3,19,3z M19,19L5,19V5h14V19z"/></g> +<g id="switch-camera"><path d="M20,4h-3.2L15,2H9L7.2,4H4C2.9,4,2,4.9,2,6v12c0,1.1,0.9,2,2,2h16c1.1,0,2-0.9,2-2V6C22,4.9,21.1,4,20,4z M15,15.5V13H9v2.5L5.5,12L9,8.5V11h6V8.5l3.5,3.5L15,15.5z"/></g> +<g id="switch-video"><path d="M18,9.5V6c0-0.6-0.4-1-1-1H3C2.4,5,2,5.4,2,6v12c0,0.6,0.4,1,1,1h14c0.6,0,1-0.4,1-1v-3.5l4,4v-13L18,9.5z M13,15.5V13H7v2.5L3.5,12L7,8.5V11h6V8.5l3.5,3.5L13,15.5z"/></g> +<g id="tag-faces"><path d="M12,2C6.5,2,2,6.5,2,12s4.5,10,10,10c5.5,0,10-4.5,10-10S17.5,2,12,2z M12,20c-4.4,0-8-3.6-8-8s3.6-8,8-8c4.4,0,8,3.6,8,8S16.4,20,12,20z M15.5,11c0.8,0,1.5-0.7,1.5-1.5S16.3,8,15.5,8C14.7,8,14,8.7,14,9.5S14.7,11,15.5,11z M8.5,11c0.8,0,1.5-0.7,1.5-1.5S9.3,8,8.5,8C7.7,8,7,8.7,7,9.5S7.7,11,8.5,11z M12,17.5c2.3,0,4.3-1.5,5.1-3.5H6.9C7.7,16,9.7,17.5,12,17.5z"/></g> +<g id="timelapse"><path d="M16.2,7.8C15.1,6.6,13.5,6,12,6v6l-4.2,4.2c2.3,2.3,6.1,2.3,8.5,0C18.6,13.9,18.6,10.1,16.2,7.8z M12,2C6.5,2,2,6.5,2,12c0,5.5,4.5,10,10,10c5.5,0,10-4.5,10-10C22,6.5,17.5,2,12,2z M12,20c-4.4,0-8-3.6-8-8c0-4.4,3.6-8,8-8c4.4,0,8,3.6,8,8C20,16.4,16.4,20,12,20z"/></g> +<g id="timer-10"><path d="M0,7.7v1.7l3-1V18h2V6H4.7L0,7.7z M23.8,14.4c-0.1-0.3-0.4-0.5-0.6-0.7c-0.3-0.2-0.6-0.4-1-0.5s-0.8-0.3-1.4-0.4c-0.3-0.1-0.6-0.2-0.9-0.2c-0.2-0.1-0.4-0.2-0.5-0.3c-0.1-0.1-0.2-0.2-0.3-0.3C19,11.8,19,11.7,19,11.6s0-0.3,0.1-0.4c0.1-0.1,0.1-0.2,0.3-0.3c0.1-0.1,0.3-0.2,0.5-0.2c0.2-0.1,0.4-0.1,0.6-0.1c0.3,0,0.5,0,0.7,0.1c0.2,0.1,0.3,0.2,0.5,0.3c0.1,0.1,0.2,0.3,0.3,0.4c0.1,0.2,0.1,0.3,0.1,0.5h1.9c0-0.4-0.1-0.8-0.2-1.1S23.3,10,23,9.8s-0.7-0.4-1.1-0.6C21.5,9.1,21,9,20.5,9c-0.5,0-1,0.1-1.4,0.2c-0.4,0.1-0.8,0.3-1.1,0.6c-0.3,0.2-0.5,0.5-0.7,0.8c-0.2,0.3-0.2,0.7-0.2,1c0,0.4,0.1,0.7,0.2,1c0.2,0.3,0.4,0.5,0.6,0.7c0.3,0.2,0.6,0.4,1,0.5c0.4,0.1,0.8,0.3,1.3,0.4c0.4,0.1,0.7,0.2,1,0.3c0.2,0.1,0.4,0.2,0.6,0.3S22,15,22,15.1c0,0.1,0.1,0.2,0.1,0.4c0,0.3-0.1,0.6-0.4,0.8c-0.3,0.2-0.7,0.3-1.2,0.3c-0.2,0-0.4,0-0.6-0.1c-0.2-0.1-0.4-0.1-0.6-0.2S19,16,18.9,15.8c-0.1-0.2-0.2-0.4-0.2-0.7h-1.9c0,0.4,0.1,0.7,0.2,1.1c0.2,0.3,0.4,0.7,0.7,0.9c0.3,0.3,0.7,0.5,1.2,0.7s1,0.3,1.6,0.3c0.5,0,1-0.1,1.4-0.2c0.4-0.1,0.8-0.3,1.1-0.5c0.3-0.2,0.5-0.5,0.7-0.8s0.2-0.7,0.2-1.1C24,15,23.9,14.6,23.8,14.4z M13.8,7c-0.3-0.4-0.7-0.7-1.2-0.9c-0.5-0.2-1-0.3-1.6-0.3c-0.6,0-1.1,0.1-1.6,0.3C8.9,6.3,8.5,6.6,8.2,7C7.8,7.5,7.6,8,7.4,8.6C7.2,9.3,7.1,10.1,7.1,11v1.9c0,0.9,0.1,1.7,0.3,2.4c0.2,0.7,0.5,1.2,0.8,1.6c0.3,0.4,0.8,0.7,1.2,0.9s1,0.3,1.6,0.3c0.6,0,1.1-0.1,1.6-0.3c0.5-0.2,0.9-0.5,1.2-0.9c0.3-0.4,0.6-0.9,0.8-1.6c0.2-0.7,0.3-1.5,0.3-2.4V11c0-0.9-0.1-1.7-0.3-2.4C14.4,8,14.2,7.5,13.8,7z M12.9,13.2c0,0.6,0,1.1-0.1,1.5c-0.1,0.4-0.2,0.8-0.4,1c-0.2,0.3-0.4,0.5-0.6,0.6c-0.2,0.1-0.5,0.2-0.8,0.2c-0.3,0-0.6-0.1-0.8-0.2C10,16.2,9.8,16,9.6,15.8c-0.2-0.3-0.3-0.6-0.4-1c-0.1-0.4-0.1-0.9-0.1-1.5v-2.5c0-0.6,0-1.1,0.1-1.5c0.1-0.4,0.2-0.7,0.4-1C9.7,8,9.9,7.8,10.2,7.7c0.2-0.1,0.5-0.2,0.8-0.2c0.3,0,0.6,0.1,0.8,0.2C12,7.8,12.2,8,12.4,8.2c0.2,0.3,0.3,0.6,0.4,1c0.1,0.4,0.1,0.9,0.1,1.5V13.2z"/></g> +<g id="timer"><path d="M15,1H9v2h6V1z M11,14h2V8h-2V14z M19,7.4L20.5,6C20,5.5,19.5,5,19,4.5L17.6,6c-1.5-1.2-3.5-2-5.6-2c-5,0-9,4-9,9c0,5,4,9,9,9s9-4,9-9C21,10.9,20.3,8.9,19,7.4z M12,20c-3.9,0-7-3.1-7-7c0-3.9,3.1-7,7-7c3.9,0,7,3.1,7,7C19,16.9,15.9,20,12,20z"/></g> +<g id="timer-3"><path d="M11.6,13c-0.2-0.2-0.4-0.5-0.6-0.7c-0.3-0.2-0.6-0.4-0.9-0.5c0.3-0.1,0.6-0.3,0.8-0.5c0.2-0.2,0.4-0.4,0.6-0.6c0.2-0.2,0.3-0.5,0.3-0.7c0.1-0.2,0.1-0.5,0.1-0.7c0-0.6-0.1-1-0.3-1.5c-0.2-0.4-0.4-0.8-0.8-1.1c-0.3-0.3-0.7-0.5-1.2-0.6C9.2,6,8.7,5.9,8.1,5.9C7.5,5.9,7,6,6.6,6.1S5.7,6.5,5.4,6.8C5,7.1,4.8,7.5,4.6,7.9C4.4,8.3,4.3,8.7,4.3,9.2h2c0-0.3,0-0.5,0.1-0.7c0.1-0.2,0.2-0.4,0.4-0.5C7,7.8,7.2,7.7,7.4,7.6c0.2-0.1,0.5-0.1,0.7-0.1c0.6,0,1.1,0.2,1.4,0.5c0.3,0.3,0.4,0.8,0.4,1.3c0,0.3,0,0.5-0.1,0.7c-0.1,0.2-0.2,0.4-0.4,0.6C9.2,10.7,9,10.9,8.8,11c-0.2,0.1-0.5,0.1-0.9,0.1H6.7v1.6h1.2c0.3,0,0.6,0,0.9,0.1c0.3,0.1,0.5,0.2,0.7,0.4c0.2,0.2,0.3,0.4,0.4,0.6c0.1,0.2,0.2,0.5,0.2,0.9c0,0.6-0.2,1.1-0.5,1.4c-0.4,0.3-0.8,0.5-1.5,0.5c-0.3,0-0.6,0-0.8-0.1c-0.2-0.1-0.4-0.2-0.6-0.4c-0.2-0.2-0.3-0.3-0.4-0.6c-0.1-0.2-0.1-0.5-0.1-0.7h-2c0,0.5,0.1,1,0.3,1.5c0.2,0.4,0.5,0.8,0.9,1c0.4,0.3,0.8,0.5,1.2,0.6s1,0.2,1.5,0.2c0.6,0,1.1-0.1,1.6-0.2c0.5-0.2,0.9-0.4,1.3-0.7c0.4-0.3,0.6-0.7,0.8-1.1c0.2-0.4,0.3-0.9,0.3-1.5c0-0.3,0-0.6-0.1-0.9C11.9,13.5,11.8,13.2,11.6,13z M20.9,14.4c-0.1-0.3-0.4-0.5-0.6-0.7s-0.6-0.4-1-0.5c-0.4-0.1-0.8-0.3-1.4-0.4c-0.3-0.1-0.6-0.2-0.9-0.2c-0.2-0.1-0.4-0.2-0.5-0.3c-0.1-0.1-0.2-0.2-0.3-0.3c-0.1-0.1-0.1-0.2-0.1-0.4s0-0.3,0.1-0.4c0.1-0.1,0.1-0.2,0.3-0.3c0.1-0.1,0.3-0.2,0.5-0.2c0.2-0.1,0.4-0.1,0.6-0.1c0.3,0,0.5,0,0.7,0.1c0.2,0.1,0.3,0.2,0.5,0.3c0.1,0.1,0.2,0.3,0.3,0.4c0.1,0.2,0.1,0.3,0.1,0.5H21c0-0.4-0.1-0.8-0.2-1.1c-0.2-0.3-0.4-0.6-0.7-0.9S19.4,9.4,19,9.2C18.6,9.1,18.1,9,17.6,9c-0.5,0-1,0.1-1.4,0.2c-0.4,0.1-0.8,0.3-1.1,0.6s-0.5,0.5-0.7,0.8c-0.2,0.3-0.2,0.7-0.2,1c0,0.4,0.1,0.7,0.2,1c0.2,0.3,0.4,0.5,0.6,0.7c0.3,0.2,0.6,0.4,1,0.5c0.4,0.1,0.8,0.3,1.3,0.4c0.4,0.1,0.7,0.2,1,0.3c0.2,0.1,0.4,0.2,0.6,0.3s0.2,0.2,0.3,0.3c0,0.1,0.1,0.2,0.1,0.4c0,0.3-0.1,0.6-0.4,0.8c-0.3,0.2-0.7,0.3-1.2,0.3c-0.2,0-0.4,0-0.6-0.1c-0.2-0.1-0.4-0.1-0.6-0.2c-0.2-0.1-0.3-0.3-0.4-0.4c-0.1-0.2-0.2-0.4-0.2-0.7h-1.9c0,0.4,0.1,0.7,0.2,1.1c0.2,0.3,0.4,0.7,0.7,0.9c0.3,0.3,0.7,0.5,1.2,0.7s1,0.3,1.6,0.3c0.5,0,1-0.1,1.4-0.2c0.4-0.1,0.8-0.3,1.1-0.5c0.3-0.2,0.5-0.5,0.7-0.8c0.2-0.3,0.2-0.7,0.2-1.1C21.1,15,21,14.6,20.9,14.4z"/></g> +<g id="timer-auto"><path d="M12,4C9.8,4,8,5.8,8,8c0,2.2,1.8,4,4,4c2.2,0,4-1.8,4-4C16,5.8,14.2,4,12,4L12,4z M12,14c-2.7,0-8,1.3-8,4v2h16v-2C20,15.3,14.7,14,12,14L12,14z"/></g> +<g id="timer-off"><path d="M19,4.5L17.6,6c-1.5-1.2-3.5-2-5.6-2C10.2,4,8.5,4.5,7,5.5l1.5,1.5C9.5,6.3,10.7,6,12,6c3.9,0,7,3.1,7,7c0,1.3-0.3,2.5-0.9,3.5l1.5,1.5c0.9-1.4,1.5-3.1,1.5-4.9c0-2.1-0.7-4.1-2-5.6L20.5,6L19,4.5z M15,1H9v2h6V1z M11,9.4l2,2V8h-2V9.4z M3,4L1.7,5.3L4.5,8C3.6,9.5,3,11.2,3,13c0,5,4,9,9,9c1.8,0,3.6-0.6,5-1.5l2.5,2.5l1.3-1.3L13,14L3,4z M12,20c-3.9,0-7-3.1-7-7c0-1.3,0.4-2.5,1-3.5l9.6,9.6C14.5,19.6,13.3,20,12,20z"/></g> +<g id="unknown-1"><path d="M19,3H5C3.9,3,3,3.9,3,5v14c0,1.1,0.9,2,2,2h14c1.1,0,2-0.9,2-2V5C21,3.9,20.1,3,19,3z M5.5,7.5h2v-2H9v2h2V9H9v2H7.5V9h-2V7.5z M19,19L5,19L19,5V19z M17,17v-1.5h-5V17H17z"/></g> +<g id="unknown-2"><path d="M12,16h5v-1.5h-5V16z M12,2C6.5,2,2,6.5,2,12s4.5,10,10,10c5.5,0,10-4.5,10-10C22,6.5,17.5,2,12,2z M6,8h2V6h1.5v2h2v1.5h-2v2H8v-2H6V8z M12,20c-2.2,0-4.2-0.9-5.7-2.3L17.7,6.3C19.1,7.8,20,9.8,20,12C20,16.4,16.4,20,12,20z"/></g> +<g id="unknown-3"><path d="M13,8h-2v3H8v2h3v3h2v-3h3v-2h-3V8z M12,2C6.5,2,2,6.5,2,12s4.5,10,10,10c5.5,0,10-4.5,10-10C22,6.5,17.5,2,12,2z M12,20c-4.4,0-8-3.6-8-8c0-4.4,3.6-8,8-8c4.4,0,8,3.6,8,8C20,16.4,16.4,20,12,20z"/></g> +<g id="unknown-4"><path d="M12,2C6.5,2,2,6.5,2,12s4.5,10,10,10c5.5,0,10-4.5,10-10C22,6.5,17.5,2,12,2z M12,20c-4.4,0-8-3.6-8-8c0-4.4,3.6-8,8-8c4.4,0,8,3.6,8,8C20,16.4,16.4,20,12,20z M8,13h8v-2H8V13z"/></g> +<g id="unknown-5"><path d="M12,10H4v2h8V10z M12,2L12,2l0,2c4.4,0,8,3.6,8,8c0,4.4-3.6,8-8,8c-2.2,0-4.2-0.9-5.7-2.3l-1.4,1.4C6.7,20.9,9.2,22,12,22c5.5,0,10-4.5,10-10C22,6.5,17.5,2,12,2z"/></g> +<g id="unknown-6"><path d="M16,10h-2v2h2V10z M16,14h-2v2h2V14z M8,10H6v2h2V10z M12,10h-2v2h2V10z M20,4H4C2.9,4,2,4.9,2,6v12c0,1.1,0.9,2,2,2h16c1.1,0,2-0.9,2-2V6C22,4.9,21.1,4,20,4z M20,18L4,18V6h16V18z"/></g> +<g id="unknown-7"><path d="M14,16h5v-5h3l-5.5-5.5L11,11h3V16z M11,20h11v-2H11V20z M5.5,7l-3.2,9h1.9l0.7-2h3.2l0.7,2h1.9L7.5,7H5.5z M5.4,12.6L6.5,9l1.1,3.6H5.4z"/></g> +<g id="warning"><path d="M1,21h22L12,2L1,21z M13,18h-2v-2h2V18z M13,14h-2v-4h2V14z"/></g> +<g id="wb-auto"><path d="M6.9,12.6h2.3L8,9L6.9,12.6z M22,7l-1.2,6.3L19.3,7h-1.6l-1.5,6.3L15,7h-0.8C12.8,5.2,10.5,4,8,4c-4.4,0-8,3.6-8,8s3.6,8,8,8c3.1,0,5.8-1.8,7.2-4.4l0.1,0.4H17l1.5-6.1L20,16h1.8l2-9H22z M10.3,16l-0.7-2H6.4l-0.7,2H3.8L7,7h2l3.2,9H10.3z"/></g> +<g id="wb-cloudy"><path d="M19.4,10c-0.7-3.4-3.7-6-7.4-6C9.1,4,6.6,5.6,5.4,8C2.3,8.4,0,10.9,0,14c0,3.3,2.7,6,6,6h13c2.8,0,5-2.2,5-5C24,12.4,21.9,10.2,19.4,10z"/></g> +<g id="wb-incandescent"><path d="M3.5,18.5L5,20l1.8-1.8l-1.4-1.4L3.5,18.5z M11,22.4c0.3,0,2,0,2,0v-2.9h-2V22.4z M4,10.5H1v2h3V10.5z M15,6.3V1.5H9v4.8c-1.8,1-3,3-3,5.2c0,3.3,2.7,6,6,6s6-2.7,6-6C18,9.3,16.8,7.3,15,6.3z M20,10.5v2h3v-2H20z M17.2,18.2L19,20l1.4-1.4l-1.8-1.8L17.2,18.2z"/></g> +<g id="wb-irradescent"><path d="M5,14.5h14v-6H5V14.5z M11,0.6v2.9h2V0.6H11z M19,3l-1.8,1.8l1.4,1.4l1.8-1.8L19,3z M13,22.4v-2.9h-2v2.9C11.3,22.5,13,22.4,13,22.4z M20.5,18.5l-1.8-1.8l-1.4,1.4L19,20L20.5,18.5z M3.5,4.5l1.8,1.8l1.4-1.4L5,3L3.5,4.5z M5,20l1.8-1.8l-1.4-1.4l-1.8,1.8L5,20z"/></g> +<g id="wb-sunny"><path d="M6.8,4.8L5,3L3.5,4.5l1.8,1.8L6.8,4.8z M4,10.5H1v2h3V10.5z M13,0.6h-2v2.9h2V0.6z M20.5,4.5L19,3l-1.8,1.8l1.4,1.4L20.5,4.5z M17.2,18.2L19,20l1.4-1.4l-1.8-1.8L17.2,18.2z M20,10.5v2h3v-2H20z M12,5.5c-3.3,0-6,2.7-6,6s2.7,6,6,6s6-2.7,6-6S15.3,5.5,12,5.5z M11,22.4c0.3,0,2,0,2,0v-2.9h-2V22.4z M3.5,18.5L5,20l1.8-1.8l-1.4-1.4L3.5,18.5z"/></g> +</defs></svg> +</core-iconset-svg> - function isValid(m) { - if (m._isValid == null) { - m._isValid = !isNaN(m._d.getTime()) && - m._pf.overflow < 0 && - !m._pf.empty && - !m._pf.invalidMonth && - !m._pf.nullInput && - !m._pf.invalidFormat && - !m._pf.userInvalidated; +<!-- +Copyright (c) 2014 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--> - if (m._strict) { - m._isValid = m._isValid && - m._pf.charsLeftOver === 0 && - m._pf.unusedTokens.length === 0; - } - } - return m._isValid; - } - function normalizeLocale(key) { - return key ? key.toLowerCase().replace('_', '-') : key; - } - // pick the locale from the array - // try ['en-au', 'en-gb'] as 'en-au', 'en-gb', 'en', as in move through the list trying each - // substring from most specific to least, but move to the next array item if it's a more specific variant than the current root - function chooseLocale(names) { - var i = 0, j, next, locale, split; +<core-iconset-svg id="hardware" iconsize="24"> +<svg><defs> +<g id="cast"><path d="M21,3H3C1.9,3,1,3.9,1,5v3h2V5h18v14h-7v2h7c1.1,0,2-0.9,2-2V5C23,3.9,22.1,3,21,3z M1,18v3h3C4,19.3,2.7,18,1,18z M1,14v2c2.8,0,5,2.2,5,5h2C8,17.1,4.9,14,1,14z M1,10v2c5,0,9,4,9,9h2C12,14.9,7.1,10,1,10z"/></g> +<g id="cast-connected"><path d="M1,18v3h3C4,19.3,2.7,18,1,18z M1,14v2c2.8,0,5,2.2,5,5h2C8,17.1,4.9,14,1,14z M19,7H5v1.6c4,1.3,7.1,4.4,8.4,8.4H19V7z M1,10v2c5,0,9,4,9,9h2C12,14.9,7.1,10,1,10z M21,3H3C1.9,3,1,3.9,1,5v3h2V5h18v14h-7v2h7c1.1,0,2-0.9,2-2V5C23,3.9,22.1,3,21,3z"/></g> +<g id="chromecast"><path d="M12,2C6.5,2,2,6.5,2,12s4.5,10,10,10c5.5,0,10-4.5,10-10S17.5,2,12,2z M12,4c3,0,5.5,1.6,6.9,4H12c-1.9,0-3.6,1.4-3.9,3.2L5.7,7.1C7.2,5.2,9.4,4,12,4z M15,12c0,1.7-1.3,3-3,3c-1.7,0-3-1.3-3-3c0-1.7,1.3-3,3-3C13.7,9,15,10.3,15,12z M4,12c0-1.5,0.4-2.8,1.1-4l3.5,6l0,0c0.7,1.2,2,2,3.4,2c0.5,0,0.9-0.1,1.3-0.2l-2.4,4.1C7,19.4,4,16,4,12z M12,20l3.5-6l0,0c0.3-0.6,0.6-1.3,0.6-2c0-1.2-0.5-2.3-1.4-3h4.8c0.4,0.9,0.6,1.9,0.6,3C20,16.4,16.4,20,12,20z"/></g> +<g id="desktop-mac"><path d="M21,2H3C1.9,2,1,2.9,1,4v12c0,1.1,0.9,2,2,2h7l-2,3v1h8v-1l-2-3h7c1.1,0,2-0.9,2-2V4C23,2.9,22.1,2,21,2z M21,14H3V4h18V14z"/></g> +<g id="desktop-windows"><path d="M21,2H3C1.9,2,1,2.9,1,4v12c0,1.1,0.9,2,2,2h7v2H8v2h8v-2h-2v-2h7c1.1,0,2-0.9,2-2V4C23,2.9,22.1,2,21,2z M21,16H3V4h18V16z"/></g> +<g id="dock"><path d="M8,23h8v-2H8V23z M16,1L8,1C6.9,1,6,1.9,6,3v14c0,1.1,0.9,2,2,2h8c1.1,0,2-0.9,2-2V3C18,1.9,17.1,1,16,1z M16,15H8V5h8V15z"/></g> +<g id="gamepad"><path d="M15,7.5V2H9v5.5l3,3L15,7.5z M7.5,9H2v6h5.5l3-3L7.5,9z M9,16.5V22h6v-5.5l-3-3L9,16.5z M16.5,9l-3,3l3,3H22V9H16.5z"/></g> +<g id="glass"><path d="M13,11v2.5h5.9c-0.6,3.5-3.4,6-6.9,6c-4.1,0-7.5-3.4-7.5-7.5S7.9,4.5,12,4.5c2.1,0,3.9,0.9,5.2,2.3l1.8-1.8C17.2,3.2,14.8,2,12,2C6.5,2,2,6.5,2,12s4.5,10,10,10c5.5,0,9.5-4.5,9.5-10v-1H13z"/></g> +<g id="headset"><path d="M12,1c-5,0-9,4-9,9v7c0,1.7,1.3,3,3,3h3v-8H5v-2c0-3.9,3.1-7,7-7c3.9,0,7,3.1,7,7v2h-4v8h3c1.7,0,3-1.3,3-3v-7C21,5,17,1,12,1z"/></g> +<g id="headset-mic"><path d="M12,1c-5,0-9,4-9,9v7c0,1.7,1.3,3,3,3h3v-8H5v-2c0-3.9,3.1-7,7-7c3.9,0,7,3.1,7,7v2h-4v8h4v1h-7v2h6c1.7,0,3-1.3,3-3V10C21,5,17,1,12,1z"/></g> +<g id="keyboard"><path d="M20,5H4C2.9,5,2,5.9,2,7l0,10c0,1.1,0.9,2,2,2h16c1.1,0,2-0.9,2-2V7C22,5.9,21.1,5,20,5z M11,8h2v2h-2V8z M11,11h2v2h-2V11z M8,8h2v2H8V8z M8,11h2v2H8V11z M7,13H5v-2h2V13z M7,10H5V8h2V10z M16,17H8v-2h8V17z M16,13h-2v-2h2V13z M16,10h-2V8h2V10z M19,13h-2v-2h2V13z M19,10h-2V8h2V10z"/></g> +<g id="keyboard-alt"><path d="M15.5,10c0.8,0,1.5-0.7,1.5-1.5S16.3,7,15.5,7S14,7.7,14,8.5S14.7,10,15.5,10z M8.5,10C9.3,10,10,9.3,10,8.5S9.3,7,8.5,7C7.7,7,7,7.7,7,8.5S7.7,10,8.5,10z M12,17c2.6,0,4.8-1.7,5.7-4H6.3C7.2,15.3,9.4,17,12,17z M12,1C6.5,1,2,5.5,2,11c0,5.5,4.5,10,10,10c5.5,0,10-4.5,10-10C22,5.5,17.5,1,12,1z M12,19c-4.4,0-8-3.6-8-8s3.6-8,8-8c4.4,0,8,3.6,8,8S16.4,19,12,19z"/></g> +<g id="keyboard-arrow-down"><polygon points="7.4,7.8 12,12.4 16.6,7.8 18,9.2 12,15.2 6,9.2 "/></g> +<g id="keyboard-arrow-left"><polygon points="15.4,16.1 10.8,11.5 15.4,6.9 14,5.5 8,11.5 14,17.5 "/></g> +<g id="keyboard-arrow-right"><polygon points="8.6,16.3 13.2,11.8 8.6,7.2 10,5.8 16,11.8 10,17.8 "/></g> +<g id="keyboard-arrow-up"><polygon points="7.4,15.4 12,10.8 16.6,15.4 18,14 12,8 6,14 "/></g> +<g id="keyboard-backspace"><polygon points="21,11 6.8,11 10.4,7.4 9,6 3,12 9,18 10.4,16.6 6.8,13 21,13 "/></g> +<g id="keyboard-capslock"><path d="M12,8.4l4.6,4.6l1.4-1.4l-6-6l-6,6L7.4,13L12,8.4z M6,18h12v-2H6V18z"/></g> +<g id="keyboard-control"><path d="M6,10c-1.1,0-2,0.9-2,2c0,1.1,0.9,2,2,2c1.1,0,2-0.9,2-2C8,10.9,7.1,10,6,10z M18,10c-1.1,0-2,0.9-2,2c0,1.1,0.9,2,2,2c1.1,0,2-0.9,2-2C20,10.9,19.1,10,18,10z M12,10c-1.1,0-2,0.9-2,2c0,1.1,0.9,2,2,2c1.1,0,2-0.9,2-2C14,10.9,13.1,10,12,10z"/></g> +<g id="keyboard-hide"><path d="M20,3H4C2.9,3,2,3.9,2,5l0,10c0,1.1,0.9,2,2,2h16c1.1,0,2-0.9,2-2V5C22,3.9,21.1,3,20,3z M11,6h2v2h-2V6z M11,9h2v2h-2V9z M8,6h2v2H8V6z M8,9h2v2H8V9z M7,11H5V9h2V11z M7,8H5V6h2V8z M16,15H8v-2h8V15z M16,11h-2V9h2V11z M16,8h-2V6h2V8z M19,11h-2V9h2V11z M19,8h-2V6h2V8z M12,23l4-4H8L12,23z"/></g> +<g id="keyboard-return"><polygon points="19,7 19,11 5.8,11 9.4,7.4 8,6 2,12 8,18 9.4,16.6 5.8,13 21,13 21,7 "/></g> +<g id="keyboard-tab"><path d="M11.6,7.4l3.6,3.6H1v2h14.2l-3.6,3.6L13,18l6-6l-6-6L11.6,7.4z M20,6v12h2V6H20z"/></g> +<g id="keyboard-voice"><path d="M12,15c1.7,0,3-1.3,3-3l0-6c0-1.7-1.3-3-3-3c-1.7,0-3,1.3-3,3v6C9,13.7,10.3,15,12,15z M17.3,12c0,3-2.5,5.1-5.3,5.1c-2.8,0-5.3-2.1-5.3-5.1H5c0,3.4,2.7,6.2,6,6.7V22h2v-3.3c3.3-0.5,6-3.3,6-6.7H17.3z"/></g> +<g id="laptop"><path d="M20,18c1.1,0,2-0.9,2-2l0-10c0-1.1-0.9-2-2-2H4C2.9,4,2,4.9,2,6v10c0,1.1,0.9,2,2,2H0v2h24v-2H20z M4,6h16v10H4V6z"/></g> +<g id="laptop-chromebook"><path d="M22,18V3H2v15H0v2h24v-2H22z M14,18h-4v-1h4V18z M20,15H4V5h16V15z"/></g> +<g id="laptop-mac"><path d="M20,18c1.1,0,2-0.9,2-2l0-11c0-1.1-0.9-2-2-2H4C2.9,3,2,3.9,2,5v11c0,1.1,0.9,2,2,2H0c0,1.1,0.9,2,2,2h20c1.1,0,2-0.9,2-2H20z M4,5h16v11H4V5z M12,19c-0.6,0-1-0.4-1-1s0.4-1,1-1c0.6,0,1,0.4,1,1S12.6,19,12,19z"/></g> +<g id="laptop-windows"><path d="M20,18v-1c1.1,0,2-0.9,2-2l0-10c0-1.1-0.9-2-2-2H4C2.9,3,2,3.9,2,5v10c0,1.1,0.9,2,2,2v1H0v2h24v-2H20z M4,5h16v10H4V5z"/></g> +<g id="memory"><path d="M15,9H9v6h6V9z M13,13h-2v-2h2V13z M21,11V9h-2V7c0-1.1-0.9-2-2-2h-2V3h-2v2h-2V3H9v2H7C5.9,5,5,5.9,5,7v2H3v2h2v2H3v2h2v2c0,1.1,0.9,2,2,2h2v2h2v-2h2v2h2v-2h2c1.1,0,2-0.9,2-2v-2h2v-2h-2v-2H21z M17,17H7V7h10V17z"/></g> +<g id="mouse"><path d="M13,1.1V9h7C20,4.9,16.9,1.6,13,1.1z M4,15c0,4.4,3.6,8,8,8c4.4,0,8-3.6,8-8v-4H4V15z M11,1.1C7.1,1.6,4,4.9,4,9h7V1.1z"/></g> +<g id="nest-protect"><path d="M19,3H5C3.9,3,3,3.9,3,5v14c0,1.1,0.9,2,2,2h14c1.1,0,2-0.9,2-2V5C21,3.9,20.1,3,19,3z M12,18c-3.3,0-6-2.7-6-6s2.7-6,6-6c3.3,0,6,2.7,6,6S15.3,18,12,18z"/><circle cx="12" cy="12" r="4"/></g> +<g id="nest-thermostat"><path d="M12,2C6.5,2,2,6.5,2,12c0,5.5,4.5,10,10,10c5.5,0,10-4.5,10-10C22,6.5,17.5,2,12,2z M12,5c1.6,0,3,0.5,4.2,1.4L14,8.6C13.4,8.2,12.7,8,12,8c-2.2,0-4,1.8-4,4c0,1.1,0.4,2.1,1.2,2.8l-2.1,2.1C5.8,15.7,5,13.9,5,12C5,8.1,8.1,5,12,5z M16.9,16.9l-2.1-2.1c0.7-0.7,1.2-1.7,1.2-2.8c0-0.7-0.2-1.4-0.6-2l2.2-2.2C18.5,9,19,10.4,19,12C19,13.9,18.2,15.7,16.9,16.9z"/></g> +<g id="phone-android"><path d="M16,1H8C6.3,1,5,2.3,5,4v16c0,1.7,1.3,3,3,3h8c1.7,0,3-1.3,3-3V4C19,2.3,17.7,1,16,1z M14,21h-4v-1h4V21z M17.2,18H6.8V4h10.5V18z"/></g> +<g id="phone-iphone"><path d="M15.5,1h-8C6.1,1,5,2.1,5,3.5v17C5,21.9,6.1,23,7.5,23h8c1.4,0,2.5-1.1,2.5-2.5v-17C18,2.1,16.9,1,15.5,1z M11.5,22c-0.8,0-1.5-0.7-1.5-1.5s0.7-1.5,1.5-1.5c0.8,0,1.5,0.7,1.5,1.5S12.3,22,11.5,22z M16,18H7V4h9V18z"/></g> +<g id="phonelink"><path d="M4,6h18V4H4C2.9,4,2,4.9,2,6v11H0v3h14v-3H4V6z M23,8h-6c-0.5,0-1,0.5-1,1v10c0,0.5,0.5,1,1,1h6c0.5,0,1-0.5,1-1V9C24,8.5,23.5,8,23,8z M22,17h-4v-7h4V17z"/></g> +<g id="phonelink-off"><path d="M22,6V4H6.8l2,2H22z M1.9,1.6L0.6,2.9l1.8,1.8C2.2,5.1,2,5.5,2,6v11H0v3h17.7l2.4,2.4l1.3-1.3L3.9,3.6L1.9,1.6z M4,6.3L14.7,17H4V6.3z M23,8h-6c-0.5,0-1,0.5-1,1v4.2l2,2V10h4v7h-2.2l3,3H23c0.5,0,1-0.5,1-1V9C24,8.5,23.5,8,23,8z"/></g> +<g id="security"><path d="M12,1L3,5v6c0,5.6,3.8,10.7,9,12c5.2-1.3,9-6.4,9-12V5L12,1z M12,12h7c-0.5,4.1-3.3,7.8-7,8.9V12l-7,0V6.3l7-3.1V12z"/></g> +<g id="smartphone"><path d="M17,1L7,1C5.9,1,5,1.9,5,3v18c0,1.1,0.9,2,2,2h10c1.1,0,2-0.9,2-2V3C19,1.9,18.1,1,17,1z M17,19H7V5h10V19z"/></g> +<g id="speaker"><path d="M17,2H7C5.9,2,5,2.9,5,4v16c0,1.1,0.9,2,2,2l10,0c1.1,0,2-0.9,2-2V4C19,2.9,18.1,2,17,2z M12,4c1.1,0,2,0.9,2,2s-0.9,2-2,2c-1.1,0-2-0.9-2-2S10.9,4,12,4z M12,20c-2.8,0-5-2.2-5-5s2.2-5,5-5c2.8,0,5,2.2,5,5S14.8,20,12,20z M12,12c-1.7,0-3,1.3-3,3c0,1.7,1.3,3,3,3c1.7,0,3-1.3,3-3C15,13.3,13.7,12,12,12z"/></g> +<g id="tablet"><path d="M21,4H3C1.9,4,1,4.9,1,6v12c0,1.1,0.9,2,2,2h18c1.1,0,2-0.9,2-2l0-12C23,4.9,22.1,4,21,4z M19,18H5V6h14V18z"/></g> +<g id="tablet-android"><path d="M18,0H6C4.3,0,3,1.3,3,3v18c0,1.7,1.3,3,3,3h12c1.7,0,3-1.3,3-3V3C21,1.3,19.7,0,18,0z M14,22h-4v-1h4V22z M19.2,19H4.8V3h14.5V19z"/></g> +<g id="tablet-mac"><path d="M18.5,0h-14C3.1,0,2,1.1,2,2.5v19C2,22.9,3.1,24,4.5,24h14c1.4,0,2.5-1.1,2.5-2.5v-19C21,1.1,19.9,0,18.5,0z M11.5,23c-0.8,0-1.5-0.7-1.5-1.5s0.7-1.5,1.5-1.5c0.8,0,1.5,0.7,1.5,1.5S12.3,23,11.5,23z M19,19H4V3h15V19z"/></g> +<g id="tv"><path d="M21,3H3C1.9,3,1,3.9,1,5v12c0,1.1,0.9,2,2,2h5v2h8v-2h5c1.1,0,2-0.9,2-2l0-12C23,3.9,22.1,3,21,3z M21,17H3V5h18V17z"/></g> +<g id="watch"><path d="M20,12c0-2.5-1.2-4.8-3-6.3L16,0H8L7,5.7C5.2,7.2,4,9.5,4,12s1.2,4.8,3,6.3L8,24h8l1-5.7C18.8,16.8,20,14.5,20,12z M6,12c0-3.3,2.7-6,6-6c3.3,0,6,2.7,6,6s-2.7,6-6,6C8.7,18,6,15.3,6,12z"/></g> +</defs></svg> +</core-iconset-svg> - while (i < names.length) { - split = normalizeLocale(names[i]).split('-'); - j = split.length; - next = normalizeLocale(names[i + 1]); - next = next ? next.split('-') : null; - while (j > 0) { - locale = loadLocale(split.slice(0, j).join('-')); - if (locale) { - return locale; - } - if (next && next.length >= j && compareArrays(split, next, true) >= j - 1) { - //the next array item is better than a shallower substring of this one - break; - } - j--; - } - i++; - } - return null; - } - function loadLocale(name) { - var oldLocale = null; - if (!locales[name] && hasModule) { - try { - oldLocale = moment.locale(); - require('./locale/' + name); - // because defineLocale currently also sets the global locale, we want to undo that for lazy loaded locales - moment.locale(oldLocale); - } catch (e) { } - } - return locales[name]; - } +<polymer-element name="domain-icon" attributes="domain" assetpath="polymer/"> + <template> + <core-icon icon="{{icon(domain)}}"></core-icon> + </template> + <script> + Polymer('domain-icon',{ - // Return a moment from input, that is local/utc/zone equivalent to model. - function makeAs(input, model) { - return model._isUTC ? moment(input).zone(model._offset || 0) : - moment(input).local(); - } + icon: function() { + switch(this.domain) { + case "group": + return "social:communities"; - /************************************ - Locale - ************************************/ + case "device_tracker": + return "social:person"; + case "wemo": + return "settings-input-svideo"; - extend(Locale.prototype, { + case "chromecast": + // hardware:cast-connected + return "hardware:cast"; - set : function (config) { - var prop, i; - for (i in config) { - prop = config[i]; - if (typeof prop === 'function') { - this[i] = prop; - } else { - this['_' + i] = prop; - } - } - }, + case "process": + return "hardware:memory" - _months : 'January_February_March_April_May_June_July_August_September_October_November_December'.split('_'), - months : function (m) { - return this._months[m.month()]; - }, + case "sun": + return "device:brightness-low" - _monthsShort : 'Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec'.split('_'), - monthsShort : function (m) { - return this._monthsShort[m.month()]; - }, + case "light": + return "image:wb-incandescent" - monthsParse : function (monthName) { - var i, mom, regex; + default: + return "bookmark-outline"; + } + } - if (!this._monthsParse) { - this._monthsParse = []; - } + }); + </script> +</polymer-element> - for (i = 0; i < 12; i++) { - // make the regex if we don't have it already - if (!this._monthsParse[i]) { - mom = moment.utc([2000, i]); - regex = '^' + this.months(mom, '') + '|^' + this.monthsShort(mom, ''); - this._monthsParse[i] = new RegExp(regex.replace('.', ''), 'i'); - } - // test the regex - if (this._monthsParse[i].test(monthName)) { - return i; - } - } - }, - _weekdays : 'Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday'.split('_'), - weekdays : function (m) { - return this._weekdays[m.day()]; - }, +<polymer-element name="state-badge" attributes="domain state" assetpath="polymer/"> + <template> + <style> + :host { + display: inline-block; + width: 45px; + background-color: #4fc3f7; + color: white; + border-radius: 23px; + } + div { + height: 45px; + text-align: center; + } - _weekdaysShort : 'Sun_Mon_Tue_Wed_Thu_Fri_Sat'.split('_'), - weekdaysShort : function (m) { - return this._weekdaysShort[m.day()]; - }, + domain-icon { + margin: 0 auto; + } + </style> + + <div horizontal="" layout="" center=""> + <domain-icon domain="{{domain}}"></domain-icon> + </div> + + </template> + <script> + Polymer('state-badge',{ + }); + </script> +</polymer-element> + + +<polymer-element name="state-card" attributes="entity state last_changed state_attr cb_turn_on, cb_turn_off cb_edit" assetpath="polymer/"> + <template> + <style> + :host { + background-color: #fff; + border-radius: 2px; + box-shadow: rgba(0, 0, 0, 0.098) 0px 2px 4px, rgba(0, 0, 0, 0.098) 0px 0px 3px; + /* transition */ + -webkit-transition: all 0.30s ease-out; + transition: all 0.30s ease-out; + + position: relative; + background-color: white; + padding: 15px; + width: 100%; + } + + state-badge { + float: left; + cursor: pointer; + transition: background-color .2s; + } + + state-badge:hover { + background-color: #039be5; + } + + .name, .state.text { + text-transform: capitalize; + font-weight: 300; + font-size: 1.5rem; + } + + .state { + text-align: right; + } + + .info { + margin-left: 60px; + } + + .time-ago { + color: darkgrey; + margin-top: -2px; + } + + /* the splash while enabling */ + paper-toggle-button::shadow paper-radio-button::shadow #ink[checked] { + color: #0091ea; + } + + /* filling of circle when checked */ + paper-toggle-button::shadow paper-radio-button::shadow #onRadio { + background-color: #039be5; + transition: background-color .2s; + } + + /* line when checked */ + paper-toggle-button::shadow #toggleBar[checked] { + background-color: #039be5; + transition: background-color .2s; + } + </style> + + <div horizontal="" justified="" layout=""> + + <div class="entity"> + <state-badge domain="{{domain}}" state="{{state}}" on-click="{{editClicked}}"> + </state-badge> + + <div class="info"> + <div class="name"> + <template if="{{state_attr['friendly_name']}}">{{state_attr['friendly_name']}}</template> + <template if="{{!state_attr['friendly_name']}}">{{entity_id | makeReadable}}</template> + </div> + + <div class="time-ago"> + <core-tooltip label="{{last_changed}}" position="bottom"> + {{last_changed_from_now}} + </core-tooltip> + </div> + + </div> + </div> + + <template if="{{!state_unknown}}"> + <template if="{{state == 'on' || state == 'off'}}"> + <div class="state toggle" self-center="" flex=""> + <paper-toggle-button id="toggleButton" on-change="{{toggle}}"> + </paper-toggle-button> + </div> + </template> + <template if="{{state != 'on' && state != 'off'}}"> + <div class="state text"> + {{state | makeReadable}} + </div> + </template> + </template> + + <template if="{{state_unknown}}"> + <div class="state" self-center="" flex="">Updating..</div> + </template> + + </div> + + </template> + <script> + Polymer('state-card',{ + // attributes + entity: "", + state: "", + last_changed: "never", + state_attr: {}, + cb_turn_on: null, + cb_turn_off: null, + cb_edit: null, + state_unknown: false, + + // computed + domain: "", + entity_id: "", + + stateChanged: function(oldVal, newVal) { + this.state_unknown = newVal == ""; + + if(this.$.toggleButton) { + this.$.toggleButton.checked = this.state == 'on'; + } + }, + + entityChanged: function(oldVal, newVal) { + var parts = newVal.split(".") + + if(parts.length == 1) { + this.domain = "" + this.entity_id = parts[0] + } else { + this.domain = parts[0] + this.entity_id = parts.slice(1).join('.') + } + }, + + last_changedChanged: function(oldVal, newVal) { + this.last_changed_from_now = moment(this.last_changed, "HH:mm:ss DD-MM-YYYY").fromNow() + }, + + toggle: function(ev) { + if(this.$.toggleButton.checked) { + this.turn_on(); + } else { + this.turn_off(); + } + + var delayUnsetSate = function() { + this.state = ""; + } + setTimeout(delayUnsetSate.bind(this), 500); + }, + + turn_on: function() { + if(this.cb_turn_on) { + this.cb_turn_on(this.entity); + } + }, + + turn_off: function() { + if(this.cb_turn_off) { + this.cb_turn_off(this.entity); + } + }, + + editClicked: function() { + if(this.cb_edit) { + this.cb_edit(this.entity); + } + }, + + // used as filter + makeReadable: function(value) { + if(typeof value == "string") { + return value.replace(/_/g, " "); + + } else if(Array.isArray(value)) { + return value.join(", "); + + } else { + return value; + } + } + }); + </script> +</polymer-element> + + +<polymer-element name="states-cards" attributes="api filter" assetpath="polymer/"> + <template> + <style> + :host { + display: block; + width: 100%; + } + + state-card, state-add-card { + display: inline-block; + width: 350px; + margin: 10px 0 0 10px; + } + + state-add-card { + cursor: pointer; + } + + </style> + + <div horizontal="" layout="" wrap=""> + <template if="{{filter != null}}"> + <state-card entity="{{filter_state.entity_id}}" state="{{filter_state.state}}" last_changed="{{filter_state.last_changed}}" state_attr="{{filter_state.attributes}}" cb_turn_on="{{api.turn_on}}" cb_turn_off="{{api.turn_off}}" cb_edit="{{editCallback}}"> + </state-card> + </template> + + <template repeat="{{state in states}}"> + <state-card entity="{{state.entity_id}}" state="{{state.state}}" last_changed="{{state.last_changed}}" state_attr="{{state.attributes}}" cb_turn_on="{{api.turn_on}}" cb_turn_off="{{api.turn_off}}" cb_edit="{{editCallback}}"> + </state-card> + </template> + + </div> + </template> + <script> + Polymer('states-cards',{ + raw_states: [], + states: [], + filter: null, + filter_state: null, + filter_substates: null, + + filterChanged: function(oldVal, newVal) { + this.refilterStates(); + }, + + ready: function() { + this.editCallback = this.editCallback.bind(this); + }, + + domReady: function() { + this.raw_states = this.api.states + + this.api.addEventListener('states-updated', this.statesUpdated.bind(this)) + + this.refilterStates(); + }, + + statesUpdated: function() { + this.raw_states = this.api.states; + + this.refilterStates(); + }, + + refilterStates: function() { + if(this.filter == null) { + this.filter_state = null; + this.states = this.raw_states; + } else { + this.filter_state = this.api.getState(this.filter); + + var map_states = function(entity_id) { + return this.api.getState(entity_id); + }.bind(this) + + this.states = this.filter_state.attributes.entity_id.map(map_states) + } + }, + + editCallback: function(entityId) { + this.api.showEditStateDialog(entityId); + }, + + }); + </script> +</polymer-element> - _weekdaysMin : 'Su_Mo_Tu_We_Th_Fr_Sa'.split('_'), - weekdaysMin : function (m) { - return this._weekdaysMin[m.day()]; - }, - weekdaysParse : function (weekdayName) { - var i, mom, regex; +<polymer-element name="home-assistant-main" attributes="api" assetpath="polymer/"> + <template> + <style type="text/css"> - if (!this._weekdaysParse) { - this._weekdaysParse = []; - } + :host { + font-family: 'RobotoDraft', sans-serif; + } - for (i = 0; i < 7; i++) { - // make the regex if we don't have it already - if (!this._weekdaysParse[i]) { - mom = moment([2000, 1]).day(i); - regex = '^' + this.weekdays(mom, '') + '|^' + this.weekdaysShort(mom, '') + '|^' + this.weekdaysMin(mom, ''); - this._weekdaysParse[i] = new RegExp(regex.replace('.', ''), 'i'); - } - // test the regex - if (this._weekdaysParse[i].test(weekdayName)) { - return i; - } - } - }, + core-header-panel { + height: 100%; + overflow: auto; + -webkit-overflow-scrolling: touch; + background-color: #E5E5E5; + } - _longDateFormat : { - LT : 'h:mm A', - L : 'MM/DD/YYYY', - LL : 'MMMM D, YYYY', - LLL : 'MMMM D, YYYY LT', - LLLL : 'dddd, MMMM D, YYYY LT' - }, - longDateFormat : function (key) { - var output = this._longDateFormat[key]; - if (!output && this._longDateFormat[key.toUpperCase()]) { - output = this._longDateFormat[key.toUpperCase()].replace(/MMMM|MM|DD|dddd/g, function (val) { - return val.slice(1); - }); - this._longDateFormat[key] = output; - } - return output; - }, + core-toolbar { + background: #03a9f4; + font-size: 1.4rem; + color: white; + } - isPM : function (input) { - // IE8 Quirks Mode & IE7 Standards Mode do not allow accessing strings like arrays - // Using charAt should be more compatible. - return ((input + '').toLowerCase().charAt(0) === 'p'); - }, + .content { + padding-bottom: 75px; + padding-right: 10px; + } - _meridiemParse : /[ap]\.?m?\.?/i, - meridiem : function (hours, minutes, isLower) { - if (hours > 11) { - return isLower ? 'pm' : 'PM'; - } else { - return isLower ? 'am' : 'AM'; - } - }, + paper-fab { + position: fixed; + bottom: 10px; + right: 10px; + } - _calendar : { - sameDay : '[Today at] LT', - nextDay : '[Tomorrow at] LT', - nextWeek : 'dddd [at] LT', - lastDay : '[Yesterday at] LT', - lastWeek : '[Last] dddd [at] LT', - sameElse : 'L' - }, - calendar : function (key, mom) { - var output = this._calendar[key]; - return typeof output === 'function' ? output.apply(mom) : output; - }, + </style> - _relativeTime : { - future : 'in %s', - past : '%s ago', - s : 'a few seconds', - m : 'a minute', - mm : '%d minutes', - h : 'an hour', - hh : '%d hours', - d : 'a day', - dd : '%d days', - M : 'a month', - MM : '%d months', - y : 'a year', - yy : '%d years' - }, - relativeTime : function (number, withoutSuffix, string, isFuture) { - var output = this._relativeTime[string]; - return (typeof output === 'function') ? - output(number, withoutSuffix, string, isFuture) : - output.replace(/%d/i, number); - }, + <core-header-panel unresolved="" fullbleed=""> - pastFuture : function (diff, output) { - var format = this._relativeTime[diff > 0 ? 'future' : 'past']; - return typeof format === 'function' ? format(output) : format.replace(/%s/i, output); - }, + <core-toolbar class="medium-tall"> + <div flex=""> + Home Assistant + </div> + <core-icon-button icon="refresh" on-click="{{handleRefreshClick}}"></core-icon-button> + <core-icon-button icon="developer-mode-tv" on-click="{{handleEventClick}}"></core-icon-button> + <core-icon-button icon="settings-remote" on-click="{{handleServiceClick}}"></core-icon-button> - ordinal : function (number) { - return this._ordinal.replace('%d', number); - }, - _ordinal : '%d', + <div class="bottom fit" horizontal="" layout=""> + <paper-tabs id="tabsHolder" noink="" flex="" selected="0" on-core-select="{{tabClicked}}"> + + <paper-tab>ALL</paper-tab> - preparse : function (string) { - return string; - }, + <template repeat="{{state in api.states}}"> + <template if="{{isCustomGroup(state)}}"> + <paper-tab data-entity="{{state.entity_id}}">{{state.entity_id | groupName}}</paper-tab> + </template> + </template> + + </paper-tabs> + </div> + </core-toolbar> - postformat : function (string) { - return string; - }, + <div class="content" flex=""> + <states-cards api="{{api}}" filter="{{selectedTab}}"></states-cards> + <paper-fab icon="add" on-click="{{handleAddStateClick}}"></paper-fab> + </div> - week : function (mom) { - return weekOfYear(mom, this._week.dow, this._week.doy).week; - }, + </core-header-panel> - _week : { - dow : 0, // Sunday is the first day of the week. - doy : 6 // The week that contains Jan 1st is the first week of the year. - }, + </template> + <script> + Polymer('home-assistant-main',{ + selectedTab: null, - _invalidDate: 'Invalid date', - invalidDate: function () { - return this._invalidDate; - } - }); + isCustomGroup: function(state) { + return (state.entity_id.lastIndexOf('group.') == 0 && + !state.attributes.auto); + }, - /************************************ - Formatting - ************************************/ + groupName: function(entity_id) { + return entity_id.substring(6).toUpperCase().replace(/_/g, " "); + }, + tabClicked: function(ev) { + if(ev.detail.isSelected) { + // will be null for ALL tab + this.selectedTab = ev.detail.item.getAttribute('data-entity'); + } + }, - function removeFormattingTokens(input) { - if (input.match(/\[[\s\S]/)) { - return input.replace(/^\[|\]$/g, ''); - } - return input.replace(/\\/g, ''); - } + handleRefreshClick: function() { + this.api.fetchStates(); + }, - function makeFormatFunction(format) { - var array = format.match(formattingTokens), i, length; + handleEventClick: function() { + this.api.showFireEventDialog(); + }, - for (i = 0, length = array.length; i < length; i++) { - if (formatTokenFunctions[array[i]]) { - array[i] = formatTokenFunctions[array[i]]; - } else { - array[i] = removeFormattingTokens(array[i]); - } - } + handleServiceClick: function() { + this.api.showCallServiceDialog(); + }, - return function (mom) { - var output = ''; - for (i = 0; i < length; i++) { - output += array[i] instanceof Function ? array[i].call(mom, format) : array[i]; - } - return output; - }; + handleAddStateClick: function() { + this.api.showSetStateDialog(); } - // format date using native date object - function formatMoment(m, format) { - if (!m.isValid()) { - return m.localeData().invalidDate(); - } + }); + </script> +</polymer-element> +</div> +<div hidden> +<!-- +Copyright (c) 2014 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--> - format = expandFormat(format, m.localeData()); +<!-- +@group Polymer Core Elements - if (!formatFunctions[format]) { - formatFunctions[format] = makeFormatFunction(format); - } +The `core-ajax` element exposes `XMLHttpRequest` functionality. - return formatFunctions[format](m); - } + <core-ajax + auto + url="http://gdata.youtube.com/feeds/api/videos/" + params='{"alt":"json", "q":"chrome"}' + handleAs="json" + on-core-response="{{handleResponse}}"></core-ajax> - function expandFormat(format, locale) { - var i = 5; +With `auto` set to `true`, the element performs a request whenever +its `url` or `params` properties are changed. - function replaceLongDateFormatTokens(input) { - return locale.longDateFormat(input) || input; - } +Note: The `params` attribute must be double quoted JSON. - localFormattingTokens.lastIndex = 0; - while (i >= 0 && localFormattingTokens.test(format)) { - format = format.replace(localFormattingTokens, replaceLongDateFormatTokens); - localFormattingTokens.lastIndex = 0; - i -= 1; - } +You can trigger a request explicitly by calling `go` on the +element. - return format; - } +@element core-ajax +@status beta +@homepage github.io +--> +<!-- +Copyright (c) 2014 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--> +<!-- +/** + * @group Polymer Core Elements + * + * core-xhr can be used to perform XMLHttpRequests. + * + * <core-xhr id="xhr"></core-xhr> + * ... + * this.$.xhr.request({url: url, params: params, callback: callback}); + * + * @element core-xhr + */ +--> - /************************************ - Parsing - ************************************/ +<polymer-element name="core-xhr" hidden assetpath="polymer/bower_components/core-ajax/"> - // get the regex to find the next token - function getParseRegexForToken(token, config) { - var a, strict = config._strict; - switch (token) { - case 'Q': - return parseTokenOneDigit; - case 'DDDD': - return parseTokenThreeDigits; - case 'YYYY': - case 'GGGG': - case 'gggg': - return strict ? parseTokenFourDigits : parseTokenOneToFourDigits; - case 'Y': - case 'G': - case 'g': - return parseTokenSignedNumber; - case 'YYYYYY': - case 'YYYYY': - case 'GGGGG': - case 'ggggg': - return strict ? parseTokenSixDigits : parseTokenOneToSixDigits; - case 'S': - if (strict) { - return parseTokenOneDigit; - } - /* falls through */ - case 'SS': - if (strict) { - return parseTokenTwoDigits; - } - /* falls through */ - case 'SSS': - if (strict) { - return parseTokenThreeDigits; - } - /* falls through */ - case 'DDD': - return parseTokenOneToThreeDigits; - case 'MMM': - case 'MMMM': - case 'dd': - case 'ddd': - case 'dddd': - return parseTokenWord; - case 'a': - case 'A': - return config._locale._meridiemParse; - case 'X': - return parseTokenTimestampMs; - case 'Z': - case 'ZZ': - return parseTokenTimezone; - case 'T': - return parseTokenT; - case 'SSSS': - return parseTokenDigits; - case 'MM': - case 'DD': - case 'YY': - case 'GG': - case 'gg': - case 'HH': - case 'hh': - case 'mm': - case 'ss': - case 'ww': - case 'WW': - return strict ? parseTokenTwoDigits : parseTokenOneOrTwoDigits; - case 'M': - case 'D': - case 'd': - case 'H': - case 'h': - case 'm': - case 's': - case 'w': - case 'W': - case 'e': - case 'E': - return parseTokenOneOrTwoDigits; - case 'Do': - return parseTokenOrdinal; - default : - a = new RegExp(regexpEscape(unescapeFormat(token.replace('\\', '')), 'i')); - return a; - } - } + <script> - function timezoneMinutesFromString(string) { - string = string || ''; - var possibleTzMatches = (string.match(parseTokenTimezone) || []), - tzChunk = possibleTzMatches[possibleTzMatches.length - 1] || [], - parts = (tzChunk + '').match(parseTimezoneChunker) || ['-', 0, 0], - minutes = +(parts[1] * 60) + toInt(parts[2]); + Polymer('core-xhr', { - return parts[0] === '+' ? -minutes : minutes; - } + /** + * Sends a HTTP request to the server and returns the XHR object. + * + * @method request + * @param {Object} inOptions + * @param {String} inOptions.url The url to which the request is sent. + * @param {String} inOptions.method The HTTP method to use, default is GET. + * @param {boolean} inOptions.sync By default, all requests are sent asynchronously. To send synchronous requests, set to true. + * @param {Object} inOptions.params Data to be sent to the server. + * @param {Object} inOptions.body The content for the request body for POST method. + * @param {Object} inOptions.headers HTTP request headers. + * @param {String} inOptions.responseType The response type. Default is 'text'. + * @param {boolean} inOptions.withCredentials Whether or not to send credentials on the request. Default is false. + * @param {Object} inOptions.callback Called when request is completed. + * @returns {Object} XHR object. + */ + request: function(options) { + var xhr = new XMLHttpRequest(); + var url = options.url; + var method = options.method || 'GET'; + var async = !options.sync; + // + var params = this.toQueryString(options.params); + if (params && method == 'GET') { + url += (url.indexOf('?') > 0 ? '&' : '?') + params; + } + var xhrParams = this.isBodyMethod(method) ? (options.body || params) : null; + // + xhr.open(method, url, async); + if (options.responseType) { + xhr.responseType = options.responseType; + } + if (options.withCredentials) { + xhr.withCredentials = true; + } + this.makeReadyStateHandler(xhr, options.callback); + this.setRequestHeaders(xhr, options.headers); + xhr.send(xhrParams); + if (!async) { + xhr.onreadystatechange(xhr); + } + return xhr; + }, + + toQueryString: function(params) { + var r = []; + for (var n in params) { + var v = params[n]; + n = encodeURIComponent(n); + r.push(v == null ? n : (n + '=' + encodeURIComponent(v))); + } + return r.join('&'); + }, - // function to convert string input to date - function addTimeToArrayFromToken(token, input, config) { - var a, datePartArray = config._a; + isBodyMethod: function(method) { + return this.bodyMethods[(method || '').toUpperCase()]; + }, + + bodyMethods: { + POST: 1, + PUT: 1, + DELETE: 1 + }, - switch (token) { - // QUARTER - case 'Q': - if (input != null) { - datePartArray[MONTH] = (toInt(input) - 1) * 3; - } - break; - // MONTH - case 'M' : // fall through to MM - case 'MM' : - if (input != null) { - datePartArray[MONTH] = toInt(input) - 1; - } - break; - case 'MMM' : // fall through to MMMM - case 'MMMM' : - a = config._locale.monthsParse(input); - // if we didn't find a month name, mark the date as invalid. - if (a != null) { - datePartArray[MONTH] = a; - } else { - config._pf.invalidMonth = input; - } - break; - // DAY OF MONTH - case 'D' : // fall through to DD - case 'DD' : - if (input != null) { - datePartArray[DATE] = toInt(input); - } - break; - case 'Do' : - if (input != null) { - datePartArray[DATE] = toInt(parseInt(input, 10)); - } - break; - // DAY OF YEAR - case 'DDD' : // fall through to DDDD - case 'DDDD' : - if (input != null) { - config._dayOfYear = toInt(input); - } + makeReadyStateHandler: function(xhr, callback) { + xhr.onreadystatechange = function() { + if (xhr.readyState == 4) { + callback && callback.call(null, xhr.response, xhr); + } + }; + }, - break; - // YEAR - case 'YY' : - datePartArray[YEAR] = moment.parseTwoDigitYear(input); - break; - case 'YYYY' : - case 'YYYYY' : - case 'YYYYYY' : - datePartArray[YEAR] = toInt(input); - break; - // AM / PM - case 'a' : // fall through to A - case 'A' : - config._isPm = config._locale.isPM(input); - break; - // 24 HOUR - case 'H' : // fall through to hh - case 'HH' : // fall through to hh - case 'h' : // fall through to hh - case 'hh' : - datePartArray[HOUR] = toInt(input); - break; - // MINUTE - case 'm' : // fall through to mm - case 'mm' : - datePartArray[MINUTE] = toInt(input); - break; - // SECOND - case 's' : // fall through to ss - case 'ss' : - datePartArray[SECOND] = toInt(input); - break; - // MILLISECOND - case 'S' : - case 'SS' : - case 'SSS' : - case 'SSSS' : - datePartArray[MILLISECOND] = toInt(('0.' + input) * 1000); - break; - // UNIX TIMESTAMP WITH MS - case 'X': - config._d = new Date(parseFloat(input) * 1000); - break; - // TIMEZONE - case 'Z' : // fall through to ZZ - case 'ZZ' : - config._useUTC = true; - config._tzm = timezoneMinutesFromString(input); - break; - // WEEKDAY - human - case 'dd': - case 'ddd': - case 'dddd': - a = config._locale.weekdaysParse(input); - // if we didn't get a weekday name, mark the date as invalid - if (a != null) { - config._w = config._w || {}; - config._w['d'] = a; - } else { - config._pf.invalidWeekday = input; - } - break; - // WEEK, WEEK DAY - numeric - case 'w': - case 'ww': - case 'W': - case 'WW': - case 'd': - case 'e': - case 'E': - token = token.substr(0, 1); - /* falls through */ - case 'gggg': - case 'GGGG': - case 'GGGGG': - token = token.substr(0, 2); - if (input) { - config._w = config._w || {}; - config._w[token] = toInt(input); - } - break; - case 'gg': - case 'GG': - config._w = config._w || {}; - config._w[token] = moment.parseTwoDigitYear(input); + setRequestHeaders: function(xhr, headers) { + if (headers) { + for (var name in headers) { + xhr.setRequestHeader(name, headers[name]); + } } - } + } - function dayOfYearFromWeekInfo(config) { - var w, weekYear, week, weekday, dow, doy, temp; + }); - w = config._w; - if (w.GG != null || w.W != null || w.E != null) { - dow = 1; - doy = 4; + </script> + +</polymer-element> - // TODO: We need to take the current isoWeekYear, but that depends on - // how we interpret now (local, utc, fixed offset). So create - // a now version of current config (take local/utc/offset flags, and - // create now). - weekYear = dfl(w.GG, config._a[YEAR], weekOfYear(moment(), 1, 4).year); - week = dfl(w.W, 1); - weekday = dfl(w.E, 1); - } else { - dow = config._locale._week.dow; - doy = config._locale._week.doy; +<polymer-element name="core-ajax" hidden attributes="url handleAs auto params response error method headers body contentType withCredentials" assetpath="polymer/bower_components/core-ajax/"> +<script> - weekYear = dfl(w.gg, config._a[YEAR], weekOfYear(moment(), dow, doy).year); - week = dfl(w.w, 1); + Polymer('core-ajax', { + /** + * Fired when a response is received. + * + * @event core-response + */ - if (w.d != null) { - // weekday -- low day numbers are considered next week - weekday = w.d; - if (weekday < dow) { - ++week; - } - } else if (w.e != null) { - // local weekday -- counting starts from begining of week - weekday = w.e + dow; - } else { - // default to begining of week - weekday = dow; - } - } - temp = dayOfYearFromWeeks(weekYear, week, weekday, doy, dow); + /** + * Fired when an error is received. + * + * @event core-error + */ - config._a[YEAR] = temp.year; - config._dayOfYear = temp.dayOfYear; - } + /** + * Fired whenever a response or an error is received. + * + * @event core-complete + */ - // convert an array to a date. - // the array should mirror the parameters below - // note: all values past the year are optional and will default to the lowest possible value. - // [year, month, day , hour, minute, second, millisecond] - function dateFromConfig(config) { - var i, date, input = [], currentDate, yearToUse; + /** + * The URL target of the request. + * + * @attribute url + * @type string + * @default '' + */ + url: '', + + /** + * Specifies what data to store in the `response` property, and + * to deliver as `event.response` in `response` events. + * + * One of: + * + * `text`: uses `XHR.responseText`. + * + * `xml`: uses `XHR.responseXML`. + * + * `json`: uses `XHR.responseText` parsed as JSON. + * + * `arraybuffer`: uses `XHR.response`. + * + * `blob`: uses `XHR.response`. + * + * `document`: uses `XHR.response`. + * + * @attribute handleAs + * @type string + * @default 'text' + */ + handleAs: '', - if (config._d) { - return; - } + /** + * If true, automatically performs an Ajax request when either `url` or `params` changes. + * + * @attribute auto + * @type boolean + * @default false + */ + auto: false, - currentDate = currentDateArray(config); + /** + * Parameters to send to the specified URL, as JSON. + * + * @attribute params + * @type string (JSON) + * @default '' + */ + params: '', - //compute day of the year from weeks and weekdays - if (config._w && config._a[DATE] == null && config._a[MONTH] == null) { - dayOfYearFromWeekInfo(config); - } + /** + * The response for the most recently made request, or null if it hasn't + * completed yet or the request resulted in error. + * + * @attribute response + * @type Object + * @default null + */ + response: null, - //if the day of the year is set, figure out what it is - if (config._dayOfYear) { - yearToUse = dfl(config._a[YEAR], currentDate[YEAR]); + /** + * The error for the most recently made request, or null if it hasn't + * completed yet or the request resulted in success. + * + * @attribute error + * @type Object + * @default null + */ + error: null, - if (config._dayOfYear > daysInYear(yearToUse)) { - config._pf._overflowDayOfYear = true; - } + /** + * The HTTP method to use such as 'GET', 'POST', 'PUT', or 'DELETE'. + * Default is 'GET'. + * + * @attribute method + * @type string + * @default '' + */ + method: '', - date = makeUTCDate(yearToUse, 0, config._dayOfYear); - config._a[MONTH] = date.getUTCMonth(); - config._a[DATE] = date.getUTCDate(); - } + /** + * HTTP request headers to send. + * + * Example: + * + * <core-ajax + * auto + * url="http://somesite.com" + * headers='{"X-Requested-With": "XMLHttpRequest"}' + * handleAs="json" + * on-core-response="{{handleResponse}}"></core-ajax> + * + * @attribute headers + * @type Object + * @default null + */ + headers: null, - // Default to current date. - // * if no year, month, day of month are given, default to today - // * if day of month is given, default month and year - // * if month is given, default only year - // * if year is given, don't default anything - for (i = 0; i < 3 && config._a[i] == null; ++i) { - config._a[i] = input[i] = currentDate[i]; - } + /** + * Optional raw body content to send when method === "POST". + * + * Example: + * + * <core-ajax method="POST" auto url="http://somesite.com" + * body='{"foo":1, "bar":2}'> + * </core-ajax> + * + * @attribute body + * @type Object + * @default null + */ + body: null, - // Zero out whatever was not defaulted, including time - for (; i < 7; i++) { - config._a[i] = input[i] = (config._a[i] == null) ? (i === 2 ? 1 : 0) : config._a[i]; - } + /** + * Content type to use when sending data. + * + * @attribute contentType + * @type string + * @default 'application/x-www-form-urlencoded' + */ + contentType: 'application/x-www-form-urlencoded', - config._d = (config._useUTC ? makeUTCDate : makeDate).apply(null, input); - // Apply timezone offset from input. The actual zone can be changed - // with parseZone. - if (config._tzm != null) { - config._d.setUTCMinutes(config._d.getUTCMinutes() + config._tzm); - } - } + /** + * Set the withCredentials flag on the request. + * + * @attribute withCredentials + * @type boolean + * @default false + */ + withCredentials: false, - function dateFromObject(config) { - var normalizedInput; + /** + * Additional properties to send to core-xhr. + * + * Can be set to an object containing default properties + * to send as arguments to the `core-xhr.request()` method + * which implements the low-level communication. + * + * @property xhrArgs + * @type Object + * @default null + */ + xhrArgs: null, - if (config._d) { - return; - } + ready: function() { + this.xhr = document.createElement('core-xhr'); + }, - normalizedInput = normalizeObjectUnits(config._i); - config._a = [ - normalizedInput.year, - normalizedInput.month, - normalizedInput.day, - normalizedInput.hour, - normalizedInput.minute, - normalizedInput.second, - normalizedInput.millisecond - ]; + receive: function(response, xhr) { + if (this.isSuccess(xhr)) { + this.processResponse(xhr); + } else { + this.processError(xhr); + } + this.complete(xhr); + }, - dateFromConfig(config); - } + isSuccess: function(xhr) { + var status = xhr.status || 0; + return !status || (status >= 200 && status < 300); + }, - function currentDateArray(config) { - var now = new Date(); - if (config._useUTC) { - return [ - now.getUTCFullYear(), - now.getUTCMonth(), - now.getUTCDate() - ]; - } else { - return [now.getFullYear(), now.getMonth(), now.getDate()]; - } - } + processResponse: function(xhr) { + var response = this.evalResponse(xhr); + if (xhr === this.activeRequest) { + this.response = response; + } + this.fire('core-response', {response: response, xhr: xhr}); + }, - // date from string and format string - function makeDateFromStringAndFormat(config) { - if (config._f === moment.ISO_8601) { - parseISO(config); - return; - } + processError: function(xhr) { + var response = xhr.status + ': ' + xhr.responseText; + if (xhr === this.activeRequest) { + this.error = response; + } + this.fire('core-error', {response: response, xhr: xhr}); + }, - config._a = []; - config._pf.empty = true; + complete: function(xhr) { + this.fire('core-complete', {response: xhr.status, xhr: xhr}); + }, - // This array is used to make a Date, either with `new Date` or `Date.UTC` - var string = '' + config._i, - i, parsedInput, tokens, token, skipped, - stringLength = string.length, - totalParsedInputLength = 0; + evalResponse: function(xhr) { + return this[(this.handleAs || 'text') + 'Handler'](xhr); + }, - tokens = expandFormat(config._f, config._locale).match(formattingTokens) || []; + xmlHandler: function(xhr) { + return xhr.responseXML; + }, - for (i = 0; i < tokens.length; i++) { - token = tokens[i]; - parsedInput = (string.match(getParseRegexForToken(token, config)) || [])[0]; - if (parsedInput) { - skipped = string.substr(0, string.indexOf(parsedInput)); - if (skipped.length > 0) { - config._pf.unusedInput.push(skipped); - } - string = string.slice(string.indexOf(parsedInput) + parsedInput.length); - totalParsedInputLength += parsedInput.length; - } - // don't parse if it's not a known token - if (formatTokenFunctions[token]) { - if (parsedInput) { - config._pf.empty = false; - } - else { - config._pf.unusedTokens.push(token); - } - addTimeToArrayFromToken(token, parsedInput, config); - } - else if (config._strict && !parsedInput) { - config._pf.unusedTokens.push(token); - } - } + textHandler: function(xhr) { + return xhr.responseText; + }, + + jsonHandler: function(xhr) { + var r = xhr.responseText; + try { + return JSON.parse(r); + } catch (x) { + console.warn('core-ajax caught an exception trying to parse response as JSON:'); + console.warn('url:', this.url); + console.warn(x); + return r; + } + }, - // add remaining unparsed input length to the string - config._pf.charsLeftOver = stringLength - totalParsedInputLength; - if (string.length > 0) { - config._pf.unusedInput.push(string); - } + documentHandler: function(xhr) { + return xhr.response; + }, - // handle am pm - if (config._isPm && config._a[HOUR] < 12) { - config._a[HOUR] += 12; - } - // if is 12 am, change hours to 0 - if (config._isPm === false && config._a[HOUR] === 12) { - config._a[HOUR] = 0; + blobHandler: function(xhr) { + return xhr.response; + }, + + arraybufferHandler: function(xhr) { + return xhr.response; + }, + + urlChanged: function() { + if (!this.handleAs) { + var ext = String(this.url).split('.').pop(); + switch (ext) { + case 'json': + this.handleAs = 'json'; + break; } + } + this.autoGo(); + }, - dateFromConfig(config); - checkOverflow(config); - } + paramsChanged: function() { + this.autoGo(); + }, - function unescapeFormat(s) { - return s.replace(/\\(\[)|\\(\])|\[([^\]\[]*)\]|\\(.)/g, function (matched, p1, p2, p3, p4) { - return p1 || p2 || p3 || p4; - }); - } + autoChanged: function() { + this.autoGo(); + }, - // Code from http://stackoverflow.com/questions/3561493/is-there-a-regexp-escape-function-in-javascript - function regexpEscape(s) { - return s.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&'); - } + // TODO(sorvell): multiple side-effects could call autoGo + // during one micro-task, use a job to have only one action + // occur + autoGo: function() { + if (this.auto) { + this.goJob = this.job(this.goJob, this.go, 0); + } + }, - // date from string and array of format strings - function makeDateFromStringAndArray(config) { - var tempConfig, - bestMoment, + /** + * Performs an Ajax request to the specified URL. + * + * @method go + */ + go: function() { + var args = this.xhrArgs || {}; + // TODO(sjmiles): we may want XHR to default to POST if body is set + args.body = this.body || args.body; + args.params = this.params || args.params; + if (args.params && typeof(args.params) == 'string') { + args.params = JSON.parse(args.params); + } + args.headers = this.headers || args.headers || {}; + if (args.headers && typeof(args.headers) == 'string') { + args.headers = JSON.parse(args.headers); + } + var hasContentType = Object.keys(args.headers).some(function (header) { + return header.toLowerCase() === 'content-type'; + }); + if (!hasContentType && this.contentType) { + args.headers['Content-Type'] = this.contentType; + } + if (this.handleAs === 'arraybuffer' || this.handleAs === 'blob' || + this.handleAs === 'document') { + args.responseType = this.handleAs; + } + args.withCredentials = this.withCredentials; + args.callback = this.receive.bind(this); + args.url = this.url; + args.method = this.method; - scoreToBeat, - i, - currentScore; + this.response = this.error = null; + this.activeRequest = args.url && this.xhr.request(args); + return this.activeRequest; + } - if (config._f.length === 0) { - config._pf.invalidFormat = true; - config._d = new Date(NaN); - return; - } + }); - for (i = 0; i < config._f.length; i++) { - currentScore = 0; - tempConfig = copyConfig({}, config); - if (config._useUTC != null) { - tempConfig._useUTC = config._useUTC; - } - tempConfig._pf = defaultParsingFlags(); - tempConfig._f = config._f[i]; - makeDateFromStringAndFormat(tempConfig); +</script> +</polymer-element> - if (!isValid(tempConfig)) { - continue; - } +<!-- +Copyright (c) 2014 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--> - // if there is any input that was not parsed add a penalty for that format - currentScore += tempConfig._pf.charsLeftOver; +<!-- +`paper-toast` provides lightweight feedback about an operation in a small popup +at the base of the screen on mobile and at the lower left on desktop. Toasts are +above all other elements on screen, including the FAB. - //or tokens - currentScore += tempConfig._pf.unusedTokens.length * 10; +Toasts automatically disappear after a timeout or after user interaction +elsewhere on the screen, whichever comes first. Toasts can be swiped off +screen. There can be only one on the screen at a time. - tempConfig._pf.score = currentScore; +Example: - if (scoreToBeat == null || currentScore < scoreToBeat) { - scoreToBeat = currentScore; - bestMoment = tempConfig; - } - } + <paper-toast text="Your draft has been discarded." onclick="discardDraft(el)"></paper-toast> + + <script> + function discardDraft(el) { + el.show(); + } + </script> + +An action button can be presented in the toast. - extend(config, bestMoment || tempConfig); - } +Example (using Polymer's data-binding features): - // date from iso format - function parseISO(config) { - var i, l, - string = config._i, - match = isoRegex.exec(string); + <paper-toast id="toast2" text="Connection timed out. Showing limited messages."> + <div style="color: blue;" on-tap="{{retry}}">Retry</div> + </paper-toast> + +Positioning toast: - if (match) { - config._pf.iso = true; - for (i = 0, l = isoDates.length; i < l; i++) { - if (isoDates[i][1].exec(string)) { - // match[5] should be 'T' or undefined - config._f = isoDates[i][0] + (match[6] || ' '); - break; - } - } - for (i = 0, l = isoTimes.length; i < l; i++) { - if (isoTimes[i][1].exec(string)) { - config._f += isoTimes[i][0]; - break; - } - } - if (string.match(parseTokenTimezone)) { - config._f += 'Z'; - } - makeDateFromStringAndFormat(config); - } else { - config._isValid = false; - } - } +A standard toast appears near the lower left of the screen. You can change the +position by overriding bottom and left positions. - // date from iso format or fallback - function makeDateFromString(config) { - parseISO(config); - if (config._isValid === false) { - delete config._isValid; - moment.createFromInputFallback(config); - } + paper-toast { + bottom: 40px; + left: 10px; } + +To make it fit at the bottom of the screen: - function map(arr, fn) { - var res = [], i; - for (i = 0; i < arr.length; ++i) { - res.push(fn(arr[i], i)); - } - return res; + paper-toast { + bottom: 0; + left: 0; + width: 100%; } + +When the screen size is smaller than the `responsiveWidth` (default to 480px), +the toast will automatically fits at the bottom of the screen. - function makeDateFromInput(config) { - var input = config._i, matched; - if (input === undefined) { - config._d = new Date(); - } else if (isDate(input)) { - config._d = new Date(+input); - } else if ((matched = aspNetJsonRegex.exec(input)) !== null) { - config._d = new Date(+matched[1]); - } else if (typeof input === 'string') { - makeDateFromString(config); - } else if (isArray(input)) { - config._a = map(input.slice(0), function (obj) { - return parseInt(obj, 10); - }); - dateFromConfig(config); - } else if (typeof(input) === 'object') { - dateFromObject(config); - } else if (typeof(input) === 'number') { - // from milliseconds - config._d = new Date(input); - } else { - moment.createFromInputFallback(config); - } - } +@group Paper Elements +@element paper-toast +@homepage github.io +--> + +<!-- +Copyright (c) 2014 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--> - function makeDate(y, m, d, h, M, s, ms) { - //can't just apply() to create a date: - //http://stackoverflow.com/questions/181348/instantiating-a-javascript-object-by-calling-prototype-constructor-apply - var date = new Date(y, m, d, h, M, s, ms); - //the date constructor doesn't accept years < 1970 - if (y < 1970) { - date.setFullYear(y); - } - return date; - } +<!-- +Copyright (c) 2014 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--> - function makeUTCDate(y) { - var date = new Date(Date.UTC.apply(null, arguments)); - if (y < 1970) { - date.setUTCFullYear(y); - } - return date; - } +<!-- - function parseWeekday(input, locale) { - if (typeof input === 'string') { - if (!isNaN(input)) { - input = parseInt(input, 10); - } - else { - input = locale.weekdaysParse(input); - if (typeof input !== 'number') { - return null; - } +`<core-transition>` is an abstraction of an animation. It is used to implement pluggable +transitions, for example in `<core-overlay>`. You can extend this class to create a custom +animation, instantiate it, and import it where you need the animation. + +All instances of `<core-transition>` are stored in a single database with `type=transition`. +For more about the database, please see the documentation for `<core-meta>`. + +Each instance of `<core-transition>` objects are shared across all the clients, so you should +not store state information specific to the animated element in the transition. Rather, store +it on the element. + +Example: + +my-transition.html: + + <polymer-element name="my-transition" extends="core-transition"> + <script> + go: function(node) { + node.style.transition = 'opacity 1s ease-out'; + node.style.opacity = 0; } - } - return input; - } + </script> + </polymer-element> - /************************************ - Relative Time - ************************************/ + <my-transition id="my-fade-out"></my-transition> +my-transition-demo.html: - // helper function for moment.fn.from, moment.fn.fromNow, and moment.duration.fn.humanize - function substituteTimeAgo(string, number, withoutSuffix, isFuture, locale) { - return locale.relativeTime(number || 1, !!withoutSuffix, string, isFuture); - } + <link href="components/core-meta/core-meta.html" rel="import"> + <link href="my-transition.html" rel="import"> - function relativeTime(posNegDuration, withoutSuffix, locale) { - var duration = moment.duration(posNegDuration).abs(), - seconds = round(duration.as('s')), - minutes = round(duration.as('m')), - hours = round(duration.as('h')), - days = round(duration.as('d')), - months = round(duration.as('M')), - years = round(duration.as('y')), + <div id="animate-me"></div> - args = seconds < relativeTimeThresholds.s && ['s', seconds] || - minutes === 1 && ['m'] || - minutes < relativeTimeThresholds.m && ['mm', minutes] || - hours === 1 && ['h'] || - hours < relativeTimeThresholds.h && ['hh', hours] || - days === 1 && ['d'] || - days < relativeTimeThresholds.d && ['dd', days] || - months === 1 && ['M'] || - months < relativeTimeThresholds.M && ['MM', months] || - years === 1 && ['y'] || ['yy', years]; + <script> + // Get the core-transition + var meta = document.createElement('core-meta'); + meta.type = 'transition'; + var transition = meta.byId('my-fade-out'); - args[2] = withoutSuffix; - args[3] = +posNegDuration > 0; - args[4] = locale; - return substituteTimeAgo.apply({}, args); - } + // Run the animation + var animated = document.getElementById('animate-me'); + transition.go(animated); + </script> +@group Polymer Core Elements +@element core-transition +@extends core-meta +@status beta +@homepage github.io +--> +<!-- +Fired when the animation finishes. - /************************************ - Week of Year - ************************************/ +@event core-transitionend +@param {Object} detail +@param {Object} detail.node The animated node +--> - // firstDayOfWeek 0 = sun, 6 = sat - // the day of the week that starts the week - // (usually sunday or monday) - // firstDayOfWeekOfYear 0 = sun, 6 = sat - // the first week is the week that contains the first - // of this day of the week - // (eg. ISO weeks use thursday (4)) - function weekOfYear(mom, firstDayOfWeek, firstDayOfWeekOfYear) { - var end = firstDayOfWeekOfYear - firstDayOfWeek, - daysToDayOfWeek = firstDayOfWeekOfYear - mom.day(), - adjustedMoment; +<polymer-element name="core-transition" extends="core-meta" assetpath="polymer/bower_components/core-transition/"> + + <script> + Polymer('core-transition', { + + type: 'transition', - if (daysToDayOfWeek > end) { - daysToDayOfWeek -= 7; - } + /** + * Run the animation. + * + * @method go + * @param {Node} node The node to apply the animation on + * @param {Object} state State info + */ + go: function(node, state) { + this.complete(node); + }, - if (daysToDayOfWeek < end - 7) { - daysToDayOfWeek += 7; - } + /** + * Set up the animation. This may include injecting a stylesheet, + * applying styles, creating a web animations object, etc.. This + * + * @method setup + * @param {Node} node The animated node + */ + setup: function(node) { + }, - adjustedMoment = moment(mom).add(daysToDayOfWeek, 'd'); - return { - week: Math.ceil(adjustedMoment.dayOfYear() / 7), - year: adjustedMoment.year() - }; - } + /** + * Tear down the animation. + * + * @method teardown + * @param {Node} node The animated node + */ + teardown: function(node) { + }, - //http://en.wikipedia.org/wiki/ISO_week_date#Calculating_a_date_given_the_year.2C_week_number_and_weekday - function dayOfYearFromWeeks(year, week, weekday, firstDayOfWeekOfYear, firstDayOfWeek) { - var d = makeUTCDate(year, 0, 1).getUTCDay(), daysToAdd, dayOfYear; + /** + * Called when the animation completes. This function also fires the + * `core-transitionend` event. + * + * @method complete + * @param {Node} node The animated node + */ + complete: function(node) { + this.fire('core-transitionend', null, node); + }, - d = d === 0 ? 7 : d; - weekday = weekday != null ? weekday : firstDayOfWeek; - daysToAdd = firstDayOfWeek - d + (d > firstDayOfWeekOfYear ? 7 : 0) - (d < firstDayOfWeek ? 7 : 0); - dayOfYear = 7 * (week - 1) + (weekday - firstDayOfWeek) + daysToAdd + 1; + /** + * Utility function to listen to an event on a node once. + * + * @method listenOnce + * @param {Node} node The animated node + * @param {string} event Name of an event + * @param {Function} fn Event handler + * @param {Array} args Additional arguments to pass to `fn` + */ + listenOnce: function(node, event, fn, args) { + var self = this; + var listener = function() { + fn.apply(self, args); + node.removeEventListener(event, listener, false); + } + node.addEventListener(event, listener, false); + } - return { - year: dayOfYear > 0 ? year : year - 1, - dayOfYear: dayOfYear > 0 ? dayOfYear : daysInYear(year - 1) + dayOfYear - }; - } + }); + </script> +</polymer-element> +<!-- +Copyright (c) 2014 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--> - /************************************ - Top Level Functions - ************************************/ - function makeMoment(config) { - var input = config._i, - format = config._f; - config._locale = config._locale || moment.localeData(config._l); +<polymer-element name="core-key-helper" assetpath="polymer/bower_components/core-overlay/"> + <script> + Polymer('core-key-helper', { + ENTER_KEY: 13, + ESCAPE_KEY: 27 + }); + </script> +</polymer-element> + +<!-- +Copyright (c) 2014 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--> + +<polymer-element name="core-overlay-layer" assetpath="polymer/bower_components/core-overlay/"> +<template> + <style> + :host { + position: fixed; + top: 0; + left: 0; + z-index: 1000; + display: none; + } + + :host(.core-opened) { + display: block; + } + </style> + <content></content> +</template> +<script> +(function() { + + Polymer('core-overlay-layer', { + publish: { + opened: false + }, + openedChanged: function() { + this.classList.toggle('core-opened', this.opened); + }, + /** + * Adds an element to the overlay layer + */ + addElement: function(element) { + if (!this.parentNode) { + document.querySelector('body').appendChild(this); + } + if (element.parentNode !== this) { + element.__contents = []; + var ip$ = element.querySelectorAll('content'); + for (var i=0, l=ip$.length, n; (i<l) && (n = ip$[i]); i++) { + this.moveInsertedElements(n); + this.cacheDomLocation(n); + n.parentNode.removeChild(n); + element.__contents.push(n); + } + this.cacheDomLocation(element); + this.updateEventController(element); + var h = this.makeHost(); + h.shadowRoot.appendChild(element); + element.__host = h; + } + }, + makeHost: function() { + var h = document.createElement('overlay-host'); + h.createShadowRoot(); + this.appendChild(h); + return h; + }, + moveInsertedElements: function(insertionPoint) { + var n$ = insertionPoint.getDistributedNodes(); + var parent = insertionPoint.parentNode; + insertionPoint.__contents = []; + for (var i=0, l=n$.length, n; (i<l) && (n=n$[i]); i++) { + this.cacheDomLocation(n); + this.updateEventController(n); + insertionPoint.__contents.push(n); + parent.appendChild(n); + } + }, + updateEventController: function(element) { + element.eventController = this.element.findController(element); + }, + /** + * Removes an element from the overlay layer + */ + removeElement: function(element) { + element.eventController = null; + this.replaceElement(element); + var h = element.__host; + if (h) { + h.parentNode.removeChild(h); + } + }, + replaceElement: function(element) { + if (element.__contents) { + for (var i=0, c$=element.__contents, c; (c=c$[i]); i++) { + this.replaceElement(c); + } + element.__contents = null; + } + if (element.__parentNode) { + var n = element.__nextElementSibling && element.__nextElementSibling + === element.__parentNode ? element.__nextElementSibling : null; + element.__parentNode.insertBefore(element, n); + } + }, + cacheDomLocation: function(element) { + element.__nextElementSibling = element.nextElementSibling; + element.__parentNode = element.parentNode; + } + }); + +})(); +</script> +</polymer-element> - if (input === null || (format === undefined && input === '')) { - return moment.invalid({nullInput: true}); - } - if (typeof input === 'string') { - config._i = input = config._locale.preparse(input); - } +<!-- +The `core-overlay` element displays overlayed on top of other content. It starts +out hidden and is displayed by setting its `opened` property to true. +A `core-overlay's` opened state can be toggled by calling the `toggle` +method. - if (moment.isMoment(input)) { - return new Moment(input, true); - } else if (format) { - if (isArray(format)) { - makeDateFromStringAndArray(config); - } else { - makeDateFromStringAndFormat(config); - } - } else { - makeDateFromInput(config); - } +The `core-overlay` will, by default, show/hide itself when it's opened. The +`target` property may be set to another element to cause that element to +be shown when the overlay is opened. - return new Moment(config); - } +It's common to want a `core-overlay` to animate to its opened +position. The `core-overlay` element uses a `core-transition` to handle +animation. The default transition is `core-transition-fade` which +causes the overlay to fade in when displayed. See +<a href="../core-transition/">`core-transition`</a> for more +information about customizing a `core-overlay's` opening animation. The +`backdrop` property can be set to true to show a backdrop behind the overlay +that will darken the rest of the window. - moment = function (input, format, locale, strict) { - var c; +An element that should close the `core-overlay` will automatically +do so if it's given the `core-overlay-toggle` attribute. This attribute +can be customized with the `closeAttribute` property. You can also use +`closeSelector` if more general matching is needed. - if (typeof(locale) === 'boolean') { - strict = locale; - locale = undefined; - } - // object construction must be done this way. - // https://github.com/moment/moment/issues/1423 - c = {}; - c._isAMomentObject = true; - c._i = input; - c._f = format; - c._l = locale; - c._strict = strict; - c._isUTC = false; - c._pf = defaultParsingFlags(); +By default `core-overlay` will close whenever the user taps outside it or +presses the escape key. This behavior can be turned off via the +`autoCloseDisabled` property. - return makeMoment(c); - }; + <core-overlay> + <h2>Dialog</h2> + <input placeholder="say something..." autofocus> + <div>I agree with this wholeheartedly.</div> + <button core-overlay-toggle>OK</button> + </core-overlay> - moment.suppressDeprecationWarnings = false; +`core-overlay` will automatically size and position itself according to the +following rules. The overlay's size is constrained such that it does not +overflow the screen. This is done by setting maxHeight/maxWidth on the +`sizingTarget`. If the `sizingTarget` already has a setting for one of these +properties, it will not be overridden. The overlay should +be positioned via css or imperatively using the `core-overlay-position` event. +If the overlay is not positioned vertically via setting `top` or `bottom`, it +will be centered vertically. The same is true horizontally via a setting to +`left` or `right`. In addition, css `margin` can be used to provide some space +around the overlay. This can be used to ensure +that, for example, a drop shadow is always visible around the overlay. - moment.createFromInputFallback = deprecate( - 'moment construction falls back to js Date. This is ' + - 'discouraged and will be removed in upcoming major ' + - 'release. Please refer to ' + - 'https://github.com/moment/moment/issues/1407 for more info.', - function (config) { - config._d = new Date(config._i); - } - ); +@group Core Elements +@element core-overlay +@homepage github.io +--> +<!-- +Fired when the `core-overlay`'s `opened` property changes. - // Pick a moment m from moments so that m[fn](other) is true for all - // other. This relies on the function fn to be transitive. - // - // moments should either be an array of moment objects or an array, whose - // first element is an array of moment objects. - function pickBy(fn, moments) { - var res, i; - if (moments.length === 1 && isArray(moments[0])) { - moments = moments[0]; - } - if (!moments.length) { - return moment(); - } - res = moments[0]; - for (i = 1; i < moments.length; ++i) { - if (moments[i][fn](res)) { - res = moments[i]; - } - } - return res; - } +@event core-overlay-open +@param {Object} detail +@param {Object} detail.opened the opened state +--> +<!-- +Fired when the `core-overlay` has completely opened. - moment.min = function () { - var args = [].slice.call(arguments, 0); +@event core-overlay-open-completed +--> +<!-- +Fired when the `core-overlay` has completely closed. - return pickBy('isBefore', args); - }; +@event core-overlay-close-completed +--> +<!-- +Fired when the `core-overlay` needs to position itself. Optionally, implement +in order to position an overlay via code. If the overlay was not otherwise +positioned, it's important to indicate how the overlay has been positioned by +setting the `dimensions.position` object. For example, if the overlay has been +positioned via setting `right` and `top`, set dimensions.position to an +object like this: `{v: 'top', h: 'right'}`. - moment.max = function () { - var args = [].slice.call(arguments, 0); +@event core-overlay-position +@param {Object} detail +@param {Object} detail.target the overlay target +@param {Object} detail.sizingTarget the overlay sizing target +@param {Object} detail.opened the opened state +--> +<style> + .core-overlay-backdrop { + position: fixed; + top: 0; + left: 0; + width: 100vw; + height: 100vh; + background-color: black; + opacity: 0; + transition: opacity 0.2s; + } - return pickBy('isAfter', args); - }; + .core-overlay-backdrop.core-opened { + opacity: 0.6; + } +</style> - // creating with utc - moment.utc = function (input, format, locale, strict) { - var c; +<polymer-element name="core-overlay" assetpath="polymer/bower_components/core-overlay/"> +<script> +(function() { - if (typeof(locale) === 'boolean') { - strict = locale; - locale = undefined; - } - // object construction must be done this way. - // https://github.com/moment/moment/issues/1423 - c = {}; - c._isAMomentObject = true; - c._useUTC = true; - c._isUTC = true; - c._l = locale; - c._i = input; - c._f = format; - c._strict = strict; - c._pf = defaultParsingFlags(); + Polymer('core-overlay', { - return makeMoment(c).utc(); - }; + publish: { + /** + * The target element that will be shown when the overlay is + * opened. If unspecified, the core-overlay itself is the target. + * + * @attribute target + * @type Object + * @default the overlay element + */ + target: null, - // creating with unix timestamp (in seconds) - moment.unix = function (input) { - return moment(input * 1000); - }; - // duration - moment.duration = function (input, key) { - var duration = input, - // matching against regexp is expensive, do it on demand - match = null, - sign, - ret, - parseIso, - diffRes; + /** + * A `core-overlay`'s size is guaranteed to be + * constrained to the window size. To achieve this, the sizingElement + * is sized with a max-height/width. By default this element is the + * target element, but it can be specifically set to a specific element + * inside the target if that is more appropriate. This is useful, for + * example, when a region inside the overlay should scroll if needed. + * + * @attribute sizingTarget + * @type Object + * @default the target element + */ + sizingTarget: null, + + /** + * Set opened to true to show an overlay and to false to hide it. + * A `core-overlay` may be made initially opened by setting its + * `opened` attribute. + * @attribute opened + * @type boolean + * @default false + */ + opened: false, - if (moment.isDuration(input)) { - duration = { - ms: input._milliseconds, - d: input._days, - M: input._months - }; - } else if (typeof input === 'number') { - duration = {}; - if (key) { - duration[key] = input; - } else { - duration.milliseconds = input; - } - } else if (!!(match = aspNetTimeSpanJsonRegex.exec(input))) { - sign = (match[1] === '-') ? -1 : 1; - duration = { - y: 0, - d: toInt(match[DATE]) * sign, - h: toInt(match[HOUR]) * sign, - m: toInt(match[MINUTE]) * sign, - s: toInt(match[SECOND]) * sign, - ms: toInt(match[MILLISECOND]) * sign - }; - } else if (!!(match = isoDurationRegex.exec(input))) { - sign = (match[1] === '-') ? -1 : 1; - parseIso = function (inp) { - // We'd normally use ~~inp for this, but unfortunately it also - // converts floats to ints. - // inp may be undefined, so careful calling replace on it. - var res = inp && parseFloat(inp.replace(',', '.')); - // apply sign while we're at it - return (isNaN(res) ? 0 : res) * sign; - }; - duration = { - y: parseIso(match[2]), - M: parseIso(match[3]), - d: parseIso(match[4]), - h: parseIso(match[5]), - m: parseIso(match[6]), - s: parseIso(match[7]), - w: parseIso(match[8]) - }; - } else if (typeof duration === 'object' && - ('from' in duration || 'to' in duration)) { - diffRes = momentsDifference(moment(duration.from), moment(duration.to)); + /** + * If true, the overlay has a backdrop darkening the rest of the screen. + * The backdrop element is attached to the document body and may be styled + * with the class `core-overlay-backdrop`. When opened the `core-opened` + * class is applied. + * + * @attribute backdrop + * @type boolean + * @default false + */ + backdrop: false, - duration = {}; - duration.ms = diffRes.milliseconds; - duration.M = diffRes.months; - } + /** + * If true, the overlay is guaranteed to display above page content. + * + * @attribute layered + * @type boolean + * @default false + */ + layered: false, + + /** + * By default an overlay will close automatically if the user + * taps outside it or presses the escape key. Disable this + * behavior by setting the `autoCloseDisabled` property to true. + * @attribute autoCloseDisabled + * @type boolean + * @default false + */ + autoCloseDisabled: false, - ret = new Duration(duration); + /** + * By default an overlay will focus its target or an element inside + * it with the `autoFocus` attribute. Disable this + * behavior by setting the `autoFocusDisabled` property to true. + * @attribute autoFocusDisabled + * @type boolean + * @default false + */ + autoFocusDisabled: false, - if (moment.isDuration(input) && hasOwnProp(input, '_locale')) { - ret._locale = input._locale; - } + /** + * This property specifies an attribute on elements that should + * close the overlay on tap. Should not set `closeSelector` if this + * is set. + * + * @attribute closeAttribute + * @type string + * @default "core-overlay-toggle" + */ + closeAttribute: 'core-overlay-toggle', - return ret; - }; + /** + * This property specifies a selector matching elements that should + * close the overlay on tap. Should not set `closeAttribute` if this + * is set. + * + * @attribute closeSelector + * @type string + * @default "" + */ + closeSelector: '', - // version number - moment.version = VERSION; + /** + * The transition property specifies a string which identifies a + * <a href="../core-transition/">`core-transition`</a> element that + * will be used to help the overlay open and close. The default + * `core-transition-fade` will cause the overlay to fade in and out. + * + * @attribute transition + * @type string + * @default 'core-transition-fade' + */ + transition: 'core-transition-fade' - // default format - moment.defaultFormat = isoFormat; + }, - // constant that refers to the ISO standard - moment.ISO_8601 = function () {}; + captureEventName: 'tap', + targetListeners: { + 'tap': 'tapHandler', + 'keydown': 'keydownHandler', + 'core-transitionend': 'transitionend' + }, + + registerCallback: function(element) { + this.layer = document.createElement('core-overlay-layer'); + this.keyHelper = document.createElement('core-key-helper'); + this.meta = document.createElement('core-transition'); + this.scrim = document.createElement('div'); + this.scrim.className = 'core-overlay-backdrop'; + }, - // Plugins that add properties should also add the key here (null value), - // so we can properly clone ourselves. - moment.momentProperties = momentProperties; + ready: function() { + this.target = this.target || this; + // flush to ensure styles are installed before paint + Platform.flush(); + }, - // This function will be called whenever a moment is mutated. - // It is intended to keep the offset in sync with the timezone. - moment.updateOffset = function () {}; + /** + * Toggle the opened state of the overlay. + * @method toggle + */ + toggle: function() { + this.opened = !this.opened; + }, - // This function allows you to set a threshold for relative time strings - moment.relativeTimeThreshold = function (threshold, limit) { - if (relativeTimeThresholds[threshold] === undefined) { - return false; - } - if (limit === undefined) { - return relativeTimeThresholds[threshold]; - } - relativeTimeThresholds[threshold] = limit; - return true; - }; + /** + * Open the overlay. This is equivalent to setting the `opened` + * property to true. + * @method open + */ + open: function() { + this.opened = true; + }, - moment.lang = deprecate( - 'moment.lang is deprecated. Use moment.locale instead.', - function (key, value) { - return moment.locale(key, value); - } - ); + /** + * Close the overlay. This is equivalent to setting the `opened` + * property to false. + * @method close + */ + close: function() { + this.opened = false; + }, - // This function will load locale and then set the global locale. If - // no arguments are passed in, it will simply return the current global - // locale key. - moment.locale = function (key, values) { - var data; - if (key) { - if (typeof(values) !== 'undefined') { - data = moment.defineLocale(key, values); - } - else { - data = moment.localeData(key); - } + domReady: function() { + this.ensureTargetSetup(); + }, - if (data) { - moment.duration._locale = moment._locale = data; - } + targetChanged: function(old) { + if (this.target) { + // really make sure tabIndex is set + if (this.target.tabIndex < 0) { + this.target.tabIndex = -1; + } + this.addElementListenerList(this.target, this.targetListeners); + this.target.style.display = 'none'; + this.target.__overlaySetup = false; + } + if (old) { + this.removeElementListenerList(old, this.targetListeners); + var transition = this.getTransition(); + if (transition) { + transition.teardown(old); + } else { + old.style.position = ''; + old.style.outline = ''; } + old.style.display = ''; + } + }, - return moment._locale._abbr; - }; + transitionChanged: function(old) { + if (!this.target) { + return; + } + if (old) { + this.getTransition(old).teardown(this.target); + } + this.target.__overlaySetup = false; + }, - moment.defineLocale = function (name, values) { - if (values !== null) { - values.abbr = name; - if (!locales[name]) { - locales[name] = new Locale(); - } - locales[name].set(values); + // NOTE: wait to call this until we're as sure as possible that target + // is styled. + ensureTargetSetup: function() { + if (!this.target || this.target.__overlaySetup) { + return; + } + if (!this.sizingTarget) { + this.sizingTarget = this.target; + } + this.target.__overlaySetup = true; + this.target.style.display = ''; + var transition = this.getTransition(); + if (transition) { + transition.setup(this.target); + } + var style = this.target.style; + var computed = getComputedStyle(this.target); + if (computed.position === 'static') { + style.position = 'fixed'; + } + style.outline = 'none'; + style.display = 'none'; + }, - // backwards compat for now: also set the locale - moment.locale(name); + openedChanged: function() { + this.transitioning = true; + this.ensureTargetSetup(); + this.prepareRenderOpened(); + // async here to allow overlay layer to become visible. + this.async(function() { + this.target.style.display = ''; + // force layout to ensure transitions will go + this.target.offsetWidth; + this.renderOpened(); + }); + this.fire('core-overlay-open', this.opened); + }, - return locales[name]; - } else { - // useful for testing - delete locales[name]; - return null; + // tasks which must occur before opening; e.g. making the element visible + prepareRenderOpened: function() { + if (this.opened) { + addOverlay(this); + } + this.prepareBackdrop(); + // async so we don't auto-close immediately via a click. + this.async(function() { + if (!this.autoCloseDisabled) { + this.enableElementListener(this.opened, document, + this.captureEventName, 'captureHandler', true); } - }; + }); + this.enableElementListener(this.opened, window, 'resize', + 'resizeHandler'); - moment.langData = deprecate( - 'moment.langData is deprecated. Use moment.localeData instead.', - function (key) { - return moment.localeData(key); + if (this.opened) { + // force layout so SD Polyfill renders + this.target.offsetHeight; + this.discoverDimensions(); + // if we are showing, then take care when positioning + this.preparePositioning(); + this.positionTarget(); + this.updateTargetDimensions(); + this.finishPositioning(); + if (this.layered) { + this.layer.addElement(this.target); + this.layer.opened = this.opened; } - ); + } + }, - // returns locale data - moment.localeData = function (key) { - var locale; + // tasks which cause the overlay to actually open; typically play an + // animation + renderOpened: function() { + var transition = this.getTransition(); + if (transition) { + transition.go(this.target, {opened: this.opened}); + } else { + this.transitionend(); + } + this.renderBackdropOpened(); + }, - if (key && key._locale && key._locale._abbr) { - key = key._locale._abbr; + // finishing tasks; typically called via a transition + transitionend: function(e) { + // make sure this is our transition event. + if (e && e.target !== this.target) { + return; + } + this.transitioning = false; + if (!this.opened) { + this.resetTargetDimensions(); + this.target.style.display = 'none'; + this.completeBackdrop(); + removeOverlay(this); + if (this.layered) { + if (!currentOverlay()) { + this.layer.opened = this.opened; + } + this.layer.removeElement(this.target); } + } + this.fire('core-overlay-' + (this.opened ? 'open' : 'close') + + '-completed'); + this.applyFocus(); + }, - if (!key) { - return moment._locale; + prepareBackdrop: function() { + if (this.backdrop && this.opened) { + if (!this.scrim.parentNode) { + document.body.appendChild(this.scrim); + this.scrim.style.zIndex = currentOverlayZ() - 1; } + trackBackdrop(this); + } + }, - if (!isArray(key)) { - //short-circuit everything else - locale = loadLocale(key); - if (locale) { - return locale; - } - key = [key]; + renderBackdropOpened: function() { + if (this.backdrop && getBackdrops().length < 2) { + this.scrim.classList.toggle('core-opened', this.opened); + } + }, + + completeBackdrop: function() { + if (this.backdrop) { + trackBackdrop(this); + if (getBackdrops().length === 0) { + this.scrim.parentNode.removeChild(this.scrim); } + } + }, - return chooseLocale(key); - }; + preparePositioning: function() { + this.target.style.transition = this.target.style.webkitTransition = 'none'; + this.target.style.transform = this.target.style.webkitTransform = 'none'; + this.target.style.display = ''; + }, - // compare moment object - moment.isMoment = function (obj) { - return obj instanceof Moment || - (obj != null && hasOwnProp(obj, '_isAMomentObject')); - }; + discoverDimensions: function() { + if (this.dimensions) { + return; + } + var target = getComputedStyle(this.target); + var sizer = getComputedStyle(this.sizingTarget); + this.dimensions = { + position: { + v: target.top !== 'auto' ? 'top' : (target.bottom !== 'auto' ? + 'bottom' : null), + h: target.left !== 'auto' ? 'left' : (target.right !== 'auto' ? + 'right' : null), + css: target.position + }, + size: { + v: sizer.maxHeight !== 'none', + h: sizer.maxWidth !== 'none' + }, + margin: { + top: parseInt(target.marginTop) || 0, + right: parseInt(target.marginRight) || 0, + bottom: parseInt(target.marginBottom) || 0, + left: parseInt(target.marginLeft) || 0 + } + }; + }, - // for typechecking Duration objects - moment.isDuration = function (obj) { - return obj instanceof Duration; - }; + finishPositioning: function(target) { + this.target.style.display = 'none'; + this.target.style.transform = this.target.style.webkitTransform = ''; + // force layout to avoid application of transform + this.target.offsetWidth; + this.target.style.transition = this.target.style.webkitTransition = ''; + }, - for (i = lists.length - 1; i >= 0; --i) { - makeList(lists[i]); - } + getTransition: function(name) { + return this.meta.byId(name || this.transition); + }, - moment.normalizeUnits = function (units) { - return normalizeUnits(units); - }; + getFocusNode: function() { + return this.target.querySelector('[autofocus]') || this.target; + }, - moment.invalid = function (flags) { - var m = moment.utc(NaN); - if (flags != null) { - extend(m._pf, flags); + applyFocus: function() { + var focusNode = this.getFocusNode(); + if (this.opened) { + if (!this.autoFocusDisabled) { + focusNode.focus(); } - else { - m._pf.userInvalidated = true; + } else { + focusNode.blur(); + if (currentOverlay() == this) { + console.warn('Current core-overlay is attempting to focus itself as next! (bug)'); + } else { + focusOverlay(); } + } + }, - return m; - }; + positionTarget: function() { + // fire positioning event + this.fire('core-overlay-position', {target: this.target, + sizingTarget: this.sizingTarget, opened: this.opened}); + if (!this.dimensions.position.v) { + this.target.style.top = '0px'; + } + if (!this.dimensions.position.h) { + this.target.style.left = '0px'; + } + }, - moment.parseZone = function () { - return moment.apply(null, arguments).parseZone(); - }; + updateTargetDimensions: function() { + this.sizeTarget(); + this.repositionTarget(); + }, - moment.parseTwoDigitYear = function (input) { - return toInt(input) + (toInt(input) > 68 ? 1900 : 2000); - }; + sizeTarget: function() { + this.sizingTarget.style.boxSizing = 'border-box'; + var dims = this.dimensions; + var rect = this.target.getBoundingClientRect(); + if (!dims.size.v) { + this.sizeDimension(rect, dims.position.v, 'top', 'bottom', 'Height'); + } + if (!dims.size.h) { + this.sizeDimension(rect, dims.position.h, 'left', 'right', 'Width'); + } + }, - /************************************ - Moment Prototype - ************************************/ + sizeDimension: function(rect, positionedBy, start, end, extent) { + var dims = this.dimensions; + var flip = (positionedBy === end); + var m = flip ? start : end; + var ws = window['inner' + extent]; + var o = dims.margin[m] + (flip ? ws - rect[end] : + rect[start]); + var offset = 'offset' + extent; + var o2 = this.target[offset] - this.sizingTarget[offset]; + this.sizingTarget.style['max' + extent] = (ws - o - o2) + 'px'; + }, + // vertically and horizontally center if not positioned + repositionTarget: function() { + // only center if position fixed. + if (this.dimensions.position.css !== 'fixed') { + return; + } + if (!this.dimensions.position.v) { + var t = (window.innerHeight - this.target.offsetHeight) / 2; + t -= this.dimensions.margin.top; + this.target.style.top = t + 'px'; + } - extend(moment.fn = Moment.prototype, { + if (!this.dimensions.position.h) { + var l = (window.innerWidth - this.target.offsetWidth) / 2; + l -= this.dimensions.margin.left; + this.target.style.left = l + 'px'; + } + }, - clone : function () { - return moment(this); - }, + resetTargetDimensions: function() { + if (!this.dimensions.size.v) { + this.sizingTarget.style.maxHeight = ''; + } + if (!this.dimensions.size.h) { + this.sizingTarget.style.maxWidth = ''; + } + this.dimensions = null; + }, - valueOf : function () { - return +this._d + ((this._offset || 0) * 60000); - }, + tapHandler: function(e) { + // closeSelector takes precedence since closeAttribute has a default non-null value. + if (e.target && + (this.closeSelector && e.target.matches(this.closeSelector)) || + (this.closeAttribute && e.target.hasAttribute(this.closeAttribute))) { + this.toggle(); + } else { + if (this.autoCloseJob) { + this.autoCloseJob.stop(); + this.autoCloseJob = null; + } + } + }, + + // We use the traditional approach of capturing events on document + // to to determine if the overlay needs to close. However, due to + // ShadowDOM event retargeting, the event target is not useful. Instead + // of using it, we attempt to close asynchronously and prevent the close + // if a tap event is immediately heard on the target. + // TODO(sorvell): This approach will not work with modal. For + // this we need a scrim. + captureHandler: function(e) { + if (!this.autoCloseDisabled && (currentOverlay() == this)) { + this.autoCloseJob = this.job(this.autoCloseJob, function() { + this.close(); + }); + } + }, - unix : function () { - return Math.floor(+this / 1000); - }, + keydownHandler: function(e) { + if (!this.autoCloseDisabled && (e.keyCode == this.keyHelper.ESCAPE_KEY)) { + this.close(); + e.stopPropagation(); + } + }, - toString : function () { - return this.clone().locale('en').format('ddd MMM DD YYYY HH:mm:ss [GMT]ZZ'); - }, + /** + * Extensions of core-overlay should implement the `resizeHandler` + * method to adjust the size and position of the overlay when the + * browser window resizes. + * @method resizeHandler + */ + resizeHandler: function() { + this.updateTargetDimensions(); + }, - toDate : function () { - return this._offset ? new Date(+this) : this._d; - }, + // TODO(sorvell): these utility methods should not be here. + addElementListenerList: function(node, events) { + for (var i in events) { + this.addElementListener(node, i, events[i]); + } + }, - toISOString : function () { - var m = moment(this).utc(); - if (0 < m.year() && m.year() <= 9999) { - return formatMoment(m, 'YYYY-MM-DD[T]HH:mm:ss.SSS[Z]'); - } else { - return formatMoment(m, 'YYYYYY-MM-DD[T]HH:mm:ss.SSS[Z]'); - } - }, + removeElementListenerList: function(node, events) { + for (var i in events) { + this.removeElementListener(node, i, events[i]); + } + }, - toArray : function () { - var m = this; - return [ - m.year(), - m.month(), - m.date(), - m.hours(), - m.minutes(), - m.seconds(), - m.milliseconds() - ]; - }, + enableElementListener: function(enable, node, event, methodName, capture) { + if (enable) { + this.addElementListener(node, event, methodName, capture); + } else { + this.removeElementListener(node, event, methodName, capture); + } + }, - isValid : function () { - return isValid(this); - }, + addElementListener: function(node, event, methodName, capture) { + var fn = this._makeBoundListener(methodName); + if (node && fn) { + Polymer.addEventListener(node, event, fn, capture); + } + }, - isDSTShifted : function () { - if (this._a) { - return this.isValid() && compareArrays(this._a, (this._isUTC ? moment.utc(this._a) : moment(this._a)).toArray()) > 0; - } + removeElementListener: function(node, event, methodName, capture) { + var fn = this._makeBoundListener(methodName); + if (node && fn) { + Polymer.removeEventListener(node, event, fn, capture); + } + }, - return false; - }, + _makeBoundListener: function(methodName) { + var self = this, method = this[methodName]; + if (!method) { + return; + } + var bound = '_bound' + methodName; + if (!this[bound]) { + this[bound] = function(e) { + method.call(self, e); + }; + } + return this[bound]; + }, + }); - parsingFlags : function () { - return extend({}, this._pf); - }, + // TODO(sorvell): This should be an element with private state so it can + // be independent of overlay. + // track overlays for z-index and focus managemant + var overlays = []; + function addOverlay(overlay) { + var z0 = currentOverlayZ(); + overlays.push(overlay); + var z1 = currentOverlayZ(); + if (z1 <= z0) { + applyOverlayZ(overlay, z0); + } + } - invalidAt: function () { - return this._pf.overflow; - }, + function removeOverlay(overlay) { + var i = overlays.indexOf(overlay); + if (i >= 0) { + overlays.splice(i, 1); + setZ(overlay, ''); + } + } + + function applyOverlayZ(overlay, aboveZ) { + setZ(overlay.target, aboveZ + 2); + } + + function setZ(element, z) { + element.style.zIndex = z; + } - utc : function (keepLocalTime) { - return this.zone(0, keepLocalTime); - }, + function currentOverlay() { + return overlays[overlays.length-1]; + } + + var DEFAULT_Z = 10; + + function currentOverlayZ() { + var z; + var current = currentOverlay(); + if (current) { + var z1 = window.getComputedStyle(current.target).zIndex; + if (!isNaN(z1)) { + z = Number(z1); + } + } + return z || DEFAULT_Z; + } + + function focusOverlay() { + var current = currentOverlay(); + // We have to be careful to focus the next overlay _after_ any current + // transitions are complete (due to the state being toggled prior to the + // transition). Otherwise, we risk infinite recursion when a transitioning + // (closed) overlay becomes the current overlay. + // + // NOTE: We make the assumption that any overlay that completes a transition + // will call into focusOverlay to kick the process back off. Currently: + // transitionend -> applyFocus -> focusOverlay. + if (current && !current.transitioning) { + current.applyFocus(); + } + } - local : function (keepLocalTime) { - if (this._isUTC) { - this.zone(0, keepLocalTime); - this._isUTC = false; + var backdrops = []; + function trackBackdrop(element) { + if (element.opened) { + backdrops.push(element); + } else { + var i = backdrops.indexOf(element); + if (i >= 0) { + backdrops.splice(i, 1); + } + } + } - if (keepLocalTime) { - this.add(this._dateTzOffset(), 'm'); - } - } - return this; - }, + function getBackdrops() { + return backdrops; + } +})(); +</script> +</polymer-element> - format : function (inputString) { - var output = formatMoment(this, inputString || moment.defaultFormat); - return this.localeData().postformat(output); - }, +<!-- +Copyright (c) 2014 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--> - add : createAdder(1, 'add'), +<!-- - subtract : createAdder(-1, 'subtract'), +`<core-transition-css>` implements CSS transitions as `<core-transition>` objects so they can be +reused in a pluggable transition system such as in `<core-overlay>`. Currently this class has +some specific support to animate an element from and to the viewport such as a dialog, but you +can override it for different effects. - diff : function (input, units, asFloat) { - var that = makeAs(input, this), - zoneDiff = (this.zone() - that.zone()) * 6e4, - diff, output, daysAdjust; +Example: - units = normalizeUnits(units); +my-css-transition.html: - if (units === 'year' || units === 'month') { - // average number of days in the months in the given dates - diff = (this.daysInMonth() + that.daysInMonth()) * 432e5; // 24 * 60 * 60 * 1000 / 2 - // difference in months - output = ((this.year() - that.year()) * 12) + (this.month() - that.month()); - // adjust by taking difference in days, average number of days - // and dst in the given months. - daysAdjust = (this - moment(this).startOf('month')) - - (that - moment(that).startOf('month')); - // same as above but with zones, to negate all dst - daysAdjust -= ((this.zone() - moment(this).startOf('month').zone()) - - (that.zone() - moment(that).startOf('month').zone())) * 6e4; - output += daysAdjust / diff; - if (units === 'year') { - output = output / 12; - } - } else { - diff = (this - that); - output = units === 'second' ? diff / 1e3 : // 1000 - units === 'minute' ? diff / 6e4 : // 1000 * 60 - units === 'hour' ? diff / 36e5 : // 1000 * 60 * 60 - units === 'day' ? (diff - zoneDiff) / 864e5 : // 1000 * 60 * 60 * 24, negate dst - units === 'week' ? (diff - zoneDiff) / 6048e5 : // 1000 * 60 * 60 * 24 * 7, negate dst - diff; + <polymer-element name="my-css-transition" extends="core-transition-css"> + <template> + <style> + :host(.my-transition) { + opacity: 0; + transition: transform 1s ease-out, opacity 1s ease-out; } - return asFloat ? output : absRound(output); - }, + :host(.my-transition.my-opened) { + opacity: 1; + transform: none; + } + :host(.my-transition-top) { + transform: translateY(-100vh); + } + :host(.my-transition-bottom) { + transform: translateY(100vh); + } + </style> + </template> + <script> + Polymer({ + baseClass: 'my-transition', + openedClass: 'my-opened' + }); + </script> + </polymer-element> - from : function (time, withoutSuffix) { - return moment.duration({to: this, from: time}).locale(this.locale()).humanize(!withoutSuffix); - }, + <my-css-transition id="my-transition-top" transitionType="top"></my-css-transition> + <my-css-transition id="my-transition-bottom" transitionType="bottom"></my-css-transition> - fromNow : function (withoutSuffix) { - return this.from(moment(), withoutSuffix); - }, +my-css-transition-demo.html - calendar : function (time) { - // We want to compare the start of today, vs this. - // Getting start-of-today depends on whether we're zone'd or not. - var now = time || moment(), - sod = makeAs(now, this).startOf('day'), - diff = this.diff(sod, 'days', true), - format = diff < -6 ? 'sameElse' : - diff < -1 ? 'lastWeek' : - diff < 0 ? 'lastDay' : - diff < 1 ? 'sameDay' : - diff < 2 ? 'nextDay' : - diff < 7 ? 'nextWeek' : 'sameElse'; - return this.format(this.localeData().calendar(format, this)); - }, + <link href="components/core-meta/core-meta.html" rel="import"> + <link href="my-css-transition.html"> - isLeapYear : function () { - return isLeapYear(this.year()); - }, + <div id="animate-me"></div> - isDST : function () { - return (this.zone() < this.clone().month(0).zone() || - this.zone() < this.clone().month(5).zone()); - }, + <script> + // Get the core-transition + var meta = document.createElement('core-meta'); + meta.type = 'transition'; + var transition1 = meta.byId('my-transition-top'); - day : function (input) { - var day = this._isUTC ? this._d.getUTCDay() : this._d.getDay(); - if (input != null) { - input = parseWeekday(input, this.localeData()); - return this.add(input - day, 'd'); - } else { - return day; - } - }, + // Set up the animation + var animated = document.getElementById('animate-me'); + transition1.setup(animated); + transition1.go(animated, {opened: true}); + </script> - month : makeAccessor('Month', true), +The first element in the template of a `<core-transition-css>` object should be a stylesheet. It +will be injected to the scope of the animated node in the `setup` function. The node is initially +invisible with `opacity: 0`, and you can transition it to an "opened" state by passing +`{opened: true}` to the `go` function. - startOf : function (units) { - units = normalizeUnits(units); - // the following switch intentionally omits break keywords - // to utilize falling through the cases. - switch (units) { - case 'year': - this.month(0); - /* falls through */ - case 'quarter': - case 'month': - this.date(1); - /* falls through */ - case 'week': - case 'isoWeek': - case 'day': - this.hours(0); - /* falls through */ - case 'hour': - this.minutes(0); - /* falls through */ - case 'minute': - this.seconds(0); - /* falls through */ - case 'second': - this.milliseconds(0); - /* falls through */ - } +All nodes being animated will get the class `my-transition` added in the `setup` function. +Additionally, the class `my-transition-<transitionType>` will be applied. You can use the +`transitionType` attribute to implement several different behaviors with the same +`<core-transition-css>` object. In the above example, `<my-css-transition>` implements both +sliding the node from the top of the viewport and from the bottom of the viewport. + +Available transitions +--------------------- - // weeks are a special case - if (units === 'week') { - this.weekday(0); - } else if (units === 'isoWeek') { - this.isoWeekday(1); - } +`<core-transition-css>` includes several commonly used transitions. - // quarters are also special - if (units === 'quarter') { - this.month(Math.floor(this.month() / 3) * 3); - } +`core-transition-fade`: Animates from `opacity: 0` to `opacity: 1` when it opens. - return this; - }, +`core-transition-center`: Zooms the node into the final size. - endOf: function (units) { - units = normalizeUnits(units); - return this.startOf(units).add(1, (units === 'isoWeek' ? 'week' : units)).subtract(1, 'ms'); - }, +`core-transition-top`: Slides the node into the final position from the top. - isAfter: function (input, units) { - units = normalizeUnits(typeof units !== 'undefined' ? units : 'millisecond'); - if (units === 'millisecond') { - input = moment.isMoment(input) ? input : moment(input); - return +this > +input; - } else { - return +this.clone().startOf(units) > +moment(input).startOf(units); - } - }, +`core-transition-bottom`: Slides the node into the final position from the bottom. - isBefore: function (input, units) { - units = normalizeUnits(typeof units !== 'undefined' ? units : 'millisecond'); - if (units === 'millisecond') { - input = moment.isMoment(input) ? input : moment(input); - return +this < +input; - } else { - return +this.clone().startOf(units) < +moment(input).startOf(units); - } - }, +`core-transition-left`: Slides the node into the final position from the left. - isSame: function (input, units) { - units = normalizeUnits(units || 'millisecond'); - if (units === 'millisecond') { - input = moment.isMoment(input) ? input : moment(input); - return +this === +input; - } else { - return +this.clone().startOf(units) === +makeAs(input, this).startOf(units); - } - }, +`core-transition-right`: Slides the node into the final position from the right. - min: deprecate( - 'moment().min is deprecated, use moment.min instead. https://github.com/moment/moment/issues/1548', - function (other) { - other = moment.apply(null, arguments); - return other < this ? this : other; - } - ), +@group Polymer Core Elements +@element core-transition-css +@extends core-transition +@status beta +@homepage github.io +--> - max: deprecate( - 'moment().max is deprecated, use moment.max instead. https://github.com/moment/moment/issues/1548', - function (other) { - other = moment.apply(null, arguments); - return other > this ? this : other; - } - ), - // keepLocalTime = true means only change the timezone, without - // affecting the local hour. So 5:31:26 +0300 --[zone(2, true)]--> - // 5:31:26 +0200 It is possible that 5:31:26 doesn't exist int zone - // +0200, so we adjust the time as needed, to be valid. - // - // Keeping the time actually adds/subtracts (one hour) - // from the actual represented time. That is why we call updateOffset - // a second time. In case it wants us to change the offset again - // _changeInProgress == true case, then we have to adjust, because - // there is no such time in the given timezone. - zone : function (input, keepLocalTime) { - var offset = this._offset || 0, - localAdjust; - if (input != null) { - if (typeof input === 'string') { - input = timezoneMinutesFromString(input); - } - if (Math.abs(input) < 16) { - input = input * 60; - } - if (!this._isUTC && keepLocalTime) { - localAdjust = this._dateTzOffset(); - } - this._offset = input; - this._isUTC = true; - if (localAdjust != null) { - this.subtract(localAdjust, 'm'); - } - if (offset !== input) { - if (!keepLocalTime || this._changeInProgress) { - addOrSubtractDurationFromMoment(this, - moment.duration(offset - input, 'm'), 1, false); - } else if (!this._changeInProgress) { - this._changeInProgress = true; - moment.updateOffset(this, true); - this._changeInProgress = null; - } - } - } else { - return this._isUTC ? offset : this._dateTzOffset(); - } - return this; - }, - zoneAbbr : function () { - return this._isUTC ? 'UTC' : ''; - }, +<polymer-element name="core-transition-css" extends="core-transition" attributes="transitionType" assetpath="polymer/bower_components/core-transition/"> +<template> + <style no-shim="">/* Copyright (c) 2014 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt */ - zoneName : function () { - return this._isUTC ? 'Coordinated Universal Time' : ''; - }, +:host(.core-transition) { + outline: none; + overflow: auto; + opacity: 0; + transition: transform 0.2s ease-in-out, opacity 0.2s ease-in; + -webkit-transition: -webkit-transform 0.2s ease-in-out, opacity 0.2s ease-in; +} - parseZone : function () { - if (this._tzm) { - this.zone(this._tzm); - } else if (typeof this._i === 'string') { - this.zone(this._i); - } - return this; - }, - hasAlignedHourOffset : function (input) { - if (!input) { - input = 0; - } - else { - input = moment(input).zone(); - } +:host(.core-transition.core-opened) { + opacity: 1; + transform: translateZ(0); + -webkit-transform: translateZ(0); +} - return (this.zone() - input) % 60 === 0; - }, +:host(.core-transition-center) { + transform: scale(0.5); + -webkit-transform: scale(0.5); +} - daysInMonth : function () { - return daysInMonth(this.year(), this.month()); - }, +:host(.core-transition-top) { + transform: translateY(-200%); + -webkit-transform: translateY(-200%); +} - dayOfYear : function (input) { - var dayOfYear = round((moment(this).startOf('day') - moment(this).startOf('year')) / 864e5) + 1; - return input == null ? dayOfYear : this.add((input - dayOfYear), 'd'); - }, +:host(.core-transition-bottom) { + transform: translateY(200%); + -webkit-transform: translateY(200%); +} - quarter : function (input) { - return input == null ? Math.ceil((this.month() + 1) / 3) : this.month((input - 1) * 3 + this.month() % 3); - }, +:host(.core-transition-left) { + transform: translateX(-200%); + -webkit-transform: translateX(-200%); +} - weekYear : function (input) { - var year = weekOfYear(this, this.localeData()._week.dow, this.localeData()._week.doy).year; - return input == null ? year : this.add((input - year), 'y'); - }, +:host(.core-transition-right) { + transform: translateX(200%); + -webkit-transform: translateX(200%); +}</style> +</template> +<script> - isoWeekYear : function (input) { - var year = weekOfYear(this, 1, 4).year; - return input == null ? year : this.add((input - year), 'y'); - }, + Polymer('core-transition-css', { + + /** + * The class that will be applied to all animated nodes. + * + * @attribute baseClass + * @type string + * @default "core-transition" + */ + baseClass: 'core-transition', - week : function (input) { - var week = this.localeData().week(this); - return input == null ? week : this.add((input - week) * 7, 'd'); - }, + /** + * The class that will be applied to nodes in the opened state. + * + * @attribute openedClass + * @type string + * @default "core-opened" + */ + openedClass: 'core-opened', - isoWeek : function (input) { - var week = weekOfYear(this, 1, 4).week; - return input == null ? week : this.add((input - week) * 7, 'd'); - }, + /** + * The class that will be applied to nodes in the closed state. + * + * @attribute closedClass + * @type string + * @default "core-closed" + */ + closedClass: 'core-closed', + + /** + * Event to listen to for animation completion. + * + * @attribute completeEventName + * @type string + * @default "transitionEnd" + */ + completeEventName: 'transitionend', + + publish: { + /** + * A secondary configuration attribute for the animation. The class + * `<baseClass>-<transitionType` is applied to the animated node during + * `setup`. + * + * @attribute transitionType + * @type string + */ + transitionType: null + }, + + registerCallback: function(element) { + this.transitionStyle = element.templateContent().firstElementChild; + }, - weekday : function (input) { - var weekday = (this.day() + 7 - this.localeData()._week.dow) % 7; - return input == null ? weekday : this.add(input - weekday, 'd'); - }, + // template is just for loading styles, we don't need a shadowRoot + fetchTemplate: function() { + return null; + }, - isoWeekday : function (input) { - // behaves the same as moment#day except - // as a getter, returns 7 instead of 0 (1-7 range instead of 0-6) - // as a setter, sunday should belong to the previous week. - return input == null ? this.day() || 7 : this.day(this.day() % 7 ? input : input - 7); - }, + go: function(node, state) { + if (state.opened !== undefined) { + this.transitionOpened(node, state.opened); + } + }, - isoWeeksInYear : function () { - return weeksInYear(this.year(), 1, 4); - }, + setup: function(node) { + if (!node._hasTransitionStyle) { + if (!node.shadowRoot) { + node.createShadowRoot().innerHTML = '<content></content>'; + } + this.installScopeStyle(this.transitionStyle, 'transition', + node.shadowRoot); + node._hasTransitionStyle = true; + } + node.classList.add(this.baseClass); + if (this.transitionType) { + node.classList.add(this.baseClass + '-' + this.transitionType); + } + }, - weeksInYear : function () { - var weekInfo = this.localeData()._week; - return weeksInYear(this.year(), weekInfo.dow, weekInfo.doy); - }, + teardown: function(node) { + node.classList.remove(this.baseClass); + if (this.transitionType) { + node.classList.remove(this.baseClass + '-' + this.transitionType); + } + }, - get : function (units) { - units = normalizeUnits(units); - return this[units](); - }, + transitionOpened: function(node, opened) { + this.listenOnce(node, this.completeEventName, function() { + node.classList.toggle(this.revealedClass, opened); + if (!opened) { + node.classList.remove(this.closedClass); + } + this.complete(node); + }); + node.classList.toggle(this.openedClass, opened); + node.classList.toggle(this.closedClass, !opened); + } - set : function (units, value) { - units = normalizeUnits(units); - if (typeof this[units] === 'function') { - this[units](value); - } - return this; - }, + }); +</script> +</polymer-element> - // If passed a locale key, it will set the locale for this - // instance. Otherwise, it will return the locale configuration - // variables for this instance. - locale : function (key) { - var newLocaleData; +<core-transition-css id="core-transition-fade"></core-transition-css> +<core-transition-css id="core-transition-center" transitiontype="center"></core-transition-css> +<core-transition-css id="core-transition-top" transitiontype="top"></core-transition-css> +<core-transition-css id="core-transition-bottom" transitiontype="bottom"></core-transition-css> +<core-transition-css id="core-transition-left" transitiontype="left"></core-transition-css> +<core-transition-css id="core-transition-right" transitiontype="right"></core-transition-css> - if (key === undefined) { - return this._locale._abbr; - } else { - newLocaleData = moment.localeData(key); - if (newLocaleData != null) { - this._locale = newLocaleData; - } - return this; - } - }, +<!-- +Copyright (c) 2014 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--> +<!-- +/** + * @group Polymer Core Elements + * @element core-media-query + * @status beta + * @homepage github.io + * + * core-media-query can be used to data bind to a CSS media query. + * The "query" property is a bare CSS media query. + * The "queryMatches" property will be a boolean representing if the page matches that media query. + * + * core-media-query uses media query listeners to dynamically update the "queryMatches" property. + * A "core-media-change" event also fires when queryMatches changes. + * + * Example: + * + * <core-media-query query="max-width: 640px" queryMatches="{{phoneScreen}}"></core-media-query> + * + */ - lang : deprecate( - 'moment().lang() is deprecated. Use moment().localeData() instead.', - function (key) { - if (key === undefined) { - return this.localeData(); - } else { - return this.locale(key); - } - } - ), + /** + * Fired when the media query state changes + * + * @event core-media-change + */ +--> - localeData : function () { - return this._locale; - }, - _dateTzOffset : function () { - // On Firefox.24 Date#getTimezoneOffset returns a floating point. - // https://github.com/moment/moment/pull/1871 - return Math.round(this._d.getTimezoneOffset() / 15) * 15; - } - }); +<polymer-element name="core-media-query" attributes="query queryMatches" assetpath="polymer/bower_components/core-media-query/"> + <template> + <style> + :host { + display: none; + } + </style> + </template> + <script> + Polymer('core-media-query', { - function rawMonthSetter(mom, value) { - var dayOfMonth; + /** + * The Boolean return value of the media query + * + * @attribute queryMatches + * @type Boolean + * @default false + */ + queryMatches: false, - // TODO: Move this out of here! - if (typeof value === 'string') { - value = mom.localeData().monthsParse(value); - // TODO: Another silent failure? - if (typeof value !== 'number') { - return mom; - } + /** + * The CSS media query to evaulate + * + * @attribute query + * @type string + * @default '' + */ + query: '', + ready: function() { + this._mqHandler = this.queryHandler.bind(this); + this._mq = null; + }, + queryChanged: function() { + if (this._mq) { + this._mq.removeListener(this._mqHandler); + } + var query = this.query; + if (query[0] !== '(') { + query = '(' + this.query + ')'; } + this._mq = window.matchMedia(query); + this._mq.addListener(this._mqHandler); + this.queryHandler(this._mq); + }, + queryHandler: function(mq) { + this.queryMatches = mq.matches; + this.asyncFire('core-media-change', mq); + } + }); + </script> +</polymer-element> - dayOfMonth = Math.min(mom.date(), - daysInMonth(mom.year(), value)); - mom._d['set' + (mom._isUTC ? 'UTC' : '') + 'Month'](value, dayOfMonth); - return mom; - } - function rawGetter(mom, unit) { - return mom._d['get' + (mom._isUTC ? 'UTC' : '') + unit](); - } +<polymer-element name="paper-toast" attributes="text duration opened responsiveWidth swipeDisabled" role="status" assetpath="polymer/bower_components/paper-toast/"> - function rawSetter(mom, unit, value) { - if (unit === 'Month') { - return rawMonthSetter(mom, value); - } else { - return mom._d['set' + (mom._isUTC ? 'UTC' : '') + unit](value); - } - } +<template> - function makeAccessor(unit, keepTime) { - return function (value) { - if (value != null) { - rawSetter(this, unit, value); - moment.updateOffset(this, keepTime); - return this; - } else { - return rawGetter(this, unit); - } - }; - } + <style>/* +Copyright (c) 2014 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +*/ - moment.fn.millisecond = moment.fn.milliseconds = makeAccessor('Milliseconds', false); - moment.fn.second = moment.fn.seconds = makeAccessor('Seconds', false); - moment.fn.minute = moment.fn.minutes = makeAccessor('Minutes', false); - // Setting the hour should keep the time, because the user explicitly - // specified which hour he wants. So trying to maintain the same hour (in - // a new timezone) makes sense. Adding/subtracting hours does not follow - // this rule. - moment.fn.hour = moment.fn.hours = makeAccessor('Hours', true); - // moment.fn.month is defined separately - moment.fn.date = makeAccessor('Date', true); - moment.fn.dates = deprecate('dates accessor is deprecated. Use date instead.', makeAccessor('Date', true)); - moment.fn.year = makeAccessor('FullYear', true); - moment.fn.years = deprecate('years accessor is deprecated. Use year instead.', makeAccessor('FullYear', true)); +:host { + display: inline-block; + background: #323232; + color: #f1f1f1; + min-height: 48px; + min-width: 288px; + padding: 16px 24px 12px; + box-sizing: border-box; + -moz-box-sizing: border-box; + box-shadow: 0 2px 5px 0 rgba(0, 0, 0, 0.26); + border-radius: 2px; + bottom: 12px; + left: 12px; + font-size: 14px; + cursor: default; +} - // add plural methods - moment.fn.days = moment.fn.day; - moment.fn.months = moment.fn.month; - moment.fn.weeks = moment.fn.week; - moment.fn.isoWeeks = moment.fn.isoWeek; - moment.fn.quarters = moment.fn.quarter; +:host(.capsule) { + border-radius: 24px; +} - // add aliased format methods - moment.fn.toJSON = moment.fn.toISOString; +:host(.fit-bottom) { + bottom: 0; + left: 0; + width: 100%; + min-width: 0; + border-radius: 0; +} - /************************************ - Duration Prototype - ************************************/ +:host(.core-transition.dragging) { + transition: none; +} +:host(.core-transition.fade-out-down), +:host(.core-transition.fade-out-up), +:host(.core-transition.fade-out-right), +:host(.core-transition.fade-out-left) { + opacity: 0; + transition: -webkit-transform 0.08s ease-in-out, opacity 0.08s ease-in-out; + transition: transform 0.08s ease-in-out, opacity 0.08s ease-in-out; +} - function daysToYears (days) { - // 400 years have 146097 days (taking into account leap year rules) - return days * 400 / 146097; - } +:host(.core-transition.fade-out-down) { + -webkit-transform: translate(0, 100%); + transform: translate(0, 100%); +} - function yearsToDays (years) { - // years * 365 + absRound(years / 4) - - // absRound(years / 100) + absRound(years / 400); - return years * 146097 / 400; - } +:host(.core-transition.fade-out-up) { + -webkit-transform: translate(0, -100%); + transform: translate(0, -100%); +} - extend(moment.duration.fn = Duration.prototype, { +:host(.core-transition.fade-out-right) { + -webkit-transform: translate(100%, 0); + transform: translate(100%, 0); +} - _bubble : function () { - var milliseconds = this._milliseconds, - days = this._days, - months = this._months, - data = this._data, - seconds, minutes, hours, years = 0; +:host(.core-transition.fade-out-left) { + -webkit-transform: translate(-100%, 0); + transform: translate(-100%, 0); +} - // The following code bubbles up values, see the tests for - // examples of what that means. - data.milliseconds = milliseconds % 1000; +.toast-container { + overflow: hidden; +} - seconds = absRound(milliseconds / 1000); - data.seconds = seconds % 60; +.toast-action { + padding-left: 24px; + cursor: pointer; + text-transform: uppercase; +} +</style> - minutes = absRound(seconds / 60); - data.minutes = minutes % 60; + <core-overlay autofocusdisabled="" opened="{{opened}}" target="{{}}" sizingtarget="{{$.container}}" transition="core-transition-bottom"></core-overlay> - hours = absRound(minutes / 60); - data.hours = hours % 24; + <div class="toast-container" horizontal="" layout=""> - days += absRound(hours / 24); + <div class="toast-text" flex="">{{text}}</div> + + <div class="toast-text toast-action" on-tap="{{dismiss}}"> + <content></content> + </div> - // Accurately convert days to years, assume start from year 0. - years = absRound(daysToYears(days)); - days -= absRound(yearsToDays(years)); + </div> + + <core-media-query query="max-width: {{responsiveWidth}}" querymatches="{{narrowMode}}"></core-media-query> - // 30 days to a month - // TODO (iskren): Use anchor date (like 1st Jan) to compute this. - months += absRound(days / 30); - days %= 30; +</template> +<script> + + (function() { + + var currentToast; + + Polymer('paper-toast', { + + /** + * The text shows in a toast. + * + * @attribute text + * @type string + * @default '' + */ + text: '', + + /** + * The duration in milliseconds to show the toast. + * + * @attribute duration + * @type number + * @default 3000 + */ + duration: 3000, + + /** + * Set opened to true to show the toast and to false to hide it. + * + * @attribute opened + * @type boolean + * @default false + */ + opened: false, + + /** + * Min-width when the toast changes to narrow layout. In narrow layout, + * the toast fits at the bottom of the screen when opened. + * + * @attribute responsiveWidth + * @type string + * @default '480px' + */ + responsiveWidth: '480px', + + /** + * If true, the toast can't be swiped. + * + * @attribute swipeDisabled + * @type boolean + * @default false + */ + swipeDisabled: false, + + eventDelegates: { + trackstart: 'trackStart', + track: 'track', + trackend: 'trackEnd', + transitionend: 'transitionEnd' + }, + + narrowModeChanged: function() { + this.classList.toggle('fit-bottom', this.narrowMode); + }, + + openedChanged: function() { + if (this.opened) { + this.dismissJob = this.job(this.dismissJob, this.dismiss, this.duration); + } else { + this.dismissJob && this.dismissJob.stop(); + this.dismiss(); + } + }, + + /** + * Toggle the opened state of the toast. + * @method toggle + */ + toggle: function() { + this.opened = !this.opened; + }, + + /** + * Show the toast for the specified duration + * @method show + */ + show: function() { + if (currentToast) { + currentToast.dismiss(); + } + currentToast = this; + this.opened = true; + }, + + /** + * Dismiss the toast and hide it. + * @method dismiss + */ + dismiss: function() { + if (this.dragging) { + this.shouldDismiss = true; + } else { + this.opened = false; + if (currentToast === this) { + currentToast = null; + } + } + }, + + trackStart: function(e) { + if (!this.swipeDisabled) { + e.preventTap(); + this.vertical = e.yDirection; + this.w = this.offsetWidth; + this.h = this.offsetHeight; + this.dragging = true; + this.classList.add('dragging'); + } + }, + + track: function(e) { + if (this.dragging) { + var s = this.style; + if (this.vertical) { + var y = e.dy; + s.opacity = (this.h - Math.abs(y)) / this.h; + s.webkitTransform = s.transform = 'translate3d(0, ' + y + 'px, 0)'; + } else { + var x = e.dx; + s.opacity = (this.w - Math.abs(x)) / this.w; + s.webkitTransform = s.transform = 'translate3d(' + x + 'px, 0, 0)'; + } + } + }, + + trackEnd: function(e) { + if (this.dragging) { + this.classList.remove('dragging'); + this.style.opacity = null; + this.style.webkitTransform = this.style.transform = null; + var cl = this.classList; + if (this.vertical) { + cl.toggle('fade-out-down', e.yDirection === 1 && e.dy > 0); + cl.toggle('fade-out-up', e.yDirection === -1 && e.dy < 0); + } else { + cl.toggle('fade-out-right', e.xDirection === 1 && e.dx > 0); + cl.toggle('fade-out-left', e.xDirection === -1 && e.dx < 0); + } + this.dragging = false; + } + }, + + transitionEnd: function() { + var cl = this.classList; + if (cl.contains('fade-out-right') || cl.contains('fade-out-left') || + cl.contains('fade-out-down') || cl.contains('fade-out-up')) { + this.dismiss(); + cl.remove('fade-out-right', 'fade-out-left', + 'fade-out-down', 'fade-out-up'); + } else if (this.shouldDismiss) { + this.dismiss(); + } + this.shouldDismiss = false; + } + + }); + + })(); - // 12 months -> 1 year - years += absRound(months / 12); - months %= 12; +</script> +</polymer-element> - data.days = days; - data.months = months; - data.years = years; - }, - abs : function () { - this._milliseconds = Math.abs(this._milliseconds); - this._days = Math.abs(this._days); - this._months = Math.abs(this._months); - this._data.milliseconds = Math.abs(this._data.milliseconds); - this._data.seconds = Math.abs(this._data.seconds); - this._data.minutes = Math.abs(this._data.minutes); - this._data.hours = Math.abs(this._data.hours); - this._data.months = Math.abs(this._data.months); - this._data.years = Math.abs(this._data.years); +<!-- +Copyright (c) 2014 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--> - return this; - }, +<!-- +Provides a dialog overlay. - weeks : function () { - return absRound(this.days() / 7); - }, +Child elements that include a `dismissive` attribute are positioned in the lower left corner of the dialog. Elements that use the `affirmative` attribute are positioned in the lower right corner. - valueOf : function () { - return this._milliseconds + - this._days * 864e5 + - (this._months % 12) * 2592e6 + - toInt(this._months / 12) * 31536e6; - }, +Child elements that include the `dismissive` or `affirmative` attribute will automatically toggle the dialog when clicked. - humanize : function (withSuffix) { - var output = relativeTime(this, !withSuffix, this.localeData()); +One child element should have the `autofocus` attribute so that the Enter key will automatically take action. This is +especially important for screen reader environments. - if (withSuffix) { - output = this.localeData().pastFuture(+this, output); - } +Example: - return this.localeData().postformat(output); - }, + <paper-dialog heading="Title for dialog"> + <p>Lorem ipsum ....</p> + <p>Id qui scripta ...</p> + <paper-button label="More Info..." dismissive></paper-button> + <paper-button label="Decline" affirmative></paper-button> + <paper-button label="Accept" affirmative autofocus></paper-button> + </paper-dialog> - add : function (input, val) { - // supports only 2.0-style add(1, 's') or add(moment) - var dur = moment.duration(input, val); +#### Transitions - this._milliseconds += dur._milliseconds; - this._days += dur._days; - this._months += dur._months; +`<paper-dialog>` can be used with `<paper-transition>` to transition the overlay open and close. - this._bubble(); +To use a transition, import `paper-dialog-transition.html` alongside paper-dialog: - return this; - }, + <link rel="import" href="paper-dialog/paper-dialog-transition.html"> - subtract : function (input, val) { - var dur = moment.duration(input, val); +Then set the `transition` attribute: - this._milliseconds -= dur._milliseconds; - this._days -= dur._days; - this._months -= dur._months; + <paper-dialog heading="Title for dialog" transition="paper-dialog-transition-center"> - this._bubble(); + <paper-dialog heading="Title for dialog" transition="paper-dialog-transition-bottom"> - return this; - }, +@group Paper Elements +@element paper-dialog +@homepage github.io +--> +<!-- +Fired when the dialog's `opened` property changes. - get : function (units) { - units = normalizeUnits(units); - return this[units.toLowerCase() + 's'](); - }, +@event core-overlay-open +@param {Object} detail +@param {Object} detail.opened the opened state +--> - as : function (units) { - var days, months; - units = normalizeUnits(units); - if (units === 'month' || units === 'year') { - days = this._days + this._milliseconds / 864e5; - months = this._months + daysToYears(days) * 12; - return units === 'month' ? months : months / 12; - } else { - // handle milliseconds separately because of floating point math errors (issue #1867) - days = this._days + yearsToDays(this._months / 12); - switch (units) { - case 'week': return days / 7 + this._milliseconds / 6048e5; - case 'day': return days + this._milliseconds / 864e5; - case 'hour': return days * 24 + this._milliseconds / 36e5; - case 'minute': return days * 24 * 60 + this._milliseconds / 6e4; - case 'second': return days * 24 * 60 * 60 + this._milliseconds / 1000; - // Math.floor prevents floating point math errors here - case 'millisecond': return Math.floor(days * 24 * 60 * 60 * 1000) + this._milliseconds; - default: throw new Error('Unknown unit ' + units); - } - } - }, - lang : moment.fn.lang, - locale : moment.fn.locale, - toIsoString : deprecate( - 'toIsoString() is deprecated. Please use toISOString() instead ' + - '(notice the capitals)', - function () { - return this.toISOString(); - } - ), +<polymer-element name="paper-dialog" attributes="opened heading transition autoCloseDisabled backdrop layered closeSelector" role="dialog" assetpath="polymer/bower_components/paper-dialog/"> - toISOString : function () { - // inspired by https://github.com/dordille/moment-isoduration/blob/master/moment.isoduration.js - var years = Math.abs(this.years()), - months = Math.abs(this.months()), - days = Math.abs(this.days()), - hours = Math.abs(this.hours()), - minutes = Math.abs(this.minutes()), - seconds = Math.abs(this.seconds() + this.milliseconds() / 1000); + <template> - if (!this.asSeconds()) { - // this is the same as C#'s (Noda) and python (isodate)... - // but not other JS (goog.date) - return 'P0D'; - } + <style>/* + * @license + * Copyright (c) 2014 The Polymer Project Authors. All rights reserved. + * This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt + * The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt + * The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt + * Code distributed by Google as part of the polymer project is also + * subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt + */ - return (this.asSeconds() < 0 ? '-' : '') + - 'P' + - (years ? years + 'Y' : '') + - (months ? months + 'M' : '') + - (days ? days + 'D' : '') + - ((hours || minutes || seconds) ? 'T' : '') + - (hours ? hours + 'H' : '') + - (minutes ? minutes + 'M' : '') + - (seconds ? seconds + 'S' : ''); - }, +:host { + background: white; + color: rgba(0, 0, 0, 0.87); +} - localeData : function () { - return this._locale; - } - }); +#shadow { + position: absolute; + top: 0; + left: 0; + bottom: 0; + right: 0; + z-index: -1; +} - moment.duration.fn.toString = moment.duration.fn.toISOString; +#container { + overflow: hidden; +} - function makeDurationGetter(name) { - moment.duration.fn[name] = function () { - return this._data[name]; - }; - } +#main { + height: auto; + -webkit-order: 1; + -ms-flex-order: 1; + order: 1; + padding: 24px; + overflow: auto; +} - for (i in unitMillisecondFactors) { - if (hasOwnProp(unitMillisecondFactors, i)) { - makeDurationGetter(i.toLowerCase()); - } - } +h1 { + margin: 0; +} - moment.duration.fn.asMilliseconds = function () { - return this.as('ms'); - }; - moment.duration.fn.asSeconds = function () { - return this.as('s'); - }; - moment.duration.fn.asMinutes = function () { - return this.as('m'); - }; - moment.duration.fn.asHours = function () { - return this.as('h'); - }; - moment.duration.fn.asDays = function () { - return this.as('d'); - }; - moment.duration.fn.asWeeks = function () { - return this.as('weeks'); - }; - moment.duration.fn.asMonths = function () { - return this.as('M'); - }; - moment.duration.fn.asYears = function () { - return this.as('y'); - }; +#actions { + -webkit-order: 2; + -ms-flex-order: 2; + order: 2; + padding: 4px 16px 20px; +} - /************************************ - Default Locale - ************************************/ +polyfill-next-selector { content: ':host > *'; } +::content > * { + font: inherit; +} +</style> + <div id="shadow"> + <paper-shadow z="3" hasposition=""></paper-shadow> + </div> - // Set default locale, other locale will inherit from English. - moment.locale('en', { - ordinal : function (number) { - var b = number % 10, - output = (toInt(number % 100 / 10) === 1) ? 'th' : - (b === 1) ? 'st' : - (b === 2) ? 'nd' : - (b === 3) ? 'rd' : 'th'; - return number + output; - } - }); + <core-overlay id="overlay" opened="{{opened}}" autoclosedisabled?="{{autoCloseDisabled}}" backdrop?="{{backdrop}}" layered?="{{layered}}" target="{{}}" sizingtarget="{{$.container}}" closeselector="{{closeSelector}}" transition="{{transition}}" margin="20"></core-overlay> - /* EMBED_LOCALES */ + <div id="container" layout="" vertical=""> - /************************************ - Exposing Moment - ************************************/ + <div id="actions" layout="" horizontal=""> + <content select="[dismissive]"></content> + <div flex="" auto=""></div> + <content select="[affirmative]"></content> + </div> - function makeGlobal(shouldDeprecate) { - /*global ender:false */ - if (typeof ender !== 'undefined') { - return; - } - oldGlobalMoment = globalScope.moment; - if (shouldDeprecate) { - globalScope.moment = deprecate( - 'Accessing Moment through the global scope is ' + - 'deprecated, and will be removed in an upcoming ' + - 'release.', - moment); - } else { - globalScope.moment = moment; - } - } + <div id="main" flex="" auto=""> + <h1>{{heading}}</h1> + <content></content> + </div> - // CommonJS module is defined - if (hasModule) { - module.exports = moment; - } else if (typeof define === 'function' && define.amd) { - define('moment', function (require, exports, module) { - if (module.config && module.config() && module.config().noGlobal === true) { - // release the global variable - globalScope.moment = oldGlobalMoment; - } + </div> - return moment; - }); - makeGlobal(true); - } else { - makeGlobal(); - } -}).call(this); -</script> - -<!-- -Copyright (c) 2014 The Polymer Project Authors. All rights reserved. -This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt -The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt -The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt -Code distributed by Google as part of the polymer project is also -subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt ---> + </template> -<!-- -The `core-tooltip` element creates a hover tooltip centered for the content -it contains. It can be positioned on the top|bottom|left|right of content using -the `position` attribute. + <script> -To include HTML in the tooltip, include the `tip` attribute on the relevant -content. + Polymer('paper-dialog', { -<b>Example</b>: + /** + * Set opened to true to show the dialog and to false to hide it. + * A dialog may be made intially opened by setting its opened attribute. - <core-tooltip label="I'm a tooltip"> - <span>Hover over me.</span> - </core-tooltip> + * @attribute opened + * @type boolean + * @default false + */ + opened: false, -<b>Example</b> - positioning the tooltip to the right: + /** + * If true, the dialog has a backdrop darkening the rest of the screen. + * The backdrop element is attached to the document body and may be styled + * with the class `core-overlay-backdrop`. When opened the `core-opened` + * class is applied. + * + * @attribute backdrop + * @type boolean + * @default false + */ + backdrop: false, - <core-tooltip label="I'm a tooltip to the right" position="right"> - <core-icon-button icon="drawer"></core-icon-button> - </core-tooltip> + /** + * If true, the dialog is guaranteed to display above page content. + * + * @attribute layered + * @type boolean + * @default false + */ + layered: false, -<b>Example</b> - no arrow and showing by default: + /** + * By default a dialog will close automatically if the user + * taps outside it or presses the escape key. Disable this + * behavior by setting the `autoCloseDisabled` property to true. + * @attribute autoCloseDisabled + * @type boolean + * @default false + */ + autoCloseDisabled: false, - <core-tooltip label="Tooltip with no arrow and always on" noarrow show> - <img src="image.jpg"> - </core-tooltip> + /** + * This property specifies a selector matching elements that should + * close the dialog on tap. + * + * @attribute closeSelector + * @type string + * @default "" + */ + closeSelector: '[dismissive],[affirmative]', -<b>Example</b> - disable the tooltip. + /** + * @attribute heading + * @type string + * @default '' + */ + heading: '', - <core-tooltip label="Disabled label never shows" disabled> - ... - </core-tooltip> + /** + * Set this property to the id of a `core-transition` element to specify + * the transition to use when opening/closing this dialog. + * + * @attribute transition + * @type string + * @default '' + */ + transition: '', -<b>Example</b> - rich tooltip using the `tip` attribute: + /** + * Toggle the dialog's opened state. + * @method toggle + */ + toggle: function() { + this.$.overlay.toggle(); + }, - <core-tooltip> - <div>Example of a rich information tooltip</div> - <div tip> - <img src="profile.jpg">Foo <b>Bar</b> - <a href="#">@baz</a> - </div> - </core-tooltip> + headingChanged: function() { + this.setAttribute('aria-label', this.heading); + } -By default, the `tip` attribute specifies the HTML content for a rich tooltip. -You can customize this attribute with the `tipAttribute` attribute: + }); - <core-tooltip tipAttribute="htmltooltip"> - <div>Example of a rich information tooltip</div> - <div htmltooltip> - ... - </div> - </core-tooltip> + </script> -@group Polymer Core Elements -@element core-tooltip -@extends paper-focusable -@homepage http://www.polymer-project.org/components/core-tooltip/index.html +</polymer-element> + +<!-- +Copyright (c) 2014 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt --> +<polymer-element name="paper-dialog-transition" extends="core-transition-css" assetpath="polymer/bower_components/paper-dialog/"> -<!-- TODO: would be nice to inherit from label to get .htmlFor, and .control, - but the latter is readonly. --> -<!-- TODO: support off center arrows. --> -<!-- TODO: detect mobile and apply the .large class, instead of manual - control. --> -<!-- TODO: possibly reuse core-overlay. --> -<polymer-element name="core-tooltip" extends="paper-focusable" attributes="noarrow position label show tipAttribute" role="tooltip" assetpath="polymer/bower_components/core-tooltip/"> <template> - - <style>/* Copyright (c) 2014 The Polymer Project Authors. All rights reserved. + <style no-shim="">/* Copyright (c) 2014 The Polymer Project Authors. All rights reserved. This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt Code distributed by Google as part of the polymer project is also subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt */ -:host { - box-sizing: border-box; - position: relative; - display: inline-block; +:host(.paper-dialog-transition) { outline: none; + opacity: 0; + transition: transform 0.2s cubic-bezier(0.4, 0, 0.2, 1), opacity 0.2s cubic-bezier(0.4, 0, 0.2, 1); + -webkit-transition: -webkit-transform 0.2s cubic-bezier(0.4, 0, 0.2, 1), opacity 0.2s cubic-bezier(0.4, 0, 0.2, 1); } -:host(:hover:not([disabled])) .core-tooltip { - visibility: visible !important; -} - -:host([focused]) .core-tooltip { - visibility: visible !important; -} - -.core-tooltip:not(.show) { - visibility: hidden; -} - -.core-tooltip { - position: absolute; - font-size: 10px; - font-family: sans-serif; - padding: 8px; - color: white; - background-color: rgba(0,0,0,0.8); - box-sizing: border-box; - border-radius: 3px; /* TODO: not in spec. */ - white-space: nowrap; - line-height: 6px; - z-index: 1002; /* TODO: this is brittle. */ - -webkit-user-select: none; - user-select: none; -} - -:host([large]) .core-tooltip { - line-height: 14px; - font-size: 14px; - padding: 16px; -} - -.core-tooltip.noarrow::after { - display: none; +:host(.paper-dialog-transition.core-opened) { + opacity: 1; + transform: none; + -webkit-transform: none; } -.core-tooltip::after { - position: absolute; - border: solid transparent; - content: ''; - height: 0; - width: 0; - border-width: 4px; +:host(.paper-dialog-transition-bottom) { + transform: scale(0.9) translateY(200%); + -webkit-transform: scale(0.9) translateY(200%); } -.top { - margin-bottom: 10px; /* TODO: not specified in spec */ - bottom: 100%; +:host(.paper-dialog-transition-center.core-opened) { + animation: paper-dialog-transition-center-keyframes 0.2s cubic-bezier(0.4, 0, 0.2, 1); + -webkit-animation: paper-dialog-transition-center-keyframes 0.2s cubic-bezier(0.4, 0, 0.2, 1); } -.right { - margin-left: 10px; /* TODO: not specified in spec */ - left: 100%; +@keyframes paper-dialog-transition-center-keyframes { + 0% { + transform: scale(0.5) translateY(0); + -webkit-transform: scale(0.5) translateY(0); + } + 90% { + transform: scale(1) translateY(-10px); + -webkit-transform: scale(1) translateY(-10px); + } + 100% { + transform: scale(1) translateY(0); + -webkit-transform: scale(1) translateY(0); + } } -.bottom { - top: 100%; - margin-top: 10px; /* TODO: not specified in spec */ +@-webkit-keyframes paper-dialog-transition-center-keyframes { + 0% { + transform: scale(0.5) translateY(0); + -webkit-transform: scale(0.5) translateY(0); + } + 90% { + transform: scale(1) translateY(-10px); + -webkit-transform: scale(1) translateY(-10px); + } + 100% { + transform: scale(1) translateY(0); + -webkit-transform: scale(1) translateY(0); + } } +</style> +</template> -.left { - margin-right: 10px; /* TODO: not specified in spec */ - right: 100%; -} +<script> + Polymer('paper-dialog-transition',{ + baseClass: 'paper-dialog-transition' + }); +</script> -.core-tooltip.bottom::after { - bottom: 100%; - left: calc(50% - 4px); - border-bottom-color: rgba(0,0,0,0.8); -} +</polymer-element> -.core-tooltip.left::after { - left: 100%; - top: calc(50% - 4px); - border-left-color: rgba(0,0,0,0.8); -} +<paper-dialog-transition id="paper-dialog-transition-bottom" transitiontype="bottom"></paper-dialog-transition> +<paper-dialog-transition id="paper-dialog-transition-center" transitiontype="center"></paper-dialog-transition> -.core-tooltip.top::after { - top: 100%; - left: calc(50% - 4px); - border-top-color: rgba(0,0,0,0.8); -} -.core-tooltip.right::after { - right: 100%; - top: calc(50% - 4px); - border-right-color: rgba(0,0,0,0.8); -} -</style> - <div id="tooltip" hidden?="{{!hasTooltipContent}}" class="core-tooltip {{position}} {{ {noarrow: noarrow, show: show && !disabled} | tokenList}}"> - <content id="c" select="[{{tipAttribute}}]">{{label}}</content> - </div> - <content></content> -</template> -<script> - Polymer('core-tooltip',{ +<polymer-element name="events-list" attributes="api cbEventClicked" assetpath="polymer/"> + <template> + <style> + :host { + display: block; + } - /** - * A simple string label for the tooltip to display. To display a rich - * HTML tooltip instead, omit `label` and include the `tip` attribute - * on a child node of `core-tooltip`. - * - * @attribute label - * @type string - * @default null - */ - label: null, + .eventContainer { + font-size: 1rem; + } - computed: { - // Indicates whether the tooltip has a set label propety or - // an element with the `tip` attribute. - hasTooltipContent: 'label || !!tipElement' - }, + </style> - publish: { - /** - * Forces the tooltip to display. If `disabled` is set, this property is ignored. - * - * @attribute show - * @type boolean - * @default false - */ - show: {value: false, reflect: true}, + <template if="{{cbEventClicked}}"> + <style> + a { + text-decoration: underline; + cursor: pointer; + } + </style> + </template> - /** - * Positions the tooltip to the top, right, bottom, left of its content. - * - * @attribute position - * @type string - * @default 'bottom' - */ - position: {value: 'bottom', reflect: true}, + <div> + <template repeat="{{event in events}}"> + <div class="eventContainer"> + <a on-click="{{handleClick}}">{{event.event}}</a> + ({{event.listener_count}} listeners) + </div> + </template> - /** - * If true, the tooltip an arrow pointing towards the content. - * - * @attribute noarrow - * @type boolean - * @default false - */ - noarrow: {value: false, reflect: true} + </div> + </template> + <script> + Polymer('events-list',{ + cbEventClicked: null, + events: [], + + domReady: function() { + this.events = this.api.events + + this.api.addEventListener('events-updated', this.eventsUpdated.bind(this)) }, - /** - * Customizes the attribute used to specify which content - * is the rich HTML tooltip. - * - * @attribute tipAttribute - * @type string - * @default 'tip' - */ - tipAttribute: 'tip', + eventsUpdated: function() { + this.events = this.api.events; + }, - attached: function() { - this.updatedChildren(); + handleClick: function(ev) { + if(this.cbEventClicked) { + this.cbEventClicked(ev.path[0].innerHTML); + } }, - updatedChildren: function () { - this.tipElement = null; + }); + </script> +</polymer-element> - for (var i = 0, el; el = this.$.c.getDistributedNodes()[i]; ++i) { - if (el.hasAttribute && el.hasAttribute('tip')) { - this.tipElement = el; - break; - } + +<polymer-element name="event-fire-dialog" attributes="api" assetpath="polymer/"> + <template> + <style> + paper-input:first-child { + padding-top: 0; + } + + .eventContainer { + margin-left: 30px; + } + + @media all and (max-width: 620px) { + .eventContainer { + display: none; } + } - // Job ensures we're not double calling setPosition() on DOM attach. - this.job('positionJob', this.setPosition); + </style> - // Monitor children to re-position tooltip when light dom changes. - this.onMutation(this, this.updatedChildren); + <paper-dialog id="dialog" heading="Fire Event" transition="paper-dialog-transition-bottom" backdrop="true"> + <div layout="" horizontal=""> + <div> + <paper-input id="inputType" label="Event Type" floatinglabel="true" autofocus required></paper-input> + <paper-input id="inputData" label="Event Data (JSON, optional)" floatinglabel="true" multiline=""></paper-input> + </div> + <div class="eventContainer"> + <b>Available events:</b> + <events-list api="{{api}}" cbeventclicked="{{eventSelected}}"> + </events-list></div> + </div> + <paper-button dismissive="">Cancel</paper-button> + <paper-button affirmative="" on-click="{{clickFireEvent}}">Fire Event</paper-button> + </paper-dialog> + + </template> + <script> + Polymer('event-fire-dialog',{ + ready: function() { + // to ensure callback methods work.. + this.eventSelected = this.eventSelected.bind(this) + }, + + show: function(eventType, eventData) { + this.setEventType(eventType); + this.setEventData(eventData); + + this.$.dialog.toggle(); + }, + + setEventType: function(eventType) { + this.$.inputType.value = eventType; }, - labelChanged: function(oldVal, newVal) { - this.job('positionJob', this.setPosition); + setEventData: function(eventData) { + this.$.inputData.value = eventData; }, - positionChanged: function(oldVal, newVal) { - this.job('positionJob', this.setPosition); + eventSelected: function(eventType) { + this.setEventType(eventType); }, - setPosition: function() { - var controlWidth = this.clientWidth; - var controlHeight = this.clientHeight; - var toolTipWidth = this.$.tooltip.clientWidth; - var toolTipHeight = this.$.tooltip.clientHeight; - - switch (this.position) { - case 'top': - case 'bottom': - this.$.tooltip.style.left = (controlWidth - toolTipWidth) / 2 + 'px'; - this.$.tooltip.style.top = null; - break; - case 'left': - case 'right': - this.$.tooltip.style.left = null; - this.$.tooltip.style.top = (controlHeight - toolTipHeight) / 2 + 'px'; - break; - } + clickFireEvent: function() { + this.api.fire_event( + this.$.inputType.value, + this.$.inputData.value + ) } }); - -</script> + </script> </polymer-element> - - -<!-- -Copyright (c) 2014 The Polymer Project Authors. All rights reserved. -This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt -The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt -The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt -Code distributed by Google as part of the polymer project is also -subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt ---> - -<!-- -`paper-toggle-button` provides a ON/OFF switch that user can toggle the state -by tapping or by dragging the swtich. -Example: - - <paper-toggle-button></paper-toggle-button> - -Styling toggle button: - -To change the ink color for checked state: - paper-toggle-button::shadow paper-radio-button::shadow #ink[checked] { - color: #4285f4; - } - -To change the radio checked color: - - paper-toggle-button::shadow paper-radio-button::shadow #onRadio { - background-color: #4285f4; - } - -To change the bar color for checked state: - paper-toggle-button::shadow #toggleBar[checked] { - background-color: #4285f4; - } - -To change the ink color for unchecked state: - paper-toggle-button::shadow paper-radio-button::shadow #ink { - color: #b5b5b5; - } - -To change the radio unchecked color: - - paper-toggle-button::shadow paper-radio-button::shadow #offRadio { - border-color: #b5b5b5; - } -To change the bar color for unchecked state: - paper-toggle-button::shadow #toggleBar { - background-color: red; - } -@group Paper Elements -@element paper-toggle-button -@homepage github.io ---> <!-- Copyright (c) 2014 The Polymer Project Authors. All rights reserved. @@ -12920,385 +13251,294 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN --> <!-- -`paper-radio-button` is a button that can be either checked or unchecked. -User can tap the radio button to check it. But it cannot be unchecked by -tapping once checked. +`core-menu` is a selector which styles to looks like a menu. -Use `paper-radio-group` to group a set of radio buttons. When radio buttons -are inside a radio group, only one radio button in the group can be checked. + <core-menu selected="0"> + <core-item icon="settings" label="Settings"></core-item> + <core-item icon="dialog" label="Dialog"></core-item> + <core-item icon="search" label="Search"></core-item> + </core-menu> + +When an item is selected the `core-selected` class is added to it. The user can +use the class to add more stylings to the selected item. -Example: + core-item.core-selected { + color: red; + } - <paper-radio-button></paper-radio-button> - -Styling radio button: +The `selectedItem` property references the selected item. -To change the ink color for checked state: + <core-menu selected="0" selectedItem="{{item}}"> + <core-item icon="settings" label="Settings"></core-item> + <core-item icon="dialog" label="Dialog"></core-item> + <core-item icon="search" label="Search"></core-item> + </core-menu> - paper-radio-button::shadow #ink[checked] { - color: #4285f4; - } - -To change the radio checked color: - - paper-radio-button::shadow #onRadio { - background-color: #4285f4; - } - -To change the ink color for unchecked state: + <div>selected label: {{item.label}}</div> - paper-radio-button::shadow #ink { - color: #b5b5b5; - } - -To change the radio unchecked color: - - paper-radio-button::shadow #offRadio { - border-color: #b5b5b5; - } +The `core-select` event signals selection change. -@group Paper Elements -@element paper-radio-button -@homepage github.io ---> + <core-menu selected="0" on-core-select="{{selectAction}}"> + <core-item icon="settings" label="Settings"></core-item> + <core-item icon="dialog" label="Dialog"></core-item> + <core-item icon="search" label="Search"></core-item> + </core-menu> + ... -<!-- - @license - Copyright (c) 2014 The Polymer Project Authors. All rights reserved. - This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt - The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt - The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt - Code distributed by Google as part of the polymer project is also - subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt + selectAction: function(e, detail) { + if (detail.isSelected) { + var selectedItem = detail.item; + ... + } + } + +@group Polymer Core Elements +@element core-menu +@extends core-selector --> -<!-- -`core-a11y-keys` provides a normalized interface for processing keyboard commands that pertain to [WAI-ARIA best -practices](http://www.w3.org/TR/wai-aria-practices/#kbd_general_binding). The element takes care of browser differences -with respect to Keyboard events and uses an expressive syntax to filter key presses. -Use the `keys` attribute to express what combination of keys will trigger the event to fire. -Use the `target` attribute to set up event handlers on a specific node. -The `keys-pressed` event will fire when one of the key combinations set with the `keys` attribute is pressed. +<polymer-element name="core-menu" extends="core-selector" assetpath="polymer/bower_components/core-menu/"> +<template> -Example: + <style>/* +Copyright (c) 2014 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +*/ -This element will call `arrowHandler` on all arrow keys: +:host { + display: block; + margin: 12px; +} - <core-a11y-keys target="{{}}" keys="up down left right" on-keys-pressed="{{arrowHandler}}"></core-a11y-keys> +polyfill-next-selector { content: ':host > core-item'; } +::content > core-item { + cursor: default; +} +</style> + + <shadow></shadow> + +</template> +<script>Polymer('core-menu');</script></polymer-element> -Keys Syntax: +<!-- +Copyright (c) 2014 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE +The complete set of authors may be found at http://polymer.github.io/AUTHORS +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS +--> -The `keys` attribute can accepts a space seprated, `+` concatenated set of modifier keys and some common keyboard keys. +<!-- +Use to create nested menus inside of `core-menu` elements. -The common keys are `a-z`, `0-9` (top row and number pad), `*` (shift 8 and number pad), `F1-F12`, `Page Up`, `Page -Down`, `Left Arrow`, `Right Arrow`, `Down Arrow`, `Up Arrow`, `Home`, `End`, `Escape`, `Space`, `Tab`, and `Enter` keys. + <core-menu selected="0"> + + <core-submenu icon="settings" label="Topics"> + <core-item label="Topic 1"></core-item> + <core-item label="Topic 2"></core-item> + </core-submenu> + + <core-submenu icon="settings" label="Favorites"> + <core-item label="Favorite 1"></core-item> + <core-item label="Favorite 2"></core-item> + <core-item label="Favorite 3"></core-item> + </core-submenu> + + </core-menu> + +There is a margin set on the submenu to indent the items. +You can override the margin by doing: -The modifier keys are `Shift`, `Control`, and `Alt`. + core-submenu::shadow #submenu { + margin-left: 20px; + } -All keys are expected to be lowercase and shortened: -`Left Arrow` is `left`, `Page Down` is `pagedown`, `Control` is `ctrl`, `F1` is `f1`, `Escape` is `esc` etc. +To style the item for the submenu, do something like this: -Keys Syntax Example: + core-submenu::shadow > #submenuItem { + color: blue; + } + +To style all the `core-item`s in the light DOM: -Given the `keys` attribute value "ctrl+shift+f7 up pagedown esc space alt+m", the `<core-a11y-keys>` element will send -the `keys-pressed` event if any of the follow key combos are pressed: Control and Shift and F7 keys, Up Arrow key, Page -Down key, Escape key, Space key, Alt and M key. + polyfill-next-selector { content: 'core-submenu > #submenu > core-item'; } + core-submenu > core-item { + color: red; + } + +The above will style `Topic1` and `Topic2` to have font color red. -Slider Example: + <core-submenu icon="settings" label="Topics"> + <core-item label="Topic1"></core-item> + <core-item label="Topic2"></core-item> + </core-submenu> + +@group Polymer Core Elements +@element core-submenu +@extends core-item +--> -The following is an example of the set of keys that fulfil the WAI-ARIA "slider" role [best -practices](http://www.w3.org/TR/wai-aria-practices/#slider): +<!-- +Copyright (c) 2014 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--> - <core-a11y-keys target="{{}}" keys="left pagedown down" on-keys-pressed="{{decrement}}"></core-a11y-keys> - <core-a11y-keys target="{{}}" keys="right pageup up" on-keys-pressed="{{increment}}"></core-a11y-keys> - <core-a11y-keys target="{{}}" keys="home" on-keys-pressed="{{setMin}}"></core-a11y-keys> - <core-a11y-keys target="{{}}" keys="end" on-keys-pressed="{{setMax}}"></core-a11y-keys> +<!-- +`core-item` is a simple line-item object: a label and/or an icon that can also +act as a link. -The `increment` function will move the slider a set amount toward the maximum value. -The `decrement` function will move the slider a set amount toward the minimum value. -The `setMin` function will move the slider to the minimum value. -The `setMax` function will move the slider to the maximum value. +Example: -Keys Syntax Grammar: + <core-item icon="settings" label="Settings"></core-item> + +To use as a link, put <a> element in the item. -[EBNF](http://en.wikipedia.org/wiki/Extended_Backus%E2%80%93Naur_Form) Grammar of the `keys` attribute. +Example: - modifier = "shift" | "ctrl" | "alt"; - ascii = ? /[a-z0-9]/ ? ; - fnkey = ? f1 through f12 ? ; - arrow = "up" | "down" | "left" | "right" ; - key = "tab" | "esc" | "space" | "*" | "pageup" | "pagedown" | "home" | "end" | arrow | ascii | fnkey ; - keycombo = { modifier, "+" }, key ; - keys = keycombo, { " ", keycombo } ; + <core-item icon="settings" label="Settings"> + <a href="#settings" target="_self"></a> + </core-item> -@group Core Elements -@element core-a11y-keys +@group Polymer Core Elements +@element core-item @homepage github.io --> -<style shim-shadowdom=""> - html /deep/ core-a11y-keys { - display: none; - } -</style> - -<polymer-element name="core-a11y-keys" assetpath="polymer/bower_components/core-a11y-keys/"> -<script> - (function() { - /* - * Chrome uses an older version of DOM Level 3 Keyboard Events - * - * Most keys are labeled as text, but some are Unicode codepoints. - * Values taken from: http://www.w3.org/TR/2007/WD-DOM-Level-3-Events-20071221/keyset.html#KeySet-Set - */ - var KEY_IDENTIFIER = { - 'U+0009': 'tab', - 'U+001B': 'esc', - 'U+0020': 'space', - 'U+002A': '*', - 'U+0030': '0', - 'U+0031': '1', - 'U+0032': '2', - 'U+0033': '3', - 'U+0034': '4', - 'U+0035': '5', - 'U+0036': '6', - 'U+0037': '7', - 'U+0038': '8', - 'U+0039': '9', - 'U+0041': 'a', - 'U+0042': 'b', - 'U+0043': 'c', - 'U+0044': 'd', - 'U+0045': 'e', - 'U+0046': 'f', - 'U+0047': 'g', - 'U+0048': 'h', - 'U+0049': 'i', - 'U+004A': 'j', - 'U+004B': 'k', - 'U+004C': 'l', - 'U+004D': 'm', - 'U+004E': 'n', - 'U+004F': 'o', - 'U+0050': 'p', - 'U+0051': 'q', - 'U+0052': 'r', - 'U+0053': 's', - 'U+0054': 't', - 'U+0055': 'u', - 'U+0056': 'v', - 'U+0057': 'w', - 'U+0058': 'x', - 'U+0059': 'y', - 'U+005A': 'z', - 'U+007F': 'del' - }; - - /* - * Special table for KeyboardEvent.keyCode. - * KeyboardEvent.keyIdentifier is better, and KeyBoardEvent.key is even better than that - * - * Values from: https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent.keyCode#Value_of_keyCode - */ - var KEY_CODE = { - 13: 'enter', - 27: 'esc', - 33: 'pageup', - 34: 'pagedown', - 35: 'end', - 36: 'home', - 32: 'space', - 37: 'left', - 38: 'up', - 39: 'right', - 40: 'down', - 46: 'del', - 106: '*' - }; +<polymer-element name="core-item" attributes="label icon src" horizontal="" center="" layout="" assetpath="polymer/bower_components/core-item/"> +<template> + <style>/* +Copyright (c) 2014 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +*/ - /* - * KeyboardEvent.key is mostly represented by printable character made by the keyboard, with unprintable keys labeled - * nicely. - * - * However, on OS X, Alt+char can make a Unicode character that follows an Apple-specific mapping. In this case, we - * fall back to .keyCode. - */ - var KEY_CHAR = /[a-z0-9*]/; +:host { + display: block; + position: relative; + min-height: 40px; + white-space: nowrap; +} - function transformKey(key) { - var validKey = ''; - if (key) { - var lKey = key.toLowerCase(); - if (lKey.length == 1) { - if (KEY_CHAR.test(lKey)) { - validKey = lKey; - } - } else if (lKey == 'multiply') { - // numpad '*' can map to Multiply on IE/Windows - validKey = '*'; - } else { - validKey = lKey; - } - } - return validKey; - } +:host(.font-scalable) { + min-height: 2.5em; +} - var IDENT_CHAR = /U\+/; - function transformKeyIdentifier(keyIdent) { - var validKey = ''; - if (keyIdent) { - if (IDENT_CHAR.test(keyIdent)) { - validKey = KEY_IDENTIFIER[keyIdent]; - } else { - validKey = keyIdent.toLowerCase(); - } - } - return validKey; - } +:host(.core-selected) { + font-weight: bold; +} - function transformKeyCode(keyCode) { - var validKey = ''; - if (Number(keyCode)) { - if (keyCode >= 65 && keyCode <= 90) { - // ascii a-z - // lowercase is 32 offset from uppercase - validKey = String.fromCharCode(32 + keyCode); - } else if (keyCode >= 112 && keyCode <= 123) { - // function keys f1-f12 - validKey = 'f' + (keyCode - 112); - } else if (keyCode >= 48 && keyCode <= 57) { - // top 0-9 keys - validKey = String(48 - keyCode); - } else if (keyCode >= 96 && keyCode <= 105) { - // num pad 0-9 - validKey = String(96 - keyCode); - } else { - validKey = KEY_CODE[keyCode]; - } - } - return validKey; - } +#icon { + margin: 0 16px 0 4px; +} - function keyboardEventToKey(ev) { - // fall back from .key, to .keyIdentifier, and then to .keyCode - var normalizedKey = transformKey(ev.key) || transformKeyIdentifier(ev.keyIdentifier) || transformKeyCode(ev.keyCode) || ''; - return { - shift: ev.shiftKey, - ctrl: ev.ctrlKey, - meta: ev.metaKey, - alt: ev.altKey, - key: normalizedKey - }; - } +:host(.font-scalable) #icon { + margin: 0 1em 0 0.25em; + height: 1.5em; + width: 1.5em; +} - /* - * Input: ctrl+shift+f7 => {ctrl: true, shift: true, key: 'f7'} - * ctrl/space => {ctrl: true} || {key: space} - */ - function stringToKey(keyCombo) { - var keys = keyCombo.split('+'); - var keyObj = Object.create(null); - keys.forEach(function(key) { - if (key == 'shift') { - keyObj.shift = true; - } else if (key == 'ctrl') { - keyObj.ctrl = true; - } else if (key == 'alt') { - keyObj.alt = true; - } else { - keyObj.key = key; - } - }); - return keyObj; - } +polyfill-next-selector { content: ':host > a'; } +::content > a { + position: absolute; + top: 0; + right: 0; + bottom: 0; + left: 0; + /* IE10 styling to ensure link is clickable. Cannot be completely + transparent or minifiers change it to `transparent` which does not work. */ + background-color: rgba(0, 0, 0, 0.000001); +} +</style> + <template if="{{icon || src}}"> + <core-icon src="{{src}}" id="icon" icon="{{icon}}" hidden?="{{!src && !icon}}"></core-icon> + </template> + <div id="label">{{label}}</div> + <content></content> +</template> +<script> - function keyMatches(a, b) { - return Boolean(a.alt) == Boolean(b.alt) && Boolean(a.ctrl) == Boolean(b.ctrl) && Boolean(a.shift) == Boolean(b.shift) && a.key === b.key; - } + Polymer('core-item', { + + /** + * The URL of an image for the icon. + * + * @attribute src + * @type string + * @default '' + */ /** - * Fired when a keycombo in `keys` is pressed. + * Specifies the icon from the Polymer icon set. * - * @event keys-pressed + * @attribute icon + * @type string + * @default '' */ - function processKeys(ev) { - var current = keyboardEventToKey(ev); - for (var i = 0, dk; i < this._desiredKeys.length; i++) { - dk = this._desiredKeys[i]; - if (keyMatches(dk, current)) { - ev.preventDefault(); - ev.stopPropagation(); - this.fire('keys-pressed', current, this, false); - break; - } - } - } - function listen(node, handler) { - if (node && node.addEventListener) { - node.addEventListener('keydown', handler); - } - } + /** + * Specifies the label for the menu item. + * + * @attribute label + * @type string + * @default '' + */ - function unlisten(node, handler) { - if (node && node.removeEventListener) { - node.removeEventListener('keydown', handler); - } - } + }); - Polymer('core-a11y-keys', { - created: function() { - this._keyHandler = processKeys.bind(this); - }, - attached: function() { - listen(this.target, this._keyHandler); - }, - detached: function() { - unlisten(this.target, this._keyHandler); - }, - publish: { - /** - * The set of key combinations to listen for. - * - * @attribute keys - * @type string (keys syntax) - * @default '' - */ - keys: '', - /** - * The node that will fire keyboard events. - * - * @attribute target - * @type Node - * @default null - */ - target: null - }, - keysChanged: function() { - // * can have multiple mappings: shift+8, * on numpad or Multiply on numpad - var normalized = this.keys.replace('*', '* shift+*'); - this._desiredKeys = normalized.toLowerCase().split(' ').map(stringToKey); - }, - targetChanged: function(oldTarget) { - unlisten(oldTarget, this._keyHandler); - listen(this.target, this._keyHandler); - } - }); - })(); </script> </polymer-element> -<polymer-element name="paper-radio-button" role="radio" tabindex="0" aria-checked="false" assetpath="polymer/bower_components/paper-radio-button/"> -<template> +<!-- +Copyright (c) 2014 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--> - <style>/* +<!-- +`core-collapse` creates a collapsible block of content. By default, the content +will be collapsed. Use `opened` to show/hide the content. + + <button on-click="{{toggle}}">toggle collapse</button> + + <core-collapse id="collapse"> + ... + </core-collapse> + + ... + + toggle: function() { + this.$.collapse.toggle(); + } + +@group Polymer Core Elements +@element core-collapse +--> + + + +<style shim-shadowdom="">/* Copyright (c) 2014 The Polymer Project Authors. All rights reserved. This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt @@ -13307,1119 +13547,922 @@ Code distributed by Google as part of the polymer project is also subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt */ -:host { - display: inline-block; - white-space: nowrap; +html /deep/ core-collapse { + display: block; } -:host(:focus) { - outline: none; +html /deep/ .core-collapse-closed { + display: none; } +</style> -#radioContainer { - position: relative; - width: 16px; - height: 16px; - cursor: pointer; -} +<polymer-element name="core-collapse" attributes="target horizontal opened duration fixedSize" assetpath="polymer/bower_components/core-collapse/"> +<template> -#radioContainer.labeled { - display: inline-block; - vertical-align: middle; -} + <content></content> -#ink { - position: absolute; - top: -16px; - left: -16px; - width: 48px; - height: 48px; - color: #5a5a5a; -} +</template> +<script> -#ink[checked] { - color: #0f9d58; -} + Polymer('core-collapse', { -#offRadio { - position: absolute; - top: 0px; - left: 0px; - width: 12px; - height: 12px; - border-radius: 50%; - border: solid 2px; - border-color: #5a5a5a; -} + /** + * Fired when the `core-collapse`'s `opened` property changes. + * + * @event core-collapse-open + */ -#onRadio { - position: absolute; - top: 0; - left: 0; - width: 16px; - height: 16px; - border-radius: 50%; - background-color: #0f9d58; - -webkit-transform: scale(0); - transform: scale(0); - transition: -webkit-transform ease 0.28s; - transition: transform ease 0.28s; -} + /** + * Fired when the target element has been resized as a result of the opened + * state changing. + * + * @event core-resize + */ -#onRadio.fill { - -webkit-transform: scale(1.1); - transform: scale(1.1); -} + /** + * The target element. + * + * @attribute target + * @type object + * @default null + */ + target: null, + + /** + * If true, the orientation is horizontal; otherwise is vertical. + * + * @attribute horizontal + * @type boolean + * @default false + */ + horizontal: false, + + /** + * Set opened to true to show the collapse element and to false to hide it. + * + * @attribute opened + * @type boolean + * @default false + */ + opened: false, + + /** + * Collapsing/expanding animation duration in second. + * + * @attribute duration + * @type number + * @default 0.33 + */ + duration: 0.33, + + /** + * If true, the size of the target element is fixed and is set + * on the element. Otherwise it will try to + * use auto to determine the natural size to use + * for collapsing/expanding. + * + * @attribute fixedSize + * @type boolean + * @default false + */ + fixedSize: false, + + created: function() { + this.transitionEndListener = this.transitionEnd.bind(this); + }, + + ready: function() { + this.target = this.target || this; + }, -#radioLabel { - position: relative; - display: inline-block; - vertical-align: middle; - margin-left: 10px; - white-space: normal; - pointer-events: none; -} + domReady: function() { + this.async(function() { + this.afterInitialUpdate = true; + }); + }, -#radioLabel[hidden] { - display: none; -} + detached: function() { + if (this.target) { + this.removeListeners(this.target); + } + }, -/* disabled state */ -:host([disabled]) { - pointer-events: none; -} + targetChanged: function(old) { + if (old) { + this.removeListeners(old); + } + if (!this.target) { + return; + } + this.isTargetReady = !!this.target; + this.classList.toggle('core-collapse-closed', this.target !== this); + this.target.style.overflow = 'hidden'; + this.horizontalChanged(); + this.addListeners(this.target); + // set core-collapse-closed class initially to hide the target + this.toggleClosedClass(true); + this.update(); + }, -:host([disabled]) #onRadio { - display: none; -} + addListeners: function(node) { + node.addEventListener('transitionend', this.transitionEndListener); + }, -:host([disabled]) #offRadio { - opacity: 0.33; - border-color: #5a5a5a; -} + removeListeners: function(node) { + node.removeEventListener('transitionend', this.transitionEndListener); + }, -:host([disabled][checked]) #offRadio { - opacity: 0.33; - background-color: #5a5a5a; -} -</style> + horizontalChanged: function() { + this.dimension = this.horizontal ? 'width' : 'height'; + }, - <core-a11y-keys target="{{}}" keys="space" on-keys-pressed="{{tap}}"></core-a11y-keys> - - <div id="radioContainer" class="{{ {labeled: label} | tokenList }}"> - - <div id="offRadio"></div> - <div id="onRadio"></div> - - <paper-ripple id="ink" class="circle recenteringTouch" checked?="{{!checked}}"></paper-ripple> - - </div> - - <div id="radioLabel" aria-hidden="true" hidden?="{{!label}}">{{label}}<content></content></div> - -</template> -<script> + openedChanged: function() { + this.update(); + this.fire('core-collapse-open', this.opened); + }, - Polymer('paper-radio-button', { - - /** - * Fired when the checked state changes due to user interaction. - * - * @event change - */ - /** - * Fired when the checked state changes. + * Toggle the opened state. * - * @event core-change + * @method toggle */ - - publish: { - /** - * Gets or sets the state, `true` is checked and `false` is unchecked. - * - * @attribute checked - * @type boolean - * @default false - */ - checked: {value: false, reflect: true}, - - /** - * The label for the radio button. - * - * @attribute label - * @type string - * @default '' - */ - label: '', - - /** - * Normally the user cannot uncheck the radio button by tapping once - * checked. Setting this property to `true` makes the radio button - * toggleable from checked to unchecked. - * - * @attribute toggles - * @type boolean - * @default false - */ - toggles: false, - - /** - * If true, the user cannot interact with this element. - * - * @attribute disabled - * @type boolean - * @default false - */ - disabled: {value: false, reflect: true} + toggle: function() { + this.opened = !this.opened; }, - - eventDelegates: { - tap: 'tap' + + setTransitionDuration: function(duration) { + var s = this.target.style; + s.transition = duration ? (this.dimension + ' ' + duration + 's') : null; + if (duration === 0) { + this.async('transitionEnd'); + } }, - - tap: function() { - var old = this.checked; - this.toggle(); - if (this.checked !== old) { - this.fire('change'); + + transitionEnd: function() { + if (this.opened && !this.fixedSize) { + this.updateSize('auto', null); } + this.setTransitionDuration(null); + this.toggleClosedClass(!this.opened); + this.asyncFire('core-resize', null, this.target); }, - - toggle: function() { - this.checked = !this.toggles || !this.checked; + + toggleClosedClass: function(closed) { + this.hasClosedClass = closed; + this.target.classList.toggle('core-collapse-closed', closed); }, - - checkedChanged: function() { - this.$.onRadio.classList.toggle('fill', this.checked); - this.setAttribute('aria-checked', this.checked ? 'true': 'false'); - this.fire('core-change'); + + updateSize: function(size, duration, forceEnd) { + this.setTransitionDuration(duration); + this.calcSize(); + var s = this.target.style; + var nochange = s[this.dimension] === size; + s[this.dimension] = size; + // transitonEnd will not be called if the size has not changed + if (forceEnd && nochange) { + this.transitionEnd(); + } }, - - labelChanged: function() { - this.setAttribute('aria-label', this.label); + + update: function() { + if (!this.target) { + return; + } + if (!this.isTargetReady) { + this.targetChanged(); + } + this.horizontalChanged(); + this[this.opened ? 'show' : 'hide'](); + }, + + calcSize: function() { + return this.target.getBoundingClientRect()[this.dimension] + 'px'; + }, + + getComputedSize: function() { + return getComputedStyle(this.target)[this.dimension]; + }, + + show: function() { + this.toggleClosedClass(false); + // for initial update, skip the expanding animation to optimize + // performance e.g. skip calcSize + if (!this.afterInitialUpdate) { + this.transitionEnd(); + return; + } + if (!this.fixedSize) { + this.updateSize('auto', null); + var s = this.calcSize(); + if (s == '0px') { + this.transitionEnd(); + return; + } + this.updateSize(0, null); + } + this.async(function() { + this.updateSize(this.size || s, this.duration, true); + }); + }, + + hide: function() { + // don't need to do anything if it's already hidden + if (this.hasClosedClass && !this.fixedSize) { + return; + } + if (this.fixedSize) { + // save the size before hiding it + this.size = this.getComputedSize(); + } else { + this.updateSize(this.calcSize(), null); + } + this.async(function() { + this.updateSize(0, this.duration); + }); } - + }); - + </script> </polymer-element> -<polymer-element name="paper-toggle-button" attributes="checked" role="button" aria-pressed="false" tabindex="0" assetpath="polymer/bower_components/paper-toggle-button/"> +<polymer-element name="core-submenu" attributes="selected selectedItem label icon src valueattr" assetpath="polymer/bower_components/core-menu/"> <template> <style>/* Copyright (c) 2014 The Polymer Project Authors. All rights reserved. -This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt -The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt -The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE +The complete set of authors may be found at http://polymer.github.io/AUTHORS +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS Code distributed by Google as part of the polymer project is also -subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS */ -:host { - display: inline-block; +:host { + display: block; + height: auto; } -:host(:focus) { - outline: none; +:host(.core-selected, [active]) { + font-weight: initial; } -#toggleContainer { - position: relative; - width: 64px; - height: 16px; +core-item { + cursor: default; } -#toggleBar { - position: absolute; - top: 8px; - left: 16px; - height: 1px; - width: 32px; - background-color: #5a5a5a; - pointer-events: none; +::content > core-item { + cursor: default; } -#toggleBar[checked] { - background-color: #0f9d58; +:host(.font-scalable) > core-item { + min-height: 2.5em; } -#toggleContainer[checked] #checkedBar { - width: 100%; +:host(.font-scalable) > core-item::shadow core-icon { + margin: 0 1em 0 0.25em; + height: 1.5em; + width: 1.5em; } -#toggleRadio { - position: absolute; - left: 0; - padding: 8px 48px 8px 0; - margin: -8px -48px -8px 0; - transition: -webkit-transform linear .08s; - transition: transform linear .08s; +#submenu { + margin: 0 0 0 44px; } -#toggleRadio[checked] { - -webkit-transform: translate(48px, 0); - transform: translate(48px, 0); - padding: 8px 0 8px 48px; - margin: -8px 0 -8px -48px; +:host(.font-scalable) > #submenu { + margin: 0 0 0 2.75em; } +</style> -#toggleRadio.dragging { - -webkit-transition: none; - transition: none; -}</style> + <core-item id="submenuItem" src="{{src}}" label="{{label}}" icon="{{icon}}" class="{{ {'core-selected' : active} | tokenList}}" on-tap="{{activate}}"> + <content select=".item-content"></content> + </core-item> - <div id="toggleContainer"> - - <div id="toggleBar" checked?="{{checked}}"></div> - - <paper-radio-button id="toggleRadio" toggles="" checked="{{checked}}" on-change="{{changeAction}}" on-core-change="{{stopPropagation}}" on-trackstart="{{trackStart}}" on-trackx="{{trackx}}" on-trackend="{{trackEnd}}"></paper-radio-button> - - </div> + <core-menu id="submenu" selected="{{selected}}" selecteditem="{{selectedItem}}" valueattr="{{valueattr}}"> + <content></content> + </core-menu> + + <core-collapse target="{{$.submenu}}" opened="{{opened}}"></core-collapse> </template> <script> - Polymer('paper-toggle-button', { - - /** - * Fired when the checked state changes due to user interaction. - * - * @event change - */ - - /** - * Fired when the checked state changes. - * - * @event core-change - */ + Polymer('core-submenu', { - /** - * Gets or sets the state, `true` is checked and `false` is unchecked. - * - * @attribute checked - * @type boolean - * @default false - */ - checked: false, + publish: { + active: {value: false, reflect: true} + }, - trackStart: function(e) { - this._w = this.$.toggleBar.offsetLeft + this.$.toggleBar.offsetWidth; - e.preventTap(); + opened: false, + + get items() { + return this.$.submenu.items; }, - trackx: function(e) { - this._x = Math.min(this._w, - Math.max(0, this.checked ? this._w + e.dx : e.dx)); - this.$.toggleRadio.classList.add('dragging'); - var s = this.$.toggleRadio.style; - s.webkitTransform = s.transform = 'translate3d(' + this._x + 'px,0,0)'; + hasItems: function() { + return !!this.items.length; }, - trackEnd: function() { - var s = this.$.toggleRadio.style; - s.transform = s.webkitTransform = ''; - this.$.toggleRadio.classList.remove('dragging'); - var old = this.checked; - this.checked = Math.abs(this._x) > this._w / 2; - if (this.checked !== old) { - this.fire('change'); - } + unselectAllItems: function() { + this.$.submenu.selected = null; + this.$.submenu.clearSelection(); }, - - checkedChanged: function() { - this.setAttribute('aria-pressed', Boolean(this.checked)); - this.fire('core-change'); + + activeChanged: function() { + if (this.hasItems()) { + this.opened = this.active; + } + if (!this.active) { + this.unselectAllItems(); + } }, - changeAction: function(e) { - e.stopPropagation(); - this.fire('change'); + toggle: function() { + this.opened = !this.opened; }, - - stopPropagation: function(e) { - e.stopPropagation(); - } + activate: function() { + if (this.hasItems() && this.active) { + this.toggle(); + this.unselectAllItems(); + } + } + }); </script> </polymer-element> - - +<polymer-element name="services-list" attributes="api cbServiceClicked" assetpath="polymer/"> + <template> + <style> + :host { + display: block; + } + + core-menu { + margin-top: 0; + font-size: 1rem; + } + a { + display: block; + } + </style> -<!-- -Copyright (c) 2014 The Polymer Project Authors. All rights reserved. -This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt -The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt -The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt -Code distributed by Google as part of the polymer project is also -subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt ---> + <template if="{{cbServiceClicked}}"> + <style> + a { + text-decoration: underline; + cursor: pointer; + } + </style> + </template> + <div> + <core-menu selected="0"> + + <template repeat="{{serv in services}}"> + <core-submenu icon="settings" label="{{serv.domain}}"> + <template repeat="{{service in serv.services}}"> + <a on-click="{{serviceClicked}}" data-domain="{{serv.domain}}">{{service}}</a> + </template> + </core-submenu> + </template> + + </core-menu> + </div> + </template> + <script> + Polymer('services-list',{ + services: [], + cbServiceClicked: null, -<core-iconset-svg id="device" iconsize="24"> -<svg><defs> -<g id="access-alarm"><path d="M22,5.7l-4.6-3.9l-1.3,1.5l4.6,3.9L22,5.7z M7.9,3.4L6.6,1.9L2,5.7l1.3,1.5L7.9,3.4z M12.5,8H11v6l4.7,2.9l0.8-1.2l-4-2.4V8z M12,4c-5,0-9,4-9,9c0,5,4,9,9,9c5,0,9-4,9-9C21,8,17,4,12,4z M12,20c-3.9,0-7-3.1-7-7c0-3.9,3.1-7,7-7c3.9,0,7,3.1,7,7C19,16.9,15.9,20,12,20z"/></g> -<g id="access-alarms"><path d="M22,5.7l-4.6-3.9l-1.3,1.5l4.6,3.9L22,5.7z M7.9,3.4L6.6,1.9L2,5.7l1.3,1.5L7.9,3.4z M12.5,8H11v6l4.7,2.9l0.8-1.2l-4-2.4V8z M12,4c-5,0-9,4-9,9c0,5,4,9,9,9s9-4,9-9C21,8,17,4,12,4z M12,20c-3.9,0-7-3.1-7-7c0-3.9,3.1-7,7-7c3.9,0,7,3.1,7,7C19,16.9,15.9,20,12,20z"/></g> -<g id="access-time"><path fill-opacity="0.9" d="M12,2C6.5,2,2,6.5,2,12s4.5,10,10,10c5.5,0,10-4.5,10-10S17.5,2,12,2z M12,20c-4.4,0-8-3.6-8-8s3.6-8,8-8c4.4,0,8,3.6,8,8S16.4,20,12,20z"/><polygon fill-opacity="0.9" points="12.5,7 11,7 11,13 16.2,16.2 17,14.9 12.5,12.2 "/></g> -<g id="add-alarm"><path d="M7.9,3.4L6.6,1.9L2,5.7l1.3,1.5L7.9,3.4z M22,5.7l-4.6-3.9l-1.3,1.5l4.6,3.9L22,5.7z M12,4c-5,0-9,4-9,9c0,5,4,9,9,9c5,0,9-4,9-9C21,8,17,4,12,4z M12,20c-3.9,0-7-3.1-7-7c0-3.9,3.1-7,7-7c3.9,0,7,3.1,7,7C19,16.9,15.9,20,12,20z M13,9h-2v3H8v2h3v3h2v-3h3v-2h-3V9z"/></g> -<g id="airplanemode-off"><path d="M13,9V3.5C13,2.7,12.3,2,11.5,2C10.7,2,10,2.7,10,3.5v3.7l7.8,7.8l3.2,1v-2L13,9z M3,5.3l5,5L2,14v2l8-2.5V19l-2,1.5V22l3.5-1l3.5,1v-1.5L13,19v-3.7l5.7,5.7l1.3-1.3L4.3,4L3,5.3z"/></g> -<g id="airplanemode-on"><path d="M21,16v-2l-8-5V3.5C13,2.7,12.3,2,11.5,2C10.7,2,10,2.7,10,3.5V9l-8,5v2l8-2.5V19l-2,1.5V22l3.5-1l3.5,1v-1.5L13,19v-5.5L21,16z"/></g> -<g id="bluetooth"><path d="M17.7,7.7L12,2h-1v7.6L6.4,5L5,6.4l5.6,5.6L5,17.6L6.4,19l4.6-4.6V22h1l5.7-5.7L13.4,12L17.7,7.7z M13,5.8l1.9,1.9L13,9.6V5.8z M14.9,16.3L13,18.2v-3.8L14.9,16.3z"/></g> -<g id="bluetooth-connected"><path d="M7,12l-2-2l-2,2l2,2L7,12z M17.7,7.7L12,2h-1v7.6L6.4,5L5,6.4l5.6,5.6L5,17.6L6.4,19l4.6-4.6V22h1l5.7-5.7L13.4,12L17.7,7.7z M13,5.8l1.9,1.9L13,9.6V5.8z M14.9,16.3L13,18.2v-3.8L14.9,16.3z M19,10l-2,2l2,2l2-2L19,10z"/></g> -<g id="bluetooth-disabled"><path d="M13,5.8l1.9,1.9l-1.6,1.6l1.4,1.4l3-3L12,2h-1v5l2,2V5.8z M5.4,4L4,5.4l6.6,6.6L5,17.6L6.4,19l4.6-4.6V22h1l4.3-4.3l2.3,2.3l1.4-1.4L5.4,4z M13,18.2v-3.8l1.9,1.9L13,18.2z"/></g> -<g id="bluetooth-searching"><path d="M14.2,12l2.3,2.3c0.3-0.7,0.4-1.5,0.4-2.3c0-0.8-0.2-1.6-0.4-2.3L14.2,12z M19.5,6.7L18.3,8c0.6,1.2,1,2.6,1,4s-0.4,2.8-1,4l1.2,1.2c1-1.5,1.5-3.4,1.5-5.3C21,10,20.5,8.2,19.5,6.7z M15.7,7.7L10,2H9v7.6L4.4,5L3,6.4L8.6,12L3,17.6L4.4,19L9,14.4V22h1l5.7-5.7L11.4,12L15.7,7.7z M11,5.8l1.9,1.9L11,9.6V5.8z M12.9,16.3L11,18.2v-3.8L12.9,16.3z"/></g> -<g id="brightness-auto"><path d="M10.9,12.6h2.3L12,9L10.9,12.6z M20,8.7V4h-4.7L12,0.7L8.7,4H4v4.7L0.7,12L4,15.3V20h4.7l3.3,3.3l3.3-3.3H20v-4.7l3.3-3.3L20,8.7z M14.3,16l-0.7-2h-3.2l-0.7,2H7.8L11,7h2l3.2,9H14.3z"/></g> -<g id="brightness-high"><path d="M20,8.7V4h-4.7L12,0.7L8.7,4H4v4.7L0.7,12L4,15.3V20h4.7l3.3,3.3l3.3-3.3H20v-4.7l3.3-3.3L20,8.7z M12,18c-3.3,0-6-2.7-6-6s2.7-6,6-6c3.3,0,6,2.7,6,6S15.3,18,12,18z M12,8c-2.2,0-4,1.8-4,4c0,2.2,1.8,4,4,4s4-1.8,4-4C16,9.8,14.2,8,12,8z"/></g> -<g id="brightness-low"><path d="M20,15.3l3.3-3.3L20,8.7V4h-4.7L12,0.7L8.7,4H4v4.7L0.7,12L4,15.3V20h4.7l3.3,3.3l3.3-3.3H20V15.3z M12,18c-3.3,0-6-2.7-6-6s2.7-6,6-6c3.3,0,6,2.7,6,6S15.3,18,12,18z"/></g> -<g id="brightness-medium"><path d="M20,15.3l3.3-3.3L20,8.7V4h-4.7L12,0.7L8.7,4H4v4.7L0.7,12L4,15.3V20h4.7l3.3,3.3l3.3-3.3H20V15.3z M12,18V6c3.3,0,6,2.7,6,6S15.3,18,12,18z"/></g> -<g id="data-usage"><path d="M13,2.1v3c3.4,0.5,6,3.4,6,6.9c0,0.9-0.2,1.7-0.5,2.5l2.6,1.5c0.6-1.2,0.9-2.6,0.9-4.1C22,6.8,18.1,2.6,13,2.1z M12,19c-3.9,0-7-3.1-7-7c0-3.5,2.6-6.4,6-6.9v-3C5.9,2.5,2,6.8,2,12c0,5.5,4.5,10,10,10c3.3,0,6.2-1.6,8.1-4.1l-2.6-1.5C16.2,18,14.2,19,12,19z"/></g> -<g id="developer-mode"><path d="M7,5h10v2h2V3c0-1.1-0.9-2-2-2L7,1C5.9,1,5,1.9,5,3v4h2V5z M15.4,16.6L20,12l-4.6-4.6L14,8.8l3.2,3.2L14,15.2L15.4,16.6z M10,15.2L6.8,12L10,8.8L8.6,7.4L4,12l4.6,4.6L10,15.2z M17,19H7v-2H5v4c0,1.1,0.9,2,2,2h10c1.1,0,2-0.9,2-2v-4h-2V19z"/></g> -<g id="event-note"><path d="M17,10H7v2h10V10z M13,14H7v2h6V14z M16,1v2H8V1H6v2H5C3.9,3,3,3.9,3,5l0,14c0,1.1,0.9,2,2,2h14c1.1,0,2-0.9,2-2V5c0-1.1-0.9-2-2-2h-1V1H16z M19,19H5V8h14V19z"/></g> -<g id="gps-fixed"><path d="M12,8c-2.2,0-4,1.8-4,4c0,2.2,1.8,4,4,4s4-1.8,4-4C16,9.8,14.2,8,12,8z M20.9,11c-0.5-4.2-3.8-7.5-7.9-7.9V1h-2v2.1C6.8,3.5,3.5,6.8,3.1,11H1v2h2.1c0.5,4.2,3.8,7.5,7.9,7.9V23h2v-2.1c4.2-0.5,7.5-3.8,7.9-7.9H23v-2H20.9z M12,19c-3.9,0-7-3.1-7-7c0-3.9,3.1-7,7-7s7,3.1,7,7C19,15.9,15.9,19,12,19z"/></g> -<g id="gps-not-fixed"><path d="M20.9,11c-0.5-4.2-3.8-7.5-7.9-7.9V1h-2v2.1C6.8,3.5,3.5,6.8,3.1,11H1v2h2.1c0.5,4.2,3.8,7.5,7.9,7.9V23h2v-2.1c4.2-0.5,7.5-3.8,7.9-7.9H23v-2H20.9z M12,19c-3.9,0-7-3.1-7-7c0-3.9,3.1-7,7-7s7,3.1,7,7C19,15.9,15.9,19,12,19z"/></g> -<g id="gps-off"><path d="M20.9,11c-0.5-4.2-3.8-7.5-7.9-7.9V1h-2v2.1C9.9,3.2,8.8,3.5,7.8,4l1.5,1.5C10.2,5.2,11.1,5,12,5c3.9,0,7,3.1,7,7c0,0.9-0.2,1.8-0.5,2.7l1.5,1.5c0.5-1,0.8-2,1-3.2H23v-2H20.9z M3,4.3l2,2C4,7.6,3.3,9.2,3.1,11H1v2h2.1c0.5,4.2,3.8,7.5,7.9,7.9V23h2v-2.1c1.8-0.2,3.4-0.9,4.7-2l2,2l1.3-1.3L4.3,3L3,4.3z M16.3,17.5C15.1,18.5,13.6,19,12,19c-3.9,0-7-3.1-7-7c0-1.6,0.5-3.1,1.5-4.3L16.3,17.5z"/></g> -<g id="location-disabled"><path d="M20.9,11c-0.5-4.2-3.8-7.5-7.9-7.9V1h-2v2.1C9.9,3.2,8.8,3.5,7.8,4l1.5,1.5C10.2,5.2,11.1,5,12,5c3.9,0,7,3.1,7,7c0,0.9-0.2,1.8-0.5,2.7l1.5,1.5c0.5-1,0.8-2,1-3.2H23v-2H20.9z M3,4.3l2,2C4,7.6,3.3,9.2,3.1,11H1v2h2.1c0.5,4.2,3.8,7.5,7.9,7.9V23h2v-2.1c1.8-0.2,3.4-0.9,4.7-2l2,2l1.3-1.3L4.3,3L3,4.3z M16.3,17.5C15.1,18.5,13.6,19,12,19c-3.9,0-7-3.1-7-7c0-1.6,0.5-3.1,1.5-4.3L16.3,17.5z"/></g> -<g id="location-searching"><path d="M20.9,11c-0.5-4.2-3.8-7.5-7.9-7.9V1h-2v2.1C6.8,3.5,3.5,6.8,3.1,11H1v2h2.1c0.5,4.2,3.8,7.5,7.9,7.9V23h2v-2.1c4.2-0.5,7.5-3.8,7.9-7.9H23v-2H20.9z M12,19c-3.9,0-7-3.1-7-7c0-3.9,3.1-7,7-7c3.9,0,7,3.1,7,7C19,15.9,15.9,19,12,19z"/></g> -<g id="network-cell"><path d="M2,22h20V2L2,22z M20,20h-3.3v-9.8L20,6.8V20z"/></g> -<g id="network-wifi"><path d="M12,2C7.5,2,3.3,3.5,0,6l12,16L24,6C20.7,3.5,16.5,2,12,2z M12,7.3C9.4,7.3,7,8,4.9,9.2l-2-2.7C5.6,4.9,8.7,4,12,4c3.3,0,6.4,0.9,9.1,2.5l-2,2.7C17,8,14.6,7.3,12,7.3z"/></g> -<g id="nfc"><path d="M20,2H4C2.9,2,2,2.9,2,4v16c0,1.1,0.9,2,2,2h16c1.1,0,2-0.9,2-2V4C22,2.9,21.1,2,20,2z M20,20H4V4h16V20z M18,6h-5c-1.1,0-2,0.9-2,2v2.3c-0.6,0.3-1,1-1,1.7c0,1.1,0.9,2,2,2c1.1,0,2-0.9,2-2c0-0.7-0.4-1.4-1-1.7V8h3v8H8V8h2V6H8H6v12h12V6z"/></g> -<g id="now-wallpaper"><path d="M4,4h7V2H4C2.9,2,2,2.9,2,4v7h2V4z M10,13l-4,5h12l-3-4l-2,2.7L10,13z M17,8.5C17,7.7,16.3,7,15.5,7S14,7.7,14,8.5s0.7,1.5,1.5,1.5S17,9.3,17,8.5z M20,2h-7v2h7v7h2V4C22,2.9,21.1,2,20,2z M20,20h-7v2h7c1.1,0,2-0.9,2-2v-7h-2V20z M4,13H2v7c0,1.1,0.9,2,2,2h7v-2H4V13z"/></g> -<g id="now-widgets"><path d="M13,13v8h8v-8h-4.3H13z M3,21h8v-8H3V21z M3,3v8h8V7.3V3H3z M16.7,1.7L11,7.3l5.7,5.7l5.7-5.7L16.7,1.7z"/></g> -<g id="screen-lock-landscape"><path d="M21,5H3C1.9,5,1,5.9,1,7v10c0,1.1,0.9,2,2,2h18c1.1,0,2-0.9,2-2V7C23,5.9,22.1,5,21,5z M19,17H5V7h14V17z"/></g> -<g id="screen-lock-portrait"><path d="M17,1H7C5.9,1,5,1.9,5,3v18c0,1.1,0.9,2,2,2h10c1.1,0,2-0.9,2-2V3C19,1.9,18.1,1,17,1z M17,19H7V5h10V19z"/></g> -<g id="screen-lock-rotation"><path d="M23.3,12.8l-2.6-2.6l-1.4,1.4l2.2,2.2l-5.7,5.7L4.5,8.2l5.7-5.7l2.1,2.1l1.4-1.4l-2.4-2.4c-0.6-0.6-1.5-0.6-2.1,0L2.7,7.1c-0.6,0.6-0.6,1.5,0,2.1l12,12c0.6,0.6,1.5,0.6,2.1,0l6.4-6.4C23.8,14.3,23.8,13.4,23.3,12.8z M8.5,20.5c-3.3-1.5-5.6-4.7-6-8.5H1c0.5,6.2,5.7,11,11.9,11c0.2,0,0.4,0,0.7,0l-3.8-3.8L8.5,20.5z M16,9h5c0.6,0,1-0.4,1-1V4c0-0.6-0.4-1-1-1V2.5C21,1.1,19.9,0,18.5,0C17.1,0,16,1.1,16,2.5V3c-0.6,0-1,0.4-1,1v4C15,8.6,15.4,9,16,9z M16.8,2.5c0-0.9,0.8-1.7,1.7-1.7c0.9,0,1.7,0.8,1.7,1.7V3h-3.4V2.5z"/></g> -<g id="screen-rotation"><path d="M16.5,2.5c3.3,1.5,5.6,4.7,6,8.5h1.5C23.4,4.8,18.3,0,12,0c-0.2,0-0.4,0-0.7,0l3.8,3.8L16.5,2.5z M10.2,1.7c-0.6-0.6-1.5-0.6-2.1,0L1.7,8.1c-0.6,0.6-0.6,1.5,0,2.1l12,12c0.6,0.6,1.5,0.6,2.1,0l6.4-6.4c0.6-0.6,0.6-1.5,0-2.1L10.2,1.7z M14.8,21.2l-12-12l6.4-6.4l12,12L14.8,21.2z M7.5,21.5c-3.3-1.5-5.6-4.7-6-8.5H0.1C0.6,19.2,5.7,24,12,24c0.2,0,0.4,0,0.7,0l-3.8-3.8L7.5,21.5z"/></g> -<g id="sd-storage"><path d="M18,2h-8L4,8l0,12c0,1.1,0.9,2,2,2h12c1.1,0,2-0.9,2-2V4C20,2.9,19.1,2,18,2z M12,8h-2V4h2V8z M15,8h-2V4h2V8z M18,8h-2V4h2V8z"/></g> -<g id="signal-cellular-1-bar"><path d="M2,22h20V2L2,22z M20,20h-8.7v-4.5L20,6.8V20z"/></g> -<g id="signal-cellular-2-bar"><path d="M2,22h20V2L2,22z M20,20h-6v-7.2l6-6V20z"/></g> -<g id="signal-cellular-3-bar"><path d="M2,22h20V2L2,22z M20,20h-3.3v-9.8L20,6.8V20z"/></g> -<g id="signal-cellular-4-bar"><polygon points="2,22 22,22 22,2 "/></g> -<g id="signal-wifi-1-bar"><path d="M12,2C7.5,2,3.3,3.5,0,6l12,16L24,6C20.7,3.5,16.5,2,12,2z M12,13.3c-1.2,0-2.4,0.3-3.5,0.7L2.9,6.5C5.6,4.9,8.7,4,12,4c3.3,0,6.4,0.9,9.1,2.5l-5.7,7.6C14.4,13.6,13.2,13.3,12,13.3z"/></g> -<g id="signal-wifi-2-bar"><path d="M12,2C7.5,2,3.3,3.5,0,6l12,16L24,6C20.7,3.5,16.5,2,12,2z M12,10c-2,0-3.8,0.5-5.5,1.3L2.9,6.5C5.6,4.9,8.7,4,12,4c3.3,0,6.4,0.9,9.1,2.5l-3.6,4.9C15.8,10.5,14,10,12,10z"/></g> -<g id="signal-wifi-3-bar"><path d="M12,2C7.5,2,3.3,3.5,0,6l12,16L24,6C20.7,3.5,16.5,2,12,2z M12,7.3C9.4,7.3,7,8,4.9,9.2l-2-2.7C5.6,4.9,8.7,4,12,4c3.3,0,6.4,0.9,9.1,2.5l-2,2.7C17,8,14.6,7.3,12,7.3z"/></g> -<g id="signal-wifi-4-bar"><path d="M12,2C7.5,2,3.3,3.5,0,6l12,16L24,6C20.7,3.5,16.5,2,12,2z"/></g> -<g id="storage"><path d="M2,19h20v-4H2V19z M4,16h2v2H4V16z M2,5v4h20V5H2z M6,8H4V6h2V8z M2,14h20v-4H2V14z M4,11h2v2H4V11z"/></g> -<g id="timer"><path d="M15,1H9v2h6V1z M11,14h2V8h-2V14z M19,7.4L20.5,6C20,5.5,19.5,5,19,4.6L17.6,6c-1.5-1.2-3.5-2-5.6-2c-5,0-9,4-9,9c0,5,4,9,9,9s9-4,9-9C21,10.9,20.3,8.9,19,7.4z M12,20c-3.9,0-7-3.1-7-7c0-3.9,3.1-7,7-7c3.9,0,7,3.1,7,7C19,16.9,15.9,20,12,20z"/></g> -<g id="usb"><path d="M15,7v4h1v2h-3V5h2l-3-4L9,5h2v8H8v-2.1C8.7,10.6,9.2,9.8,9.2,9c0-1.2-1-2.2-2.2-2.2c-1.2,0-2.2,1-2.2,2.2c0,0.8,0.5,1.6,1.2,1.9V13c0,1.1,0.9,2,2,2h3v3.1c-0.7,0.4-1.2,1.1-1.2,1.9c0,1.2,1,2.2,2.2,2.2c1.2,0,2.2-1,2.2-2.2c0-0.9-0.5-1.6-1.2-1.9V15h3c1.1,0,2-0.9,2-2v-2h1V7H15z"/></g> -<g id="wifi-tethering"><path d="M12,11c-1.1,0-2,0.9-2,2c0,1.1,0.9,2,2,2c1.1,0,2-0.9,2-2C14,11.9,13.1,11,12,11z M18,13c0-3.3-2.7-6-6-6c-3.3,0-6,2.7-6,6c0,2.2,1.2,4.1,3,5.2l1-1.7c-1.2-0.7-2-2-2-3.4c0-2.2,1.8-4,4-4s4,1.8,4,4c0,1.5-0.8,2.8-2,3.4l1,1.7C16.8,17.1,18,15.2,18,13z M12,3C6.5,3,2,7.5,2,13c0,3.7,2,6.9,5,8.6l1-1.7c-2.4-1.4-4-4-4-6.9c0-4.4,3.6-8,8-8s8,3.6,8,8c0,3-1.6,5.5-4,6.9l1,1.7c3-1.7,5-5,5-8.6C22,7.5,17.5,3,12,3z"/></g> -</defs></svg> -</core-iconset-svg> + domReady: function() { + this.services = this.api.services -<!-- -Copyright (c) 2014 The Polymer Project Authors. All rights reserved. -This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt -The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt -The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt -Code distributed by Google as part of the polymer project is also -subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt ---> + this.api.addEventListener('services-updated', this.servicesUpdated.bind(this)) + }, + servicesUpdated: function() { + this.services = this.api.services; + }, + serviceClicked: function(ev) { + if(this.cbServiceClicked) { + var target = ev.path[0]; + var domain = target.getAttributeNode("data-domain").value; + var service = target.innerHTML; -<core-iconset-svg id="social" iconsize="24"> -<svg><defs> -<g id="cake"><path d="M12,7c1.1,0,2-0.9,2-2c0-0.4-0.1-0.7-0.3-1L12,1l-1.7,3C10.1,4.3,10,4.6,10,5C10,6.1,10.9,7,12,7z M21,21v-4c0-1.1-0.9-2-2-2h-1v-3c0-1.1-0.9-2-2-2h-3V8h-2v2H8c-1.1,0-2,0.9-2,2v3H5c-1.1,0-2,0.9-2,2v4H1v2h22v-2H21z"/></g> -<g id="circles"><path d="M16.7,15c-0.8,2.3-3,4-5.7,4c-3.3,0-6-2.7-6-6c0-2.6,1.7-4.8,4-5.7C9,7.2,9,7.1,9,7c0-1,0.2-2,0.5-2.9C5.3,4.8,2,8.5,2,13c0,5,4,9,9,9c4.5,0,8.2-3.3,8.9-7.5C19,14.8,18,15,17,15C16.9,15,16.8,15,16.7,15z"/><path d="M17,1c-3.3,0-6,2.7-6,6s2.7,6,6,6c3.3,0,6-2.7,6-6S20.3,1,17,1z M17,10c-1.7,0-3-1.3-3-3s1.3-3,3-3c1.7,0,3,1.3,3,3S18.7,10,17,10z"/></g> -<g id="circles-add"><path d="M12,2C6.5,2,2,6.5,2,12c0,5.5,4.5,10,10,10s10-4.5,10-10C22,6.5,17.5,2,12,2z M12,20c-4.4,0-8-3.6-8-8s3.6-8,8-8c4.4,0,8,3.6,8,8S16.4,20,12,20z"/><path d="M13,11V8h-2v3H8v2h3v3h2v-3h3v-2H13z"/></g> -<g id="circles-extended"><path d="M12,10c2.2,0,4-1.8,4-4c0-2.2-1.8-4-4-4C9.8,2,8,3.8,8,6C8,8.2,9.8,10,12,10z M12,4c1.1,0,2,0.9,2,2c0,1.1-0.9,2-2,2c-1.1,0-2-0.9-2-2C10,4.9,10.9,4,12,4z M6,13c-2.2,0-4,1.8-4,4c0,2.2,1.8,4,4,4c2.2,0,4-1.8,4-4C10,14.8,8.2,13,6,13z M6,19c-1.1,0-2-0.9-2-2c0-1.1,0.9-2,2-2c1.1,0,2,0.9,2,2C8,18.1,7.1,19,6,19z M12,11.1c-1,0-1.9,0.9-1.9,1.9s0.9,1.9,1.9,1.9c1,0,1.9-0.9,1.9-1.9S13,11.1,12,11.1z M18,13c-2.2,0-4,1.8-4,4c0,2.2,1.8,4,4,4c2.2,0,4-1.8,4-4C22,14.8,20.2,13,18,13z M18,19c-1.1,0-2-0.9-2-2c0-1.1,0.9-2,2-2c1.1,0,2,0.9,2,2C20,18.1,19.1,19,18,19z"/></g> -<g id="communities"><path d="M9,12c-1.1,0-2,0.9-2,2s0.9,2,2,2c1.1,0,2-0.9,2-2S10.1,12,9,12z M14,9c0-1.1-0.9-2-2-2c-1.1,0-2,0.9-2,2s0.9,2,2,2C13.1,11,14,10.1,14,9z M12,2C6.5,2,2,6.5,2,12c0,5.5,4.5,10,10,10c5.5,0,10-4.5,10-10C22,6.5,17.5,2,12,2z M12,20c-4.4,0-8-3.6-8-8c0-4.4,3.6-8,8-8c4.4,0,8,3.6,8,8C20,16.4,16.4,20,12,20z M15,12c-1.1,0-2,0.9-2,2s0.9,2,2,2c1.1,0,2-0.9,2-2S16.1,12,15,12z"/></g> -<g id="domain"><path d="M12,7V3H2v18h20V7H12z M6,19H4v-2h2V19z M6,15H4v-2h2V15z M6,11H4V9h2V11z M6,7H4V5h2V7z M10,19H8v-2h2V19z M10,15H8v-2h2V15z M10,11H8V9h2V11z M10,7H8V5h2V7z M20,19h-8v-2h2v-2h-2v-2h2v-2h-2V9h8V19z M18,11h-2v2h2V11z M18,15h-2v2h2V15z"/></g> -<g id="group"><path d="M16,11c1.7,0,3-1.3,3-3c0-1.7-1.3-3-3-3c-1.7,0-3,1.3-3,3C13,9.7,14.3,11,16,11z M8,11c1.7,0,3-1.3,3-3c0-1.7-1.3-3-3-3C6.3,5,5,6.3,5,8C5,9.7,6.3,11,8,11z M8,13c-2.3,0-7,1.2-7,3.5V19h14v-2.5C15,14.2,10.3,13,8,13z M16,13c-0.3,0-0.6,0-1,0.1c1.2,0.8,2,2,2,3.4V19h6v-2.5C23,14.2,18.3,13,16,13z"/></g> -<g id="group-add"><path d="M8,10H5V7H3v3H0v2h3v3h2v-3h3V10z M18,11c1.7,0,3-1.3,3-3c0-1.7-1.3-3-3-3c-0.3,0-0.6,0.1-0.9,0.1C17.7,6,18,6.9,18,8s-0.3,2-0.9,2.9C17.4,10.9,17.7,11,18,11z M13,11c1.7,0,3-1.3,3-3c0-1.7-1.3-3-3-3c-1.7,0-3,1.3-3,3C10,9.7,11.3,11,13,11z M19.6,13.2c0.8,0.7,1.4,1.7,1.4,2.8v2h3v-2C24,14.5,21.6,13.5,19.6,13.2z M13,13c-2,0-6,1-6,3v2h12v-2C19,14,15,13,13,13z"/></g> -<g id="location-city"><path d="M15,11V5l-3-3L9,5v2H3v14h18V11H15z M7,19H5v-2h2V19z M7,15H5v-2h2V15z M7,11H5V9h2V11z M13,19h-2v-2h2V19z M13,15h-2v-2h2V15z M13,11h-2V9h2V11z M13,7h-2V5h2V7z M19,19h-2v-2h2V19z M19,15h-2v-2h2V15z"/></g> -<g id="mood"><path d="M12,2C6.5,2,2,6.5,2,12s4.5,10,10,10c5.5,0,10-4.5,10-10S17.5,2,12,2z M12,20c-4.4,0-8-3.6-8-8s3.6-8,8-8c4.4,0,8,3.6,8,8S16.4,20,12,20z M15.5,11c0.8,0,1.5-0.7,1.5-1.5S16.3,8,15.5,8S14,8.7,14,9.5S14.7,11,15.5,11z M8.5,11c0.8,0,1.5-0.7,1.5-1.5S9.3,8,8.5,8S7,8.7,7,9.5S7.7,11,8.5,11z M12,17.5c2.3,0,4.3-1.5,5.1-3.5H6.9C7.7,16,9.7,17.5,12,17.5z"/></g> -<g id="notifications"><path d="M11.5,22c1.1,0,2-0.9,2-2h-4C9.5,21.1,10.4,22,11.5,22z M18,16v-5.5c0-3.1-2.1-5.6-5-6.3V3.5C13,2.7,12.3,2,11.5,2C10.7,2,10,2.7,10,3.5v0.7c-2.9,0.7-5,3.2-5,6.3V16l-2,2v1h17v-1L18,16z"/></g> -<g id="notifications-none"><path d="M11.5,22c1.1,0,2-0.9,2-2h-4C9.5,21.1,10.4,22,11.5,22z M18,16v-5.5c0-3.1-2.1-5.6-5-6.3V3.5C13,2.7,12.3,2,11.5,2C10.7,2,10,2.7,10,3.5v0.7c-2.9,0.7-5,3.2-5,6.3V16l-2,2v1h17v-1L18,16z M16,17H7v-6.5C7,8,9,6,11.5,6C14,6,16,8,16,10.5V17z"/></g> -<g id="notifications-off"><path d="M11.5,22c1.1,0,2-0.9,2-2h-4C9.5,21.1,10.4,22,11.5,22z M18,10.5c0-3.1-2.1-5.6-5-6.3V3.5C13,2.7,12.3,2,11.5,2C10.7,2,10,2.7,10,3.5v0.7C9.5,4.3,9,4.5,8.6,4.7l9.4,9.4V10.5z M17.7,19l2,2l1.3-1.3L4.3,3L3,4.3l2.9,2.9C5.3,8.2,5,9.3,5,10.5V16l-2,2v1H17.7z"/></g> -<g id="notifications-on"><path d="M6.6,3.6L5.2,2.2C2.8,4,1.2,6.8,1,10h2C3.2,7.3,4.5,5,6.6,3.6z M20,10h2c-0.2-3.2-1.7-6-4.1-7.8l-1.4,1.4C18.5,5,19.8,7.3,20,10z M18,10.5c0-3.1-2.1-5.6-5-6.3V3.5C13,2.7,12.3,2,11.5,2C10.7,2,10,2.7,10,3.5v0.7c-2.9,0.7-5,3.2-5,6.3V16l-2,2v1h17v-1l-2-2V10.5z M11.5,22c0.1,0,0.3,0,0.4,0c0.7-0.1,1.2-0.6,1.4-1.2c0.1-0.2,0.2-0.5,0.2-0.8h-4C9.5,21.1,10.4,22,11.5,22z"/></g> -<g id="notifications-paused"><path d="M11.5,22c1.1,0,2-0.9,2-2h-4C9.5,21.1,10.4,22,11.5,22z M18,16v-5.5c0-3.1-2.1-5.6-5-6.3V3.5C13,2.7,12.3,2,11.5,2C10.7,2,10,2.7,10,3.5v0.7c-2.9,0.7-5,3.2-5,6.3V16l-2,2v1h17v-1L18,16z M14,9.8l-2.8,3.4H14V15H9v-1.8l2.8-3.4H9V8h5V9.8z"/></g> -<g id="pages"><path d="M3,5v6h5L7,7l4,1V3H5C3.9,3,3,3.9,3,5z M8,13H3v6c0,1.1,0.9,2,2,2h6v-5l-4,1L8,13z M17,17l-4-1v5h6c1.1,0,2-0.9,2-2v-6l-5,0L17,17z M19,3h-6v5l4-1l-1,4h5V5C21,3.9,20.1,3,19,3z"/></g> -<g id="party-mode"><path d="M20,4h-3.2L15,2H9L7.2,4H4C2.9,4,2,4.9,2,6v12c0,1.1,0.9,2,2,2h16c1.1,0,2-0.9,2-2V6C22,4.9,21.1,4,20,4z M12,7c1.6,0,3.1,0.8,4,2h-4c-1.7,0-3,1.3-3,3c0,0.4,0.1,0.7,0.2,1H7.1C7,12.7,7,12.3,7,12C7,9.2,9.2,7,12,7z M12,17c-1.6,0-3.1-0.8-4-2h4c1.7,0,3-1.3,3-3c0-0.4-0.1-0.7-0.2-1h2.1c0.1,0.3,0.1,0.7,0.1,1C17,14.8,14.8,17,12,17z"/></g> -<g id="people"><path d="M16,11c1.7,0,3-1.3,3-3c0-1.7-1.3-3-3-3c-1.7,0-3,1.3-3,3C13,9.7,14.3,11,16,11z M8,11c1.7,0,3-1.3,3-3c0-1.7-1.3-3-3-3C6.3,5,5,6.3,5,8C5,9.7,6.3,11,8,11z M8,13c-2.3,0-7,1.2-7,3.5V19h14v-2.5C15,14.2,10.3,13,8,13z M16,13c-0.3,0-0.6,0-1,0.1c1.2,0.8,2,2,2,3.4V19h6v-2.5C23,14.2,18.3,13,16,13z"/></g> -<g id="person"><path d="M12,12c2.2,0,4-1.8,4-4c0-2.2-1.8-4-4-4C9.8,4,8,5.8,8,8C8,10.2,9.8,12,12,12z M12,14c-2.7,0-8,1.3-8,4v2h16v-2C20,15.3,14.7,14,12,14z"/></g> -<g id="person-add"><path d="M15,12c2.2,0,4-1.8,4-4c0-2.2-1.8-4-4-4c-2.2,0-4,1.8-4,4C11,10.2,12.8,12,15,12z M6,10V7H4v3H1v2h3v3h2v-3h3v-2H6z M15,14c-2.7,0-8,1.3-8,4v2h16v-2C23,15.3,17.7,14,15,14z"/></g> -<g id="person-outline"><path d="M12,5.9c1.2,0,2.1,0.9,2.1,2.1s-0.9,2.1-2.1,2.1S9.9,9.2,9.9,8S10.8,5.9,12,5.9 M12,14.9c3,0,6.1,1.5,6.1,2.1v1.1H5.9V17C5.9,16.4,9,14.9,12,14.9 M12,4C9.8,4,8,5.8,8,8c0,2.2,1.8,4,4,4c2.2,0,4-1.8,4-4C16,5.8,14.2,4,12,4L12,4z M12,13c-2.7,0-8,1.3-8,4v3h16v-3C20,14.3,14.7,13,12,13L12,13z"/></g> -<g id="plus-one"><polygon points="10,8 8,8 8,12 4,12 4,14 8,14 8,18 10,18 10,14 14,14 14,12 10,12 "/></g> -<g id="poll"><path d="M19,3H5C3.9,3,3,3.9,3,5v14c0,1.1,0.9,2,2,2h14c1.1,0,2-0.9,2-2V5C21,3.9,20.1,3,19,3z M9,17H7v-7h2V17z M13,17h-2V7h2V17z M17,17h-2v-4h2V17z"/></g> -<g id="post-blogger"><path d="M20,2H4C2.9,2,2,2.9,2,4l0,16c0,1.1,0.9,2,2,2h16c1.1,0,2-0.9,2-2V4C22,2.9,21.1,2,20,2z M16,9v1c0,0.6,0.4,1,1,1c0.6,0,1,0.4,1,1v3c0,1.7-1.3,3-3,3H9c-1.7,0-3-1.3-3-3V8c0-1.7,1.3-3,3-3h4c1.7,0,3,1.3,3,3V9z M10,10h2.6c0.6,0,1-0.4,1-1c0-0.6-0.4-1-1-1H10C9.4,8,9,8.4,9,9C9,9.6,9.4,10,10,10z M14,13h-4c-0.6,0-1,0.4-1,1c0,0.6,0.4,1,1,1h4c0.6,0,1-0.4,1-1C15,13.4,14.6,13,14,13z"/></g> -<g id="post-facebook"><path d="M20,2H4C2.9,2,2,2.9,2,4l0,16c0,1.1,0.9,2,2,2h16c1.1,0,2-0.9,2-2V4C22,2.9,21.1,2,20,2z M19,4v3h-2c-0.6,0-1,0.4-1,1v2h3v3h-3v7h-3v-7h-2v-3h2V7.5C13,5.6,14.6,4,16.5,4H19z"/></g> -<g id="post-github"><path d="M7.2 6.6h-.1c-.5 1.4-.2 2.3-.1 2.6-.6.7-1 1.6-1 2.6 0 3.8 2.4 4.6 4.6 4.9-.2 0-.6.2-.8.8-.4.2-1.8.7-2.6-.7 0 0-.5-.8-1.3-.9 0 0-.8 0-.1.5 0 0 .6.3.9 1.3 0 0 .5 1.7 3 1.1v3.1h5v-3.5c0-1-.4-1.5-.8-1.8 2.2-.2 4.6-1 4.6-4.8 0-1.1-.4-2-1-2.6.1-.3.4-1.2-.1-2.6 0 0-.8-.3-2.7 1-.8-.2-1.6-.3-2.5-.3-.8 0-1.7.1-2.5.3-1.4-1-2.2-1-2.6-1zm12.8 15.4h-16c-1.1 0-2-.9-2-2v-16c0-1.1.9-2 2-2h16c1.1 0 2 .9 2 2v16c0 1.1-.9 2-2 2z"/></g> -<g id="post-gplus"><path d="M11.2,8.9c0-1-0.6-3-2.1-3c-0.6,0-1.3,0.4-1.3,1.7c0,1.2,0.6,2.9,2,2.9C9.8,10.5,11.2,10.4,11.2,8.9z M10.6,13.8c-0.1,0-0.2,0-0.3,0h0c-0.3,0-1.2,0.1-1.8,0.3C7.8,14.3,7,14.8,7,15.8c0,1.1,1,2.2,3,2.2c1.5,0,2.4-1,2.4-2C12.4,15.3,11.9,14.8,10.6,13.8z M20,2H4C2.9,2,2,2.9,2,4l0,16c0,1.1,0.9,2,2,2h16c1.1,0,2-0.9,2-2V4C22,2.9,21.1,2,20,2z M9.1,19.2c-2.8,0-4.1-1.6-4.1-3c0-0.5,0.1-1.6,1.5-2.4c0.8-0.5,1.8-0.8,3.1-0.9c-0.2-0.2-0.3-0.5-0.3-1c0-0.2,0-0.3,0.1-0.5H9c-2,0-3.2-1.5-3.2-3c0-1.7,1.3-3.6,4.1-3.6h4.2l-0.3,0.3l-0.7,0.7L13,5.9h-0.7c0.4,0.4,0.9,1.1,0.9,2.2c0,1.4-0.7,2.1-1.6,2.7c-0.2,0.1-0.4,0.4-0.4,0.7c0,0.3,0.2,0.5,0.4,0.6c0.1,0.1,0.3,0.2,0.5,0.3c0.8,0.6,1.9,1.3,1.9,2.9C14,17.1,12.7,19.2,9.1,19.2z M19,12h-2v2h-1v-2h-2v-1h2V9h1v2h2V12z"/></g> -<g id="post-instagram"><path d="M20,2H4C2.9,2,2,2.9,2,4l0,16c0,1.1,0.9,2,2,2h16c1.1,0,2-0.9,2-2V4C22,2.9,21.1,2,20,2z M12,8c2.2,0,4,1.8,4,4s-1.8,4-4,4c-2.2,0-4-1.8-4-4S9.8,8,12,8z M4.5,20C4.2,20,4,19.8,4,19.5V11h2.1C6,11.3,6,11.7,6,12c0,3.3,2.7,6,6,6c3.3,0,6-2.7,6-6c0-0.3,0-0.7-0.1-1H20v8.5c0,0.3-0.2,0.5-0.5,0.5H4.5z M20,6.5C20,6.8,19.8,7,19.5,7h-2C17.2,7,17,6.8,17,6.5v-2C17,4.2,17.2,4,17.5,4h2C19.8,4,20,4.2,20,4.5V6.5z"/></g> -<g id="post-linkedin"><path d="M20,2H4C2.9,2,2,2.9,2,4l0,16c0,1.1,0.9,2,2,2h16c1.1,0,2-0.9,2-2V4C22,2.9,21.1,2,20,2z M8,19H5v-9h3V19z M6.5,8.3c-1,0-1.8-0.8-1.8-1.8s0.8-1.8,1.8-1.8s1.8,0.8,1.8,1.8S7.5,8.3,6.5,8.3z M19,19h-3v-5.3c0-0.8-0.7-1.5-1.5-1.5c-0.8,0-1.5,0.7-1.5,1.5V19h-3v-9h3v1.2c0.5-0.8,1.6-1.4,2.5-1.4c1.9,0,3.5,1.6,3.5,3.5V19z"/></g> -<g id="post-pinterest"><path d="M20,2H4C2.9,2,2,2.9,2,4l0,16c0,1.1,0.9,2,2,2h16c1.1,0,2-0.9,2-2V4C22,2.9,21.1,2,20,2z M13,16.2c-0.8,0-1.6-0.3-2.1-0.9l-1,3.2l-0.1,0.2l0,0c-0.2,0.3-0.5,0.5-0.9,0.5c-0.6,0-1.1-0.5-1.1-1.1c0-0.1,0-0.1,0-0.1l0,0l0.1-0.2l1.8-5.6c0,0-0.2-0.6-0.2-1.5c0-1.7,0.9-2.2,1.7-2.2c0.7,0,1.4,0.3,1.4,1.3c0,1.3-0.9,2-0.9,3c0,0.7,0.6,1.3,1.3,1.3c2.3,0,3.2-1.8,3.2-3.4c0-2.2-1.9-4-4.2-4c-2.3,0-4.2,1.8-4.2,4c0,0.7,0.2,1.3,0.5,1.9c0.1,0.2,0.1,0.3,0.1,0.5c0,0.6-0.4,1-1,1c-0.4,0-0.7-0.2-0.9-0.5c-0.5-0.9-0.8-1.9-0.8-3c0-3.3,2.8-6,6.2-6c3.4,0,6.2,2.7,6.2,6C18.2,13.4,16.6,16.2,13,16.2z"/></g> -<g id="post-tumblr"><path d="M20,2H4C2.9,2,2,2.9,2,4l0,16c0,1.1,0.9,2,2,2h16c1.1,0,2-0.9,2-2V4C22,2.9,21.1,2,20,2z M16,11h-3c0,0,0,3.8,0,3.9c0,0.7,0.1,1.1,1.1,1.1c0.9,0,1.9,0,1.9,0v3c0,0-1,0.1-2.1,0.1c-2.6,0-3.9-1.6-3.9-3.4c0-1.2,0-4.7,0-4.7H8V8.2c2.4-0.2,2.6-2,2.8-3.2H13v3h3V11z"/></g> -<g id="post-twitter"><path d="M20,2H4C2.9,2,2,2.9,2,4l0,16c0,1.1,0.9,2,2,2h16c1.1,0,2-0.9,2-2V4C22,2.9,21.1,2,20,2z M17.7,9.3c-0.1,4.6-3,7.8-7.4,8c-1.8,0.1-3.1-0.5-4.3-1.2c1.3,0.2,3-0.3,3.9-1.1c-1.3-0.1-2.1-0.8-2.5-1.9c0.4,0.1,0.8,0,1.1,0c-1.2-0.4-2-1.1-2.1-2.7c0.3,0.2,0.7,0.3,1.1,0.3c-0.9-0.5-1.5-2.4-0.8-3.6c1.3,1.4,2.9,2.6,5.5,2.8c-0.7-2.8,3.1-4.3,4.6-2.4c0.7-0.1,1.2-0.4,1.7-0.6c-0.2,0.7-0.6,1.1-1.1,1.5c0.5-0.1,1-0.2,1.4-0.4C18.7,8.5,18.2,8.9,17.7,9.3z"/></g> -<g id="public"><path d="M12,2C6.5,2,2,6.5,2,12c0,5.5,4.5,10,10,10c5.5,0,10-4.5,10-10C22,6.5,17.5,2,12,2z M11,19.9c-3.9-0.5-7-3.9-7-7.9c0-0.6,0.1-1.2,0.2-1.8L9,15v1c0,1.1,0.9,2,2,2V19.9z M17.9,17.4c-0.3-0.8-1-1.4-1.9-1.4h-1v-3c0-0.6-0.4-1-1-1H8v-2h2c0.6,0,1-0.4,1-1V7h2c1.1,0,2-0.9,2-2V4.6c2.9,1.2,5,4.1,5,7.4C20,14.1,19.2,16,17.9,17.4z"/></g> -<g id="school"><path d="M5,13.2v4l7,3.8l7-3.8v-4L12,17L5,13.2z M12,3L1,9l11,6l9-4.9V17h2V9L12,3z"/></g> -<g id="share"><path d="M21,11l-7-7v4C7,9,4,14,3,19c2.5-3.5,6-5.1,11-5.1V18L21,11z"/></g> -<g id="share-alt"><path d="M18,16.1c-0.8,0-1.5,0.3-2,0.8l-7.1-4.2C9,12.5,9,12.2,9,12s0-0.5-0.1-0.7L16,7.2C16.5,7.7,17.2,8,18,8c1.7,0,3-1.3,3-3s-1.3-3-3-3s-3,1.3-3,3c0,0.2,0,0.5,0.1,0.7L8,9.8C7.5,9.3,6.8,9,6,9c-1.7,0-2.9,1.2-2.9,2.9c0,1.7,1.3,3,3,3c0.8,0,1.5-0.3,2-0.8l7.1,4.2c-0.1,0.3-0.1,0.5-0.1,0.7c0,1.6,1.3,2.9,2.9,2.9s2.9-1.3,2.9-2.9S19.6,16.1,18,16.1z"/></g> -<g id="whatshot"><path d="M13.5,0.7c0,0,0.7,2.6,0.7,4.8c0,2.1-1.4,3.7-3.4,3.7c-2.1,0-3.6-1.7-3.6-3.7l0-0.4C5.2,7.5,4,10.6,4,14c0,4.4,3.6,8,8,8c4.4,0,8-3.6,8-8C20,8.6,17.4,3.8,13.5,0.7z M11.7,19c-1.8,0-3.2-1.4-3.2-3.1c0-1.6,1-2.8,2.8-3.1c1.8-0.4,3.6-1.2,4.6-2.6c0.4,1.3,0.6,2.6,0.6,4C16.5,16.8,14.4,19,11.7,19z"/></g> -</defs></svg> -</core-iconset-svg> + this.cbServiceClicked(domain, service); + } + } -<!-- -Copyright (c) 2014 The Polymer Project Authors. All rights reserved. -This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt -The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt -The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt -Code distributed by Google as part of the polymer project is also -subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt ---> + }); + </script> +</polymer-element> +<polymer-element name="service-call-dialog" attributes="api" assetpath="polymer/"> + <template> + <style> + paper-input:first-child { + padding-top: 0; + } -<core-iconset-svg id="image" iconsize="24"> -<svg><defs> -<g id="add-to-photos"><path d="M4,6H2v14c0,1.1,0.9,2,2,2h14v-2H4V6z M20,2H8C6.9,2,6,2.9,6,4v12c0,1.1,0.9,2,2,2h12c1.1,0,2-0.9,2-2V4C22,2.9,21.1,2,20,2z M19,11h-4v4h-2v-4H9V9h4V5h2v4h4V11z"/></g> -<g id="adjust"><path d="M12,2C6.5,2,2,6.5,2,12s4.5,10,10,10s10-4.5,10-10S17.5,2,12,2z M12,20c-4.4,0-8-3.6-8-8s3.6-8,8-8s8,3.6,8,8S16.4,20,12,20z M15,12c0,1.7-1.3,3-3,3s-3-1.3-3-3s1.3-3,3-3S15,10.3,15,12z"/></g> -<g id="aspect-ratio"><path d="M16,10h-2v2h2V10z M16,14h-2v2h2V14z M8,10H6v2h2V10z M12,10h-2v2h2V10z M20,4H4C2.9,4,2,4.9,2,6v12c0,1.1,0.9,2,2,2h16c1.1,0,2-0.9,2-2V6C22,4.9,21.1,4,20,4z M20,18L4,18V6h16V18z"/></g> -<g id="assistant-photo"><polygon points="14.4,6 14,4 5,4 5,21 7,21 7,14 12.6,14 13,16 20,16 20,6 "/></g> -<g id="auto-awesome"><path d="M19,9l1.2-2.8L23,5l-2.8-1.2L19,1l-1.2,2.8L15,5l2.8,1.2L19,9z M11.5,9.5L9,4L6.5,9.5L1,12l5.5,2.5L9,20l2.5-5.5L17,12L11.5,9.5z M19,15l-1.2,2.7L15,19l2.8,1.2L19,23l1.2-2.8L23,19l-2.8-1.2L19,15z"/></g> -<g id="auto-awesome-mix"><path d="M3,5v14c0,1.1,0.9,2,2,2h6V3H5C3.9,3,3,3.9,3,5z M19,3h-6v8h8V5C21,3.9,20.1,3,19,3z M13,21h6c1.1,0,2-0.9,2-2v-6h-8V21z"/></g> -<g id="auto-awesome-motion"><path d="M14,2H4C2.9,2,2,2.9,2,4v10h2V4h10V2z M18,6H8C6.9,6,6,6.9,6,8v10h2V8h10V6z M20,10h-8c-1.1,0-2,0.9-2,2v8c0,1.1,0.9,2,2,2h8c1.1,0,2-0.9,2-2v-8C22,10.9,21.1,10,20,10z"/></g> -<g id="auto-fix"><polygon points="7.5,5.6 10,7 8.6,4.5 10,2 7.5,3.4 5,2 6.4,4.5 5,7 "/></g> -<g id="auto-fix-high"><polygon points="7.5,5.6 10,7 8.6,4.5 10,2 7.5,3.4 5,2 6.4,4.5 5,7 "/></g> -<g id="auto-fix-normal"><polygon points="22,2 19.5,3.4 17,2 18.4,4.5 17,7 19.5,5.6 22,7 20.6,4.5 "/></g> -<g id="auto-fix-off"><path d="M23,1l-2.5,1.4L18,1l1.4,2.5L18,6l2.5-1.4L23,6l-1.4-2.5L23,1z M14.7,7.2l2.1,2.1l-2.4,2.4l0.8,0.8l2.6-2.6c0.4-0.4,0.4-1,0-1.4l-2.3-2.3c-0.4-0.4-1-0.4-1.4,0l-2.6,2.6l0.8,0.8L14.7,7.2z M13.9,13.9l-3.8-3.8h0L3.3,3.3L2,4.5l6.9,6.9L2.3,18c-0.4,0.4-0.4,1,0,1.4l2.3,2.3c0.4,0.4,1,0.4,1.4,0l6.6-6.6l6.9,6.9l1.3-1.3L13.9,13.9L13.9,13.9z"/></g> -<g id="auto-stories"><path d="M18,1l-5,4v16l5-3.9V1z M1,7v12c0,1.1,0.9,2,2,2h8V5H3C1.9,5,1,5.9,1,7z M21,5h-1v13.1l-0.8,0.6l-3,2.3H21c1.1,0,2-0.9,2-2V7C23,5.9,22.1,5,21,5z"/></g> -<g id="blur-circular"><path d="M10,9c-0.6,0-1,0.4-1,1s0.4,1,1,1s1-0.4,1-1S10.6,9,10,9z M10,13c-0.6,0-1,0.4-1,1s0.4,1,1,1s1-0.4,1-1S10.6,13,10,13z M7,9.5c-0.3,0-0.5,0.2-0.5,0.5s0.2,0.5,0.5,0.5s0.5-0.2,0.5-0.5S7.3,9.5,7,9.5z M10,16.5c-0.3,0-0.5,0.2-0.5,0.5s0.2,0.5,0.5,0.5s0.5-0.2,0.5-0.5S10.3,16.5,10,16.5z M7,13.5c-0.3,0-0.5,0.2-0.5,0.5s0.2,0.5,0.5,0.5s0.5-0.2,0.5-0.5S7.3,13.5,7,13.5z M10,7.5c0.3,0,0.5-0.2,0.5-0.5S10.3,6.5,10,6.5S9.5,6.7,9.5,7S9.7,7.5,10,7.5z M14,9c-0.6,0-1,0.4-1,1s0.4,1,1,1s1-0.4,1-1S14.6,9,14,9z M14,7.5c0.3,0,0.5-0.2,0.5-0.5S14.3,6.5,14,6.5S13.5,6.7,13.5,7S13.7,7.5,14,7.5z M17,13.5c-0.3,0-0.5,0.2-0.5,0.5s0.2,0.5,0.5,0.5s0.5-0.2,0.5-0.5S17.3,13.5,17,13.5z M17,9.5c-0.3,0-0.5,0.2-0.5,0.5s0.2,0.5,0.5,0.5s0.5-0.2,0.5-0.5S17.3,9.5,17,9.5z M12,2C6.5,2,2,6.5,2,12s4.5,10,10,10s10-4.5,10-10S17.5,2,12,2z M12,20c-4.4,0-8-3.6-8-8s3.6-8,8-8s8,3.6,8,8S16.4,20,12,20z M14,16.5c-0.3,0-0.5,0.2-0.5,0.5s0.2,0.5,0.5,0.5s0.5-0.2,0.5-0.5S14.3,16.5,14,16.5z M14,13c-0.6,0-1,0.4-1,1s0.4,1,1,1s1-0.4,1-1S14.6,13,14,13z"/></g> -<g id="blur-linear"><path d="M5,17.5c0.8,0,1.5-0.7,1.5-1.5S5.8,14.5,5,14.5S3.5,15.2,3.5,16S4.2,17.5,5,17.5z M9,13c0.6,0,1-0.4,1-1s-0.4-1-1-1s-1,0.4-1,1S8.4,13,9,13z M9,9c0.6,0,1-0.4,1-1S9.6,7,9,7S8,7.4,8,8S8.4,9,9,9z M3,21h18v-2H3V21z M5,9.5c0.8,0,1.5-0.7,1.5-1.5S5.8,6.5,5,6.5S3.5,7.2,3.5,8S4.2,9.5,5,9.5z M5,13.5c0.8,0,1.5-0.7,1.5-1.5S5.8,10.5,5,10.5S3.5,11.2,3.5,12S4.2,13.5,5,13.5z M9,17c0.6,0,1-0.4,1-1s-0.4-1-1-1s-1,0.4-1,1S8.4,17,9,17z M17,16.5c0.3,0,0.5-0.2,0.5-0.5s-0.2-0.5-0.5-0.5s-0.5,0.2-0.5,0.5S16.7,16.5,17,16.5z M3,3v2h18V3H3z M17,8.5c0.3,0,0.5-0.2,0.5-0.5c0-0.3-0.2-0.5-0.5-0.5S16.5,7.7,16.5,8C16.5,8.3,16.7,8.5,17,8.5z M17,12.5c0.3,0,0.5-0.2,0.5-0.5s-0.2-0.5-0.5-0.5s-0.5,0.2-0.5,0.5S16.7,12.5,17,12.5z M13,9c0.6,0,1-0.4,1-1s-0.4-1-1-1s-1,0.4-1,1S12.4,9,13,9z M13,13c0.6,0,1-0.4,1-1s-0.4-1-1-1s-1,0.4-1,1S12.4,13,13,13z M13,17c0.6,0,1-0.4,1-1s-0.4-1-1-1s-1,0.4-1,1S12.4,17,13,17z"/></g> -<g id="blur-off"><path d="M14,7c0.6,0,1-0.4,1-1s-0.4-1-1-1s-1,0.4-1,1S13.4,7,14,7z M13.8,11.5c0.1,0,0.1,0,0.2,0c0.8,0,1.5-0.7,1.5-1.5S14.8,8.5,14,8.5s-1.5,0.7-1.5,1.5c0,0.1,0,0.1,0,0.2C12.6,10.9,13.1,11.4,13.8,11.5z M14,3.5c0.3,0,0.5-0.2,0.5-0.5S14.3,2.5,14,2.5S13.5,2.7,13.5,3S13.7,3.5,14,3.5z M10,3.5c0.3,0,0.5-0.2,0.5-0.5S10.3,2.5,10,2.5S9.5,2.7,9.5,3S9.7,3.5,10,3.5z M21,10.5c0.3,0,0.5-0.2,0.5-0.5S21.3,9.5,21,9.5s-0.5,0.2-0.5,0.5S20.7,10.5,21,10.5z M10,7c0.6,0,1-0.4,1-1s-0.4-1-1-1S9,5.4,9,6S9.4,7,10,7z M18,15c0.6,0,1-0.4,1-1s-0.4-1-1-1s-1,0.4-1,1S17.4,15,18,15z M18,11c0.6,0,1-0.4,1-1s-0.4-1-1-1s-1,0.4-1,1S17.4,11,18,11z M18,7c0.6,0,1-0.4,1-1s-0.4-1-1-1s-1,0.4-1,1S17.4,7,18,7z M14,20.5c-0.3,0-0.5,0.2-0.5,0.5s0.2,0.5,0.5,0.5s0.5-0.2,0.5-0.5S14.3,20.5,14,20.5z M2.5,5.3l3.8,3.8C6.2,9,6.1,9,6,9c-0.6,0-1,0.4-1,1s0.4,1,1,1s1-0.4,1-1c0-0.1,0-0.2-0.1-0.3l2.8,2.8C9,12.6,8.5,13.3,8.5,14c0,0.8,0.7,1.5,1.5,1.5c0.7,0,1.4-0.5,1.5-1.3l2.8,2.8C14.2,17,14.1,17,14,17c-0.6,0-1,0.4-1,1s0.4,1,1,1s1-0.4,1-1c0-0.1,0-0.2-0.1-0.3l3.8,3.8l1.3-1.3L3.8,4L2.5,5.3z M10,17c-0.6,0-1,0.4-1,1s0.4,1,1,1s1-0.4,1-1S10.6,17,10,17z M21,13.5c-0.3,0-0.5,0.2-0.5,0.5s0.2,0.5,0.5,0.5s0.5-0.2,0.5-0.5S21.3,13.5,21,13.5z M6,13c-0.6,0-1,0.4-1,1s0.4,1,1,1s1-0.4,1-1S6.6,13,6,13z M3,9.5c-0.3,0-0.5,0.2-0.5,0.5s0.2,0.5,0.5,0.5s0.5-0.2,0.5-0.5S3.3,9.5,3,9.5z M10,20.5c-0.3,0-0.5,0.2-0.5,0.5s0.2,0.5,0.5,0.5s0.5-0.2,0.5-0.5S10.3,20.5,10,20.5z M6,17c-0.6,0-1,0.4-1,1s0.4,1,1,1s1-0.4,1-1S6.6,17,6,17z M3,13.5c-0.3,0-0.5,0.2-0.5,0.5s0.2,0.5,0.5,0.5s0.5-0.2,0.5-0.5S3.3,13.5,3,13.5z"/></g> -<g id="blur-on"><path d="M6,13c-0.6,0-1,0.4-1,1s0.4,1,1,1s1-0.4,1-1S6.6,13,6,13z M6,17c-0.6,0-1,0.4-1,1s0.4,1,1,1s1-0.4,1-1S6.6,17,6,17z M6,9c-0.6,0-1,0.4-1,1s0.4,1,1,1s1-0.4,1-1S6.6,9,6,9z M3,9.5c-0.3,0-0.5,0.2-0.5,0.5s0.2,0.5,0.5,0.5s0.5-0.2,0.5-0.5S3.3,9.5,3,9.5z M6,5C5.4,5,5,5.4,5,6s0.4,1,1,1s1-0.4,1-1S6.6,5,6,5z M21,10.5c0.3,0,0.5-0.2,0.5-0.5S21.3,9.5,21,9.5s-0.5,0.2-0.5,0.5S20.7,10.5,21,10.5z M14,7c0.6,0,1-0.4,1-1s-0.4-1-1-1s-1,0.4-1,1S13.4,7,14,7z M14,3.5c0.3,0,0.5-0.2,0.5-0.5S14.3,2.5,14,2.5S13.5,2.7,13.5,3S13.7,3.5,14,3.5z M3,13.5c-0.3,0-0.5,0.2-0.5,0.5s0.2,0.5,0.5,0.5s0.5-0.2,0.5-0.5S3.3,13.5,3,13.5z M10,20.5c-0.3,0-0.5,0.2-0.5,0.5s0.2,0.5,0.5,0.5s0.5-0.2,0.5-0.5S10.3,20.5,10,20.5z M10,3.5c0.3,0,0.5-0.2,0.5-0.5S10.3,2.5,10,2.5S9.5,2.7,9.5,3S9.7,3.5,10,3.5z M10,7c0.6,0,1-0.4,1-1s-0.4-1-1-1S9,5.4,9,6S9.4,7,10,7z M10,12.5c-0.8,0-1.5,0.7-1.5,1.5s0.7,1.5,1.5,1.5s1.5-0.7,1.5-1.5S10.8,12.5,10,12.5z M18,13c-0.6,0-1,0.4-1,1s0.4,1,1,1s1-0.4,1-1S18.6,13,18,13z M18,17c-0.6,0-1,0.4-1,1s0.4,1,1,1s1-0.4,1-1S18.6,17,18,17z M18,9c-0.6,0-1,0.4-1,1s0.4,1,1,1s1-0.4,1-1S18.6,9,18,9z M18,5c-0.6,0-1,0.4-1,1s0.4,1,1,1s1-0.4,1-1S18.6,5,18,5z M21,13.5c-0.3,0-0.5,0.2-0.5,0.5s0.2,0.5,0.5,0.5s0.5-0.2,0.5-0.5S21.3,13.5,21,13.5z M14,17c-0.6,0-1,0.4-1,1s0.4,1,1,1s1-0.4,1-1S14.6,17,14,17z M14,20.5c-0.3,0-0.5,0.2-0.5,0.5s0.2,0.5,0.5,0.5s0.5-0.2,0.5-0.5S14.3,20.5,14,20.5z M10,8.5c-0.8,0-1.5,0.7-1.5,1.5s0.7,1.5,1.5,1.5s1.5-0.7,1.5-1.5S10.8,8.5,10,8.5z M10,17c-0.6,0-1,0.4-1,1s0.4,1,1,1s1-0.4,1-1S10.6,17,10,17z M14,12.5c-0.8,0-1.5,0.7-1.5,1.5s0.7,1.5,1.5,1.5s1.5-0.7,1.5-1.5S14.8,12.5,14,12.5z M14,8.5c-0.8,0-1.5,0.7-1.5,1.5s0.7,1.5,1.5,1.5s1.5-0.7,1.5-1.5S14.8,8.5,14,8.5z"/></g> -<g id="brightness-1"><circle cx="12" cy="12" r="10"/></g> -<g id="brightness-2"><path d="M10,2C8.2,2,6.5,2.5,5,3.3c3,1.7,5,5,5,8.7s-2,6.9-5,8.7c1.5,0.9,3.2,1.3,5,1.3c5.5,0,10-4.5,10-10S15.5,2,10,2z"/></g> -<g id="brightness-3"><path d="M9,2C8,2,6.9,2.2,6,2.5c4.1,1.3,7,5.1,7,9.5s-2.9,8.3-7,9.5C6.9,21.8,8,22,9,22c5.5,0,10-4.5,10-10S14.5,2,9,2z"/></g> -<g id="brightness-4"><path d="M20,8.7V4h-4.7L12,0.7L8.7,4H4v4.7L0.7,12L4,15.3V20h4.7l3.3,3.3l3.3-3.3H20v-4.7l3.3-3.3L20,8.7z M12,18c-0.9,0-1.7-0.2-2.5-0.6c2.1-0.9,3.5-3,3.5-5.4s-1.4-4.5-3.5-5.4C10.3,6.2,11.1,6,12,6c3.3,0,6,2.7,6,6S15.3,18,12,18z"/></g> -<g id="brightness-5"><path d="M20,15.3l3.3-3.3L20,8.7V4h-4.7L12,0.7L8.7,4H4v4.7L0.7,12L4,15.3V20h4.7l3.3,3.3l3.3-3.3H20V15.3z M12,18c-3.3,0-6-2.7-6-6s2.7-6,6-6c3.3,0,6,2.7,6,6S15.3,18,12,18z"/></g> -<g id="brightness-6"><path d="M20,15.3l3.3-3.3L20,8.7V4h-4.7L12,0.7L8.7,4H4v4.7L0.7,12L4,15.3V20h4.7l3.3,3.3l3.3-3.3H20V15.3z M12,18V6c3.3,0,6,2.7,6,6S15.3,18,12,18z"/></g> -<g id="brightness-7"><path d="M20,8.7V4h-4.7L12,0.7L8.7,4H4v4.7L0.7,12L4,15.3V20h4.7l3.3,3.3l3.3-3.3H20v-4.7l3.3-3.3L20,8.7z M12,18c-3.3,0-6-2.7-6-6s2.7-6,6-6c3.3,0,6,2.7,6,6S15.3,18,12,18z M12,8c-2.2,0-4,1.8-4,4c0,2.2,1.8,4,4,4s4-1.8,4-4C16,9.8,14.2,8,12,8z"/></g> -<g id="brush"><path d="M7,14c-1.7,0-3,1.3-3,3c0,1.3-1.2,2-2,2c0.9,1.2,2.5,2,4,2c2.2,0,4-1.8,4-4C10,15.3,8.7,14,7,14z M20.7,4.6l-1.3-1.3c-0.4-0.4-1-0.4-1.4,0l-9,9l2.8,2.8l9-9C21.1,5.7,21.1,5,20.7,4.6z"/></g> -<g id="camera"><path d="M9.4,10.5l4.8-8.3C13.5,2.1,12.7,2,12,2C9.6,2,7.4,2.8,5.7,4.3l3.7,6.3L9.4,10.5z M21.5,9c-0.9-2.9-3.1-5.3-6-6.3L11.9,9H21.5z M21.8,10h-7.5l0.3,0.5l4.8,8.3C21,17,22,14.6,22,12C22,11.3,21.9,10.6,21.8,10z M8.5,12L4.6,5.2C3,7,2,9.4,2,12c0,0.7,0.1,1.4,0.2,2h7.5L8.5,12z M2.5,15c0.9,2.9,3.1,5.3,6,6.3l3.7-6.3H2.5z M13.7,15l-3.9,6.8c0.7,0.2,1.4,0.2,2.2,0.2c2.4,0,4.6-0.8,6.3-2.3l-3.7-6.3L13.7,15z"/></g> -<g id="camera-alt"><circle cx="12" cy="12" r="3.2"/><path d="M9,2L7.2,4H4C2.9,4,2,4.9,2,6v12c0,1.1,0.9,2,2,2h16c1.1,0,2-0.9,2-2V6c0-1.1-0.9-2-2-2h-3.2L15,2H9z M12,17c-2.8,0-5-2.2-5-5s2.2-5,5-5s5,2.2,5,5S14.8,17,12,17z"/></g> -<g id="camera-front"><path d="M12,12c1.7,0,3-1.3,3-3s-1.3-3-3-3c-1.7,0-3,1.3-3,3S10.3,12,12,12z M18,0H6C4.9,0,4,0.9,4,2v20c0,1.1,0.9,2,2,2h12c1.1,0,2-0.9,2-2V2C20,0.9,19.1,0,18,0z M11,1h2v2h-2V1z M13,22v-2H9v-2h4v-2l3,3L13,22z M18,17c0-2-4-3-6-3c-2,0-6,1-6,3V4h12V17z"/></g> -<g id="camera-rear"><path d="M18,0H6C4.9,0,4,0.9,4,2v20c0,1.1,0.9,2,2,2h12c1.1,0,2-0.9,2-2V2C20,0.9,19.1,0,18,0z M12,2c1.1,0,2,0.9,2,2s-0.9,2-2,2s-2-0.9-2-2S10.9,2,12,2z M13,22v-2H9v-2h4v-2l3,3L13,22z"/></g> -<g id="camera-roll"><path d="M14,5c0-1.1-0.9-2-2-2h-1V2c0-0.6-0.4-1-1-1H6C5.4,1,5,1.4,5,2v1H4C2.9,3,2,3.9,2,5v15c0,1.1,0.9,2,2,2h8c1.1,0,2-0.9,2-2h8V5H14z M12,18h-2v-2h2V18z M12,9h-2V7h2V9z M16,18h-2v-2h2V18z M16,9h-2V7h2V9z M20,18h-2v-2h2V18z M20,9h-2V7h2V9z"/></g> -<g id="center-focus-strong"><path d="M12,8c-2.2,0-4,1.8-4,4s1.8,4,4,4s4-1.8,4-4S14.2,8,12,8z M5,15H3v4c0,1.1,0.9,2,2,2h4v-2H5V15z M5,5h4V3H5C3.9,3,3,3.9,3,5v4h2V5z M19,3h-4v2h4v4h2V5C21,3.9,20.1,3,19,3z M19,19h-4v2h4c1.1,0,2-0.9,2-2v-4h-2V19z"/></g> -<g id="center-focus-weak"><path d="M5,15H3v4c0,1.1,0.9,2,2,2h4v-2H5V15z M5,5h4V3H5C3.9,3,3,3.9,3,5v4h2V5z M19,3h-4v2h4v4h2V5C21,3.9,20.1,3,19,3z M19,19h-4v2h4c1.1,0,2-0.9,2-2v-4h-2V19z M12,8c-2.2,0-4,1.8-4,4s1.8,4,4,4s4-1.8,4-4S14.2,8,12,8z M12,14c-1.1,0-2-0.9-2-2s0.9-2,2-2s2,0.9,2,2S13.1,14,12,14z"/></g> -<g id="collections"><path d="M22,16V4c0-1.1-0.9-2-2-2H8C6.9,2,6,2.9,6,4v12c0,1.1,0.9,2,2,2h12C21.1,18,22,17.1,22,16z M11,12l2,2.7l3-3.7l4,5H8L11,12z M2,6v14c0,1.1,0.9,2,2,2h14v-2H4V6H2z"/></g> -<g id="colorize"><path d="M20.7,5.6l-2.3-2.3c-0.4-0.4-1-0.4-1.4,0l-3.1,3.1l-1.9-1.9l-1.4,1.4l1.4,1.4L3,16.3V21h4.8l8.9-8.9l1.4,1.4l1.4-1.4l-1.9-1.9L20.7,7C21.1,6.7,21.1,6,20.7,5.6z M6.9,19L5,17.1L13.1,9l1.9,1.9L6.9,19z"/></g> -<g id="color-lens"><path d="M12,3c-5,0-9,4-9,9s4,9,9,9c0.8,0,1.5-0.7,1.5-1.5c0-0.4-0.1-0.7-0.4-1c-0.2-0.3-0.4-0.6-0.4-1c0-0.8,0.7-1.5,1.5-1.5H16c2.8,0,5-2.2,5-5C21,6.6,17,3,12,3z M6.5,12C5.7,12,5,11.3,5,10.5S5.7,9,6.5,9C7.3,9,8,9.7,8,10.5S7.3,12,6.5,12z M9.5,8C8.7,8,8,7.3,8,6.5S8.7,5,9.5,5C10.3,5,11,5.7,11,6.5S10.3,8,9.5,8z M14.5,8C13.7,8,13,7.3,13,6.5S13.7,5,14.5,5C15.3,5,16,5.7,16,6.5S15.3,8,14.5,8z M17.5,12c-0.8,0-1.5-0.7-1.5-1.5S16.7,9,17.5,9c0.8,0,1.5,0.7,1.5,1.5S18.3,12,17.5,12z"/></g> -<g id="compare"><path d="M10,3H5C3.9,3,3,3.9,3,5v14c0,1.1,0.9,2,2,2h5v2h2V1h-2V3z M10,18H5l5-6V18z M19,3h-5v2h5v13l-5-6v9h5c1.1,0,2-0.9,2-2V5C21,3.9,20.1,3,19,3z"/></g> -<g id="control-point"><path d="M13,7h-2v4H7v2h4v4h2v-4h4v-2h-4V7z M12,2C6.5,2,2,6.5,2,12s4.5,10,10,10s10-4.5,10-10S17.5,2,12,2z M12,20c-4.4,0-8-3.6-8-8s3.6-8,8-8s8,3.6,8,8S16.4,20,12,20z"/></g> -<g id="control-point-duplicate"><polygon points="16,8 14,8 14,11 11,11 11,13 14,13 14,16 16,16 16,13 19,13 19,11 16,11 "/></g> -<g id="crop-16-9"><path d="M19,6H5C3.9,6,3,6.9,3,8v8c0,1.1,0.9,2,2,2h14c1.1,0,2-0.9,2-2V8C21,6.9,20.1,6,19,6z M19,16H5V8h14V16z"/></g> -<g id="crop"><path d="M17,15h2V7c0-1.1-0.9-2-2-2H9v2h8V15z M7,17V1H5v4H1v2h4v10c0,1.1,0.9,2,2,2h10v4h2v-4h4v-2H7z"/></g> -<g id="crop-3-2"><path d="M19,4H5C3.9,4,3,4.9,3,6v12c0,1.1,0.9,2,2,2h14c1.1,0,2-0.9,2-2V6C21,4.9,20.1,4,19,4z M19,18H5V6h14V18z"/></g> -<g id="crop-5-4"><path d="M19,5H5C3.9,5,3,5.9,3,7v10c0,1.1,0.9,2,2,2h14c1.1,0,2-0.9,2-2V7C21,5.9,20.1,5,19,5z M19,17H5V7h14V17z"/></g> -<g id="crop-7-5"><path d="M19,7H5C3.9,7,3,7.9,3,9v6c0,1.1,0.9,2,2,2h14c1.1,0,2-0.9,2-2V9C21,7.9,20.1,7,19,7z M19,15H5V9h14V15z"/></g> -<g id="crop-din"><path d="M19,3H5C3.9,3,3,3.9,3,5v14c0,1.1,0.9,2,2,2h14c1.1,0,2-0.9,2-2V5C21,3.9,20.1,3,19,3z M19,19H5V5h14V19z"/></g> -<g id="crop-free"><path d="M3,5v4h2V5h4V3H5C3.9,3,3,3.9,3,5z M5,15H3v4c0,1.1,0.9,2,2,2h4v-2H5V15z M19,19h-4v2h4c1.1,0,2-0.9,2-2v-4h-2V19z M19,3h-4v2h4v4h2V5C21,3.9,20.1,3,19,3z"/></g> -<g id="crop-landscape"><path d="M19,5H5C3.9,5,3,5.9,3,7v10c0,1.1,0.9,2,2,2h14c1.1,0,2-0.9,2-2V7C21,5.9,20.1,5,19,5z M19,17H5V7h14V17z"/></g> -<g id="crop-original"><path d="M19,3H5C3.9,3,3,3.9,3,5v14c0,1.1,0.9,2,2,2h14c1.1,0,2-0.9,2-2V5C21,3.9,20.1,3,19,3z M19,19H5V5h14V19z M14,12.3l-2.8,3.5l-2-2.4L6.5,17h11L14,12.3z"/></g> -<g id="crop-portrait"><path d="M17,3H7C5.9,3,5,3.9,5,5v14c0,1.1,0.9,2,2,2h10c1.1,0,2-0.9,2-2V5C19,3.9,18.1,3,17,3z M17,19H7V5h10V19z"/></g> -<g id="crop-square"><path d="M18,4H6C4.9,4,4,4.9,4,6v12c0,1.1,0.9,2,2,2h12c1.1,0,2-0.9,2-2V6C20,4.9,19.1,4,18,4z M18,18H6V6h12V18z"/></g> -<g id="dehaze"><path d="M2,15.5v2c6.7-4.4,13.3,4.4,20,0v-2C15.3,19.9,8.7,11.1,2,15.5z M2,10.5v2c6.7-4.4,13.3,4.4,20,0v-2C15.3,14.9,8.7,6.1,2,10.5z M2,5.5v2c6.7-4.4,13.3,4.4,20,0v-2C15.3,9.9,8.7,1.1,2,5.5z"/></g> -<g id="details"><path d="M3,4l9,16l9-16H3z M6.4,6h11.2L12,16L6.4,6z"/></g> -<g id="edit"><path d="M3,17.3V21h3.8L17.8,9.9l-3.8-3.8L3,17.3z M20.7,7c0.4-0.4,0.4-1,0-1.4l-2.3-2.3c-0.4-0.4-1-0.4-1.4,0l-1.8,1.8l3.7,3.8L20.7,7z"/></g> -<g id="exposure"><path d="M19,3H5C3.9,3,3,3.9,3,5v14c0,1.1,0.9,2,2,2h14c1.1,0,2-0.9,2-2V5C21,3.9,20.1,3,19,3z M5.5,7.5h2v-2H9v2h2V9H9v2H7.5V9h-2V7.5z M19,19L5,19L19,5V19z M17,17v-1.5h-5V17H17z"/></g> -<g id="exposure-minus-1"><path d="M4,11v2h8v-2H4z M19,18h-2V7.4l-3,1V6.7L18.7,5H19V18z"/></g> -<g id="exposure-minus-2"><path d="M15,16.3l2.9-3.1c0.4-0.4,0.7-0.8,1-1.2c0.3-0.4,0.6-0.8,0.8-1.2c0.2-0.4,0.4-0.8,0.5-1.2c0.1-0.4,0.2-0.8,0.2-1.2c0-0.5-0.1-1-0.3-1.5S19.8,6.3,19.4,6c-0.3-0.3-0.8-0.5-1.3-0.7C17.7,5.1,17.1,5,16.5,5c-0.7,0-1.3,0.1-1.8,0.3c-0.5,0.2-1,0.5-1.4,0.9c-0.4,0.4-0.7,0.8-0.8,1.3c-0.2,0.5-0.3,1-0.3,1.5h2.1c0-0.3,0-0.6,0.1-0.9c0.1-0.3,0.2-0.5,0.4-0.7C15,7.2,15.2,7,15.5,6.9c0.3-0.1,0.6-0.2,1-0.2c0.3,0,0.6,0.1,0.8,0.2c0.2,0.1,0.4,0.2,0.6,0.4c0.2,0.2,0.3,0.4,0.4,0.6c0.1,0.2,0.1,0.5,0.1,0.8c0,0.2,0,0.4-0.1,0.7c-0.1,0.2-0.2,0.5-0.3,0.7c-0.1,0.2-0.3,0.5-0.6,0.8c-0.2,0.3-0.5,0.6-0.9,1l-4.2,4.6V18H21v-1.7H15z M2,11v2h8v-2H2z"/></g> -<g id="exposure-plus-1"><path d="M10,7H8v4H4v2h4v4h2v-4h4v-2h-4V7z M20,18h-2V7.4l-3,1V6.7L19.7,5H20V18z"/></g> -<g id="exposure-plus-2"><path d="M16,16.3l2.9-3.1c0.4-0.4,0.7-0.8,1-1.2c0.3-0.4,0.6-0.8,0.8-1.2c0.2-0.4,0.4-0.8,0.5-1.2c0.1-0.4,0.2-0.8,0.2-1.2c0-0.5-0.1-1-0.3-1.5S20.8,6.3,20.4,6c-0.3-0.3-0.8-0.5-1.3-0.7C18.7,5.1,18.1,5,17.5,5c-0.7,0-1.3,0.1-1.8,0.3c-0.5,0.2-1,0.5-1.4,0.9c-0.4,0.4-0.7,0.8-0.8,1.3c-0.2,0.5-0.3,1-0.3,1.5h2.1c0-0.3,0-0.6,0.1-0.9c0.1-0.3,0.2-0.5,0.4-0.7C16,7.2,16.2,7,16.5,6.9c0.3-0.1,0.6-0.2,1-0.2c0.3,0,0.6,0.1,0.8,0.2c0.2,0.1,0.4,0.2,0.6,0.4c0.2,0.2,0.3,0.4,0.4,0.6c0.1,0.2,0.1,0.5,0.1,0.8c0,0.2,0,0.4-0.1,0.7c-0.1,0.2-0.2,0.5-0.3,0.7c-0.1,0.2-0.3,0.5-0.6,0.8c-0.2,0.3-0.5,0.6-0.9,1l-4.2,4.6V18H22v-1.7H16z M8,7H6v4H2v2h4v4h2v-4h4v-2H8V7z"/></g> -<g id="exposure-zero"><path d="M16.1,12.5c0,1-0.1,1.9-0.3,2.6c-0.2,0.7-0.5,1.3-0.8,1.7c-0.4,0.4-0.8,0.8-1.3,1S12.6,18,12,18c-0.6,0-1.2-0.1-1.7-0.3s-0.9-0.5-1.3-1c-0.4-0.4-0.6-1-0.8-1.7c-0.2-0.7-0.3-1.5-0.3-2.6v-2c0-1,0.1-1.9,0.3-2.5C8.4,7.2,8.6,6.7,9,6.2c0.4-0.4,0.8-0.7,1.3-0.9C10.8,5.1,11.4,5,12,5c0.6,0,1.2,0.1,1.7,0.3c0.5,0.2,0.9,0.5,1.3,0.9c0.4,0.4,0.6,1,0.8,1.7c0.2,0.7,0.3,1.5,0.3,2.5V12.5z M14,10.1c0-0.6,0-1.2-0.1-1.6c-0.1-0.4-0.2-0.8-0.4-1.1S13.1,7,12.9,6.9c-0.3-0.1-0.5-0.2-0.9-0.2c-0.3,0-0.6,0.1-0.9,0.2c-0.3,0.1-0.5,0.3-0.6,0.6s-0.3,0.6-0.4,1.1C10,9,10,9.5,10,10.1v2.7c0,0.6,0,1.2,0.1,1.6s0.2,0.8,0.4,1.1s0.4,0.5,0.6,0.6s0.5,0.2,0.9,0.2c0.3,0,0.6-0.1,0.9-0.2c0.2-0.1,0.5-0.3,0.6-0.6c0.2-0.3,0.3-0.6,0.4-1.1c0.1-0.4,0.1-1,0.1-1.6V10.1z"/></g> -<g id="filter-1"><path d="M3,5H1v16c0,1.1,0.9,2,2,2h16v-2H3V5z M14,15h2V5h-4v2h2V15z M21,1H7C5.9,1,5,1.9,5,3v14c0,1.1,0.9,2,2,2h14c1.1,0,2-0.9,2-2V3C23,1.9,22.1,1,21,1z M21,17H7V3h14V17z"/></g> -<g id="filter-2"><path d="M3,5H1v16c0,1.1,0.9,2,2,2h16v-2H3V5z M21,1H7C5.9,1,5,1.9,5,3v14c0,1.1,0.9,2,2,2h14c1.1,0,2-0.9,2-2V3C23,1.9,22.1,1,21,1z M21,17H7V3h14V17z M17,13h-4v-2h2c1.1,0,2-0.9,2-2V7c0-1.1-0.9-2-2-2h-4v2h4v2h-2c-1.1,0-2,0.9-2,2v4h6V13z"/></g> -<g id="filter"><path d="M16,10.3l-2.8,3.5l-2-2.4L8.5,15h11L16,10.3z M3,5H1v16c0,1.1,0.9,2,2,2h16v-2H3V5z M21,1H7C5.9,1,5,1.9,5,3v14c0,1.1,0.9,2,2,2h14c1.1,0,2-0.9,2-2V3C23,1.9,22.1,1,21,1z M21,17H7V3h14V17z"/></g> -<g id="filter-3"><path d="M21,1H7C5.9,1,5,1.9,5,3v14c0,1.1,0.9,2,2,2h14c1.1,0,2-0.9,2-2V3C23,1.9,22.1,1,21,1z M21,17H7V3h14V17z M3,5H1v16c0,1.1,0.9,2,2,2h16v-2H3V5z M17,13v-1.5c0-0.8-0.7-1.5-1.5-1.5c0.8,0,1.5-0.7,1.5-1.5V7c0-1.1-0.9-2-2-2h-4v2h4v2h-2v2h2v2h-4v2h4C16.1,15,17,14.1,17,13z"/></g> -<g id="filter-4"><path d="M3,5H1v16c0,1.1,0.9,2,2,2h16v-2H3V5z M15,15h2V5h-2v4h-2V5h-2v6h4V15z M21,1H7C5.9,1,5,1.9,5,3v14c0,1.1,0.9,2,2,2h14c1.1,0,2-0.9,2-2V3C23,1.9,22.1,1,21,1z M21,17H7V3h14V17z"/></g> -<g id="filter-5"><path d="M21,1H7C5.9,1,5,1.9,5,3v14c0,1.1,0.9,2,2,2h14c1.1,0,2-0.9,2-2V3C23,1.9,22.1,1,21,1z M21,17H7V3h14V17z M3,5H1v16c0,1.1,0.9,2,2,2h16v-2H3V5z M17,13v-2c0-1.1-0.9-2-2-2h-2V7h4V5h-6v6h4v2h-4v2h4C16.1,15,17,14.1,17,13z"/></g> -<g id="filter-6"><path d="M3,5H1v16c0,1.1,0.9,2,2,2h16v-2H3V5z M21,1H7C5.9,1,5,1.9,5,3v14c0,1.1,0.9,2,2,2h14c1.1,0,2-0.9,2-2V3C23,1.9,22.1,1,21,1z M21,17H7V3h14V17z M13,15h2c1.1,0,2-0.9,2-2v-2c0-1.1-0.9-2-2-2h-2V7h4V5h-4c-1.1,0-2,0.9-2,2v6C11,14.1,11.9,15,13,15z M13,11h2v2h-2V11z"/></g> -<g id="filter-7"><path d="M3,5H1v16c0,1.1,0.9,2,2,2h16v-2H3V5z M21,1H7C5.9,1,5,1.9,5,3v14c0,1.1,0.9,2,2,2h14c1.1,0,2-0.9,2-2V3C23,1.9,22.1,1,21,1z M21,17H7V3h14V17z M13,15l4-8V5h-6v2h4l-4,8H13z"/></g> -<g id="filter-8"><path d="M3,5H1v16c0,1.1,0.9,2,2,2h16v-2H3V5z M21,1H7C5.9,1,5,1.9,5,3v14c0,1.1,0.9,2,2,2h14c1.1,0,2-0.9,2-2V3C23,1.9,22.1,1,21,1z M21,17H7V3h14V17z M13,15h2c1.1,0,2-0.9,2-2v-1.5c0-0.8-0.7-1.5-1.5-1.5c0.8,0,1.5-0.7,1.5-1.5V7c0-1.1-0.9-2-2-2h-2c-1.1,0-2,0.9-2,2v1.5c0,0.8,0.7,1.5,1.5,1.5c-0.8,0-1.5,0.7-1.5,1.5V13C11,14.1,11.9,15,13,15z M13,7h2v2h-2V7z M13,11h2v2h-2V11z"/></g> -<g id="filter-9"><path d="M3,5H1v16c0,1.1,0.9,2,2,2h16v-2H3V5z M21,1H7C5.9,1,5,1.9,5,3v14c0,1.1,0.9,2,2,2h14c1.1,0,2-0.9,2-2V3C23,1.9,22.1,1,21,1z M21,17H7V3h14V17z"/><path d="M15,5h-2c-1.1,0-2,0.9-2,2v2c0,1.1,0.9,2,2,2h2v2h-4v2h4c1.1,0,2-0.9,2-2V7C17,5.9,16.1,5,15,5z M15,9h-2V7h2V9z"/></g> -<g id="filter-9-plus"><path d="M3,5H1v16c0,1.1,0.9,2,2,2h16v-2H3V5z M14,12V8c0-1.1-0.9-2-2-2h-1C9.9,6,9,6.9,9,8v1c0,1.1,0.9,2,2,2h1v1H9v2h3C13.1,14,14,13.1,14,12z M11,9V8h1v1H11z M21,1H7C5.9,1,5,1.9,5,3v14c0,1.1,0.9,2,2,2h14c1.1,0,2-0.9,2-2V3C23,1.9,22.1,1,21,1z M21,9h-2V7h-2v2h-2v2h2v2h2v-2h2v6H7V3h14V9z"/></g> -<g id="filter-b-and-w"><path d="M19,3H5C3.9,3,3,3.9,3,5v14c0,1.1,0.9,2,2,2h14c1.1,0,2-0.9,2-2V5C21,3.9,20.1,3,19,3z M19,19l-7-8v8H5l7-8V5h7V19z"/></g> -<g id="filter-center-focus"><path d="M5,15H3v4c0,1.1,0.9,2,2,2h4v-2H5V15z M5,5h4V3H5C3.9,3,3,3.9,3,5v4h2V5z M19,3h-4v2h4v4h2V5C21,3.9,20.1,3,19,3z M19,19h-4v2h4c1.1,0,2-0.9,2-2v-4h-2V19z M12,9c-1.7,0-3,1.3-3,3s1.3,3,3,3s3-1.3,3-3S13.7,9,12,9z"/></g> -<g id="filter-drama"><path d="M19.4,10c-0.7-3.4-3.7-6-7.4-6C9.1,4,6.6,5.6,5.4,8C2.3,8.4,0,10.9,0,14c0,3.3,2.7,6,6,6h13c2.8,0,5-2.2,5-5C24,12.4,21.9,10.2,19.4,10z M19,18H6c-2.2,0-4-1.8-4-4s1.8-4,4-4c2.2,0,4,1.8,4,4h2c0-2.8-1.9-5.1-4.4-5.8C8.6,6.9,10.2,6,12,6c3,0,5.5,2.5,5.5,5.5V12H19c1.7,0,3,1.3,3,3S20.7,18,19,18z"/></g> -<g id="filter-frames"><path d="M20,4h-4l-4-4L8,4H4C2.9,4,2,4.9,2,6v14c0,1.1,0.9,2,2,2h16c1.1,0,2-0.9,2-2V6C22,4.9,21.1,4,20,4z M20,20H4V6h4.5L12,2.5L15.5,6H20V20z M18,8H6v10h12"/></g> -<g id="filter-hdr"><path d="M14,6l-3.8,5l2.8,3.8L11.5,16C9.8,13.7,7,10,7,10l-6,8h22L14,6z"/></g> -<g id="filter-none"><path d="M3,5H1v16c0,1.1,0.9,2,2,2h16v-2H3V5z M21,1H7C5.9,1,5,1.9,5,3v14c0,1.1,0.9,2,2,2h14c1.1,0,2-0.9,2-2V3C23,1.9,22.1,1,21,1z M21,17H7V3h14V17z"/></g> -<g id="filter-retrolux"><path d="M13,16.4L19,7l-7-7L5,7l6,9.4v0.1C10.4,16.2,9.7,16,9,16c-2.2,0-4,1.8-4,4s1.8,4,4,4c1.8,0,3.4-1.3,3.9-3l3,3l1.4-1.4L13,18.3V16.4z M11,20c0,1.1-0.9,2-2,2s-2-0.9-2-2s0.9-2,2-2c0.5,0,1,0.2,1.4,0.6l0.6,0.6V20z"/></g> -<g id="filter-tilt-shift"><path d="M11,4.1v-2C9,2.3,7.2,3,5.7,4.3l1.4,1.4C8.2,4.8,9.5,4.3,11,4.1z M18.3,4.3C16.8,3,15,2.3,13,2.1v2c1.5,0.2,2.8,0.8,3.9,1.6L18.3,4.3z M19.9,11h2c-0.2-2-1-3.8-2.2-5.3l-1.4,1.4C19.2,8.2,19.7,9.5,19.9,11z M5.7,7.1L4.3,5.7C3,7.2,2.3,9,2.1,11h2C4.3,9.5,4.8,8.2,5.7,7.1z M4.1,13h-2c0.2,2,1,3.8,2.2,5.3l1.4-1.4C4.8,15.8,4.3,14.5,4.1,13z M15,12c0-1.7-1.3-3-3-3s-3,1.3-3,3s1.3,3,3,3S15,13.7,15,12z M18.3,16.9l1.4,1.4c1.2-1.5,2-3.3,2.2-5.3h-2C19.7,14.5,19.2,15.8,18.3,16.9z M13,19.9v2c2-0.2,3.8-1,5.3-2.2l-1.4-1.4C15.8,19.2,14.5,19.7,13,19.9z M5.7,19.7c1.5,1.2,3.3,2,5.3,2.2v-2c-1.5-0.2-2.8-0.8-3.9-1.6L5.7,19.7z"/></g> -<g id="filter-vintage"><path d="M18.7,12.4c-0.3-0.2-0.6-0.3-0.9-0.4c0.3-0.1,0.6-0.2,0.9-0.4c1.9-1.1,3-3.1,3-5.2c-1.8-1-4.1-1.1-6,0c-0.3,0.2-0.5,0.3-0.8,0.5C15,6.6,15,6.3,15,6c0-2.2-1.2-4.2-3-5.2c-1.8,1-3,3-3,5.2c0,0.3,0,0.6,0.1,0.9C8.8,6.7,8.6,6.6,8.3,6.4c-1.9-1.1-4.2-1-6,0c0,2.1,1.1,4.1,3,5.2c0.3,0.2,0.6,0.3,0.9,0.4c-0.3,0.1-0.6,0.2-0.9,0.4c-1.9,1.1-3,3.1-3,5.2c1.8,1,4.1,1.1,6,0c0.3-0.2,0.5-0.3,0.8-0.5C9,17.4,9,17.7,9,18c0,2.2,1.2,4.2,3,5.2c1.8-1,3-3,3-5.2c0-0.3,0-0.6-0.1-0.9c0.2,0.2,0.5,0.4,0.8,0.5c1.9,1.1,4.2,1,6,0C21.7,15.5,20.6,13.5,18.7,12.4z M12,16c-2.2,0-4-1.8-4-4s1.8-4,4-4c2.2,0,4,1.8,4,4S14.2,16,12,16z"/></g> -<g id="flare"><path d="M7,11H1v2h6V11z M9.2,7.8L7.1,5.6L5.6,7.1l2.1,2.1L9.2,7.8z M13,1h-2v6h2V1z M18.4,7.1l-1.4-1.4l-2.1,2.1l1.4,1.4L18.4,7.1z M17,11v2h6v-2H17z M12,9c-1.7,0-3,1.3-3,3s1.3,3,3,3s3-1.3,3-3S13.7,9,12,9z M14.8,16.2l2.1,2.1l1.4-1.4l-2.1-2.1L14.8,16.2z M5.6,16.9l1.4,1.4l2.1-2.1l-1.4-1.4L5.6,16.9z M11,23h2v-6h-2V23z"/></g> -<g id="flash-auto"><path d="M3,2v12h3v9l7-12H9l4-9H3z M19,2h-2l-3.2,9h1.9l0.7-2h3.2l0.7,2h1.9L19,2z M16.9,7.6L18,4l1.1,3.6H16.9z"/></g> -<g id="flash-off"><path d="M3.3,3L2,4.3l5,5V13h3v9l3.6-6.1l4.1,4.1l1.3-1.3L3.3,3z M17,10h-4l4-8H7v2.2l8.5,8.5L17,10z"/></g> -<g id="flash-on"><polygon points="7,2 7,13 10,13 10,22 17,10 13,10 17,2 "/></g> -<g id="flip"><path d="M15,21h2v-2h-2V21z M19,9h2V7h-2V9z M3,5v14c0,1.1,0.9,2,2,2h4v-2H5V5h4V3H5C3.9,3,3,3.9,3,5z M19,3v2h2C21,3.9,20.1,3,19,3z M11,23h2V1h-2V23z M19,17h2v-2h-2V17z M15,5h2V3h-2V5z M19,13h2v-2h-2V13z M19,21c1.1,0,2-0.9,2-2h-2V21z"/></g> -<g id="gradient"><rect x="11" y="9" width="2" height="2"/><rect x="9" y="11" width="2" height="2"/><rect x="13" y="11" width="2" height="2"/><rect x="15" y="9" width="2" height="2"/><rect x="7" y="9" width="2" height="2"/><path d="M19,3H5C3.9,3,3,3.9,3,5v14c0,1.1,0.9,2,2,2h14c1.1,0,2-0.9,2-2V5C21,3.9,20.1,3,19,3z M9,18H7v-2h2V18z M13,18h-2v-2h2V18z M17,18h-2v-2h2V18z M19,11h-2v2h2v2h-2v-2h-2v2h-2v-2h-2v2H9v-2H7v2H5v-2h2v-2H5V5h14V11z"/></g> -<g id="grain"><path d="M10,12c-1.1,0-2,0.9-2,2c0,1.1,0.9,2,2,2s2-0.9,2-2C12,12.9,11.1,12,10,12z M6,8c-1.1,0-2,0.9-2,2c0,1.1,0.9,2,2,2s2-0.9,2-2C8,8.9,7.1,8,6,8z M6,16c-1.1,0-2,0.9-2,2c0,1.1,0.9,2,2,2s2-0.9,2-2C8,16.9,7.1,16,6,16z M18,8c1.1,0,2-0.9,2-2c0-1.1-0.9-2-2-2s-2,0.9-2,2C16,7.1,16.9,8,18,8z M14,16c-1.1,0-2,0.9-2,2c0,1.1,0.9,2,2,2s2-0.9,2-2C16,16.9,15.1,16,14,16z M18,12c-1.1,0-2,0.9-2,2c0,1.1,0.9,2,2,2s2-0.9,2-2C20,12.9,19.1,12,18,12z M14,8c-1.1,0-2,0.9-2,2c0,1.1,0.9,2,2,2s2-0.9,2-2C16,8.9,15.1,8,14,8z M10,4C8.9,4,8,4.9,8,6c0,1.1,0.9,2,2,2s2-0.9,2-2C12,4.9,11.1,4,10,4z"/></g> -<g id="grid-off"><path d="M8,4v1.5l2,2V4h4v4h-3.5l2,2H14v1.5l2,2V10h4v4h-3.5l2,2H20v1.5l2,2V4c0-1.1-0.9-2-2-2H4.5l2,2H8z M16,4h4v4h-4V4z M21.4,21.4L21.4,21.4L20,20L4,4L2.6,2.6L1.3,1.3L0,2.5l2,2V20c0,1.1,0.9,2,2,2h15.5l2,2l1.3-1.3L21.4,21.4z M10,12.5l1.5,1.5H10V12.5z M4,6.5L5.5,8H4V6.5z M8,20l-4,0v-4h4V20z M8,14H4v-4h3.5L8,10.5V14z M14,20l-4,0v-4h3.5l0.5,0.5V20z M16,20v-1.5l1.5,1.5L16,20z"/></g> -<g id="grid-on"><path d="M20,2H4C2.9,2,2,2.9,2,4v16c0,1.1,0.9,2,2,2h16c1.1,0,2-0.9,2-2V4C22,2.9,21.1,2,20,2z M8,20l-4,0v-4h4V20z M8,14H4v-4h4V14z M8,8H4V4h4V8z M14,20l-4,0v-4h4V20z M14,14h-4v-4h4V14z M14,8h-4V4h4V8z M20,20l-4,0v-4h4V20z M20,14h-4v-4h4V14z M20,8h-4V4h4V8z"/></g> -<g id="hdr-off"><path d="M20.7,11.8c0.2-0.2,0.3-0.6,0.3-1c0-0.2,0-0.4-0.1-0.6c0-0.2-0.1-0.3-0.2-0.4s-0.2-0.2-0.3-0.3c-0.1-0.1-0.3-0.1-0.5-0.1h-1.1v2.7h1.1C20.3,12.2,20.5,12.1,20.7,11.8z"/><path d="M11.6,15.5c0.3,0,0.8,0,1-0.1c0.2-0.1,0.4-0.2,0.5-0.4c0,0,0,0,0,0l-2.3-2.3v2.9H11.6z"/><path d="M15.3,11.8c0-0.6-0.1-1.1-0.3-1.6c-0.2-0.5-0.4-0.9-0.7-1.2c-0.3-0.3-0.7-0.6-1.1-0.7S12.4,8,11.8,8h-0.5l4,4V11.8z M2.5,4.3L6.2,8h-1v3.6H2.8V8H1v9h1.8v-3.9h2.4V17H7V8.8l2,2V17h2.6c0.5,0,1.2-0.1,1.6-0.3c0.4-0.2,0.7-0.4,1-0.7l4.9,4.9l1.3-1.3L3.8,3L2.5,4.3z M10.8,12.6l2.3,2.3c0,0,0,0,0,0c-0.1,0.2-0.3,0.3-0.5,0.4c-0.2,0.1-0.7,0.1-1,0.1h-0.8V12.6z M21.5,13.2c0.2-0.1,0.4-0.2,0.5-0.4c0.2-0.2,0.3-0.3,0.4-0.5c0.1-0.2,0.2-0.4,0.3-0.7c0.1-0.3,0.1-0.6,0.1-0.9c0-0.4-0.1-0.8-0.2-1.2c-0.1-0.3-0.3-0.6-0.6-0.8s-0.5-0.4-0.9-0.5C20.7,8.1,20.3,8,19.9,8H17v5.7l1.8,1.8v-1.8h0.9l1.4,3.3H23v-0.1L21.5,13.2z M20.7,11.8c-0.2,0.2-0.5,0.4-0.8,0.4h-1.1V9.5H20c0.2,0,0.3,0,0.5,0.1c0.1,0.1,0.2,0.2,0.3,0.3s0.1,0.3,0.2,0.4c0,0.2,0.1,0.4,0.1,0.6C21,11.3,20.9,11.6,20.7,11.8z"/></g> -<g id="hdr-on"><path d="M5.2,11.6H2.8V8H1v9h1.8v-3.9h2.4V17H7V8H5.2V11.6z M14.3,9c-0.3-0.3-0.7-0.6-1.1-0.7S12.4,8,11.8,8H9v9h2.6c0.5,0,1.2-0.1,1.6-0.3c0.4-0.2,0.8-0.4,1.1-0.7c0.3-0.3,0.5-0.7,0.7-1.2c0.2-0.5,0.2-1,0.2-1.6v-1.4c0-0.6-0.1-1.1-0.3-1.6C14.9,9.7,14.6,9.3,14.3,9z M13.5,13.2c0,0.4,0,0.8-0.1,1c-0.1,0.3-0.1,0.5-0.3,0.7s-0.3,0.3-0.5,0.4c-0.2,0.1-0.7,0.1-1,0.1h-0.8v-6h1c0.3,0,0.6,0,0.8,0.1c0.2,0.1,0.4,0.2,0.5,0.4c0.1,0.2,0.2,0.4,0.3,0.7c0.1,0.3,0.1,0.6,0.1,1.1V13.2z M21.5,13.2c0.2-0.1,0.4-0.2,0.5-0.4c0.2-0.2,0.3-0.3,0.4-0.5c0.1-0.2,0.2-0.4,0.3-0.7c0.1-0.3,0.1-0.6,0.1-0.9c0-0.4-0.1-0.8-0.2-1.2c-0.1-0.3-0.3-0.6-0.6-0.8s-0.5-0.4-0.9-0.5C20.7,8.1,20.3,8,19.9,8H17v9h1.8v-3.3h0.9l1.4,3.3H23v-0.1L21.5,13.2z M20.7,11.8c-0.2,0.2-0.5,0.4-0.8,0.4h-1.1V9.5H20c0.2,0,0.3,0,0.5,0.1c0.1,0.1,0.2,0.2,0.3,0.3s0.1,0.3,0.2,0.4c0,0.2,0.1,0.4,0.1,0.6C21,11.3,20.9,11.6,20.7,11.8z"/></g> -<g id="hdr-plus-off"><path d="M16.5,16h0.1v-0.1l-1.2-2.9c0.2-0.1,0.3-0.2,0.4-0.3c0.1-0.1,0.2-0.3,0.3-0.4c0.1-0.2,0.2-0.3,0.2-0.5c0-0.2,0.1-0.4,0.1-0.7c0-0.3-0.1-0.7-0.2-0.9c-0.1-0.3-0.2-0.5-0.4-0.7c-0.2-0.2-0.4-0.3-0.7-0.4C14.9,9,14.6,9,14.3,9H12v2.5L16.5,16z M13.4,10.2h0.9c0.1,0,0.3,0,0.4,0.1c0.1,0,0.2,0.1,0.3,0.2c0.1,0.1,0.1,0.2,0.1,0.3c0,0.1,0,0.3,0,0.4c0,0.3-0.1,0.6-0.2,0.8c-0.1,0.2-0.4,0.3-0.6,0.3h-0.9V10.2z M12,14l-1-1l-1.4-1.4l-1.4-1.4L2.3,4.3L1,5.5L4.5,9H3.6v2.8H1.4V9H0v7h1.4v-3h2.2v3H5V9.5l1.1,1.1V16h2c0.4,0,0.9-0.1,1.3-0.2c0.3-0.1,0.6-0.3,0.9-0.6c0.1-0.1,0.1-0.2,0.2-0.2l5,5l1.3-1.3l-3.3-3.3L12,14z M9.3,14.4c-0.1,0.1-0.2,0.2-0.4,0.3c-0.2,0.1-0.5,0.1-0.8,0.1H7.5v-2.8l2,2C9.4,14.2,9.4,14.3,9.3,14.4z M21,12.5v-2h-1.5v2h-2V14h2v2H21v-2h2v-1.5H21z"/></g> -<g id="hdr-plus-on"><path d="M15.9,12.8c0.1-0.1,0.2-0.3,0.3-0.4c0.1-0.2,0.2-0.3,0.2-0.5c0-0.2,0.1-0.4,0.1-0.7c0-0.3-0.1-0.7-0.2-0.9c-0.1-0.3-0.2-0.5-0.4-0.7c-0.2-0.2-0.4-0.3-0.7-0.4C14.9,9,14.6,9,14.3,9H12v7h1.4v-2.6h0.7l1.1,2.6h1.5v-0.1l-1.2-2.9C15.6,13,15.8,12.9,15.9,12.8z M14.9,12c-0.1,0.2-0.4,0.3-0.6,0.3h-0.9v-2.1h0.9c0.1,0,0.3,0,0.4,0.1c0.1,0,0.2,0.1,0.3,0.2c0.1,0.1,0.1,0.2,0.1,0.3c0,0.1,0,0.3,0,0.4C15.1,11.5,15,11.8,14.9,12z M21,12.5v-2h-1.5v2h-2V14h2v2H21v-2h2v-1.5H21z M3.6,11.8H1.4V9H0v7h1.4v-3h2.2v3H5V9H3.6V11.8z M10.3,9.8C10,9.5,9.7,9.3,9.4,9.2S8.7,9,8.3,9H6.1v7h2c0.4,0,0.9-0.1,1.3-0.2c0.3-0.1,0.6-0.3,0.9-0.6c0.2-0.3,0.4-0.6,0.5-0.9c0.1-0.4,0.2-0.8,0.2-1.3V12c0-0.5-0.1-0.9-0.2-1.3S10.5,10,10.3,9.8z M9.6,13c0,0.3,0,0.6-0.1,0.8c0,0.2-0.1,0.4-0.2,0.6c-0.1,0.1-0.2,0.2-0.4,0.3c-0.2,0.1-0.5,0.1-0.8,0.1H7.5v-4.6h0.8c0.2,0,0.4,0,0.6,0.1c0.2,0.1,0.3,0.2,0.4,0.3c0.1,0.1,0.2,0.3,0.2,0.5c0,0.2,0.1,0.5,0.1,0.8V13z"/></g> -<g id="hdr-strong"><path d="M17,6c-3.3,0-6,2.7-6,6s2.7,6,6,6s6-2.7,6-6S20.3,6,17,6z"/><path d="M5,8c-2.2,0-4,1.8-4,4s1.8,4,4,4s4-1.8,4-4S7.2,8,5,8z M5,14c-1.1,0-2-0.9-2-2s0.9-2,2-2s2,0.9,2,2S6.1,14,5,14z"/></g> -<g id="hdr-weak"><path d="M5,8c-2.2,0-4,1.8-4,4s1.8,4,4,4s4-1.8,4-4S7.2,8,5,8z M17,6c-3.3,0-6,2.7-6,6s2.7,6,6,6s6-2.7,6-6S20.3,6,17,6z M17,16c-2.2,0-4-1.8-4-4s1.8-4,4-4c2.2,0,4,1.8,4,4S19.2,16,17,16z"/></g> -<g id="healing"><path d="M17.7,12l4-4c0.4-0.4,0.4-1,0-1.4l-4.3-4.3c-0.4-0.4-1-0.4-1.4,0l-4,4l-4-4C7.8,2.1,7.5,2,7.3,2S6.8,2.1,6.6,2.3L2.3,6.6C1.9,7,1.9,7.7,2.3,8l4,4l-4,4c-0.4,0.4-0.4,1,0,1.4l4.3,4.3c0.4,0.4,1,0.4,1.4,0l4-4l4,4c0.2,0.2,0.5,0.3,0.7,0.3c0.3,0,0.5-0.1,0.7-0.3l4.3-4.3c0.4-0.4,0.4-1,0-1.4L17.7,12z M12,9c0.6,0,1,0.4,1,1s-0.4,1-1,1c-0.6,0-1-0.4-1-1S11.4,9,12,9z M7.3,11L3.7,7.3l3.6-3.6l3.6,3.6L7.3,11z M10,13c-0.6,0-1-0.4-1-1s0.4-1,1-1c0.6,0,1,0.4,1,1S10.6,13,10,13z M12,15c-0.6,0-1-0.4-1-1s0.4-1,1-1c0.6,0,1,0.4,1,1S12.6,15,12,15z M14,11c0.6,0,1,0.4,1,1s-0.4,1-1,1c-0.6,0-1-0.4-1-1S13.4,11,14,11z M16.7,20.3L13,16.7l3.6-3.6l3.6,3.6L16.7,20.3z"/></g> -<g id="image"><path d="M21,19V5c0-1.1-0.9-2-2-2H5C3.9,3,3,3.9,3,5v14c0,1.1,0.9,2,2,2h14C20.1,21,21,20.1,21,19z M8.5,13.5l2.5,3l3.5-4.5l4.5,6H5L8.5,13.5z"/></g> -<g id="iso"><path d="M19,3H5C3.9,3,3,3.9,3,5v14c0,1.1,0.9,2,2,2h14c1.1,0,2-0.9,2-2V5C21,3.9,20.1,3,19,3z M5.5,7.5h2v-2H9v2h2V9H9v2H7.5V9h-2V7.5z M19,19L5,19L19,5V19z M17,17v-1.5h-5V17H17z"/></g> -<g id="landscape"><path d="M14,6l-3.8,5l2.9,3.8L11.5,16C9.8,13.8,7,10,7,10l-6,8h22L14,6z"/></g> -<g id="movie-creation"><path d="M18,4l2,4h-3l-2-4h-2l2,4h-3l-2-4H8l2,4H7L5,4H4C2.9,4,2,4.9,2,6l0,12c0,1.1,0.9,2,2,2h16c1.1,0,2-0.9,2-2V4H18z"/></g> -<g id="palette"><path d="M12,3c-5,0-9,4-9,9s4,9,9,9c0.8,0,1.5-0.7,1.5-1.5c0-0.4-0.1-0.7-0.4-1c-0.2-0.3-0.4-0.6-0.4-1c0-0.8,0.7-1.5,1.5-1.5H16c2.8,0,5-2.2,5-5C21,6.6,17,3,12,3z M6.5,12C5.7,12,5,11.3,5,10.5S5.7,9,6.5,9C7.3,9,8,9.7,8,10.5S7.3,12,6.5,12z M9.5,8C8.7,8,8,7.3,8,6.5S8.7,5,9.5,5C10.3,5,11,5.7,11,6.5S10.3,8,9.5,8z M14.5,8C13.7,8,13,7.3,13,6.5S13.7,5,14.5,5C15.3,5,16,5.7,16,6.5S15.3,8,14.5,8z M17.5,12c-0.8,0-1.5-0.7-1.5-1.5S16.7,9,17.5,9c0.8,0,1.5,0.7,1.5,1.5S18.3,12,17.5,12z"/></g> -<g id="panorama"><polygon points="21,13.5 21,13.5 21,13.5 "/></g> -<g id="panorama-fisheye"><path d="M12,2C6.5,2,2,6.5,2,12s4.5,10,10,10c5.5,0,10-4.5,10-10S17.5,2,12,2z M12,20c-4.4,0-8-3.6-8-8s3.6-8,8-8s8,3.6,8,8S16.4,20,12,20z"/></g> -<g id="panorama-horizontal"><path d="M20,6.5v10.9c-2.6-0.8-5.3-1.2-8-1.2c-2.7,0-5.4,0.4-8,1.2V6.5c2.6,0.8,5.3,1.2,8,1.2C14.7,7.7,17.4,7.3,20,6.5 M21.4,4c-0.1,0-0.2,0-0.3,0.1c-2.9,1.1-6,1.6-9.1,1.6S5.8,5.2,2.9,4.1C2.8,4,2.7,4,2.6,4C2.2,4,2,4.2,2,4.6v14.7C2,19.8,2.2,20,2.6,20c0.1,0,0.2,0,0.3-0.1c2.9-1.1,6-1.6,9.1-1.6s6.2,0.5,9.1,1.6c0.1,0,0.2,0.1,0.3,0.1c0.3,0,0.6-0.2,0.6-0.6V4.6C22,4.2,21.8,4,21.4,4L21.4,4z"/></g> -<g id="panorama-vertical"><path d="M19.9,21.1c-1.1-2.9-1.6-6-1.6-9.1s0.5-6.2,1.6-9.1C20,2.8,20,2.7,20,2.6C20,2.2,19.8,2,19.4,2H4.6C4.2,2,4,2.2,4,2.6c0,0.1,0,0.2,0.1,0.3c1.1,2.9,1.6,6,1.6,9.1s-0.5,6.2-1.6,9.1C4,21.2,4,21.3,4,21.4C4,21.8,4.2,22,4.6,22h14.7c0.4,0,0.6-0.2,0.6-0.6C20,21.3,20,21.2,19.9,21.1z M6.5,20c0.8-2.6,1.2-5.3,1.2-8c0-2.7-0.4-5.4-1.2-8h10.9c-0.8,2.6-1.2,5.3-1.2,8c0,2.7,0.4,5.4,1.2,8H6.5z"/></g> -<g id="panorama-wide-angle"><path d="M12,6c2.4,0,4.7,0.2,7.3,0.6C19.8,8.4,20,10.2,20,12s-0.2,3.6-0.7,5.4C16.7,17.8,14.4,18,12,18s-4.7-0.2-7.3-0.6C4.2,15.6,4,13.8,4,12s0.2-3.6,0.7-5.4C7.3,6.2,9.6,6,12,6 M12,4C9.3,4,6.8,4.2,4,4.7L3.1,4.9L2.9,5.8C2.3,7.9,2,9.9,2,12s0.3,4.1,0.9,6.2l0.3,0.9L4,19.3c2.7,0.5,5.2,0.7,8,0.7s5.2-0.2,8-0.7l0.9-0.2l0.3-0.9c0.6-2.1,0.9-4.1,0.9-6.2s-0.3-4.1-0.9-6.2l-0.3-0.9L20,4.7C17.2,4.2,14.7,4,12,4L12,4z"/></g> -<g id="photo"><path d="M21,19V5c0-1.1-0.9-2-2-2H5C3.9,3,3,3.9,3,5v14c0,1.1,0.9,2,2,2h14C20.1,21,21,20.1,21,19z M8.5,13.5l2.5,3l3.5-4.5l4.5,6H5L8.5,13.5z"/></g> -<g id="photo-album"><path d="M18,2H6C4.9,2,4,2.9,4,4v16c0,1.1,0.9,2,2,2h12c1.1,0,2-0.9,2-2V4C20,2.9,19.1,2,18,2z M6,4h5v8l-2.5-1.5L6,12V4z M6,19l3-3.9l2.1,2.6l3-3.9L18,19H6z"/></g> -<g id="photo-library"><path d="M22,16V4c0-1.1-0.9-2-2-2H8C6.9,2,6,2.9,6,4v12c0,1.1,0.9,2,2,2h12C21.1,18,22,17.1,22,16z M11,12l2,2.7l3-3.7l4,5H8L11,12z M2,6v14c0,1.1,0.9,2,2,2h14v-2H4V6H2z"/></g> -<g id="photosphere"><path d="M22.1,7.6C20.4,3.7,16.5,1,12,1S3.6,3.7,1.9,7.6C1.3,7.9,0.6,8.2,0,8.5v7c0.6,0.3,1.3,0.6,1.9,0.9C3.6,20.3,7.5,23,12,23s8.4-2.7,10.1-6.6c0.7-0.3,1.3-0.6,1.9-0.9v-7C23.4,8.2,22.7,7.9,22.1,7.6z M19.9,6.8c-1.2-0.4-2.5-0.7-3.8-0.9c-0.4-1.1-0.8-2.1-1.3-2.9C16.9,3.6,18.7,5,19.9,6.8z M12,2.5c0.8,0,1.8,1.1,2.5,3.1c-0.8-0.1-1.7-0.1-2.5-0.1s-1.7,0.1-2.5,0.1C10.2,3.6,11.2,2.5,12,2.5z M9.2,2.9c-0.5,0.8-1,1.8-1.3,2.9C6.6,6.1,5.3,6.4,4.1,6.8C5.3,5,7.1,3.6,9.2,2.9z M4.1,17.2c1.2,0.4,2.5,0.7,3.8,0.9c0.4,1.1,0.8,2.1,1.3,2.9C7.1,20.4,5.3,19,4.1,17.2z M12,21.5c-0.8,0-1.8-1.1-2.5-3.1c0.8,0.1,1.7,0.1,2.5,0.1s1.7-0.1,2.5-0.1C13.8,20.4,12.8,21.5,12,21.5z M14.8,21.1c0.5-0.8,1-1.8,1.3-2.9c1.3-0.2,2.5-0.5,3.8-0.9C18.7,19,16.9,20.4,14.8,21.1z M22.5,14.6l-0.3,0.1c-1.1,0.5-2.2,0.9-3.4,1.3L15,11.6L12,15l-4-5l-4.4,5.5C3,15.2,2.4,15,1.8,14.7l-0.3-0.1V9.4l0.3-0.1c6.4-3,14-3,20.4,0l0.3,0.1V14.6z"/></g> -<g id="portrait"><path d="M12,12.2c1.2,0,2.2-1,2.2-2.2c0-1.2-1-2.2-2.2-2.2c-1.2,0-2.2,1-2.2,2.2C9.8,11.2,10.8,12.2,12,12.2z M16.5,16.2c0-1.5-3-2.2-4.5-2.2s-4.5,0.8-4.5,2.2V17h9V16.2z M19,3H5C3.9,3,3,3.9,3,5v14c0,1.1,0.9,2,2,2h14c1.1,0,2-0.9,2-2V5C21,3.9,20.1,3,19,3z M19,19L5,19V5h14V19z"/></g> -<g id="slideshow"><path d="M10,8v8l5-4L10,8z M19,3H5C3.9,3,3,3.9,3,5v14c0,1.1,0.9,2,2,2h14c1.1,0,2-0.9,2-2V5C21,3.9,20.1,3,19,3z M19,19L5,19V5h14V19z"/></g> -<g id="switch-camera"><path d="M20,4h-3.2L15,2H9L7.2,4H4C2.9,4,2,4.9,2,6v12c0,1.1,0.9,2,2,2h16c1.1,0,2-0.9,2-2V6C22,4.9,21.1,4,20,4z M15,15.5V13H9v2.5L5.5,12L9,8.5V11h6V8.5l3.5,3.5L15,15.5z"/></g> -<g id="switch-video"><path d="M18,9.5V6c0-0.6-0.4-1-1-1H3C2.4,5,2,5.4,2,6v12c0,0.6,0.4,1,1,1h14c0.6,0,1-0.4,1-1v-3.5l4,4v-13L18,9.5z M13,15.5V13H7v2.5L3.5,12L7,8.5V11h6V8.5l3.5,3.5L13,15.5z"/></g> -<g id="tag-faces"><path d="M12,2C6.5,2,2,6.5,2,12s4.5,10,10,10c5.5,0,10-4.5,10-10S17.5,2,12,2z M12,20c-4.4,0-8-3.6-8-8s3.6-8,8-8c4.4,0,8,3.6,8,8S16.4,20,12,20z M15.5,11c0.8,0,1.5-0.7,1.5-1.5S16.3,8,15.5,8C14.7,8,14,8.7,14,9.5S14.7,11,15.5,11z M8.5,11c0.8,0,1.5-0.7,1.5-1.5S9.3,8,8.5,8C7.7,8,7,8.7,7,9.5S7.7,11,8.5,11z M12,17.5c2.3,0,4.3-1.5,5.1-3.5H6.9C7.7,16,9.7,17.5,12,17.5z"/></g> -<g id="timelapse"><path d="M16.2,7.8C15.1,6.6,13.5,6,12,6v6l-4.2,4.2c2.3,2.3,6.1,2.3,8.5,0C18.6,13.9,18.6,10.1,16.2,7.8z M12,2C6.5,2,2,6.5,2,12c0,5.5,4.5,10,10,10c5.5,0,10-4.5,10-10C22,6.5,17.5,2,12,2z M12,20c-4.4,0-8-3.6-8-8c0-4.4,3.6-8,8-8c4.4,0,8,3.6,8,8C20,16.4,16.4,20,12,20z"/></g> -<g id="timer-10"><path d="M0,7.7v1.7l3-1V18h2V6H4.7L0,7.7z M23.8,14.4c-0.1-0.3-0.4-0.5-0.6-0.7c-0.3-0.2-0.6-0.4-1-0.5s-0.8-0.3-1.4-0.4c-0.3-0.1-0.6-0.2-0.9-0.2c-0.2-0.1-0.4-0.2-0.5-0.3c-0.1-0.1-0.2-0.2-0.3-0.3C19,11.8,19,11.7,19,11.6s0-0.3,0.1-0.4c0.1-0.1,0.1-0.2,0.3-0.3c0.1-0.1,0.3-0.2,0.5-0.2c0.2-0.1,0.4-0.1,0.6-0.1c0.3,0,0.5,0,0.7,0.1c0.2,0.1,0.3,0.2,0.5,0.3c0.1,0.1,0.2,0.3,0.3,0.4c0.1,0.2,0.1,0.3,0.1,0.5h1.9c0-0.4-0.1-0.8-0.2-1.1S23.3,10,23,9.8s-0.7-0.4-1.1-0.6C21.5,9.1,21,9,20.5,9c-0.5,0-1,0.1-1.4,0.2c-0.4,0.1-0.8,0.3-1.1,0.6c-0.3,0.2-0.5,0.5-0.7,0.8c-0.2,0.3-0.2,0.7-0.2,1c0,0.4,0.1,0.7,0.2,1c0.2,0.3,0.4,0.5,0.6,0.7c0.3,0.2,0.6,0.4,1,0.5c0.4,0.1,0.8,0.3,1.3,0.4c0.4,0.1,0.7,0.2,1,0.3c0.2,0.1,0.4,0.2,0.6,0.3S22,15,22,15.1c0,0.1,0.1,0.2,0.1,0.4c0,0.3-0.1,0.6-0.4,0.8c-0.3,0.2-0.7,0.3-1.2,0.3c-0.2,0-0.4,0-0.6-0.1c-0.2-0.1-0.4-0.1-0.6-0.2S19,16,18.9,15.8c-0.1-0.2-0.2-0.4-0.2-0.7h-1.9c0,0.4,0.1,0.7,0.2,1.1c0.2,0.3,0.4,0.7,0.7,0.9c0.3,0.3,0.7,0.5,1.2,0.7s1,0.3,1.6,0.3c0.5,0,1-0.1,1.4-0.2c0.4-0.1,0.8-0.3,1.1-0.5c0.3-0.2,0.5-0.5,0.7-0.8s0.2-0.7,0.2-1.1C24,15,23.9,14.6,23.8,14.4z M13.8,7c-0.3-0.4-0.7-0.7-1.2-0.9c-0.5-0.2-1-0.3-1.6-0.3c-0.6,0-1.1,0.1-1.6,0.3C8.9,6.3,8.5,6.6,8.2,7C7.8,7.5,7.6,8,7.4,8.6C7.2,9.3,7.1,10.1,7.1,11v1.9c0,0.9,0.1,1.7,0.3,2.4c0.2,0.7,0.5,1.2,0.8,1.6c0.3,0.4,0.8,0.7,1.2,0.9s1,0.3,1.6,0.3c0.6,0,1.1-0.1,1.6-0.3c0.5-0.2,0.9-0.5,1.2-0.9c0.3-0.4,0.6-0.9,0.8-1.6c0.2-0.7,0.3-1.5,0.3-2.4V11c0-0.9-0.1-1.7-0.3-2.4C14.4,8,14.2,7.5,13.8,7z M12.9,13.2c0,0.6,0,1.1-0.1,1.5c-0.1,0.4-0.2,0.8-0.4,1c-0.2,0.3-0.4,0.5-0.6,0.6c-0.2,0.1-0.5,0.2-0.8,0.2c-0.3,0-0.6-0.1-0.8-0.2C10,16.2,9.8,16,9.6,15.8c-0.2-0.3-0.3-0.6-0.4-1c-0.1-0.4-0.1-0.9-0.1-1.5v-2.5c0-0.6,0-1.1,0.1-1.5c0.1-0.4,0.2-0.7,0.4-1C9.7,8,9.9,7.8,10.2,7.7c0.2-0.1,0.5-0.2,0.8-0.2c0.3,0,0.6,0.1,0.8,0.2C12,7.8,12.2,8,12.4,8.2c0.2,0.3,0.3,0.6,0.4,1c0.1,0.4,0.1,0.9,0.1,1.5V13.2z"/></g> -<g id="timer"><path d="M15,1H9v2h6V1z M11,14h2V8h-2V14z M19,7.4L20.5,6C20,5.5,19.5,5,19,4.5L17.6,6c-1.5-1.2-3.5-2-5.6-2c-5,0-9,4-9,9c0,5,4,9,9,9s9-4,9-9C21,10.9,20.3,8.9,19,7.4z M12,20c-3.9,0-7-3.1-7-7c0-3.9,3.1-7,7-7c3.9,0,7,3.1,7,7C19,16.9,15.9,20,12,20z"/></g> -<g id="timer-3"><path d="M11.6,13c-0.2-0.2-0.4-0.5-0.6-0.7c-0.3-0.2-0.6-0.4-0.9-0.5c0.3-0.1,0.6-0.3,0.8-0.5c0.2-0.2,0.4-0.4,0.6-0.6c0.2-0.2,0.3-0.5,0.3-0.7c0.1-0.2,0.1-0.5,0.1-0.7c0-0.6-0.1-1-0.3-1.5c-0.2-0.4-0.4-0.8-0.8-1.1c-0.3-0.3-0.7-0.5-1.2-0.6C9.2,6,8.7,5.9,8.1,5.9C7.5,5.9,7,6,6.6,6.1S5.7,6.5,5.4,6.8C5,7.1,4.8,7.5,4.6,7.9C4.4,8.3,4.3,8.7,4.3,9.2h2c0-0.3,0-0.5,0.1-0.7c0.1-0.2,0.2-0.4,0.4-0.5C7,7.8,7.2,7.7,7.4,7.6c0.2-0.1,0.5-0.1,0.7-0.1c0.6,0,1.1,0.2,1.4,0.5c0.3,0.3,0.4,0.8,0.4,1.3c0,0.3,0,0.5-0.1,0.7c-0.1,0.2-0.2,0.4-0.4,0.6C9.2,10.7,9,10.9,8.8,11c-0.2,0.1-0.5,0.1-0.9,0.1H6.7v1.6h1.2c0.3,0,0.6,0,0.9,0.1c0.3,0.1,0.5,0.2,0.7,0.4c0.2,0.2,0.3,0.4,0.4,0.6c0.1,0.2,0.2,0.5,0.2,0.9c0,0.6-0.2,1.1-0.5,1.4c-0.4,0.3-0.8,0.5-1.5,0.5c-0.3,0-0.6,0-0.8-0.1c-0.2-0.1-0.4-0.2-0.6-0.4c-0.2-0.2-0.3-0.3-0.4-0.6c-0.1-0.2-0.1-0.5-0.1-0.7h-2c0,0.5,0.1,1,0.3,1.5c0.2,0.4,0.5,0.8,0.9,1c0.4,0.3,0.8,0.5,1.2,0.6s1,0.2,1.5,0.2c0.6,0,1.1-0.1,1.6-0.2c0.5-0.2,0.9-0.4,1.3-0.7c0.4-0.3,0.6-0.7,0.8-1.1c0.2-0.4,0.3-0.9,0.3-1.5c0-0.3,0-0.6-0.1-0.9C11.9,13.5,11.8,13.2,11.6,13z M20.9,14.4c-0.1-0.3-0.4-0.5-0.6-0.7s-0.6-0.4-1-0.5c-0.4-0.1-0.8-0.3-1.4-0.4c-0.3-0.1-0.6-0.2-0.9-0.2c-0.2-0.1-0.4-0.2-0.5-0.3c-0.1-0.1-0.2-0.2-0.3-0.3c-0.1-0.1-0.1-0.2-0.1-0.4s0-0.3,0.1-0.4c0.1-0.1,0.1-0.2,0.3-0.3c0.1-0.1,0.3-0.2,0.5-0.2c0.2-0.1,0.4-0.1,0.6-0.1c0.3,0,0.5,0,0.7,0.1c0.2,0.1,0.3,0.2,0.5,0.3c0.1,0.1,0.2,0.3,0.3,0.4c0.1,0.2,0.1,0.3,0.1,0.5H21c0-0.4-0.1-0.8-0.2-1.1c-0.2-0.3-0.4-0.6-0.7-0.9S19.4,9.4,19,9.2C18.6,9.1,18.1,9,17.6,9c-0.5,0-1,0.1-1.4,0.2c-0.4,0.1-0.8,0.3-1.1,0.6s-0.5,0.5-0.7,0.8c-0.2,0.3-0.2,0.7-0.2,1c0,0.4,0.1,0.7,0.2,1c0.2,0.3,0.4,0.5,0.6,0.7c0.3,0.2,0.6,0.4,1,0.5c0.4,0.1,0.8,0.3,1.3,0.4c0.4,0.1,0.7,0.2,1,0.3c0.2,0.1,0.4,0.2,0.6,0.3s0.2,0.2,0.3,0.3c0,0.1,0.1,0.2,0.1,0.4c0,0.3-0.1,0.6-0.4,0.8c-0.3,0.2-0.7,0.3-1.2,0.3c-0.2,0-0.4,0-0.6-0.1c-0.2-0.1-0.4-0.1-0.6-0.2c-0.2-0.1-0.3-0.3-0.4-0.4c-0.1-0.2-0.2-0.4-0.2-0.7h-1.9c0,0.4,0.1,0.7,0.2,1.1c0.2,0.3,0.4,0.7,0.7,0.9c0.3,0.3,0.7,0.5,1.2,0.7s1,0.3,1.6,0.3c0.5,0,1-0.1,1.4-0.2c0.4-0.1,0.8-0.3,1.1-0.5c0.3-0.2,0.5-0.5,0.7-0.8c0.2-0.3,0.2-0.7,0.2-1.1C21.1,15,21,14.6,20.9,14.4z"/></g> -<g id="timer-auto"><path d="M12,4C9.8,4,8,5.8,8,8c0,2.2,1.8,4,4,4c2.2,0,4-1.8,4-4C16,5.8,14.2,4,12,4L12,4z M12,14c-2.7,0-8,1.3-8,4v2h16v-2C20,15.3,14.7,14,12,14L12,14z"/></g> -<g id="timer-off"><path d="M19,4.5L17.6,6c-1.5-1.2-3.5-2-5.6-2C10.2,4,8.5,4.5,7,5.5l1.5,1.5C9.5,6.3,10.7,6,12,6c3.9,0,7,3.1,7,7c0,1.3-0.3,2.5-0.9,3.5l1.5,1.5c0.9-1.4,1.5-3.1,1.5-4.9c0-2.1-0.7-4.1-2-5.6L20.5,6L19,4.5z M15,1H9v2h6V1z M11,9.4l2,2V8h-2V9.4z M3,4L1.7,5.3L4.5,8C3.6,9.5,3,11.2,3,13c0,5,4,9,9,9c1.8,0,3.6-0.6,5-1.5l2.5,2.5l1.3-1.3L13,14L3,4z M12,20c-3.9,0-7-3.1-7-7c0-1.3,0.4-2.5,1-3.5l9.6,9.6C14.5,19.6,13.3,20,12,20z"/></g> -<g id="unknown-1"><path d="M19,3H5C3.9,3,3,3.9,3,5v14c0,1.1,0.9,2,2,2h14c1.1,0,2-0.9,2-2V5C21,3.9,20.1,3,19,3z M5.5,7.5h2v-2H9v2h2V9H9v2H7.5V9h-2V7.5z M19,19L5,19L19,5V19z M17,17v-1.5h-5V17H17z"/></g> -<g id="unknown-2"><path d="M12,16h5v-1.5h-5V16z M12,2C6.5,2,2,6.5,2,12s4.5,10,10,10c5.5,0,10-4.5,10-10C22,6.5,17.5,2,12,2z M6,8h2V6h1.5v2h2v1.5h-2v2H8v-2H6V8z M12,20c-2.2,0-4.2-0.9-5.7-2.3L17.7,6.3C19.1,7.8,20,9.8,20,12C20,16.4,16.4,20,12,20z"/></g> -<g id="unknown-3"><path d="M13,8h-2v3H8v2h3v3h2v-3h3v-2h-3V8z M12,2C6.5,2,2,6.5,2,12s4.5,10,10,10c5.5,0,10-4.5,10-10C22,6.5,17.5,2,12,2z M12,20c-4.4,0-8-3.6-8-8c0-4.4,3.6-8,8-8c4.4,0,8,3.6,8,8C20,16.4,16.4,20,12,20z"/></g> -<g id="unknown-4"><path d="M12,2C6.5,2,2,6.5,2,12s4.5,10,10,10c5.5,0,10-4.5,10-10C22,6.5,17.5,2,12,2z M12,20c-4.4,0-8-3.6-8-8c0-4.4,3.6-8,8-8c4.4,0,8,3.6,8,8C20,16.4,16.4,20,12,20z M8,13h8v-2H8V13z"/></g> -<g id="unknown-5"><path d="M12,10H4v2h8V10z M12,2L12,2l0,2c4.4,0,8,3.6,8,8c0,4.4-3.6,8-8,8c-2.2,0-4.2-0.9-5.7-2.3l-1.4,1.4C6.7,20.9,9.2,22,12,22c5.5,0,10-4.5,10-10C22,6.5,17.5,2,12,2z"/></g> -<g id="unknown-6"><path d="M16,10h-2v2h2V10z M16,14h-2v2h2V14z M8,10H6v2h2V10z M12,10h-2v2h2V10z M20,4H4C2.9,4,2,4.9,2,6v12c0,1.1,0.9,2,2,2h16c1.1,0,2-0.9,2-2V6C22,4.9,21.1,4,20,4z M20,18L4,18V6h16V18z"/></g> -<g id="unknown-7"><path d="M14,16h5v-5h3l-5.5-5.5L11,11h3V16z M11,20h11v-2H11V20z M5.5,7l-3.2,9h1.9l0.7-2h3.2l0.7,2h1.9L7.5,7H5.5z M5.4,12.6L6.5,9l1.1,3.6H5.4z"/></g> -<g id="warning"><path d="M1,21h22L12,2L1,21z M13,18h-2v-2h2V18z M13,14h-2v-4h2V14z"/></g> -<g id="wb-auto"><path d="M6.9,12.6h2.3L8,9L6.9,12.6z M22,7l-1.2,6.3L19.3,7h-1.6l-1.5,6.3L15,7h-0.8C12.8,5.2,10.5,4,8,4c-4.4,0-8,3.6-8,8s3.6,8,8,8c3.1,0,5.8-1.8,7.2-4.4l0.1,0.4H17l1.5-6.1L20,16h1.8l2-9H22z M10.3,16l-0.7-2H6.4l-0.7,2H3.8L7,7h2l3.2,9H10.3z"/></g> -<g id="wb-cloudy"><path d="M19.4,10c-0.7-3.4-3.7-6-7.4-6C9.1,4,6.6,5.6,5.4,8C2.3,8.4,0,10.9,0,14c0,3.3,2.7,6,6,6h13c2.8,0,5-2.2,5-5C24,12.4,21.9,10.2,19.4,10z"/></g> -<g id="wb-incandescent"><path d="M3.5,18.5L5,20l1.8-1.8l-1.4-1.4L3.5,18.5z M11,22.4c0.3,0,2,0,2,0v-2.9h-2V22.4z M4,10.5H1v2h3V10.5z M15,6.3V1.5H9v4.8c-1.8,1-3,3-3,5.2c0,3.3,2.7,6,6,6s6-2.7,6-6C18,9.3,16.8,7.3,15,6.3z M20,10.5v2h3v-2H20z M17.2,18.2L19,20l1.4-1.4l-1.8-1.8L17.2,18.2z"/></g> -<g id="wb-irradescent"><path d="M5,14.5h14v-6H5V14.5z M11,0.6v2.9h2V0.6H11z M19,3l-1.8,1.8l1.4,1.4l1.8-1.8L19,3z M13,22.4v-2.9h-2v2.9C11.3,22.5,13,22.4,13,22.4z M20.5,18.5l-1.8-1.8l-1.4,1.4L19,20L20.5,18.5z M3.5,4.5l1.8,1.8l1.4-1.4L5,3L3.5,4.5z M5,20l1.8-1.8l-1.4-1.4l-1.8,1.8L5,20z"/></g> -<g id="wb-sunny"><path d="M6.8,4.8L5,3L3.5,4.5l1.8,1.8L6.8,4.8z M4,10.5H1v2h3V10.5z M13,0.6h-2v2.9h2V0.6z M20.5,4.5L19,3l-1.8,1.8l1.4,1.4L20.5,4.5z M17.2,18.2L19,20l1.4-1.4l-1.8-1.8L17.2,18.2z M20,10.5v2h3v-2H20z M12,5.5c-3.3,0-6,2.7-6,6s2.7,6,6,6s6-2.7,6-6S15.3,5.5,12,5.5z M11,22.4c0.3,0,2,0,2,0v-2.9h-2V22.4z M3.5,18.5L5,20l1.8-1.8l-1.4-1.4L3.5,18.5z"/></g> -</defs></svg> -</core-iconset-svg> + .serviceContainer { + margin-left: 30px; + } + + @media all and (max-width: 620px) { + .serviceContainer { + display: none; + } + } + + </style> + + <paper-dialog id="dialog" heading="Call Service" transition="paper-dialog-transition-bottom" backdrop="true"> + <div layout="" horizontal=""> + <div> + <paper-input id="inputDomain" label="Domain" floatinglabel="true" autofocus required></paper-input> + <paper-input id="inputService" label="Service" floatinglabel="true" required></paper-input> + <paper-input id="inputData" label="Service Data (JSON, optional)" floatinglabel="true" multiline=""></paper-input> + </div> + <div class="serviceContainer"> + <b>Available services:</b> + <services-list api="{{api}}" cbserviceclicked="{{serviceSelected}}"> + </services-list></div> + </div> + <paper-button dismissive="">Cancel</paper-button> + <paper-button affirmative="" on-click="{{clickCallService}}">Call Service</paper-button> + </paper-dialog> + + </template> + <script> + Polymer('service-call-dialog',{ + ready: function() { + // to ensure callback methods work.. + this.serviceSelected = this.serviceSelected.bind(this) + }, + + show: function(domain, service, serviceData) { + this.setService(domain, service); + this.$.inputData.value = serviceData; + this.$.dialog.toggle(); + }, + + setService: function(domain, service) { + this.$.inputDomain.value = domain; + this.$.inputService.value = service; + }, -<!-- -Copyright (c) 2014 The Polymer Project Authors. All rights reserved. -This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt -The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt -The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt -Code distributed by Google as part of the polymer project is also -subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt ---> + serviceSelected: function(domain, service) { + this.setService(domain, service); + }, + clickCallService: function() { + this.api.call_service( + this.$.inputDomain.value, + this.$.inputService.value, + this.$.inputData.value + ) + } + }); + </script> +</polymer-element> -<core-iconset-svg id="hardware" iconsize="24"> -<svg><defs> -<g id="cast"><path d="M21,3H3C1.9,3,1,3.9,1,5v3h2V5h18v14h-7v2h7c1.1,0,2-0.9,2-2V5C23,3.9,22.1,3,21,3z M1,18v3h3C4,19.3,2.7,18,1,18z M1,14v2c2.8,0,5,2.2,5,5h2C8,17.1,4.9,14,1,14z M1,10v2c5,0,9,4,9,9h2C12,14.9,7.1,10,1,10z"/></g> -<g id="cast-connected"><path d="M1,18v3h3C4,19.3,2.7,18,1,18z M1,14v2c2.8,0,5,2.2,5,5h2C8,17.1,4.9,14,1,14z M19,7H5v1.6c4,1.3,7.1,4.4,8.4,8.4H19V7z M1,10v2c5,0,9,4,9,9h2C12,14.9,7.1,10,1,10z M21,3H3C1.9,3,1,3.9,1,5v3h2V5h18v14h-7v2h7c1.1,0,2-0.9,2-2V5C23,3.9,22.1,3,21,3z"/></g> -<g id="chromecast"><path d="M12,2C6.5,2,2,6.5,2,12s4.5,10,10,10c5.5,0,10-4.5,10-10S17.5,2,12,2z M12,4c3,0,5.5,1.6,6.9,4H12c-1.9,0-3.6,1.4-3.9,3.2L5.7,7.1C7.2,5.2,9.4,4,12,4z M15,12c0,1.7-1.3,3-3,3c-1.7,0-3-1.3-3-3c0-1.7,1.3-3,3-3C13.7,9,15,10.3,15,12z M4,12c0-1.5,0.4-2.8,1.1-4l3.5,6l0,0c0.7,1.2,2,2,3.4,2c0.5,0,0.9-0.1,1.3-0.2l-2.4,4.1C7,19.4,4,16,4,12z M12,20l3.5-6l0,0c0.3-0.6,0.6-1.3,0.6-2c0-1.2-0.5-2.3-1.4-3h4.8c0.4,0.9,0.6,1.9,0.6,3C20,16.4,16.4,20,12,20z"/></g> -<g id="desktop-mac"><path d="M21,2H3C1.9,2,1,2.9,1,4v12c0,1.1,0.9,2,2,2h7l-2,3v1h8v-1l-2-3h7c1.1,0,2-0.9,2-2V4C23,2.9,22.1,2,21,2z M21,14H3V4h18V14z"/></g> -<g id="desktop-windows"><path d="M21,2H3C1.9,2,1,2.9,1,4v12c0,1.1,0.9,2,2,2h7v2H8v2h8v-2h-2v-2h7c1.1,0,2-0.9,2-2V4C23,2.9,22.1,2,21,2z M21,16H3V4h18V16z"/></g> -<g id="dock"><path d="M8,23h8v-2H8V23z M16,1L8,1C6.9,1,6,1.9,6,3v14c0,1.1,0.9,2,2,2h8c1.1,0,2-0.9,2-2V3C18,1.9,17.1,1,16,1z M16,15H8V5h8V15z"/></g> -<g id="gamepad"><path d="M15,7.5V2H9v5.5l3,3L15,7.5z M7.5,9H2v6h5.5l3-3L7.5,9z M9,16.5V22h6v-5.5l-3-3L9,16.5z M16.5,9l-3,3l3,3H22V9H16.5z"/></g> -<g id="glass"><path d="M13,11v2.5h5.9c-0.6,3.5-3.4,6-6.9,6c-4.1,0-7.5-3.4-7.5-7.5S7.9,4.5,12,4.5c2.1,0,3.9,0.9,5.2,2.3l1.8-1.8C17.2,3.2,14.8,2,12,2C6.5,2,2,6.5,2,12s4.5,10,10,10c5.5,0,9.5-4.5,9.5-10v-1H13z"/></g> -<g id="headset"><path d="M12,1c-5,0-9,4-9,9v7c0,1.7,1.3,3,3,3h3v-8H5v-2c0-3.9,3.1-7,7-7c3.9,0,7,3.1,7,7v2h-4v8h3c1.7,0,3-1.3,3-3v-7C21,5,17,1,12,1z"/></g> -<g id="headset-mic"><path d="M12,1c-5,0-9,4-9,9v7c0,1.7,1.3,3,3,3h3v-8H5v-2c0-3.9,3.1-7,7-7c3.9,0,7,3.1,7,7v2h-4v8h4v1h-7v2h6c1.7,0,3-1.3,3-3V10C21,5,17,1,12,1z"/></g> -<g id="keyboard"><path d="M20,5H4C2.9,5,2,5.9,2,7l0,10c0,1.1,0.9,2,2,2h16c1.1,0,2-0.9,2-2V7C22,5.9,21.1,5,20,5z M11,8h2v2h-2V8z M11,11h2v2h-2V11z M8,8h2v2H8V8z M8,11h2v2H8V11z M7,13H5v-2h2V13z M7,10H5V8h2V10z M16,17H8v-2h8V17z M16,13h-2v-2h2V13z M16,10h-2V8h2V10z M19,13h-2v-2h2V13z M19,10h-2V8h2V10z"/></g> -<g id="keyboard-alt"><path d="M15.5,10c0.8,0,1.5-0.7,1.5-1.5S16.3,7,15.5,7S14,7.7,14,8.5S14.7,10,15.5,10z M8.5,10C9.3,10,10,9.3,10,8.5S9.3,7,8.5,7C7.7,7,7,7.7,7,8.5S7.7,10,8.5,10z M12,17c2.6,0,4.8-1.7,5.7-4H6.3C7.2,15.3,9.4,17,12,17z M12,1C6.5,1,2,5.5,2,11c0,5.5,4.5,10,10,10c5.5,0,10-4.5,10-10C22,5.5,17.5,1,12,1z M12,19c-4.4,0-8-3.6-8-8s3.6-8,8-8c4.4,0,8,3.6,8,8S16.4,19,12,19z"/></g> -<g id="keyboard-arrow-down"><polygon points="7.4,7.8 12,12.4 16.6,7.8 18,9.2 12,15.2 6,9.2 "/></g> -<g id="keyboard-arrow-left"><polygon points="15.4,16.1 10.8,11.5 15.4,6.9 14,5.5 8,11.5 14,17.5 "/></g> -<g id="keyboard-arrow-right"><polygon points="8.6,16.3 13.2,11.8 8.6,7.2 10,5.8 16,11.8 10,17.8 "/></g> -<g id="keyboard-arrow-up"><polygon points="7.4,15.4 12,10.8 16.6,15.4 18,14 12,8 6,14 "/></g> -<g id="keyboard-backspace"><polygon points="21,11 6.8,11 10.4,7.4 9,6 3,12 9,18 10.4,16.6 6.8,13 21,13 "/></g> -<g id="keyboard-capslock"><path d="M12,8.4l4.6,4.6l1.4-1.4l-6-6l-6,6L7.4,13L12,8.4z M6,18h12v-2H6V18z"/></g> -<g id="keyboard-control"><path d="M6,10c-1.1,0-2,0.9-2,2c0,1.1,0.9,2,2,2c1.1,0,2-0.9,2-2C8,10.9,7.1,10,6,10z M18,10c-1.1,0-2,0.9-2,2c0,1.1,0.9,2,2,2c1.1,0,2-0.9,2-2C20,10.9,19.1,10,18,10z M12,10c-1.1,0-2,0.9-2,2c0,1.1,0.9,2,2,2c1.1,0,2-0.9,2-2C14,10.9,13.1,10,12,10z"/></g> -<g id="keyboard-hide"><path d="M20,3H4C2.9,3,2,3.9,2,5l0,10c0,1.1,0.9,2,2,2h16c1.1,0,2-0.9,2-2V5C22,3.9,21.1,3,20,3z M11,6h2v2h-2V6z M11,9h2v2h-2V9z M8,6h2v2H8V6z M8,9h2v2H8V9z M7,11H5V9h2V11z M7,8H5V6h2V8z M16,15H8v-2h8V15z M16,11h-2V9h2V11z M16,8h-2V6h2V8z M19,11h-2V9h2V11z M19,8h-2V6h2V8z M12,23l4-4H8L12,23z"/></g> -<g id="keyboard-return"><polygon points="19,7 19,11 5.8,11 9.4,7.4 8,6 2,12 8,18 9.4,16.6 5.8,13 21,13 21,7 "/></g> -<g id="keyboard-tab"><path d="M11.6,7.4l3.6,3.6H1v2h14.2l-3.6,3.6L13,18l6-6l-6-6L11.6,7.4z M20,6v12h2V6H20z"/></g> -<g id="keyboard-voice"><path d="M12,15c1.7,0,3-1.3,3-3l0-6c0-1.7-1.3-3-3-3c-1.7,0-3,1.3-3,3v6C9,13.7,10.3,15,12,15z M17.3,12c0,3-2.5,5.1-5.3,5.1c-2.8,0-5.3-2.1-5.3-5.1H5c0,3.4,2.7,6.2,6,6.7V22h2v-3.3c3.3-0.5,6-3.3,6-6.7H17.3z"/></g> -<g id="laptop"><path d="M20,18c1.1,0,2-0.9,2-2l0-10c0-1.1-0.9-2-2-2H4C2.9,4,2,4.9,2,6v10c0,1.1,0.9,2,2,2H0v2h24v-2H20z M4,6h16v10H4V6z"/></g> -<g id="laptop-chromebook"><path d="M22,18V3H2v15H0v2h24v-2H22z M14,18h-4v-1h4V18z M20,15H4V5h16V15z"/></g> -<g id="laptop-mac"><path d="M20,18c1.1,0,2-0.9,2-2l0-11c0-1.1-0.9-2-2-2H4C2.9,3,2,3.9,2,5v11c0,1.1,0.9,2,2,2H0c0,1.1,0.9,2,2,2h20c1.1,0,2-0.9,2-2H20z M4,5h16v11H4V5z M12,19c-0.6,0-1-0.4-1-1s0.4-1,1-1c0.6,0,1,0.4,1,1S12.6,19,12,19z"/></g> -<g id="laptop-windows"><path d="M20,18v-1c1.1,0,2-0.9,2-2l0-10c0-1.1-0.9-2-2-2H4C2.9,3,2,3.9,2,5v10c0,1.1,0.9,2,2,2v1H0v2h24v-2H20z M4,5h16v10H4V5z"/></g> -<g id="memory"><path d="M15,9H9v6h6V9z M13,13h-2v-2h2V13z M21,11V9h-2V7c0-1.1-0.9-2-2-2h-2V3h-2v2h-2V3H9v2H7C5.9,5,5,5.9,5,7v2H3v2h2v2H3v2h2v2c0,1.1,0.9,2,2,2h2v2h2v-2h2v2h2v-2h2c1.1,0,2-0.9,2-2v-2h2v-2h-2v-2H21z M17,17H7V7h10V17z"/></g> -<g id="mouse"><path d="M13,1.1V9h7C20,4.9,16.9,1.6,13,1.1z M4,15c0,4.4,3.6,8,8,8c4.4,0,8-3.6,8-8v-4H4V15z M11,1.1C7.1,1.6,4,4.9,4,9h7V1.1z"/></g> -<g id="nest-protect"><path d="M19,3H5C3.9,3,3,3.9,3,5v14c0,1.1,0.9,2,2,2h14c1.1,0,2-0.9,2-2V5C21,3.9,20.1,3,19,3z M12,18c-3.3,0-6-2.7-6-6s2.7-6,6-6c3.3,0,6,2.7,6,6S15.3,18,12,18z"/><circle cx="12" cy="12" r="4"/></g> -<g id="nest-thermostat"><path d="M12,2C6.5,2,2,6.5,2,12c0,5.5,4.5,10,10,10c5.5,0,10-4.5,10-10C22,6.5,17.5,2,12,2z M12,5c1.6,0,3,0.5,4.2,1.4L14,8.6C13.4,8.2,12.7,8,12,8c-2.2,0-4,1.8-4,4c0,1.1,0.4,2.1,1.2,2.8l-2.1,2.1C5.8,15.7,5,13.9,5,12C5,8.1,8.1,5,12,5z M16.9,16.9l-2.1-2.1c0.7-0.7,1.2-1.7,1.2-2.8c0-0.7-0.2-1.4-0.6-2l2.2-2.2C18.5,9,19,10.4,19,12C19,13.9,18.2,15.7,16.9,16.9z"/></g> -<g id="phone-android"><path d="M16,1H8C6.3,1,5,2.3,5,4v16c0,1.7,1.3,3,3,3h8c1.7,0,3-1.3,3-3V4C19,2.3,17.7,1,16,1z M14,21h-4v-1h4V21z M17.2,18H6.8V4h10.5V18z"/></g> -<g id="phone-iphone"><path d="M15.5,1h-8C6.1,1,5,2.1,5,3.5v17C5,21.9,6.1,23,7.5,23h8c1.4,0,2.5-1.1,2.5-2.5v-17C18,2.1,16.9,1,15.5,1z M11.5,22c-0.8,0-1.5-0.7-1.5-1.5s0.7-1.5,1.5-1.5c0.8,0,1.5,0.7,1.5,1.5S12.3,22,11.5,22z M16,18H7V4h9V18z"/></g> -<g id="phonelink"><path d="M4,6h18V4H4C2.9,4,2,4.9,2,6v11H0v3h14v-3H4V6z M23,8h-6c-0.5,0-1,0.5-1,1v10c0,0.5,0.5,1,1,1h6c0.5,0,1-0.5,1-1V9C24,8.5,23.5,8,23,8z M22,17h-4v-7h4V17z"/></g> -<g id="phonelink-off"><path d="M22,6V4H6.8l2,2H22z M1.9,1.6L0.6,2.9l1.8,1.8C2.2,5.1,2,5.5,2,6v11H0v3h17.7l2.4,2.4l1.3-1.3L3.9,3.6L1.9,1.6z M4,6.3L14.7,17H4V6.3z M23,8h-6c-0.5,0-1,0.5-1,1v4.2l2,2V10h4v7h-2.2l3,3H23c0.5,0,1-0.5,1-1V9C24,8.5,23.5,8,23,8z"/></g> -<g id="security"><path d="M12,1L3,5v6c0,5.6,3.8,10.7,9,12c5.2-1.3,9-6.4,9-12V5L12,1z M12,12h7c-0.5,4.1-3.3,7.8-7,8.9V12l-7,0V6.3l7-3.1V12z"/></g> -<g id="smartphone"><path d="M17,1L7,1C5.9,1,5,1.9,5,3v18c0,1.1,0.9,2,2,2h10c1.1,0,2-0.9,2-2V3C19,1.9,18.1,1,17,1z M17,19H7V5h10V19z"/></g> -<g id="speaker"><path d="M17,2H7C5.9,2,5,2.9,5,4v16c0,1.1,0.9,2,2,2l10,0c1.1,0,2-0.9,2-2V4C19,2.9,18.1,2,17,2z M12,4c1.1,0,2,0.9,2,2s-0.9,2-2,2c-1.1,0-2-0.9-2-2S10.9,4,12,4z M12,20c-2.8,0-5-2.2-5-5s2.2-5,5-5c2.8,0,5,2.2,5,5S14.8,20,12,20z M12,12c-1.7,0-3,1.3-3,3c0,1.7,1.3,3,3,3c1.7,0,3-1.3,3-3C15,13.3,13.7,12,12,12z"/></g> -<g id="tablet"><path d="M21,4H3C1.9,4,1,4.9,1,6v12c0,1.1,0.9,2,2,2h18c1.1,0,2-0.9,2-2l0-12C23,4.9,22.1,4,21,4z M19,18H5V6h14V18z"/></g> -<g id="tablet-android"><path d="M18,0H6C4.3,0,3,1.3,3,3v18c0,1.7,1.3,3,3,3h12c1.7,0,3-1.3,3-3V3C21,1.3,19.7,0,18,0z M14,22h-4v-1h4V22z M19.2,19H4.8V3h14.5V19z"/></g> -<g id="tablet-mac"><path d="M18.5,0h-14C3.1,0,2,1.1,2,2.5v19C2,22.9,3.1,24,4.5,24h14c1.4,0,2.5-1.1,2.5-2.5v-19C21,1.1,19.9,0,18.5,0z M11.5,23c-0.8,0-1.5-0.7-1.5-1.5s0.7-1.5,1.5-1.5c0.8,0,1.5,0.7,1.5,1.5S12.3,23,11.5,23z M19,19H4V3h15V19z"/></g> -<g id="tv"><path d="M21,3H3C1.9,3,1,3.9,1,5v12c0,1.1,0.9,2,2,2h5v2h8v-2h5c1.1,0,2-0.9,2-2l0-12C23,3.9,22.1,3,21,3z M21,17H3V5h18V17z"/></g> -<g id="watch"><path d="M20,12c0-2.5-1.2-4.8-3-6.3L16,0H8L7,5.7C5.2,7.2,4,9.5,4,12s1.2,4.8,3,6.3L8,24h8l1-5.7C18.8,16.8,20,14.5,20,12z M6,12c0-3.3,2.7-6,6-6c3.3,0,6,2.7,6,6s-2.7,6-6,6C8.7,18,6,15.3,6,12z"/></g> -</defs></svg> -</core-iconset-svg> -<polymer-element name="domain-icon" attributes="domain" assetpath="polymer/"> - <template> - <core-icon icon="{{icon(domain)}}"></core-icon> - </template> - <script> - Polymer('domain-icon',{ - icon: function() { - switch(this.domain) { - case "group": - return "social:communities"; - case "device_tracker": - return "social:person"; - case "wemo": - return "settings-input-svideo"; - case "chromecast": - // hardware:cast-connected - return "hardware:cast"; - case "process": - return "hardware:memory" +<polymer-element name="entity-list" attributes="api cbEntityClicked" assetpath="polymer/"> + <template> + <style> + :host { + display: block; + } - case "sun": - return "device:brightness-low" + .entityContainer { + font-size: 1rem; + } + </style> - case "light": - return "image:wb-incandescent" + <template if="{{cbEntityClicked}}"> + <style> + a { + text-decoration: underline; + cursor: pointer; + } + </style> + </template> - default: - return "bookmark-outline"; + <div> + <template repeat="{{state in states}}"> + <div class="eventContainer"> + <a on-click="{{handleClick}}">{{state.entity_id}}</a> + </div> + </template> + + </div> + </template> + <script> + Polymer('entity-list',{ + cbEventClicked: null, + states: [], + + domReady: function() { + this.api.addEventListener('states-updated', this.statesUpdated.bind(this)) + this.statesUpdated() + }, + + statesUpdated: function() { + this.states = this.api.states; + }, + + handleClick: function(ev) { + if(this.cbEntityClicked) { + this.cbEntityClicked(ev.path[0].innerHTML); } - } + }, }); </script> </polymer-element> -<polymer-element name="state-badge" attributes="domain state" assetpath="polymer/"> +<polymer-element name="state-set-dialog" attributes="api" assetpath="polymer/"> <template> <style> - :host { - display: inline-block; - width: 45px; - background-color: #4fc3f7; - color: white; - border-radius: 23px; + paper-input:first-child { + padding-top: 0; } - div { - height: 45px; - text-align: center; + + .stateContainer { + margin-left: 30px; } - domain-icon { - margin: 0 auto; + @media all and (max-width: 620px) { + .stateContainer { + display: none; + } } + </style> - <div horizontal="" layout="" center=""> - <domain-icon domain="{{domain}}"></domain-icon> + <paper-dialog id="dialog" heading="Set State" transition="paper-dialog-transition-center" backdrop="true"> + <div layout="" horizontal=""> + <div> + <paper-input id="inputEntityID" label="Entity ID" floatinglabel="true" autofocus required></paper-input> + <paper-input id="inputState" label="State" floatinglabel="true" required></paper-input> + <paper-input id="inputData" label="State attributes (JSON, optional)" floatinglabel="true" multiline=""></paper-input> + </div> + <div class="stateContainer"> + <b>Current entities:</b> + <entity-list api="{{api}}" cbentityclicked="{{entitySelected}}"></entity-list> + </div> </div> + <paper-button dismissive="">Cancel</paper-button> + <paper-button affirmative="" on-click="{{clickSetState}}">Set State</paper-button> + </paper-dialog> + + </template> + <script> + Polymer('state-set-dialog',{ + ready: function() { + // to ensure callback methods work.. + this.entitySelected = this.entitySelected.bind(this) + }, + + show: function(entityId, state, stateData) { + this.setEntityId(entityId); + this.setState(state); + this.setStateData(stateData); + + this.$.dialog.toggle(); + }, + + setEntityId: function(entityId) { + this.$.inputEntityID.value = entityId; + }, + + setState: function(state) { + this.$.inputState.value = state; + }, + + setStateData: function(stateData) { + var value = stateData ? JSON.stringify(stateData, null, ' ') : ""; + + this.$.inputData.value = value; + }, + + entitySelected: function(entityId) { + this.setEntityId(entityId); + + var state = this.api.getState(entityId); + this.setState(state.state); + this.setStateData(state.attributes); + }, + + clickSetState: function() { + this.api.set_state( + this.$.inputEntityID.value, + this.$.inputState.value, + JSON.parse(this.$.inputData.value) + ); + } + }); + </script> +</polymer-element> + + +<polymer-element name="home-assistant-api" attributes="auth" assetpath="polymer/"> + <template> + <style> + core-ajax { + display: none; + } + </style> + + <paper-toast id="toast" role="alert" text=""></paper-toast> + <event-fire-dialog id="eventDialog" api="{{api}}"></event-fire-dialog> + <service-call-dialog id="serviceDialog" api="{{api}}"></service-call-dialog> + <state-set-dialog id="stateDialog" api="{{api}}"></state-set-dialog> + + <core-ajax id="statesAjax" method="GET" url="/api/states" headers="{{ha_headers}}" on-core-response="{{statesLoaded}}" handleas="json"> + </core-ajax> + + <core-ajax id="eventsAjax" method="GET" url="/api/events" headers="{{ha_headers}}" on-core-response="{{eventsLoaded}}" handleas="json"> + </core-ajax> + + <core-ajax id="servicesAjax" method="GET" url="/api/services" headers="{{ha_headers}}" on-core-response="{{servicesLoaded}}" handleas="json"> + </core-ajax> + + </template> + <script> + Polymer('home-assistant-api',{ + auth: "not-set", + states: [], + services: {}, + events: {}, + stateUpdateTimeout: null, - </template> - <script> - Polymer('state-badge',{ - }); - </script> -</polymer-element> - - -<polymer-element name="state-card" attributes="entity state last_changed state_attr cb_turn_on, cb_turn_off cb_edit" assetpath="polymer/"> - <template> - <style> - :host { - background-color: #fff; - border-radius: 2px; - box-shadow: rgba(0, 0, 0, 0.098) 0px 2px 4px, rgba(0, 0, 0, 0.098) 0px 0px 3px; - /* transition */ - -webkit-transition: all 0.30s ease-out; - transition: all 0.30s ease-out; - - position: relative; - background-color: white; - padding: 15px; - width: 100%; - } - - state-badge { - float: left; - } - - .name, .state.text { - text-transform: capitalize; - font-weight: 300; - font-size: 1.5rem; - } - - .state { - text-align: right; - } - - .info { - margin-left: 60px; - } - - .time-ago { - color: darkgrey; - margin-top: -2px; - } - - /* the splash while enabling */ - paper-toggle-button::shadow paper-radio-button::shadow #ink[checked] { - color: #0091ea; - } - - /* filling of circle when checked */ - paper-toggle-button::shadow paper-radio-button::shadow #onRadio { - background-color: #0091ea; - } - - /* line when checked */ - paper-toggle-button::shadow #toggleBar[checked] { - background-color: #0091ea; - } - </style> - - <div horizontal="" justified="" layout=""> - - <div class="entity"> - <state-badge domain="{{domain}}" state="{{state}}" on-click="{{editClicked}}"> - </state-badge> - - <div class="info"> - <div class="name"> - <template if="{{state_attr['friendly_name']}}">{{state_attr['friendly_name']}}</template> - <template if="{{!state_attr['friendly_name']}}">{{entity_id | makeReadable}}</template> - </div> - - <div class="time-ago"> - <core-tooltip label="{{last_changed}}" position="bottom"> - {{last_changed_from_now}} - </core-tooltip> - </div> - - </div> - </div> - - <template if="{{state == 'on' || state == 'off'}}"> - <div class="state toggle" self-center="" flex=""> - <paper-toggle-button id="toggleButton" on-change="{{toggle}}"> - </paper-toggle-button> - </div> - </template> - <template if="{{state != 'on' && state != 'off'}}"> - <div class="state text"> - {{state | makeReadable}} - </div> - </template> - - </div> - - </template> - <script> - Polymer('state-card',{ - // attributes - entity: "", - state: "", - last_changed: "never", - state_attr: {}, - cb_turn_on: null, - cb_turn_off: null, - cb_edit: null, - - // computed - domain: "", - entity_id: "", - - stateChanged: function() { - if(this.$.toggleButton) { - this.$.toggleButton.checked = this.state == 'on'; - } - }, - - entityChanged: function(oldVal, newVal) { - var parts = newVal.split(".") - - if(parts.length == 1) { - this.domain = "" - this.entity_id = parts[0] - } else { - this.domain = parts[0] - this.entity_id = parts.slice(1).join('.') - } - }, - - last_changedChanged: function(oldVal, newVal) { - this.last_changed_from_now = moment(this.last_changed, "HH:mm:ss DD-MM-YYYY").fromNow() - }, - - toggle: function(ev) { - if(this.$.toggleButton.checked) { - this.turn_on(); - } else { - this.turn_off(); - } - }, - - turn_on: function() { - if(this.cb_turn_on) { - this.cb_turn_on(this.entity); - } - }, - - turn_off: function() { - if(this.cb_turn_off) { - this.cb_turn_off(this.entity); - } - }, - - editClicked: function() { - if(this.cb_edit) { - this.cb_edit(this.entity); - } - }, - - // used as filter - makeReadable: function(value) { - if(typeof value == "string") { - return value.replace(/_/g, " "); - - } else if(Array.isArray(value)) { - return value.join(", "); - - } else { - return value; - } - } - }); - </script> -</polymer-element> - - -<polymer-element name="states-cards" attributes="api filter" assetpath="polymer/"> - <template> - <style> - :host { - display: block; - width: 100%; - } - - state-card, state-add-card { - display: inline-block; - width: 350px; - margin: 10px 0 0 10px; - } - - state-add-card { - cursor: pointer; - } - - </style> - - <div horizontal="" layout="" wrap=""> - <template if="{{filter != null}}"> - <state-card entity="{{filter_state.entity_id}}" state="{{filter_state.state}}" last_changed="{{filter_state.last_changed}}" state_attr="{{filter_state.attributes}}" cb_turn_on="{{api.turn_on}}" cb_turn_off="{{api.turn_off}}" cb_edit="{{editCallback}}"> - </state-card> - </template> - - <template repeat="{{state in states}}"> - <state-card entity="{{state.entity_id}}" state="{{state.state}}" last_changed="{{state.last_changed}}" state_attr="{{state.attributes}}" cb_turn_on="{{api.turn_on}}" cb_turn_off="{{api.turn_off}}" cb_edit="{{editCallback}}"> - </state-card> - </template> - - </div> - </template> - <script> - Polymer('states-cards',{ - raw_states: [], - states: [], - filter: null, - filter_state: null, - filter_substates: null, - - filterChanged: function(oldVal, newVal) { - this.refilterStates(); - }, - - ready: function() { - this.editCallback = this.editCallback.bind(this); - }, - - domReady: function() { - this.states = this.api.states - - this.api.addEventListener('states-updated', this.statesUpdated.bind(this)) - }, - - statesUpdated: function() { - this.raw_states = this.api.states; - - this.refilterStates(); - }, - - refilterStates: function() { - if(this.filter == null) { - this.filter_state = null; - this.states = this.raw_states; - } else { - this.filter_state = this.api.getState(this.filter); - - var map_states = function(entity_id) { - return this.api.getState(entity_id); - }.bind(this) - - this.states = this.filter_state.attributes.entity_id.map(map_states) - } - }, - - editCallback: function(entityId) { - this.api.showEditStateDialog(entityId); - }, - - }); - </script> -</polymer-element> + computed: { + ha_headers: '{"HA-access": auth}' + }, + created: function() { + this.api = this; -<polymer-element name="home-assistant-main" attributes="auth" assetpath="polymer/"> - <template> - <style type="text/css"> + // so we can pass these methods safely as callbacks + this.turn_on = this.turn_on.bind(this); + this.turn_off = this.turn_off.bind(this); + }, - :host { - font-family: 'RobotoDraft', sans-serif; + // local methods + getState: function(entityId) { + for(var i = 0; i < this.states.length; i++) { + if(this.states[i].entity_id == entityId) { + return this.states[i]; + } } + }, - core-header-panel { - height: 100%; - overflow: auto; - -webkit-overflow-scrolling: touch; - background-color: #E5E5E5; + getCustomGroups: function() { + return this.states.filter(function(state) { + return (state.entity_id.lastIndexOf("group.") == 0 && + !state.attributes.auto); + }) + }, + + _laterFetchStates: function() { + if(this.stateUpdateTimeout) { + clearTimeout(this.stateUpdateTimeout); } - core-toolbar { - background: #03a9f4; - font-size: 1.4rem; - color: white; - height: 95px; + // update states in 60 seconds + this.stateUpdateTimeout = setTimeout(this.fetchStates.bind(this), 60000); + }, + + _sortStates: function(states) { + return states.sort(function(one, two) { + if (one.entity_id > two.entity_id) { + return 1; + } else if (one.entity_id < two.entity_id) { + return -1; + } else { + return 0; + } + }) + }, + + _pushNewState: function(new_state) { + var state; + var stateFound = false; + + for(var i = 0; i < this.states.length; i++) { + if(this.states[i].entity_id == new_state.entity_id) { + state = this.states[i]; + state.attributes = new_state.attributes; + state.last_changed = new_state.last_changed; + state.state = new_state.state; + + stateFound = true; + break; + } } - .content { - padding-bottom: 75px; - padding-right: 10px; + if(!stateFound) { + this.states.push(new_state); + this._sortStates(this.states); } - paper-fab { - position: fixed; - bottom: 10px; - right: 10px; + this.fire('states-updated') + }, + + // call api methods + fetchState: function(entityId) { + var successStateUpdate = function(new_state) { + this._pushNewState(new_state); } - </style> + this.call_api("GET", "states/" + entityId, null, successStateUpdate.bind(this)); + }, - <home-assistant-api auth="{{auth}}" id="api"></home-assistant-api> + fetchStates: function(onSuccess, onError) { + var successStatesUpdate = function(newStates) { + this.states = this._sortStates(newStates); - <core-header-panel unresolved="" fullbleed=""> + this.fire('states-updated') - <core-toolbar> - <div flex=""> - Home Assistant - </div> - <core-icon-button icon="refresh" on-click="{{handleRefreshClick}}"></core-icon-button> - <core-icon-button icon="developer-mode-tv" on-click="{{handleEventClick}}"></core-icon-button> - <core-icon-button icon="settings-remote" on-click="{{handleServiceClick}}"></core-icon-button> + this._laterFetchStates(); - <div class="bottom fit" horizontal="" layout=""> - <paper-tabs id="tabsHolder" noink="" flex="" selected="0" on-core-select="{{tabClicked}}"> - - <paper-tab>ALL</paper-tab> + if(onSuccess) { + onSuccess(newStates); + } + } - <template repeat="{{state in api.states}}"> - <template if="{{isCustomGroup(state)}}"> - <paper-tab data-entity="{{state.entity_id}}">{{state.entity_id | groupName}}</paper-tab> - </template> - </template> - - </paper-tabs> - </div> - </core-toolbar> + this.call_api("GET", "states", null, successStatesUpdate.bind(this), onError); + }, - <div class="content" flex=""> - <states-cards api="{{api}}" filter="{{selectedTab}}"></states-cards> - <paper-fab icon="add" on-click="{{handleAddStateClick}}"></paper-fab> - </div> + fetchEvents: function() { + var successEventsUpdated = function(events) { + this.events = events; - </core-header-panel> + this.fire('events-updated') + } - </template> - <script> - Polymer('home-assistant-main',{ - selectedTab: null, + this.call_api("GET", "events", null, successEventsUpdated.bind(this)); + }, - ready: function() { - this.api = this.$.api; + fetchServices: function() { + var successServicesUpdated = function(services) { + this.services = services; + + this.fire('services-updated') + } + + this.call_api("GET", "services", null, + successServicesUpdated.bind(this)); }, - isCustomGroup: function(state) { - return (state.entity_id.lastIndexOf('group.') == 0 && - !state.attributes.auto); + turn_on: function(entity_id) { + this.call_service("homeassistant", "turn_on", {entity_id: entity_id}); }, - groupName: function(entity_id) { - return entity_id.substring(6).toUpperCase().replace(/_/g, " "); + turn_off: function(entity_id) { + this.call_service("homeassistant", "turn_off", {entity_id: entity_id}) }, - tabClicked: function(ev) { - if(ev.detail.isSelected) { - // will be null for ALL tab - this.selectedTab = ev.detail.item.getAttribute('data-entity'); + set_state: function(entity_id, state, attributes) { + var payload = {state: state} + + if(attributes) { + payload.attributes = attributes; + } + + var successToast = function(new_state) { + this.showToast("State of "+entity_id+" successful set to "+state+"."); + this._pushNewState(new_state); } + + this.call_api("POST", "states/" + entity_id, + payload, successToast.bind(this)); }, - handleRefreshClick: function() { - this.api.fetchStates(); + call_service: function(domain, service, parameters) { + var successToast = function() { + this.showToast("Service "+domain+"/"+service+" successful called."); + + // if we call a service on an entity_id, update the state + if(parameters && parameters.entity_id) { + var update_func; + + // if entity_id is a string, update 1 state, else all. + if(typeof(parameters.entity_id === "string")) { + update_func = function() { + this.fetchState(parameters.entity_id); + } + } else { + update_func = this.fetchStates + } + + setTimeout(update_func.bind(this), 1000); + } + } + + this.call_api("POST", "services/" + domain + "/" + service, + parameters, successToast.bind(this)); }, - handleEventClick: function() { - this.api.showFireEventDialog(); + fire_event: function(eventType, eventData) { + eventData = eventData ? JSON.parse(eventData) : ""; + + var successToast = function() { + this.showToast("Event "+eventType+" successful fired."); + } + + this.call_api("POST", "events/" + eventType, + eventData, successToast.bind(this)); }, - handleServiceClick: function() { - this.api.showCallServiceDialog(); + call_api: function(method, path, parameters, onSuccess, onError) { + var req = new XMLHttpRequest(); + req.open(method, "/api/" + path, true) + req.setRequestHeader("HA-access", this.auth); + + req.onreadystatechange = function() { + + if(req.readyState == 4) { + if(req.status > 199 && req.status < 300) { + if(onSuccess) { + onSuccess(JSON.parse(req.responseText)); + } + } else { + if(onError) { + var data = req.responseText ? JSON.parse(req.responseText) : {}; + onError(data); + } + } + + + } + }.bind(this) + + if(parameters) { + req.send(JSON.stringify(parameters)); + } else { + req.send(); + } }, - handleAddStateClick: function() { - this.api.showSetStateDialog(); + // show dialogs + showEditStateDialog: function(entityId) { + var state = this.getState(entityId); + + this.showSetStateDialog(entityId, state.state, state.attributes) + }, + + showSetStateDialog: function(entityId, state, stateAttributes) { + entityId = entityId || ""; + state = state || ""; + stateAttributes = stateAttributes || null; + + this.$.stateDialog.show(entityId, state, stateAttributes); + }, + + showFireEventDialog: function(eventType, eventData) { + eventType = eventType || ""; + eventData = eventData || ""; + + this.$.eventDialog.show(eventType, eventData); + }, + + showCallServiceDialog: function(domain, service, serviceData) { + domain = domain || ""; + service = service || ""; + serviceData = serviceData || ""; + + this.$.serviceDialog.show(domain, service, serviceData); + }, + + showToast: function(message) { + this.$.toast.text = message; + this.$.toast.show(); } }); - </script> + </script> </polymer-element> </div> -<div hidden>undefined</div> -<div hidden>undefined</div> <polymer-element name="splash-login" attributes="auth" assetpath="polymer/"> <template> @@ -14441,6 +14484,8 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN </style> + <home-assistant-api auth="{{auth}}" id="api"></home-assistant-api> + <template if="{{state == 'no_auth'}}"> <div layout="" horizontal="" center="" fit="" class="login"> <div layout="" vertical="" center="" flex=""> @@ -14449,7 +14494,8 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN <div class="interact" layout="" vertical=""> <div id="loginform"> - <paper-input id="passwordInput" label="Password" type="password" value="{{auth}}"></paper-input> + <paper-input id="passwordInput" label="Password" type="password" value="{{auth}}" on-keyup="{{passwordKeyup}}" autofocus> + </paper-input> <paper-button on-click="{{validatePassword}}">Log In</paper-button> </div> @@ -14459,18 +14505,19 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN </div> </template> <template if="{{state == 'valid_auth'}}"> - <home-assistant-main auth="{{auth}}"></home-assistant-main> + <home-assistant-main api="{{api}}"></home-assistant-main> </template> </template> <script> Polymer('splash-login',{ - // can be no_auth, test_auth, valid_auth + // can be no_auth, valid_auth state: "no_auth", auth: "", ready: function() { + this.api = this.$.api; }, domReady: function() { @@ -14479,35 +14526,39 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN } }, + passwordKeyup: function(ev) { + if(ev.keyCode == 13) { + this.validatePassword(); + } + }, + validatePassword: function() { this.$.passwordInput.commit(); - this.$.loginform.setAttribute('hidden', null) - this.$.validateMessage.removeAttribute('hidden') - - var req = new XMLHttpRequest(); - req.open("GET", "/api/", true); - req.setRequestHeader("HA-access", this.auth); - - req.onreadystatechange = function() { - if(req.readyState == 4) { - if(req.status == 200) { - this.state = 'valid_auth' - } else { - this.auth = ""; + this.$.loginform.setAttribute('hidden', null); + this.$.validateMessage.removeAttribute('hidden'); - this.$.passwordInput.error = "Invalid Password"; - this.$.passwordInput.required = 1; + var passwordValid = function(result) { + this.api.fetchServices(); + this.api.fetchEvents(); - this.$.loginform.removeAttribute('hidden'); - this.$.validateMessage.setAttribute('hidden', null); + this.state = "valid_auth"; + } - this.state = 'no_auth' - } + var passwordInvalid = function(result) { + if(result && result.message) { + this.$.passwordInput.error = result.message; + } else { + this.$.passwordInput.error = "Unexpected result from API"; } - }.bind(this) + this.auth = null; + this.$.passwordInput.setAttribute('required', true); + this.$.loginform.removeAttribute('hidden'); + this.$.validateMessage.setAttribute('hidden', null); + this.$.passwordInput.focus(); + } - req.send(); - }, + this.api.fetchStates(passwordValid.bind(this), passwordInvalid.bind(this)); + } }); </script> diff --git a/homeassistant/components/http/www_static/polymer/home-assistant-api.html b/homeassistant/components/http/www_static/polymer/home-assistant-api.html index 04d2fa6a8ee..4c48f9ca33f 100644 --- a/homeassistant/components/http/www_static/polymer/home-assistant-api.html +++ b/homeassistant/components/http/www_static/polymer/home-assistant-api.html @@ -20,7 +20,6 @@ <state-set-dialog id="stateDialog" api={{api}}></state-set-dialog> <core-ajax id="statesAjax" - auto method="GET" url="/api/states" headers="{{ha_headers}}" @@ -29,7 +28,6 @@ </core-ajax> <core-ajax id="eventsAjax" - auto method="GET" url="/api/events" headers="{{ha_headers}}" @@ -38,7 +36,6 @@ </core-ajax> <core-ajax id="servicesAjax" - auto method="GET" url="/api/services" headers="{{ha_headers}}" @@ -67,6 +64,22 @@ this.turn_off = this.turn_off.bind(this); }, + // local methods + getState: function(entityId) { + for(var i = 0; i < this.states.length; i++) { + if(this.states[i].entity_id == entityId) { + return this.states[i]; + } + } + }, + + getCustomGroups: function() { + return this.states.filter(function(state) { + return (state.entity_id.lastIndexOf("group.") == 0 && + !state.attributes.auto); + }) + }, + _laterFetchStates: function() { if(this.stateUpdateTimeout) { clearTimeout(this.stateUpdateTimeout); @@ -88,29 +101,6 @@ }) }, - statesLoaded: function() { - // Make a copy of the loaded data - this.states = this._sortStates(this.$.statesAjax.response.slice(0)); - - this.fire('states-updated') - - this._laterFetchStates(); - }, - - eventsLoaded: function() { - // Make a copy of the loaded data - this.events = this.$.eventsAjax.response; - - this.fire('events-updated') - }, - - servicesLoaded: function() { - // Make a copy of the loaded data - this.services = this.$.servicesAjax.response; - - this.fire('services-updated') - }, - _pushNewState: function(new_state) { var state; var stateFound = false; @@ -131,32 +121,54 @@ this.states.push(new_state); this._sortStates(this.states); } + + this.fire('states-updated') }, - fetchState: function(entity_id) { + // call api methods + fetchState: function(entityId) { var successStateUpdate = function(new_state) { this._pushNewState(new_state); } - this.call_api("GET", "states/" + entity_id, null, successStateUpdate.bind(this)); + this.call_api("GET", "states/" + entityId, null, successStateUpdate.bind(this)); }, - fetchStates: function() { - this.$.statesAjax.go(); - }, + fetchStates: function(onSuccess, onError) { + var successStatesUpdate = function(newStates) { + this.states = this._sortStates(newStates); - getState: function(entityId) { - for(var i = 0; i < this.states.length; i++) { - if(this.states[i].entity_id == entityId) { - return this.states[i]; + this.fire('states-updated') + + this._laterFetchStates(); + + if(onSuccess) { + onSuccess(newStates); } } + + this.call_api("GET", "states", null, successStatesUpdate.bind(this), onError); }, - getCustomGroups: function() { - return this.states.filter(function(state) { - return state.entity_id.lastIndexOf("group.") == 0; - }) + fetchEvents: function() { + var successEventsUpdated = function(events) { + this.events = events; + + this.fire('events-updated') + } + + this.call_api("GET", "events", null, successEventsUpdated.bind(this)); + }, + + fetchServices: function() { + var successServicesUpdated = function(services) { + this.services = services; + + this.fire('services-updated') + } + + this.call_api("GET", "services", null, + successServicesUpdated.bind(this)); }, turn_on: function(entity_id) { @@ -186,6 +198,22 @@ call_service: function(domain, service, parameters) { var successToast = function() { this.showToast("Service "+domain+"/"+service+" successful called."); + + // if we call a service on an entity_id, update the state + if(parameters && parameters.entity_id) { + var update_func; + + // if entity_id is a string, update 1 state, else all. + if(typeof(parameters.entity_id === "string")) { + update_func = function() { + this.fetchState(parameters.entity_id); + } + } else { + update_func = this.fetchStates + } + + setTimeout(update_func.bind(this), 1000); + } } this.call_api("POST", "services/" + domain + "/" + service, @@ -203,34 +231,26 @@ eventData, successToast.bind(this)); }, - call_api: function(method, path, parameters, callback) { + call_api: function(method, path, parameters, onSuccess, onError) { var req = new XMLHttpRequest(); req.open(method, "/api/" + path, true) req.setRequestHeader("HA-access", this.auth); req.onreadystatechange = function() { - if(req.readyState == 4 && req.status > 199 && req.status < 300) { - - if(callback) { - callback(JSON.parse(req.responseText)) - } - // if we targetted an entity id, update state after 2 seconds - if(parameters && parameters.entity_id) { - var updateCallback; - - // if a string, update just that entity, otherwise update all - if(typeof(parameters.entity_id) == "string") { - updateCallback = function() { - this.fetchState(parameters.entity_id); - } - - } else { - updateCallback = this.fetchStates(); + if(req.readyState == 4) { + if(req.status > 199 && req.status < 300) { + if(onSuccess) { + onSuccess(JSON.parse(req.responseText)); + } + } else { + if(onError) { + var data = req.responseText ? JSON.parse(req.responseText) : {}; + onError(data); } - - setTimeout(updateCallback.bind(this), 2000); } + + } }.bind(this) @@ -241,6 +261,7 @@ } }, + // show dialogs showEditStateDialog: function(entityId) { var state = this.getState(entityId); diff --git a/homeassistant/components/http/www_static/polymer/home-assistant-main.html b/homeassistant/components/http/www_static/polymer/home-assistant-main.html index 47315f7f60e..ff361341893 100644 --- a/homeassistant/components/http/www_static/polymer/home-assistant-main.html +++ b/homeassistant/components/http/www_static/polymer/home-assistant-main.html @@ -5,10 +5,9 @@ <link rel="import" href="bower_components/paper-tabs/paper-tabs.html"> <link rel="import" href="bower_components/paper-tabs/paper-tab.html"> -<link rel="import" href="home-assistant-api.html"> <link rel="import" href="states-cards.html"> -<polymer-element name="home-assistant-main" attributes="auth"> +<polymer-element name="home-assistant-main" attributes="api"> <template> <style type="text/css"> @@ -42,7 +41,6 @@ </style> - <home-assistant-api auth="{{auth}}" id="api"></home-assistant-api> <core-header-panel unresolved fullbleed> @@ -82,10 +80,6 @@ Polymer({ selectedTab: null, - ready: function() { - this.api = this.$.api; - }, - isCustomGroup: function(state) { return (state.entity_id.lastIndexOf('group.') == 0 && !state.attributes.auto); diff --git a/homeassistant/components/http/www_static/polymer/splash-login.html b/homeassistant/components/http/www_static/polymer/splash-login.html index beba5b693ce..16b9adac2ed 100644 --- a/homeassistant/components/http/www_static/polymer/splash-login.html +++ b/homeassistant/components/http/www_static/polymer/splash-login.html @@ -1,8 +1,10 @@ <link rel="import" href="bower_components/font-roboto/roboto.html"> -<link rel="import" href="home-assistant-main.html"> <link rel="import" href="bower_components/paper-button/paper-button.html"> <link rel="import" href="bower_components/paper-input/paper-input.html"> +<link rel="import" href="home-assistant-main.html"> +<link rel="import" href="home-assistant-api.html"> + <polymer-element name="splash-login" attributes="auth"> <template> <style type="text/css"> @@ -23,6 +25,8 @@ </style> + <home-assistant-api auth="{{auth}}" id="api"></home-assistant-api> + <template if="{{state == 'no_auth'}}"> <div layout horizontal center fit class='login'> <div layout vertical center flex> @@ -31,7 +35,10 @@ <div class='interact' layout vertical> <div id='loginform'> - <paper-input id="passwordInput" label="Password" type="password" value="{{auth}}"></paper-input> + <paper-input + id="passwordInput" label="Password" type="password" + value="{{auth}}" on-keyup="{{passwordKeyup}}" autofocus> + </paper-input> <paper-button on-click={{validatePassword}}>Log In</paper-button> </div> @@ -41,18 +48,19 @@ </div> </template> <template if="{{state == 'valid_auth'}}"> - <home-assistant-main auth="{{auth}}"></home-assistant-main> + <home-assistant-main api="{{api}}"></home-assistant-main> </template> </template> <script> Polymer({ - // can be no_auth, test_auth, valid_auth + // can be no_auth, valid_auth state: "no_auth", auth: "", ready: function() { + this.api = this.$.api; }, domReady: function() { @@ -61,35 +69,39 @@ } }, + passwordKeyup: function(ev) { + if(ev.keyCode == 13) { + this.validatePassword(); + } + }, + validatePassword: function() { this.$.passwordInput.commit(); - this.$.loginform.setAttribute('hidden', null) - this.$.validateMessage.removeAttribute('hidden') - - var req = new XMLHttpRequest(); - req.open("GET", "/api/", true); - req.setRequestHeader("HA-access", this.auth); - - req.onreadystatechange = function() { - if(req.readyState == 4) { - if(req.status == 200) { - this.state = 'valid_auth' - } else { - this.auth = ""; + this.$.loginform.setAttribute('hidden', null); + this.$.validateMessage.removeAttribute('hidden'); - this.$.passwordInput.error = "Invalid Password"; - this.$.passwordInput.required = 1; + var passwordValid = function(result) { + this.api.fetchServices(); + this.api.fetchEvents(); - this.$.loginform.removeAttribute('hidden'); - this.$.validateMessage.setAttribute('hidden', null); + this.state = "valid_auth"; + } - this.state = 'no_auth' - } + var passwordInvalid = function(result) { + if(result && result.message) { + this.$.passwordInput.error = result.message; + } else { + this.$.passwordInput.error = "Unexpected result from API"; } - }.bind(this) + this.auth = null; + this.$.passwordInput.setAttribute('required', true); + this.$.loginform.removeAttribute('hidden'); + this.$.validateMessage.setAttribute('hidden', null); + this.$.passwordInput.focus(); + } - req.send(); - }, + this.api.fetchStates(passwordValid.bind(this), passwordInvalid.bind(this)); + } }); </script> diff --git a/homeassistant/components/http/www_static/polymer/state-card.html b/homeassistant/components/http/www_static/polymer/state-card.html index 3ccd230a45d..b9d871aad95 100755 --- a/homeassistant/components/http/www_static/polymer/state-card.html +++ b/homeassistant/components/http/www_static/polymer/state-card.html @@ -26,6 +26,12 @@ state-badge { float: left; + cursor: pointer; + transition: background-color .2s; + } + + state-badge:hover { + background-color: #039be5; } .name, .state.text { @@ -54,12 +60,14 @@ /* filling of circle when checked */ paper-toggle-button::shadow paper-radio-button::shadow #onRadio { - background-color: #0091ea; + background-color: #039be5; + transition: background-color .2s; } /* line when checked */ paper-toggle-button::shadow #toggleBar[checked] { - background-color: #0091ea; + background-color: #039be5; + transition: background-color .2s; } </style> @@ -87,20 +95,26 @@ </div> </div> - <template if="{{state == 'on' || state == 'off'}}"> - <div class='state toggle' self-center flex> - <paper-toggle-button - id="toggleButton" - on-change="{{toggle}}"> - </paper-toggle-button> - </div> + <template if="{{!state_unknown}}"> + <template if="{{state == 'on' || state == 'off'}}"> + <div class='state toggle' self-center flex> + <paper-toggle-button + id="toggleButton" + on-change="{{toggle}}"> + </paper-toggle-button> + </div> + </template> + <template if="{{state != 'on' && state != 'off'}}"> + <div class='state text'> + {{state | makeReadable}} + </div> + </template> </template> - <template if="{{state != 'on' && state != 'off'}}"> - <div class='state text'> - {{state | makeReadable}} - </div> + + <template if="{{state_unknown}}"> + <div class="state" self-center flex>Updating..</div> </template> - + </div> </template> @@ -114,12 +128,15 @@ cb_turn_on: null, cb_turn_off: null, cb_edit: null, + state_unknown: false, // computed domain: "", entity_id: "", - stateChanged: function() { + stateChanged: function(oldVal, newVal) { + this.state_unknown = newVal == ""; + if(this.$.toggleButton) { this.$.toggleButton.checked = this.state == 'on'; } @@ -147,6 +164,11 @@ } else { this.turn_off(); } + + var delayUnsetSate = function() { + this.state = ""; + } + setTimeout(delayUnsetSate.bind(this), 500); }, turn_on: function() { diff --git a/homeassistant/components/http/www_static/polymer/states-cards.html b/homeassistant/components/http/www_static/polymer/states-cards.html index a74ffe99379..64c4ad26582 100755 --- a/homeassistant/components/http/www_static/polymer/states-cards.html +++ b/homeassistant/components/http/www_static/polymer/states-cards.html @@ -65,9 +65,11 @@ }, domReady: function() { - this.states = this.api.states + this.raw_states = this.api.states this.api.addEventListener('states-updated', this.statesUpdated.bind(this)) + + this.refilterStates(); }, statesUpdated: function() { -- GitLab