jellyfin-web/dashboard-ui/vulcanize-out.html
Luke Pulverenti 0bc95efe7e update icons
2015-06-20 20:49:42 -04:00

13502 lines
375 KiB
HTML

<html><head><meta charset="UTF-8"><!--
@license
Copyright (c) 2015 The Polymer Project Authors. All rights reserved.
This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE
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
--><!--
@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
--><!--
@license
Copyright (c) 2015 The Polymer Project Authors. All rights reserved.
This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
Code distributed by Google as part of the polymer project is also
subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
--><script>(function () {
function resolve() {
document.body.removeAttribute('unresolved');
}
if (window.WebComponents) {
addEventListener('WebComponentsReady', resolve);
} else {
if (document.readyState === 'interactive' || document.readyState === 'complete') {
resolve();
} else {
addEventListener('DOMContentLoaded', resolve);
}
}
}());
Polymer = {
Settings: function () {
var user = window.Polymer || {};
location.search.slice(1).split('&').forEach(function (o) {
o = o.split('=');
o[0] && (user[o[0]] = o[1] || true);
});
var wantShadow = user.dom === 'shadow';
var hasShadow = Boolean(Element.prototype.createShadowRoot);
var nativeShadow = hasShadow && !window.ShadowDOMPolyfill;
var useShadow = wantShadow && hasShadow;
var hasNativeImports = Boolean('import' in document.createElement('link'));
var useNativeImports = hasNativeImports;
var useNativeCustomElements = !window.CustomElements || window.CustomElements.useNative;
return {
wantShadow: wantShadow,
hasShadow: hasShadow,
nativeShadow: nativeShadow,
useShadow: useShadow,
useNativeShadow: useShadow && nativeShadow,
useNativeImports: useNativeImports,
useNativeCustomElements: useNativeCustomElements
};
}()
};
(function () {
var userPolymer = window.Polymer;
window.Polymer = function (prototype) {
var ctor = desugar(prototype);
prototype = ctor.prototype;
var options = { prototype: prototype };
if (prototype.extends) {
options.extends = prototype.extends;
}
Polymer.telemetry._registrate(prototype);
document.registerElement(prototype.is, options);
return ctor;
};
var desugar = function (prototype) {
prototype = Polymer.Base.chainObject(prototype, Polymer.Base);
prototype.registerCallback();
return prototype.constructor;
};
window.Polymer = Polymer;
if (userPolymer) {
for (var i in userPolymer) {
Polymer[i] = userPolymer[i];
}
}
Polymer.Class = desugar;
}());
Polymer.telemetry = {
registrations: [],
_regLog: function (prototype) {
console.log('[' + prototype.is + ']: registered');
},
_registrate: function (prototype) {
this.registrations.push(prototype);
Polymer.log && this._regLog(prototype);
},
dumpRegistrations: function () {
this.registrations.forEach(this._regLog);
}
};
Object.defineProperty(window, 'currentImport', {
enumerable: true,
configurable: true,
get: function () {
return (document._currentScript || document.currentScript).ownerDocument;
}
});
Polymer.Base = {
_addFeature: function (feature) {
this.extend(this, feature);
},
registerCallback: function () {
this._registerFeatures();
this._doBehavior('registered');
},
createdCallback: function () {
Polymer.telemetry.instanceCount++;
this.root = this;
this._doBehavior('created');
this._initFeatures();
},
attachedCallback: function () {
this.isAttached = true;
this._doBehavior('attached');
},
detachedCallback: function () {
this.isAttached = false;
this._doBehavior('detached');
},
attributeChangedCallback: function (name) {
this._setAttributeToProperty(this, name);
this._doBehavior('attributeChanged', arguments);
},
extend: function (prototype, api) {
if (prototype && api) {
Object.getOwnPropertyNames(api).forEach(function (n) {
this.copyOwnProperty(n, api, prototype);
}, this);
}
return prototype || api;
},
copyOwnProperty: function (name, source, target) {
var pd = Object.getOwnPropertyDescriptor(source, name);
if (pd) {
Object.defineProperty(target, name, pd);
}
},
_log: console.log.apply.bind(console.log, console),
_warn: console.warn.apply.bind(console.warn, console),
_error: console.error.apply.bind(console.error, console),
_logf: function () {
return this._logPrefix.concat([this.is]).concat(Array.prototype.slice.call(arguments, 0));
}
};
Polymer.Base._logPrefix = function () {
var color = window.chrome || /firefox/i.test(navigator.userAgent);
return color ? [
'%c[%s::%s]:',
'font-weight: bold; background-color:#EEEE00;'
] : ['[%s::%s]:'];
}();
Polymer.Base.chainObject = function (object, inherited) {
if (object && inherited && object !== inherited) {
if (!Object.__proto__) {
object = Polymer.Base.extend(Object.create(inherited), object);
}
object.__proto__ = inherited;
}
return object;
};
Polymer.Base = Polymer.Base.chainObject(Polymer.Base, HTMLElement.prototype);
Polymer.telemetry.instanceCount = 0;
(function () {
var modules = {};
var DomModule = function () {
return document.createElement('dom-module');
};
DomModule.prototype = Object.create(HTMLElement.prototype);
DomModule.prototype.constructor = DomModule;
DomModule.prototype.createdCallback = function () {
var id = this.id || this.getAttribute('name') || this.getAttribute('is');
if (id) {
this.id = id;
modules[id] = this;
}
};
DomModule.prototype.import = function (id, slctr) {
var m = modules[id];
if (!m) {
forceDocumentUpgrade();
m = modules[id];
}
if (m && slctr) {
m = m.querySelector(slctr);
}
return m;
};
var cePolyfill = window.CustomElements && !CustomElements.useNative;
if (cePolyfill) {
var ready = CustomElements.ready;
CustomElements.ready = true;
}
document.registerElement('dom-module', DomModule);
if (cePolyfill) {
CustomElements.ready = ready;
}
function forceDocumentUpgrade() {
if (cePolyfill) {
var script = document._currentScript || document.currentScript;
if (script) {
CustomElements.upgradeAll(script.ownerDocument);
}
}
}
}());
Polymer.Base._addFeature({
_prepIs: function () {
if (!this.is) {
var module = (document._currentScript || document.currentScript).parentNode;
if (module.localName === 'dom-module') {
var id = module.id || module.getAttribute('name') || module.getAttribute('is');
this.is = id;
}
}
}
});
Polymer.Base._addFeature({
behaviors: [],
_prepBehaviors: function () {
if (this.behaviors.length) {
this.behaviors = this._flattenBehaviorsList(this.behaviors);
}
this._prepAllBehaviors(this.behaviors);
},
_flattenBehaviorsList: function (behaviors) {
var flat = [];
behaviors.forEach(function (b) {
if (b instanceof Array) {
flat = flat.concat(this._flattenBehaviorsList(b));
} else if (b) {
flat.push(b);
} else {
this._warn(this._logf('_flattenBehaviorsList', 'behavior is null, check for missing or 404 import'));
}
}, this);
return flat;
},
_prepAllBehaviors: function (behaviors) {
for (var i = behaviors.length - 1; i >= 0; i--) {
this._mixinBehavior(behaviors[i]);
}
for (var i = 0, l = behaviors.length; i < l; i++) {
this._prepBehavior(behaviors[i]);
}
this._prepBehavior(this);
},
_mixinBehavior: function (b) {
Object.getOwnPropertyNames(b).forEach(function (n) {
switch (n) {
case 'hostAttributes':
case 'registered':
case 'properties':
case 'observers':
case 'listeners':
case 'created':
case 'attached':
case 'detached':
case 'attributeChanged':
case 'configure':
case 'ready':
break;
default:
if (!this.hasOwnProperty(n)) {
this.copyOwnProperty(n, b, this);
}
break;
}
}, this);
},
_doBehavior: function (name, args) {
this.behaviors.forEach(function (b) {
this._invokeBehavior(b, name, args);
}, this);
this._invokeBehavior(this, name, args);
},
_invokeBehavior: function (b, name, args) {
var fn = b[name];
if (fn) {
fn.apply(this, args || Polymer.nar);
}
},
_marshalBehaviors: function () {
this.behaviors.forEach(function (b) {
this._marshalBehavior(b);
}, this);
this._marshalBehavior(this);
}
});
Polymer.Base._addFeature({
_prepExtends: function () {
if (this.extends) {
this.__proto__ = this._getExtendedPrototype(this.extends);
}
},
_getExtendedPrototype: function (tag) {
return this._getExtendedNativePrototype(tag);
},
_nativePrototypes: {},
_getExtendedNativePrototype: function (tag) {
var p = this._nativePrototypes[tag];
if (!p) {
var np = this.getNativePrototype(tag);
p = this.extend(Object.create(np), Polymer.Base);
this._nativePrototypes[tag] = p;
}
return p;
},
getNativePrototype: function (tag) {
return Object.getPrototypeOf(document.createElement(tag));
}
});
Polymer.Base._addFeature({
_prepConstructor: function () {
this._factoryArgs = this.extends ? [
this.extends,
this.is
] : [this.is];
var ctor = function () {
return this._factory(arguments);
};
if (this.hasOwnProperty('extends')) {
ctor.extends = this.extends;
}
Object.defineProperty(this, 'constructor', {
value: ctor,
writable: true,
configurable: true
});
ctor.prototype = this;
},
_factory: function (args) {
var elt = document.createElement.apply(document, this._factoryArgs);
if (this.factoryImpl) {
this.factoryImpl.apply(elt, args);
}
return elt;
}
});
Polymer.nob = Object.create(null);
Polymer.Base._addFeature({
properties: {},
getPropertyInfo: function (property) {
var info = this._getPropertyInfo(property, this.properties);
if (!info) {
this.behaviors.some(function (b) {
return info = this._getPropertyInfo(property, b.properties);
}, this);
}
return info || Polymer.nob;
},
_getPropertyInfo: function (property, properties) {
var p = properties && properties[property];
if (typeof p === 'function') {
p = properties[property] = { type: p };
}
if (p) {
p.defined = true;
}
return p;
}
});
Polymer.CaseMap = {
_caseMap: {},
dashToCamelCase: function (dash) {
var mapped = Polymer.CaseMap._caseMap[dash];
if (mapped) {
return mapped;
}
if (dash.indexOf('-') < 0) {
return Polymer.CaseMap._caseMap[dash] = dash;
}
return Polymer.CaseMap._caseMap[dash] = dash.replace(/-([a-z])/g, function (m) {
return m[1].toUpperCase();
});
},
camelToDashCase: function (camel) {
var mapped = Polymer.CaseMap._caseMap[camel];
if (mapped) {
return mapped;
}
return Polymer.CaseMap._caseMap[camel] = camel.replace(/([a-z][A-Z])/g, function (g) {
return g[0] + '-' + g[1].toLowerCase();
});
}
};
Polymer.Base._addFeature({
_prepAttributes: function () {
this._aggregatedAttributes = {};
},
_addHostAttributes: function (attributes) {
if (attributes) {
this.mixin(this._aggregatedAttributes, attributes);
}
},
_marshalHostAttributes: function () {
this._applyAttributes(this, this._aggregatedAttributes);
},
_applyAttributes: function (node, attr$) {
for (var n in attr$) {
if (!this.hasAttribute(n) && n !== 'class') {
this.serializeValueToAttribute(attr$[n], n, this);
}
}
},
_marshalAttributes: function () {
this._takeAttributesToModel(this);
},
_takeAttributesToModel: function (model) {
for (var i = 0, l = this.attributes.length; i < l; i++) {
this._setAttributeToProperty(model, this.attributes[i].name);
}
},
_setAttributeToProperty: function (model, attrName) {
if (!this._serializing) {
var propName = Polymer.CaseMap.dashToCamelCase(attrName);
var info = this.getPropertyInfo(propName);
if (info.defined || this._propertyEffects && this._propertyEffects[propName]) {
var val = this.getAttribute(attrName);
model[propName] = this.deserialize(val, info.type);
}
}
},
_serializing: false,
reflectPropertyToAttribute: function (name) {
this._serializing = true;
this.serializeValueToAttribute(this[name], Polymer.CaseMap.camelToDashCase(name));
this._serializing = false;
},
serializeValueToAttribute: function (value, attribute, node) {
var str = this.serialize(value);
(node || this)[str === undefined ? 'removeAttribute' : 'setAttribute'](attribute, str);
},
deserialize: function (value, type) {
switch (type) {
case Number:
value = Number(value);
break;
case Boolean:
value = value !== null;
break;
case Object:
try {
value = JSON.parse(value);
} catch (x) {
}
break;
case Array:
try {
value = JSON.parse(value);
} catch (x) {
value = null;
console.warn('Polymer::Attributes: couldn`t decode Array as JSON');
}
break;
case Date:
value = new Date(value);
break;
case String:
default:
break;
}
return value;
},
serialize: function (value) {
switch (typeof value) {
case 'boolean':
return value ? '' : undefined;
case 'object':
if (value instanceof Date) {
return value;
} else if (value) {
try {
return JSON.stringify(value);
} catch (x) {
return '';
}
}
default:
return value != null ? value : undefined;
}
}
});
Polymer.Base._addFeature({
_setupDebouncers: function () {
this._debouncers = {};
},
debounce: function (jobName, callback, wait) {
this._debouncers[jobName] = Polymer.Debounce.call(this, this._debouncers[jobName], callback, wait);
},
isDebouncerActive: function (jobName) {
var debouncer = this._debouncers[jobName];
return debouncer && debouncer.finish;
},
flushDebouncer: function (jobName) {
var debouncer = this._debouncers[jobName];
if (debouncer) {
debouncer.complete();
}
},
cancelDebouncer: function (jobName) {
var debouncer = this._debouncers[jobName];
if (debouncer) {
debouncer.stop();
}
}
});
Polymer.version = '1.0.4';
Polymer.Base._addFeature({
_registerFeatures: function () {
this._prepIs();
this._prepAttributes();
this._prepBehaviors();
this._prepExtends();
this._prepConstructor();
},
_prepBehavior: function (b) {
this._addHostAttributes(b.hostAttributes);
},
_marshalBehavior: function (b) {
},
_initFeatures: function () {
this._marshalHostAttributes();
this._setupDebouncers();
this._marshalBehaviors();
}
});</script>
<script>Polymer.Base._addFeature({
_prepTemplate: function () {
this._template = this._template || Polymer.DomModule.import(this.is, 'template');
if (this._template && this._template.hasAttribute('is')) {
this._warn(this._logf('_prepTemplate', 'top-level Polymer template ' + 'must not be a type-extension, found', this._template, 'Move inside simple <template>.'));
}
},
_stampTemplate: function () {
if (this._template) {
this.root = this.instanceTemplate(this._template);
}
},
instanceTemplate: function (template) {
var dom = document.importNode(template._content || template.content, true);
return dom;
}
});
(function () {
var baseAttachedCallback = Polymer.Base.attachedCallback;
Polymer.Base._addFeature({
_hostStack: [],
ready: function () {
},
_pushHost: function (host) {
this.dataHost = host = host || Polymer.Base._hostStack[Polymer.Base._hostStack.length - 1];
if (host && host._clients) {
host._clients.push(this);
}
this._beginHost();
},
_beginHost: function () {
Polymer.Base._hostStack.push(this);
if (!this._clients) {
this._clients = [];
}
},
_popHost: function () {
Polymer.Base._hostStack.pop();
},
_tryReady: function () {
if (this._canReady()) {
this._ready();
}
},
_canReady: function () {
return !this.dataHost || this.dataHost._clientsReadied;
},
_ready: function () {
this._beforeClientsReady();
this._setupRoot();
this._readyClients();
this._afterClientsReady();
this._readySelf();
},
_readyClients: function () {
this._beginDistribute();
var c$ = this._clients;
for (var i = 0, l = c$.length, c; i < l && (c = c$[i]); i++) {
c._ready();
}
this._finishDistribute();
this._clientsReadied = true;
this._clients = null;
},
_readySelf: function () {
this._doBehavior('ready');
this._readied = true;
if (this._attachedPending) {
this._attachedPending = false;
this.attachedCallback();
}
},
_beforeClientsReady: function () {
},
_afterClientsReady: function () {
},
_beforeAttached: function () {
},
attachedCallback: function () {
if (this._readied) {
this._beforeAttached();
baseAttachedCallback.call(this);
} else {
this._attachedPending = true;
}
}
});
}());
Polymer.ArraySplice = function () {
function newSplice(index, removed, addedCount) {
return {
index: index,
removed: removed,
addedCount: addedCount
};
}
var EDIT_LEAVE = 0;
var EDIT_UPDATE = 1;
var EDIT_ADD = 2;
var EDIT_DELETE = 3;
function ArraySplice() {
}
ArraySplice.prototype = {
calcEditDistances: function (current, currentStart, currentEnd, old, oldStart, oldEnd) {
var rowCount = oldEnd - oldStart + 1;
var columnCount = currentEnd - currentStart + 1;
var distances = new Array(rowCount);
for (var i = 0; i < rowCount; i++) {
distances[i] = new Array(columnCount);
distances[i][0] = i;
}
for (var j = 0; j < columnCount; j++)
distances[0][j] = j;
for (var i = 1; i < rowCount; i++) {
for (var j = 1; j < columnCount; j++) {
if (this.equals(current[currentStart + j - 1], old[oldStart + i - 1]))
distances[i][j] = distances[i - 1][j - 1];
else {
var north = distances[i - 1][j] + 1;
var west = distances[i][j - 1] + 1;
distances[i][j] = north < west ? north : west;
}
}
}
return distances;
},
spliceOperationsFromEditDistances: function (distances) {
var i = distances.length - 1;
var j = distances[0].length - 1;
var current = distances[i][j];
var edits = [];
while (i > 0 || j > 0) {
if (i == 0) {
edits.push(EDIT_ADD);
j--;
continue;
}
if (j == 0) {
edits.push(EDIT_DELETE);
i--;
continue;
}
var northWest = distances[i - 1][j - 1];
var west = distances[i - 1][j];
var north = distances[i][j - 1];
var min;
if (west < north)
min = west < northWest ? west : northWest;
else
min = north < northWest ? north : northWest;
if (min == northWest) {
if (northWest == current) {
edits.push(EDIT_LEAVE);
} else {
edits.push(EDIT_UPDATE);
current = northWest;
}
i--;
j--;
} else if (min == west) {
edits.push(EDIT_DELETE);
i--;
current = west;
} else {
edits.push(EDIT_ADD);
j--;
current = north;
}
}
edits.reverse();
return edits;
},
calcSplices: function (current, currentStart, currentEnd, old, oldStart, oldEnd) {
var prefixCount = 0;
var suffixCount = 0;
var minLength = Math.min(currentEnd - currentStart, oldEnd - oldStart);
if (currentStart == 0 && oldStart == 0)
prefixCount = this.sharedPrefix(current, old, minLength);
if (currentEnd == current.length && oldEnd == old.length)
suffixCount = this.sharedSuffix(current, old, minLength - prefixCount);
currentStart += prefixCount;
oldStart += prefixCount;
currentEnd -= suffixCount;
oldEnd -= suffixCount;
if (currentEnd - currentStart == 0 && oldEnd - oldStart == 0)
return [];
if (currentStart == currentEnd) {
var splice = newSplice(currentStart, [], 0);
while (oldStart < oldEnd)
splice.removed.push(old[oldStart++]);
return [splice];
} else if (oldStart == oldEnd)
return [newSplice(currentStart, [], currentEnd - currentStart)];
var ops = this.spliceOperationsFromEditDistances(this.calcEditDistances(current, currentStart, currentEnd, old, oldStart, oldEnd));
var splice = undefined;
var splices = [];
var index = currentStart;
var oldIndex = oldStart;
for (var i = 0; i < ops.length; i++) {
switch (ops[i]) {
case EDIT_LEAVE:
if (splice) {
splices.push(splice);
splice = undefined;
}
index++;
oldIndex++;
break;
case EDIT_UPDATE:
if (!splice)
splice = newSplice(index, [], 0);
splice.addedCount++;
index++;
splice.removed.push(old[oldIndex]);
oldIndex++;
break;
case EDIT_ADD:
if (!splice)
splice = newSplice(index, [], 0);
splice.addedCount++;
index++;
break;
case EDIT_DELETE:
if (!splice)
splice = newSplice(index, [], 0);
splice.removed.push(old[oldIndex]);
oldIndex++;
break;
}
}
if (splice) {
splices.push(splice);
}
return splices;
},
sharedPrefix: function (current, old, searchLength) {
for (var i = 0; i < searchLength; i++)
if (!this.equals(current[i], old[i]))
return i;
return searchLength;
},
sharedSuffix: function (current, old, searchLength) {
var index1 = current.length;
var index2 = old.length;
var count = 0;
while (count < searchLength && this.equals(current[--index1], old[--index2]))
count++;
return count;
},
calculateSplices: function (current, previous) {
return this.calcSplices(current, 0, current.length, previous, 0, previous.length);
},
equals: function (currentValue, previousValue) {
return currentValue === previousValue;
}
};
return new ArraySplice();
}();
Polymer.EventApi = function () {
var Settings = Polymer.Settings;
var EventApi = function (event) {
this.event = event;
};
if (Settings.useShadow) {
EventApi.prototype = {
get rootTarget() {
return this.event.path[0];
},
get localTarget() {
return this.event.target;
},
get path() {
return this.event.path;
}
};
} else {
EventApi.prototype = {
get rootTarget() {
return this.event.target;
},
get localTarget() {
var current = this.event.currentTarget;
var currentRoot = current && Polymer.dom(current).getOwnerRoot();
var p$ = this.path;
for (var i = 0; i < p$.length; i++) {
if (Polymer.dom(p$[i]).getOwnerRoot() === currentRoot) {
return p$[i];
}
}
},
get path() {
if (!this.event._path) {
var path = [];
var o = this.rootTarget;
while (o) {
path.push(o);
o = Polymer.dom(o).parentNode || o.host;
}
path.push(window);
this.event._path = path;
}
return this.event._path;
}
};
}
var factory = function (event) {
if (!event.__eventApi) {
event.__eventApi = new EventApi(event);
}
return event.__eventApi;
};
return { factory: factory };
}();
Polymer.domInnerHTML = function () {
var escapeAttrRegExp = /[&\u00A0"]/g;
var escapeDataRegExp = /[&\u00A0<>]/g;
function escapeReplace(c) {
switch (c) {
case '&':
return '&amp;';
case '<':
return '&lt;';
case '>':
return '&gt;';
case '"':
return '&quot;';
case '\xA0':
return '&nbsp;';
}
}
function escapeAttr(s) {
return s.replace(escapeAttrRegExp, escapeReplace);
}
function escapeData(s) {
return s.replace(escapeDataRegExp, escapeReplace);
}
function makeSet(arr) {
var set = {};
for (var i = 0; i < arr.length; i++) {
set[arr[i]] = true;
}
return set;
}
var voidElements = makeSet([
'area',
'base',
'br',
'col',
'command',
'embed',
'hr',
'img',
'input',
'keygen',
'link',
'meta',
'param',
'source',
'track',
'wbr'
]);
var plaintextParents = makeSet([
'style',
'script',
'xmp',
'iframe',
'noembed',
'noframes',
'plaintext',
'noscript'
]);
function getOuterHTML(node, parentNode, composed) {
switch (node.nodeType) {
case Node.ELEMENT_NODE:
var tagName = node.localName;
var s = '<' + tagName;
var attrs = node.attributes;
for (var i = 0, attr; attr = attrs[i]; i++) {
s += ' ' + attr.name + '="' + escapeAttr(attr.value) + '"';
}
s += '>';
if (voidElements[tagName]) {
return s;
}
return s + getInnerHTML(node, composed) + '</' + tagName + '>';
case Node.TEXT_NODE:
var data = node.data;
if (parentNode && plaintextParents[parentNode.localName]) {
return data;
}
return escapeData(data);
case Node.COMMENT_NODE:
return '<!--' + node.data + '-->';
default:
console.error(node);
throw new Error('not implemented');
}
}
function getInnerHTML(node, composed) {
if (node instanceof HTMLTemplateElement)
node = node.content;
var s = '';
var c$ = Polymer.dom(node).childNodes;
c$ = composed ? node._composedChildren : c$;
for (var i = 0, l = c$.length, child; i < l && (child = c$[i]); i++) {
s += getOuterHTML(child, node, composed);
}
return s;
}
return { getInnerHTML: getInnerHTML };
}();
Polymer.DomApi = function () {
'use strict';
var Settings = Polymer.Settings;
var getInnerHTML = Polymer.domInnerHTML.getInnerHTML;
var nativeInsertBefore = Element.prototype.insertBefore;
var nativeRemoveChild = Element.prototype.removeChild;
var nativeAppendChild = Element.prototype.appendChild;
var dirtyRoots = [];
var DomApi = function (node) {
this.node = node;
if (this.patch) {
this.patch();
}
};
DomApi.prototype = {
flush: function () {
for (var i = 0, host; i < dirtyRoots.length; i++) {
host = dirtyRoots[i];
host.flushDebouncer('_distribute');
}
dirtyRoots = [];
},
_lazyDistribute: function (host) {
if (host.shadyRoot && host.shadyRoot._distributionClean) {
host.shadyRoot._distributionClean = false;
host.debounce('_distribute', host._distributeContent);
dirtyRoots.push(host);
}
},
appendChild: function (node) {
var handled;
this._removeNodeFromHost(node, true);
if (this._nodeIsInLogicalTree(this.node)) {
this._addLogicalInfo(node, this.node);
this._addNodeToHost(node);
handled = this._maybeDistribute(node, this.node);
}
if (!handled && !this._tryRemoveUndistributedNode(node)) {
var container = this.node._isShadyRoot ? this.node.host : this.node;
addToComposedParent(container, node);
nativeAppendChild.call(container, node);
}
return node;
},
insertBefore: function (node, ref_node) {
if (!ref_node) {
return this.appendChild(node);
}
var handled;
this._removeNodeFromHost(node, true);
if (this._nodeIsInLogicalTree(this.node)) {
saveLightChildrenIfNeeded(this.node);
var children = this.childNodes;
var index = children.indexOf(ref_node);
if (index < 0) {
throw Error('The ref_node to be inserted before is not a child ' + 'of this node');
}
this._addLogicalInfo(node, this.node, index);
this._addNodeToHost(node);
handled = this._maybeDistribute(node, this.node);
}
if (!handled && !this._tryRemoveUndistributedNode(node)) {
ref_node = ref_node.localName === CONTENT ? this._firstComposedNode(ref_node) : ref_node;
var container = this.node._isShadyRoot ? this.node.host : this.node;
addToComposedParent(container, node, ref_node);
nativeInsertBefore.call(container, node, ref_node);
}
return node;
},
removeChild: function (node) {
if (factory(node).parentNode !== this.node) {
console.warn('The node to be removed is not a child of this node', node);
}
var handled;
if (this._nodeIsInLogicalTree(this.node)) {
this._removeNodeFromHost(node);
handled = this._maybeDistribute(node, this.node);
}
if (!handled) {
var container = this.node._isShadyRoot ? this.node.host : this.node;
if (container === node.parentNode) {
removeFromComposedParent(container, node);
nativeRemoveChild.call(container, node);
}
}
return node;
},
replaceChild: function (node, ref_node) {
this.insertBefore(node, ref_node);
this.removeChild(ref_node);
return node;
},
getOwnerRoot: function () {
return this._ownerShadyRootForNode(this.node);
},
_ownerShadyRootForNode: function (node) {
if (!node) {
return;
}
if (node._ownerShadyRoot === undefined) {
var root;
if (node._isShadyRoot) {
root = node;
} else {
var parent = Polymer.dom(node).parentNode;
if (parent) {
root = parent._isShadyRoot ? parent : this._ownerShadyRootForNode(parent);
} else {
root = null;
}
}
node._ownerShadyRoot = root;
}
return node._ownerShadyRoot;
},
_maybeDistribute: function (node, parent) {
var fragContent = node.nodeType === Node.DOCUMENT_FRAGMENT_NODE && node.querySelector(CONTENT);
var wrappedContent = fragContent && fragContent.parentNode.nodeType !== Node.DOCUMENT_FRAGMENT_NODE;
var hasContent = fragContent || node.localName === CONTENT;
if (hasContent) {
var root = this._ownerShadyRootForNode(parent);
if (root) {
var host = root.host;
this._updateInsertionPoints(host);
this._lazyDistribute(host);
}
}
var parentNeedsDist = this._parentNeedsDistribution(parent);
if (parentNeedsDist) {
this._lazyDistribute(parent);
}
return parentNeedsDist || hasContent && !wrappedContent;
},
_tryRemoveUndistributedNode: function (node) {
if (this.node.shadyRoot) {
if (node.parentNode) {
nativeRemoveChild.call(node.parentNode, node);
}
return true;
}
},
_updateInsertionPoints: function (host) {
host.shadyRoot._insertionPoints = factory(host.shadyRoot).querySelectorAll(CONTENT);
},
_nodeIsInLogicalTree: function (node) {
return Boolean(node._lightParent || node._isShadyRoot || this._ownerShadyRootForNode(node) || node.shadyRoot);
},
_parentNeedsDistribution: function (parent) {
return parent && parent.shadyRoot && hasInsertionPoint(parent.shadyRoot);
},
_removeNodeFromHost: function (node, ensureComposedRemoval) {
var hostNeedsDist;
var root;
var parent = node._lightParent;
if (parent) {
root = this._ownerShadyRootForNode(node);
if (root) {
root.host._elementRemove(node);
hostNeedsDist = this._removeDistributedChildren(root, node);
}
this._removeLogicalInfo(node, node._lightParent);
}
this._removeOwnerShadyRoot(node);
if (root && hostNeedsDist) {
this._updateInsertionPoints(root.host);
this._lazyDistribute(root.host);
} else if (ensureComposedRemoval) {
removeFromComposedParent(parent || node.parentNode, node);
}
},
_removeDistributedChildren: function (root, container) {
var hostNeedsDist;
var ip$ = root._insertionPoints;
for (var i = 0; i < ip$.length; i++) {
var content = ip$[i];
if (this._contains(container, content)) {
var dc$ = factory(content).getDistributedNodes();
for (var j = 0; j < dc$.length; j++) {
hostNeedsDist = true;
var node = dc$[i];
var parent = node.parentNode;
if (parent) {
removeFromComposedParent(parent, node);
nativeRemoveChild.call(parent, node);
}
}
}
}
return hostNeedsDist;
},
_contains: function (container, node) {
while (node) {
if (node == container) {
return true;
}
node = factory(node).parentNode;
}
},
_addNodeToHost: function (node) {
var checkNode = node.nodeType === Node.DOCUMENT_FRAGMENT_NODE ? node.firstChild : node;
var root = this._ownerShadyRootForNode(checkNode);
if (root) {
root.host._elementAdd(node);
}
},
_addLogicalInfo: function (node, container, index) {
saveLightChildrenIfNeeded(container);
var children = factory(container).childNodes;
index = index === undefined ? children.length : index;
if (node.nodeType === Node.DOCUMENT_FRAGMENT_NODE) {
var c$ = Array.prototype.slice.call(node.childNodes);
for (var i = 0, n; i < c$.length && (n = c$[i]); i++) {
children.splice(index++, 0, n);
n._lightParent = container;
}
} else {
children.splice(index, 0, node);
node._lightParent = container;
}
},
_removeLogicalInfo: function (node, container) {
var children = factory(container).childNodes;
var index = children.indexOf(node);
if (index < 0 || container !== node._lightParent) {
throw Error('The node to be removed is not a child of this node');
}
children.splice(index, 1);
node._lightParent = null;
},
_removeOwnerShadyRoot: function (node) {
var hasCachedRoot = factory(node).getOwnerRoot() !== undefined;
if (hasCachedRoot) {
var c$ = factory(node).childNodes;
for (var i = 0, l = c$.length, n; i < l && (n = c$[i]); i++) {
this._removeOwnerShadyRoot(n);
}
}
node._ownerShadyRoot = undefined;
},
_firstComposedNode: function (content) {
var n$ = factory(content).getDistributedNodes();
for (var i = 0, l = n$.length, n, p$; i < l && (n = n$[i]); i++) {
p$ = factory(n).getDestinationInsertionPoints();
if (p$[p$.length - 1] === content) {
return n;
}
}
},
querySelector: function (selector) {
return this.querySelectorAll(selector)[0];
},
querySelectorAll: function (selector) {
return this._query(function (n) {
return matchesSelector.call(n, selector);
}, this.node);
},
_query: function (matcher, node) {
node = node || this.node;
var list = [];
this._queryElements(factory(node).childNodes, matcher, list);
return list;
},
_queryElements: function (elements, matcher, list) {
for (var i = 0, l = elements.length, c; i < l && (c = elements[i]); i++) {
if (c.nodeType === Node.ELEMENT_NODE) {
this._queryElement(c, matcher, list);
}
}
},
_queryElement: function (node, matcher, list) {
if (matcher(node)) {
list.push(node);
}
this._queryElements(factory(node).childNodes, matcher, list);
},
getDestinationInsertionPoints: function () {
return this.node._destinationInsertionPoints || [];
},
getDistributedNodes: function () {
return this.node._distributedNodes || [];
},
queryDistributedElements: function (selector) {
var c$ = this.childNodes;
var list = [];
this._distributedFilter(selector, c$, list);
for (var i = 0, l = c$.length, c; i < l && (c = c$[i]); i++) {
if (c.localName === CONTENT) {
this._distributedFilter(selector, factory(c).getDistributedNodes(), list);
}
}
return list;
},
_distributedFilter: function (selector, list, results) {
results = results || [];
for (var i = 0, l = list.length, d; i < l && (d = list[i]); i++) {
if (d.nodeType === Node.ELEMENT_NODE && d.localName !== CONTENT && matchesSelector.call(d, selector)) {
results.push(d);
}
}
return results;
},
_clear: function () {
while (this.childNodes.length) {
this.removeChild(this.childNodes[0]);
}
},
setAttribute: function (name, value) {
this.node.setAttribute(name, value);
this._distributeParent();
},
removeAttribute: function (name) {
this.node.removeAttribute(name);
this._distributeParent();
},
_distributeParent: function () {
if (this._parentNeedsDistribution(this.parentNode)) {
this._lazyDistribute(this.parentNode);
}
}
};
Object.defineProperty(DomApi.prototype, 'classList', {
get: function () {
if (!this._classList) {
this._classList = new DomApi.ClassList(this);
}
return this._classList;
},
configurable: true
});
DomApi.ClassList = function (host) {
this.domApi = host;
this.node = host.node;
};
DomApi.ClassList.prototype = {
add: function () {
this.node.classList.add.apply(this.node.classList, arguments);
this.domApi._distributeParent();
},
remove: function () {
this.node.classList.remove.apply(this.node.classList, arguments);
this.domApi._distributeParent();
},
toggle: function () {
this.node.classList.toggle.apply(this.node.classList, arguments);
this.domApi._distributeParent();
}
};
if (!Settings.useShadow) {
Object.defineProperties(DomApi.prototype, {
childNodes: {
get: function () {
var c$ = getLightChildren(this.node);
return Array.isArray(c$) ? c$ : Array.prototype.slice.call(c$);
},
configurable: true
},
children: {
get: function () {
return Array.prototype.filter.call(this.childNodes, function (n) {
return n.nodeType === Node.ELEMENT_NODE;
});
},
configurable: true
},
parentNode: {
get: function () {
return this.node._lightParent || (this.node.__patched ? this.node._composedParent : this.node.parentNode);
},
configurable: true
},
firstChild: {
get: function () {
return this.childNodes[0];
},
configurable: true
},
lastChild: {
get: function () {
var c$ = this.childNodes;
return c$[c$.length - 1];
},
configurable: true
},
nextSibling: {
get: function () {
var c$ = this.parentNode && factory(this.parentNode).childNodes;
if (c$) {
return c$[Array.prototype.indexOf.call(c$, this.node) + 1];
}
},
configurable: true
},
previousSibling: {
get: function () {
var c$ = this.parentNode && factory(this.parentNode).childNodes;
if (c$) {
return c$[Array.prototype.indexOf.call(c$, this.node) - 1];
}
},
configurable: true
},
firstElementChild: {
get: function () {
return this.children[0];
},
configurable: true
},
lastElementChild: {
get: function () {
var c$ = this.children;
return c$[c$.length - 1];
},
configurable: true
},
nextElementSibling: {
get: function () {
var c$ = this.parentNode && factory(this.parentNode).children;
if (c$) {
return c$[Array.prototype.indexOf.call(c$, this.node) + 1];
}
},
configurable: true
},
previousElementSibling: {
get: function () {
var c$ = this.parentNode && factory(this.parentNode).children;
if (c$) {
return c$[Array.prototype.indexOf.call(c$, this.node) - 1];
}
},
configurable: true
},
textContent: {
get: function () {
if (this.node.nodeType === Node.TEXT_NODE) {
return this.node.textContent;
} else {
return Array.prototype.map.call(this.childNodes, function (c) {
return c.textContent;
}).join('');
}
},
set: function (text) {
this._clear();
if (text) {
this.appendChild(document.createTextNode(text));
}
},
configurable: true
},
innerHTML: {
get: function () {
if (this.node.nodeType === Node.TEXT_NODE) {
return null;
} else {
return getInnerHTML(this.node);
}
},
set: function (text) {
if (this.node.nodeType !== Node.TEXT_NODE) {
this._clear();
var d = document.createElement('div');
d.innerHTML = text;
for (var e = d.firstChild; e; e = e.nextSibling) {
this.appendChild(e);
}
}
},
configurable: true
}
});
DomApi.prototype._getComposedInnerHTML = function () {
return getInnerHTML(this.node, true);
};
} else {
DomApi.prototype.querySelectorAll = function (selector) {
return Array.prototype.slice.call(this.node.querySelectorAll(selector));
};
DomApi.prototype.getOwnerRoot = function () {
var n = this.node;
while (n) {
if (n.nodeType === Node.DOCUMENT_FRAGMENT_NODE && n.host) {
return n;
}
n = n.parentNode;
}
};
DomApi.prototype.getDestinationInsertionPoints = function () {
var n$ = this.node.getDestinationInsertionPoints();
return n$ ? Array.prototype.slice.call(n$) : [];
};
DomApi.prototype.getDistributedNodes = function () {
var n$ = this.node.getDistributedNodes();
return n$ ? Array.prototype.slice.call(n$) : [];
};
DomApi.prototype._distributeParent = function () {
};
Object.defineProperties(DomApi.prototype, {
childNodes: {
get: function () {
return Array.prototype.slice.call(this.node.childNodes);
},
configurable: true
},
children: {
get: function () {
return Array.prototype.slice.call(this.node.children);
},
configurable: true
},
textContent: {
get: function () {
return this.node.textContent;
},
set: function (value) {
return this.node.textContent = value;
},
configurable: true
},
innerHTML: {
get: function () {
return this.node.innerHTML;
},
set: function (value) {
return this.node.innerHTML = value;
},
configurable: true
}
});
var forwards = [
'parentNode',
'firstChild',
'lastChild',
'nextSibling',
'previousSibling',
'firstElementChild',
'lastElementChild',
'nextElementSibling',
'previousElementSibling'
];
forwards.forEach(function (name) {
Object.defineProperty(DomApi.prototype, name, {
get: function () {
return this.node[name];
},
configurable: true
});
});
}
var CONTENT = 'content';
var factory = function (node, patch) {
node = node || document;
if (!node.__domApi) {
node.__domApi = new DomApi(node, patch);
}
return node.__domApi;
};
Polymer.dom = function (obj, patch) {
if (obj instanceof Event) {
return Polymer.EventApi.factory(obj);
} else {
return factory(obj, patch);
}
};
Polymer.dom.flush = DomApi.prototype.flush;
function getLightChildren(node) {
var children = node._lightChildren;
return children ? children : node.childNodes;
}
function getComposedChildren(node) {
if (!node._composedChildren) {
node._composedChildren = Array.prototype.slice.call(node.childNodes);
}
return node._composedChildren;
}
function addToComposedParent(parent, node, ref_node) {
var children = getComposedChildren(parent);
var i = ref_node ? children.indexOf(ref_node) : -1;
if (node.nodeType === Node.DOCUMENT_FRAGMENT_NODE) {
var fragChildren = getComposedChildren(node);
for (var j = 0; j < fragChildren.length; j++) {
addNodeToComposedChildren(fragChildren[j], parent, children, i + j);
}
node._composedChildren = null;
} else {
addNodeToComposedChildren(node, parent, children, i);
}
}
function addNodeToComposedChildren(node, parent, children, i) {
node._composedParent = parent;
children.splice(i >= 0 ? i : children.length, 0, node);
}
function removeFromComposedParent(parent, node) {
node._composedParent = null;
if (parent) {
var children = getComposedChildren(parent);
var i = children.indexOf(node);
if (i >= 0) {
children.splice(i, 1);
}
}
}
function saveLightChildrenIfNeeded(node) {
if (!node._lightChildren) {
var c$ = Array.prototype.slice.call(node.childNodes);
for (var i = 0, l = c$.length, child; i < l && (child = c$[i]); i++) {
child._lightParent = child._lightParent || node;
}
node._lightChildren = c$;
}
}
function hasInsertionPoint(root) {
return Boolean(root._insertionPoints.length);
}
var p = Element.prototype;
var matchesSelector = p.matches || p.matchesSelector || p.mozMatchesSelector || p.msMatchesSelector || p.oMatchesSelector || p.webkitMatchesSelector;
return {
getLightChildren: getLightChildren,
getComposedChildren: getComposedChildren,
removeFromComposedParent: removeFromComposedParent,
saveLightChildrenIfNeeded: saveLightChildrenIfNeeded,
matchesSelector: matchesSelector,
hasInsertionPoint: hasInsertionPoint,
ctor: DomApi,
factory: factory
};
}();
(function () {
Polymer.Base._addFeature({
_prepShady: function () {
this._useContent = this._useContent || Boolean(this._template);
if (this._useContent) {
this._template._hasInsertionPoint = this._template.content.querySelector('content');
}
},
_poolContent: function () {
if (this._useContent) {
saveLightChildrenIfNeeded(this);
}
},
_setupRoot: function () {
if (this._useContent) {
this._createLocalRoot();
if (!this.dataHost) {
upgradeLightChildren(this._lightChildren);
}
}
},
_createLocalRoot: function () {
this.shadyRoot = this.root;
this.shadyRoot._distributionClean = false;
this.shadyRoot._isShadyRoot = true;
this.shadyRoot._dirtyRoots = [];
this.shadyRoot._insertionPoints = this._template._hasInsertionPoint ? this.shadyRoot.querySelectorAll('content') : [];
saveLightChildrenIfNeeded(this.shadyRoot);
this.shadyRoot.host = this;
},
get domHost() {
var root = Polymer.dom(this).getOwnerRoot();
return root && root.host;
},
distributeContent: function (updateInsertionPoints) {
if (this.shadyRoot) {
var dom = Polymer.dom(this);
if (updateInsertionPoints) {
dom._updateInsertionPoints(this);
}
var host = getTopDistributingHost(this);
dom._lazyDistribute(host);
}
},
_distributeContent: function () {
if (this._useContent && !this.shadyRoot._distributionClean) {
this._beginDistribute();
this._distributeDirtyRoots();
this._finishDistribute();
}
},
_beginDistribute: function () {
if (this._useContent && hasInsertionPoint(this.shadyRoot)) {
this._resetDistribution();
this._distributePool(this.shadyRoot, this._collectPool());
}
},
_distributeDirtyRoots: function () {
var c$ = this.shadyRoot._dirtyRoots;
for (var i = 0, l = c$.length, c; i < l && (c = c$[i]); i++) {
c._distributeContent();
}
this.shadyRoot._dirtyRoots = [];
},
_finishDistribute: function () {
if (this._useContent) {
if (hasInsertionPoint(this.shadyRoot)) {
this._composeTree();
} else {
if (!this.shadyRoot._hasDistributed) {
this.textContent = '';
this._composedChildren = null;
this.appendChild(this.shadyRoot);
} else {
var children = this._composeNode(this);
this._updateChildNodes(this, children);
}
}
this.shadyRoot._hasDistributed = true;
this.shadyRoot._distributionClean = true;
}
},
elementMatches: function (selector, node) {
node = node || this;
return matchesSelector.call(node, selector);
},
_resetDistribution: function () {
var children = getLightChildren(this);
for (var i = 0; i < children.length; i++) {
var child = children[i];
if (child._destinationInsertionPoints) {
child._destinationInsertionPoints = undefined;
}
if (isInsertionPoint(child)) {
clearDistributedDestinationInsertionPoints(child);
}
}
var root = this.shadyRoot;
var p$ = root._insertionPoints;
for (var j = 0; j < p$.length; j++) {
p$[j]._distributedNodes = [];
}
},
_collectPool: function () {
var pool = [];
var children = getLightChildren(this);
for (var i = 0; i < children.length; i++) {
var child = children[i];
if (isInsertionPoint(child)) {
pool.push.apply(pool, child._distributedNodes);
} else {
pool.push(child);
}
}
return pool;
},
_distributePool: function (node, pool) {
var p$ = node._insertionPoints;
for (var i = 0, l = p$.length, p; i < l && (p = p$[i]); i++) {
this._distributeInsertionPoint(p, pool);
maybeRedistributeParent(p, this);
}
},
_distributeInsertionPoint: function (content, pool) {
var anyDistributed = false;
for (var i = 0, l = pool.length, node; i < l; i++) {
node = pool[i];
if (!node) {
continue;
}
if (this._matchesContentSelect(node, content)) {
distributeNodeInto(node, content);
pool[i] = undefined;
anyDistributed = true;
}
}
if (!anyDistributed) {
var children = getLightChildren(content);
for (var j = 0; j < children.length; j++) {
distributeNodeInto(children[j], content);
}
}
},
_composeTree: function () {
this._updateChildNodes(this, this._composeNode(this));
var p$ = this.shadyRoot._insertionPoints;
for (var i = 0, l = p$.length, p, parent; i < l && (p = p$[i]); i++) {
parent = p._lightParent || p.parentNode;
if (!parent._useContent && parent !== this && parent !== this.shadyRoot) {
this._updateChildNodes(parent, this._composeNode(parent));
}
}
},
_composeNode: function (node) {
var children = [];
var c$ = getLightChildren(node.shadyRoot || node);
for (var i = 0; i < c$.length; i++) {
var child = c$[i];
if (isInsertionPoint(child)) {
var distributedNodes = child._distributedNodes;
for (var j = 0; j < distributedNodes.length; j++) {
var distributedNode = distributedNodes[j];
if (isFinalDestination(child, distributedNode)) {
children.push(distributedNode);
}
}
} else {
children.push(child);
}
}
return children;
},
_updateChildNodes: function (container, children) {
var composed = getComposedChildren(container);
var splices = Polymer.ArraySplice.calculateSplices(children, composed);
for (var i = 0, d = 0, s; i < splices.length && (s = splices[i]); i++) {
for (var j = 0, n; j < s.removed.length && (n = s.removed[j]); j++) {
remove(n);
composed.splice(s.index + d, 1);
}
d -= s.addedCount;
}
for (var i = 0, s, next; i < splices.length && (s = splices[i]); i++) {
next = composed[s.index];
for (var j = s.index, n; j < s.index + s.addedCount; j++) {
n = children[j];
insertBefore(container, n, next);
composed.splice(j, 0, n);
}
}
},
_matchesContentSelect: function (node, contentElement) {
var select = contentElement.getAttribute('select');
if (!select) {
return true;
}
select = select.trim();
if (!select) {
return true;
}
if (!(node instanceof Element)) {
return false;
}
var validSelectors = /^(:not\()?[*.#[a-zA-Z_|]/;
if (!validSelectors.test(select)) {
return false;
}
return this.elementMatches(select, node);
},
_elementAdd: function () {
},
_elementRemove: function () {
}
});
var saveLightChildrenIfNeeded = Polymer.DomApi.saveLightChildrenIfNeeded;
var getLightChildren = Polymer.DomApi.getLightChildren;
var matchesSelector = Polymer.DomApi.matchesSelector;
var hasInsertionPoint = Polymer.DomApi.hasInsertionPoint;
var getComposedChildren = Polymer.DomApi.getComposedChildren;
var removeFromComposedParent = Polymer.DomApi.removeFromComposedParent;
function distributeNodeInto(child, insertionPoint) {
insertionPoint._distributedNodes.push(child);
var points = child._destinationInsertionPoints;
if (!points) {
child._destinationInsertionPoints = [insertionPoint];
} else {
points.push(insertionPoint);
}
}
function clearDistributedDestinationInsertionPoints(content) {
var e$ = content._distributedNodes;
if (e$) {
for (var i = 0; i < e$.length; i++) {
var d = e$[i]._destinationInsertionPoints;
if (d) {
d.splice(d.indexOf(content) + 1, d.length);
}
}
}
}
function maybeRedistributeParent(content, host) {
var parent = content._lightParent;
if (parent && parent.shadyRoot && hasInsertionPoint(parent.shadyRoot) && parent.shadyRoot._distributionClean) {
parent.shadyRoot._distributionClean = false;
host.shadyRoot._dirtyRoots.push(parent);
}
}
function isFinalDestination(insertionPoint, node) {
var points = node._destinationInsertionPoints;
return points && points[points.length - 1] === insertionPoint;
}
function isInsertionPoint(node) {
return node.localName == 'content';
}
var nativeInsertBefore = Element.prototype.insertBefore;
var nativeRemoveChild = Element.prototype.removeChild;
function insertBefore(parentNode, newChild, refChild) {
var newChildParent = getComposedParent(newChild);
if (newChildParent !== parentNode) {
removeFromComposedParent(newChildParent, newChild);
}
remove(newChild);
saveLightChildrenIfNeeded(parentNode);
nativeInsertBefore.call(parentNode, newChild, refChild || null);
newChild._composedParent = parentNode;
}
function remove(node) {
var parentNode = getComposedParent(node);
if (parentNode) {
saveLightChildrenIfNeeded(parentNode);
node._composedParent = null;
nativeRemoveChild.call(parentNode, node);
}
}
function getComposedParent(node) {
return node.__patched ? node._composedParent : node.parentNode;
}
function getTopDistributingHost(host) {
while (host && hostNeedsRedistribution(host)) {
host = host.domHost;
}
return host;
}
function hostNeedsRedistribution(host) {
var c$ = Polymer.dom(host).children;
for (var i = 0, c; i < c$.length; i++) {
c = c$[i];
if (c.localName === 'content') {
return host.domHost;
}
}
}
var needsUpgrade = window.CustomElements && !CustomElements.useNative;
function upgradeLightChildren(children) {
if (needsUpgrade && children) {
for (var i = 0; i < children.length; i++) {
CustomElements.upgrade(children[i]);
}
}
}
}());
if (Polymer.Settings.useShadow) {
Polymer.Base._addFeature({
_poolContent: function () {
},
_beginDistribute: function () {
},
distributeContent: function () {
},
_distributeContent: function () {
},
_finishDistribute: function () {
},
_createLocalRoot: function () {
this.createShadowRoot();
this.shadowRoot.appendChild(this.root);
this.root = this.shadowRoot;
}
});
}
Polymer.DomModule = document.createElement('dom-module');
Polymer.Base._addFeature({
_registerFeatures: function () {
this._prepIs();
this._prepAttributes();
this._prepBehaviors();
this._prepExtends();
this._prepConstructor();
this._prepTemplate();
this._prepShady();
},
_prepBehavior: function (b) {
this._addHostAttributes(b.hostAttributes);
},
_initFeatures: function () {
this._poolContent();
this._pushHost();
this._stampTemplate();
this._popHost();
this._marshalHostAttributes();
this._setupDebouncers();
this._marshalBehaviors();
this._tryReady();
},
_marshalBehavior: function (b) {
}
});</script>
<script>Polymer.nar = [];
Polymer.Annotations = {
parseAnnotations: function (template) {
var list = [];
var content = template._content || template.content;
this._parseNodeAnnotations(content, list);
return list;
},
_parseNodeAnnotations: function (node, list) {
return node.nodeType === Node.TEXT_NODE ? this._parseTextNodeAnnotation(node, list) : this._parseElementAnnotations(node, list);
},
_testEscape: function (value) {
var escape = value.slice(0, 2);
if (escape === '{{' || escape === '[[') {
return escape;
}
},
_parseTextNodeAnnotation: function (node, list) {
var v = node.textContent;
var escape = this._testEscape(v);
if (escape) {
node.textContent = ' ';
var annote = {
bindings: [{
kind: 'text',
mode: escape[0],
value: v.slice(2, -2).trim()
}]
};
list.push(annote);
return annote;
}
},
_parseElementAnnotations: function (element, list) {
var annote = {
bindings: [],
events: []
};
this._parseChildNodesAnnotations(element, annote, list);
if (element.attributes) {
this._parseNodeAttributeAnnotations(element, annote, list);
if (this.prepElement) {
this.prepElement(element);
}
}
if (annote.bindings.length || annote.events.length || annote.id) {
list.push(annote);
}
return annote;
},
_parseChildNodesAnnotations: function (root, annote, list, callback) {
if (root.firstChild) {
for (var i = 0, node = root.firstChild; node; node = node.nextSibling, i++) {
if (node.localName === 'template' && !node.hasAttribute('preserve-content')) {
this._parseTemplate(node, i, list, annote);
}
var childAnnotation = this._parseNodeAnnotations(node, list, callback);
if (childAnnotation) {
childAnnotation.parent = annote;
childAnnotation.index = i;
}
}
}
},
_parseTemplate: function (node, index, list, parent) {
var content = document.createDocumentFragment();
content._notes = this.parseAnnotations(node);
content.appendChild(node.content);
list.push({
bindings: Polymer.nar,
events: Polymer.nar,
templateContent: content,
parent: parent,
index: index
});
},
_parseNodeAttributeAnnotations: function (node, annotation) {
for (var i = node.attributes.length - 1, a; a = node.attributes[i]; i--) {
var n = a.name, v = a.value;
if (n === 'id' && !this._testEscape(v)) {
annotation.id = v;
} else if (n.slice(0, 3) === 'on-') {
node.removeAttribute(n);
annotation.events.push({
name: n.slice(3),
value: v
});
} else {
var b = this._parseNodeAttributeAnnotation(node, n, v);
if (b) {
annotation.bindings.push(b);
}
}
}
},
_parseNodeAttributeAnnotation: function (node, n, v) {
var escape = this._testEscape(v);
if (escape) {
var customEvent;
var name = n;
var mode = escape[0];
v = v.slice(2, -2).trim();
var not = false;
if (v[0] == '!') {
v = v.substring(1);
not = true;
}
var kind = 'property';
if (n[n.length - 1] == '$') {
name = n.slice(0, -1);
kind = 'attribute';
}
var notifyEvent, colon;
if (mode == '{' && (colon = v.indexOf('::')) > 0) {
notifyEvent = v.substring(colon + 2);
v = v.substring(0, colon);
customEvent = true;
}
if (node.localName == 'input' && n == 'value') {
node.setAttribute(n, '');
}
node.removeAttribute(n);
if (kind === 'property') {
name = Polymer.CaseMap.dashToCamelCase(name);
}
return {
kind: kind,
mode: mode,
name: name,
value: v,
negate: not,
event: notifyEvent,
customEvent: customEvent
};
}
},
_localSubTree: function (node, host) {
return node === host ? node.childNodes : node._lightChildren || node.childNodes;
},
findAnnotatedNode: function (root, annote) {
var parent = annote.parent && Polymer.Annotations.findAnnotatedNode(root, annote.parent);
return !parent ? root : Polymer.Annotations._localSubTree(parent, root)[annote.index];
}
};
(function () {
function resolveCss(cssText, ownerDocument) {
return cssText.replace(CSS_URL_RX, function (m, pre, url, post) {
return pre + '\'' + resolve(url.replace(/["']/g, ''), ownerDocument) + '\'' + post;
});
}
function resolveAttrs(element, ownerDocument) {
for (var name in URL_ATTRS) {
var a$ = URL_ATTRS[name];
for (var i = 0, l = a$.length, a, at, v; i < l && (a = a$[i]); i++) {
if (name === '*' || element.localName === name) {
at = element.attributes[a];
v = at && at.value;
if (v && v.search(BINDING_RX) < 0) {
at.value = a === 'style' ? resolveCss(v, ownerDocument) : resolve(v, ownerDocument);
}
}
}
}
}
function resolve(url, ownerDocument) {
if (url && url[0] === '#') {
return url;
}
var resolver = getUrlResolver(ownerDocument);
resolver.href = url;
return resolver.href || url;
}
var tempDoc;
var tempDocBase;
function resolveUrl(url, baseUri) {
if (!tempDoc) {
tempDoc = document.implementation.createHTMLDocument('temp');
tempDocBase = tempDoc.createElement('base');
tempDoc.head.appendChild(tempDocBase);
}
tempDocBase.href = baseUri;
return resolve(url, tempDoc);
}
function getUrlResolver(ownerDocument) {
return ownerDocument.__urlResolver || (ownerDocument.__urlResolver = ownerDocument.createElement('a'));
}
var CSS_URL_RX = /(url\()([^)]*)(\))/g;
var URL_ATTRS = {
'*': [
'href',
'src',
'style',
'url'
],
form: ['action']
};
var BINDING_RX = /\{\{|\[\[/;
Polymer.ResolveUrl = {
resolveCss: resolveCss,
resolveAttrs: resolveAttrs,
resolveUrl: resolveUrl
};
}());
Polymer.Base._addFeature({
_prepAnnotations: function () {
if (!this._template) {
this._notes = [];
} else {
Polymer.Annotations.prepElement = this._prepElement.bind(this);
this._notes = Polymer.Annotations.parseAnnotations(this._template);
this._processAnnotations(this._notes);
Polymer.Annotations.prepElement = null;
}
},
_processAnnotations: function (notes) {
for (var i = 0; i < notes.length; i++) {
var note = notes[i];
for (var j = 0; j < note.bindings.length; j++) {
var b = note.bindings[j];
b.signature = this._parseMethod(b.value);
if (!b.signature) {
b.model = this._modelForPath(b.value);
}
}
if (note.templateContent) {
this._processAnnotations(note.templateContent._notes);
var pp = note.templateContent._parentProps = this._discoverTemplateParentProps(note.templateContent._notes);
var bindings = [];
for (var prop in pp) {
bindings.push({
index: note.index,
kind: 'property',
mode: '{',
name: '_parent_' + prop,
model: prop,
value: prop
});
}
note.bindings = note.bindings.concat(bindings);
}
}
},
_discoverTemplateParentProps: function (notes) {
var pp = {};
notes.forEach(function (n) {
n.bindings.forEach(function (b) {
if (b.signature) {
var args = b.signature.args;
for (var k = 0; k < args.length; k++) {
pp[args[k].model] = true;
}
} else {
pp[b.model] = true;
}
});
if (n.templateContent) {
var tpp = n.templateContent._parentProps;
Polymer.Base.mixin(pp, tpp);
}
});
return pp;
},
_prepElement: function (element) {
Polymer.ResolveUrl.resolveAttrs(element, this._template.ownerDocument);
},
_findAnnotatedNode: Polymer.Annotations.findAnnotatedNode,
_marshalAnnotationReferences: function () {
if (this._template) {
this._marshalIdNodes();
this._marshalAnnotatedNodes();
this._marshalAnnotatedListeners();
}
},
_configureAnnotationReferences: function () {
this._configureTemplateContent();
},
_configureTemplateContent: function () {
this._notes.forEach(function (note, i) {
if (note.templateContent) {
this._nodes[i]._content = note.templateContent;
}
}, this);
},
_marshalIdNodes: function () {
this.$ = {};
this._notes.forEach(function (a) {
if (a.id) {
this.$[a.id] = this._findAnnotatedNode(this.root, a);
}
}, this);
},
_marshalAnnotatedNodes: function () {
if (this._nodes) {
this._nodes = this._nodes.map(function (a) {
return this._findAnnotatedNode(this.root, a);
}, this);
}
},
_marshalAnnotatedListeners: function () {
this._notes.forEach(function (a) {
if (a.events && a.events.length) {
var node = this._findAnnotatedNode(this.root, a);
a.events.forEach(function (e) {
this.listen(node, e.name, e.value);
}, this);
}
}, this);
}
});
Polymer.Base._addFeature({
listeners: {},
_listenListeners: function (listeners) {
var node, name, key;
for (key in listeners) {
if (key.indexOf('.') < 0) {
node = this;
name = key;
} else {
name = key.split('.');
node = this.$[name[0]];
name = name[1];
}
this.listen(node, name, listeners[key]);
}
},
listen: function (node, eventName, methodName) {
this._listen(node, eventName, this._createEventHandler(node, eventName, methodName));
},
_boundListenerKey: function (eventName, methodName) {
return eventName + ':' + methodName;
},
_recordEventHandler: function (host, eventName, target, methodName, handler) {
var hbl = host.__boundListeners;
if (!hbl) {
hbl = host.__boundListeners = new WeakMap();
}
var bl = hbl.get(target);
if (!bl) {
bl = {};
hbl.set(target, bl);
}
var key = this._boundListenerKey(eventName, methodName);
bl[key] = handler;
},
_recallEventHandler: function (host, eventName, target, methodName) {
var hbl = host.__boundListeners;
if (!hbl) {
return;
}
var bl = hbl.get(target);
if (!bl) {
return;
}
var key = this._boundListenerKey(eventName, methodName);
return bl[key];
},
_createEventHandler: function (node, eventName, methodName) {
var host = this;
var handler = function (e) {
if (host[methodName]) {
host[methodName](e, e.detail);
} else {
host._warn(host._logf('_createEventHandler', 'listener method `' + methodName + '` not defined'));
}
};
this._recordEventHandler(host, eventName, node, methodName, handler);
return handler;
},
unlisten: function (node, eventName, methodName) {
var handler = this._recallEventHandler(this, eventName, node, methodName);
if (handler) {
this._unlisten(node, eventName, handler);
}
},
_listen: function (node, eventName, handler) {
node.addEventListener(eventName, handler);
},
_unlisten: function (node, eventName, handler) {
node.removeEventListener(eventName, handler);
}
});
(function () {
'use strict';
var HAS_NATIVE_TA = typeof document.head.style.touchAction === 'string';
var GESTURE_KEY = '__polymerGestures';
var HANDLED_OBJ = '__polymerGesturesHandled';
var TOUCH_ACTION = '__polymerGesturesTouchAction';
var TAP_DISTANCE = 25;
var TRACK_DISTANCE = 5;
var TRACK_LENGTH = 2;
var MOUSE_TIMEOUT = 2500;
var MOUSE_EVENTS = [
'mousedown',
'mousemove',
'mouseup',
'click'
];
var mouseCanceller = function (mouseEvent) {
mouseEvent[HANDLED_OBJ] = { skip: true };
if (mouseEvent.type === 'click') {
var path = Polymer.dom(mouseEvent).path;
for (var i = 0; i < path.length; i++) {
if (path[i] === POINTERSTATE.mouse.target) {
return;
}
}
mouseEvent.preventDefault();
mouseEvent.stopPropagation();
}
};
function setupTeardownMouseCanceller(setup) {
for (var i = 0, en; i < MOUSE_EVENTS.length; i++) {
en = MOUSE_EVENTS[i];
if (setup) {
document.addEventListener(en, mouseCanceller, true);
} else {
document.removeEventListener(en, mouseCanceller, true);
}
}
}
function ignoreMouse() {
if (!POINTERSTATE.mouse.mouseIgnoreJob) {
setupTeardownMouseCanceller(true);
}
var unset = function () {
setupTeardownMouseCanceller();
POINTERSTATE.mouse.target = null;
POINTERSTATE.mouse.mouseIgnoreJob = null;
};
POINTERSTATE.mouse.mouseIgnoreJob = Polymer.Debounce(POINTERSTATE.mouse.mouseIgnoreJob, unset, MOUSE_TIMEOUT);
}
var POINTERSTATE = {
mouse: {
target: null,
mouseIgnoreJob: null
},
touch: {
x: 0,
y: 0,
id: -1,
scrollDecided: false
}
};
function firstTouchAction(ev) {
var path = Polymer.dom(ev).path;
var ta = 'auto';
for (var i = 0, n; i < path.length; i++) {
n = path[i];
if (n[TOUCH_ACTION]) {
ta = n[TOUCH_ACTION];
break;
}
}
return ta;
}
var Gestures = {
gestures: {},
recognizers: [],
deepTargetFind: function (x, y) {
var node = document.elementFromPoint(x, y);
var next = node;
while (next && next.shadowRoot) {
next = next.shadowRoot.elementFromPoint(x, y);
if (next) {
node = next;
}
}
return node;
},
handleNative: function (ev) {
var handled;
var type = ev.type;
var node = ev.currentTarget;
var gobj = node[GESTURE_KEY];
var gs = gobj[type];
if (!gs) {
return;
}
if (!ev[HANDLED_OBJ]) {
ev[HANDLED_OBJ] = {};
if (type.slice(0, 5) === 'touch') {
var t = ev.changedTouches[0];
if (type === 'touchstart') {
if (ev.touches.length === 1) {
POINTERSTATE.touch.id = t.identifier;
}
}
if (POINTERSTATE.touch.id !== t.identifier) {
return;
}
if (!HAS_NATIVE_TA) {
if (type === 'touchstart' || type === 'touchmove') {
Gestures.handleTouchAction(ev);
}
}
if (type === 'touchend') {
POINTERSTATE.mouse.target = Polymer.dom(ev).rootTarget;
ignoreMouse(true);
}
}
}
handled = ev[HANDLED_OBJ];
if (handled.skip) {
return;
}
var recognizers = Gestures.recognizers;
for (var i = 0, r; i < recognizers.length; i++) {
r = recognizers[i];
if (gs[r.name] && !handled[r.name]) {
handled[r.name] = true;
r[type](ev);
}
}
},
handleTouchAction: function (ev) {
var t = ev.changedTouches[0];
var type = ev.type;
if (type === 'touchstart') {
POINTERSTATE.touch.x = t.clientX;
POINTERSTATE.touch.y = t.clientY;
POINTERSTATE.touch.scrollDecided = false;
} else if (type === 'touchmove') {
if (POINTERSTATE.touch.scrollDecided) {
return;
}
POINTERSTATE.touch.scrollDecided = true;
var ta = firstTouchAction(ev);
var prevent = false;
var dx = Math.abs(POINTERSTATE.touch.x - t.clientX);
var dy = Math.abs(POINTERSTATE.touch.y - t.clientY);
if (!ev.cancelable) {
} else if (ta === 'none') {
prevent = true;
} else if (ta === 'pan-x') {
prevent = dy > dx;
} else if (ta === 'pan-y') {
prevent = dx > dy;
}
if (prevent) {
ev.preventDefault();
}
}
},
add: function (node, evType, handler) {
var recognizer = this.gestures[evType];
var deps = recognizer.deps;
var name = recognizer.name;
var gobj = node[GESTURE_KEY];
if (!gobj) {
node[GESTURE_KEY] = gobj = {};
}
for (var i = 0, dep, gd; i < deps.length; i++) {
dep = deps[i];
gd = gobj[dep];
if (!gd) {
gobj[dep] = gd = {};
node.addEventListener(dep, this.handleNative);
}
gd[name] = (gd[name] || 0) + 1;
}
node.addEventListener(evType, handler);
if (recognizer.touchAction) {
this.setTouchAction(node, recognizer.touchAction);
}
},
remove: function (node, evType, handler) {
var recognizer = this.gestures[evType];
var deps = recognizer.deps;
var name = recognizer.name;
var gobj = node[GESTURE_KEY];
if (gobj) {
for (var i = 0, dep, gd; i < deps.length; i++) {
dep = deps[i];
gd = gobj[dep];
if (gd && gd[name]) {
gd[name] = (gd[name] || 1) - 1;
if (gd[name] === 0) {
node.removeEventListener(dep, this.handleNative);
}
}
}
}
node.removeEventListener(evType, handler);
},
register: function (recog) {
this.recognizers.push(recog);
for (var i = 0; i < recog.emits.length; i++) {
this.gestures[recog.emits[i]] = recog;
}
},
findRecognizerByEvent: function (evName) {
for (var i = 0, r; i < this.recognizers.length; i++) {
r = this.recognizers[i];
for (var j = 0, n; j < r.emits.length; j++) {
n = r.emits[j];
if (n === evName) {
return r;
}
}
}
return null;
},
setTouchAction: function (node, value) {
if (HAS_NATIVE_TA) {
node.style.touchAction = value;
}
node[TOUCH_ACTION] = value;
},
fire: function (target, type, detail) {
var ev = Polymer.Base.fire(type, detail, {
node: target,
bubbles: true,
cancelable: true
});
if (ev.defaultPrevented) {
var se = detail.sourceEvent;
if (se && se.preventDefault) {
se.preventDefault();
}
}
},
prevent: function (evName) {
var recognizer = this.findRecognizerByEvent(evName);
if (recognizer.info) {
recognizer.info.prevent = true;
}
}
};
Gestures.register({
name: 'downup',
deps: [
'mousedown',
'touchstart',
'touchend'
],
emits: [
'down',
'up'
],
mousedown: function (e) {
var t = e.currentTarget;
var self = this;
var upfn = function upfn(e) {
self.fire('up', t, e);
document.removeEventListener('mouseup', upfn);
};
document.addEventListener('mouseup', upfn);
this.fire('down', t, e);
},
touchstart: function (e) {
this.fire('down', e.currentTarget, e.changedTouches[0]);
},
touchend: function (e) {
this.fire('up', e.currentTarget, e.changedTouches[0]);
},
fire: function (type, target, event) {
var self = this;
Gestures.fire(target, type, {
x: event.clientX,
y: event.clientY,
sourceEvent: event,
prevent: Gestures.prevent.bind(Gestures)
});
}
});
Gestures.register({
name: 'track',
touchAction: 'none',
deps: [
'mousedown',
'touchstart',
'touchmove',
'touchend'
],
emits: ['track'],
info: {
x: 0,
y: 0,
state: 'start',
started: false,
moves: [],
addMove: function (move) {
if (this.moves.length > TRACK_LENGTH) {
this.moves.shift();
}
this.moves.push(move);
},
prevent: false
},
clearInfo: function () {
this.info.state = 'start';
this.info.started = false;
this.info.moves = [];
this.info.x = 0;
this.info.y = 0;
this.info.prevent = false;
},
hasMovedEnough: function (x, y) {
if (this.info.prevent) {
return false;
}
if (this.info.started) {
return true;
}
var dx = Math.abs(this.info.x - x);
var dy = Math.abs(this.info.y - y);
return dx >= TRACK_DISTANCE || dy >= TRACK_DISTANCE;
},
mousedown: function (e) {
var t = e.currentTarget;
var self = this;
var movefn = function movefn(e) {
var x = e.clientX, y = e.clientY;
if (self.hasMovedEnough(x, y)) {
self.info.state = self.info.started ? e.type === 'mouseup' ? 'end' : 'track' : 'start';
self.info.addMove({
x: x,
y: y
});
self.fire(t, e);
self.info.started = true;
}
};
var upfn = function upfn(e) {
if (self.info.started) {
Gestures.prevent('tap');
movefn(e);
}
self.clearInfo();
document.removeEventListener('mousemove', movefn);
document.removeEventListener('mouseup', upfn);
};
document.addEventListener('mousemove', movefn);
document.addEventListener('mouseup', upfn);
this.info.x = e.clientX;
this.info.y = e.clientY;
},
touchstart: function (e) {
var ct = e.changedTouches[0];
this.info.x = ct.clientX;
this.info.y = ct.clientY;
},
touchmove: function (e) {
var t = e.currentTarget;
var ct = e.changedTouches[0];
var x = ct.clientX, y = ct.clientY;
if (this.hasMovedEnough(x, y)) {
this.info.addMove({
x: x,
y: y
});
this.fire(t, ct);
this.info.state = 'track';
this.info.started = true;
}
},
touchend: function (e) {
var t = e.currentTarget;
var ct = e.changedTouches[0];
if (this.info.started) {
Gestures.prevent('tap');
this.info.state = 'end';
this.info.addMove({
x: ct.clientX,
y: ct.clientY
});
this.fire(t, ct);
}
this.clearInfo();
},
fire: function (target, touch) {
var secondlast = this.info.moves[this.info.moves.length - 2];
var lastmove = this.info.moves[this.info.moves.length - 1];
var dx = lastmove.x - this.info.x;
var dy = lastmove.y - this.info.y;
var ddx, ddy = 0;
if (secondlast) {
ddx = lastmove.x - secondlast.x;
ddy = lastmove.y - secondlast.y;
}
return Gestures.fire(target, 'track', {
state: this.info.state,
x: touch.clientX,
y: touch.clientY,
dx: dx,
dy: dy,
ddx: ddx,
ddy: ddy,
sourceEvent: touch,
hover: function () {
return Gestures.deepTargetFind(touch.clientX, touch.clientY);
}
});
}
});
Gestures.register({
name: 'tap',
deps: [
'mousedown',
'click',
'touchstart',
'touchend'
],
emits: ['tap'],
info: {
x: NaN,
y: NaN,
prevent: false
},
reset: function () {
this.info.x = NaN;
this.info.y = NaN;
this.info.prevent = false;
},
save: function (e) {
this.info.x = e.clientX;
this.info.y = e.clientY;
},
mousedown: function (e) {
this.save(e);
},
click: function (e) {
this.forward(e);
},
touchstart: function (e) {
this.save(e.changedTouches[0]);
},
touchend: function (e) {
this.forward(e.changedTouches[0]);
},
forward: function (e) {
var dx = Math.abs(e.clientX - this.info.x);
var dy = Math.abs(e.clientY - this.info.y);
if (isNaN(dx) || isNaN(dy) || dx <= TAP_DISTANCE && dy <= TAP_DISTANCE) {
if (!this.info.prevent) {
Gestures.fire(e.target, 'tap', {
x: e.clientX,
y: e.clientY,
sourceEvent: e
});
}
}
this.reset();
}
});
var DIRECTION_MAP = {
x: 'pan-x',
y: 'pan-y',
none: 'none',
all: 'auto'
};
Polymer.Base._addFeature({
_listen: function (node, eventName, handler) {
if (Gestures.gestures[eventName]) {
Gestures.add(node, eventName, handler);
} else {
node.addEventListener(eventName, handler);
}
},
_unlisten: function (node, eventName, handler) {
if (Gestures.gestures[eventName]) {
Gestures.remove(node, eventName, handler);
} else {
node.removeEventListener(eventName, handler);
}
},
setScrollDirection: function (direction, node) {
node = node || this;
Gestures.setTouchAction(node, DIRECTION_MAP[direction] || 'auto');
}
});
Polymer.Gestures = Gestures;
}());
Polymer.Async = function () {
var currVal = 0;
var lastVal = 0;
var callbacks = [];
var twiddle = document.createTextNode('');
function runAsync(callback, waitTime) {
if (waitTime > 0) {
return ~setTimeout(callback, waitTime);
} else {
twiddle.textContent = currVal++;
callbacks.push(callback);
return currVal - 1;
}
}
function cancelAsync(handle) {
if (handle < 0) {
clearTimeout(~handle);
} else {
var idx = handle - lastVal;
if (idx >= 0) {
if (!callbacks[idx]) {
throw 'invalid async handle: ' + handle;
}
callbacks[idx] = null;
}
}
}
function atEndOfMicrotask() {
var len = callbacks.length;
for (var i = 0; i < len; i++) {
var cb = callbacks[i];
if (cb) {
cb();
}
}
callbacks.splice(0, len);
lastVal += len;
}
new (window.MutationObserver || JsMutationObserver)(atEndOfMicrotask).observe(twiddle, { characterData: true });
return {
run: runAsync,
cancel: cancelAsync
};
}();
Polymer.Debounce = function () {
var Async = Polymer.Async;
var Debouncer = function (context) {
this.context = context;
this.boundComplete = this.complete.bind(this);
};
Debouncer.prototype = {
go: function (callback, wait) {
var h;
this.finish = function () {
Async.cancel(h);
};
h = Async.run(this.boundComplete, wait);
this.callback = callback;
},
stop: function () {
if (this.finish) {
this.finish();
this.finish = null;
}
},
complete: function () {
if (this.finish) {
this.stop();
this.callback.call(this.context);
}
}
};
function debounce(debouncer, callback, wait) {
if (debouncer) {
debouncer.stop();
} else {
debouncer = new Debouncer(this);
}
debouncer.go(callback, wait);
return debouncer;
}
return debounce;
}();
Polymer.Base._addFeature({
$$: function (slctr) {
return Polymer.dom(this.root).querySelector(slctr);
},
toggleClass: function (name, bool, node) {
node = node || this;
if (arguments.length == 1) {
bool = !node.classList.contains(name);
}
if (bool) {
Polymer.dom(node).classList.add(name);
} else {
Polymer.dom(node).classList.remove(name);
}
},
toggleAttribute: function (name, bool, node) {
node = node || this;
if (arguments.length == 1) {
bool = !node.hasAttribute(name);
}
if (bool) {
Polymer.dom(node).setAttribute(name, '');
} else {
Polymer.dom(node).removeAttribute(name);
}
},
classFollows: function (name, toElement, fromElement) {
if (fromElement) {
Polymer.dom(fromElement).classList.remove(name);
}
if (toElement) {
Polymer.dom(toElement).classList.add(name);
}
},
attributeFollows: function (name, toElement, fromElement) {
if (fromElement) {
Polymer.dom(fromElement).removeAttribute(name);
}
if (toElement) {
Polymer.dom(toElement).setAttribute(name, '');
}
},
getContentChildNodes: function (slctr) {
return Polymer.dom(Polymer.dom(this.root).querySelector(slctr || 'content')).getDistributedNodes();
},
getContentChildren: function (slctr) {
return this.getContentChildNodes(slctr).filter(function (n) {
return n.nodeType === Node.ELEMENT_NODE;
});
},
fire: function (type, detail, options) {
options = options || Polymer.nob;
var node = options.node || this;
var detail = detail === null || detail === undefined ? Polymer.nob : detail;
var bubbles = options.bubbles === undefined ? true : options.bubbles;
var cancelable = Boolean(options.cancelable);
var event = new CustomEvent(type, {
bubbles: Boolean(bubbles),
cancelable: cancelable,
detail: detail
});
node.dispatchEvent(event);
return event;
},
async: function (callback, waitTime) {
return Polymer.Async.run(callback.bind(this), waitTime);
},
cancelAsync: function (handle) {
Polymer.Async.cancel(handle);
},
arrayDelete: function (path, item) {
var index;
if (Array.isArray(path)) {
index = path.indexOf(item);
if (index >= 0) {
return path.splice(index, 1);
}
} else {
var arr = this.get(path);
index = arr.indexOf(item);
if (index >= 0) {
return this.splice(path, index, 1);
}
}
},
transform: function (transform, node) {
node = node || this;
node.style.webkitTransform = transform;
node.style.transform = transform;
},
translate3d: function (x, y, z, node) {
node = node || this;
this.transform('translate3d(' + x + ',' + y + ',' + z + ')', node);
},
importHref: function (href, onload, onerror) {
var l = document.createElement('link');
l.rel = 'import';
l.href = href;
if (onload) {
l.onload = onload.bind(this);
}
if (onerror) {
l.onerror = onerror.bind(this);
}
document.head.appendChild(l);
return l;
},
create: function (tag, props) {
var elt = document.createElement(tag);
if (props) {
for (var n in props) {
elt[n] = props[n];
}
}
return elt;
},
mixin: function (target, source) {
for (var i in source) {
target[i] = source[i];
}
}
});
Polymer.Bind = {
prepareModel: function (model) {
model._propertyEffects = {};
model._bindListeners = [];
var api = this._modelApi;
for (var n in api) {
model[n] = api[n];
}
},
_modelApi: {
_notifyChange: function (property) {
var eventName = Polymer.CaseMap.camelToDashCase(property) + '-changed';
this.fire(eventName, { value: this[property] }, { bubbles: false });
},
_propertySet: function (property, value, effects) {
var old = this.__data__[property];
if (old !== value && (old === old || value === value)) {
this.__data__[property] = value;
if (typeof value == 'object') {
this._clearPath(property);
}
if (this._propertyChanged) {
this._propertyChanged(property, value, old);
}
if (effects) {
this._effectEffects(property, value, effects, old);
}
}
return old;
},
_effectEffects: function (property, value, effects, old) {
effects.forEach(function (fx) {
var fn = Polymer.Bind['_' + fx.kind + 'Effect'];
if (fn) {
fn.call(this, property, value, fx.effect, old);
}
}, this);
},
_clearPath: function (path) {
for (var prop in this.__data__) {
if (prop.indexOf(path + '.') === 0) {
this.__data__[prop] = undefined;
}
}
}
},
ensurePropertyEffects: function (model, property) {
var fx = model._propertyEffects[property];
if (!fx) {
fx = model._propertyEffects[property] = [];
}
return fx;
},
addPropertyEffect: function (model, property, kind, effect) {
var fx = this.ensurePropertyEffects(model, property);
fx.push({
kind: kind,
effect: effect
});
},
createBindings: function (model) {
var fx$ = model._propertyEffects;
if (fx$) {
for (var n in fx$) {
var fx = fx$[n];
fx.sort(this._sortPropertyEffects);
this._createAccessors(model, n, fx);
}
}
},
_sortPropertyEffects: function () {
var EFFECT_ORDER = {
'compute': 0,
'annotation': 1,
'computedAnnotation': 2,
'reflect': 3,
'notify': 4,
'observer': 5,
'complexObserver': 6,
'function': 7
};
return function (a, b) {
return EFFECT_ORDER[a.kind] - EFFECT_ORDER[b.kind];
};
}(),
_createAccessors: function (model, property, effects) {
var defun = {
get: function () {
return this.__data__[property];
}
};
var setter = function (value) {
this._propertySet(property, value, effects);
};
if (model.getPropertyInfo && model.getPropertyInfo(property).readOnly) {
model['_set' + this.upper(property)] = setter;
} else {
defun.set = setter;
}
Object.defineProperty(model, property, defun);
},
upper: function (name) {
return name[0].toUpperCase() + name.substring(1);
},
_addAnnotatedListener: function (model, index, property, path, event) {
var fn = this._notedListenerFactory(property, path, this._isStructured(path), this._isEventBogus);
var eventName = event || Polymer.CaseMap.camelToDashCase(property) + '-changed';
model._bindListeners.push({
index: index,
property: property,
path: path,
changedFn: fn,
event: eventName
});
},
_isStructured: function (path) {
return path.indexOf('.') > 0;
},
_isEventBogus: function (e, target) {
return e.path && e.path[0] !== target;
},
_notedListenerFactory: function (property, path, isStructured, bogusTest) {
return function (e, target) {
if (!bogusTest(e, target)) {
if (e.detail && e.detail.path) {
this.notifyPath(this._fixPath(path, property, e.detail.path), e.detail.value);
} else {
var value = target[property];
if (!isStructured) {
this[path] = target[property];
} else {
if (this.__data__[path] != value) {
this.set(path, value);
}
}
}
}
};
},
prepareInstance: function (inst) {
inst.__data__ = Object.create(null);
},
setupBindListeners: function (inst) {
inst._bindListeners.forEach(function (info) {
var node = inst._nodes[info.index];
node.addEventListener(info.event, inst._notifyListener.bind(inst, info.changedFn));
});
}
};
Polymer.Base.extend(Polymer.Bind, {
_shouldAddListener: function (effect) {
return effect.name && effect.mode === '{' && !effect.negate && effect.kind != 'attribute';
},
_annotationEffect: function (source, value, effect) {
if (source != effect.value) {
value = this.get(effect.value);
this.__data__[effect.value] = value;
}
var calc = effect.negate ? !value : value;
if (!effect.customEvent || this._nodes[effect.index][effect.name] !== calc) {
return this._applyEffectValue(calc, effect);
}
},
_reflectEffect: function (source) {
this.reflectPropertyToAttribute(source);
},
_notifyEffect: function (source) {
this._notifyChange(source);
},
_functionEffect: function (source, value, fn, old) {
fn.call(this, source, value, old);
},
_observerEffect: function (source, value, effect, old) {
var fn = this[effect.method];
if (fn) {
fn.call(this, value, old);
} else {
this._warn(this._logf('_observerEffect', 'observer method `' + effect.method + '` not defined'));
}
},
_complexObserverEffect: function (source, value, effect) {
var fn = this[effect.method];
if (fn) {
var args = Polymer.Bind._marshalArgs(this.__data__, effect, source, value);
if (args) {
fn.apply(this, args);
}
} else {
this._warn(this._logf('_complexObserverEffect', 'observer method `' + effect.method + '` not defined'));
}
},
_computeEffect: function (source, value, effect) {
var args = Polymer.Bind._marshalArgs(this.__data__, effect, source, value);
if (args) {
var fn = this[effect.method];
if (fn) {
this[effect.property] = fn.apply(this, args);
} else {
this._warn(this._logf('_computeEffect', 'compute method `' + effect.method + '` not defined'));
}
}
},
_annotatedComputationEffect: function (source, value, effect) {
var computedHost = this._rootDataHost || this;
var fn = computedHost[effect.method];
if (fn) {
var args = Polymer.Bind._marshalArgs(this.__data__, effect, source, value);
if (args) {
var computedvalue = fn.apply(computedHost, args);
if (effect.negate) {
computedvalue = !computedvalue;
}
this._applyEffectValue(computedvalue, effect);
}
} else {
computedHost._warn(computedHost._logf('_annotatedComputationEffect', 'compute method `' + effect.method + '` not defined'));
}
},
_marshalArgs: function (model, effect, path, value) {
var values = [];
var args = effect.args;
for (var i = 0, l = args.length; i < l; i++) {
var arg = args[i];
var name = arg.name;
var v;
if (arg.literal) {
v = arg.value;
} else if (arg.structured) {
v = Polymer.Base.get(name, model);
} else {
v = model[name];
}
if (args.length > 1 && v === undefined) {
return;
}
if (arg.wildcard) {
var baseChanged = name.indexOf(path + '.') === 0;
var matches = effect.trigger.name.indexOf(name) === 0 && !baseChanged;
values[i] = {
path: matches ? path : name,
value: matches ? value : v,
base: v
};
} else {
values[i] = v;
}
}
return values;
}
});
Polymer.Base._addFeature({
_addPropertyEffect: function (property, kind, effect) {
Polymer.Bind.addPropertyEffect(this, property, kind, effect);
},
_prepEffects: function () {
Polymer.Bind.prepareModel(this);
this._addAnnotationEffects(this._notes);
},
_prepBindings: function () {
Polymer.Bind.createBindings(this);
},
_addPropertyEffects: function (properties) {
if (properties) {
for (var p in properties) {
var prop = properties[p];
if (prop.observer) {
this._addObserverEffect(p, prop.observer);
}
if (prop.computed) {
this._addComputedEffect(p, prop.computed);
}
if (prop.notify) {
this._addPropertyEffect(p, 'notify');
}
if (prop.reflectToAttribute) {
this._addPropertyEffect(p, 'reflect');
}
if (prop.readOnly) {
Polymer.Bind.ensurePropertyEffects(this, p);
}
}
}
},
_addComputedEffect: function (name, expression) {
var sig = this._parseMethod(expression);
sig.args.forEach(function (arg) {
this._addPropertyEffect(arg.model, 'compute', {
method: sig.method,
args: sig.args,
trigger: arg,
property: name
});
}, this);
},
_addObserverEffect: function (property, observer) {
this._addPropertyEffect(property, 'observer', {
method: observer,
property: property
});
},
_addComplexObserverEffects: function (observers) {
if (observers) {
observers.forEach(function (observer) {
this._addComplexObserverEffect(observer);
}, this);
}
},
_addComplexObserverEffect: function (observer) {
var sig = this._parseMethod(observer);
sig.args.forEach(function (arg) {
this._addPropertyEffect(arg.model, 'complexObserver', {
method: sig.method,
args: sig.args,
trigger: arg
});
}, this);
},
_addAnnotationEffects: function (notes) {
this._nodes = [];
notes.forEach(function (note) {
var index = this._nodes.push(note) - 1;
note.bindings.forEach(function (binding) {
this._addAnnotationEffect(binding, index);
}, this);
}, this);
},
_addAnnotationEffect: function (note, index) {
if (Polymer.Bind._shouldAddListener(note)) {
Polymer.Bind._addAnnotatedListener(this, index, note.name, note.value, note.event);
}
if (note.signature) {
this._addAnnotatedComputationEffect(note, index);
} else {
note.index = index;
this._addPropertyEffect(note.model, 'annotation', note);
}
},
_addAnnotatedComputationEffect: function (note, index) {
var sig = note.signature;
if (sig.static) {
this.__addAnnotatedComputationEffect('__static__', index, note, sig, null);
} else {
sig.args.forEach(function (arg) {
if (!arg.literal) {
this.__addAnnotatedComputationEffect(arg.model, index, note, sig, arg);
}
}, this);
}
},
__addAnnotatedComputationEffect: function (property, index, note, sig, trigger) {
this._addPropertyEffect(property, 'annotatedComputation', {
index: index,
kind: note.kind,
property: note.name,
negate: note.negate,
method: sig.method,
args: sig.args,
trigger: trigger
});
},
_parseMethod: function (expression) {
var m = expression.match(/(\w*)\((.*)\)/);
if (m) {
var sig = {
method: m[1],
static: true
};
if (m[2].trim()) {
var args = m[2].replace(/\\,/g, '&comma;').split(',');
return this._parseArgs(args, sig);
} else {
sig.args = Polymer.nar;
return sig;
}
}
},
_parseArgs: function (argList, sig) {
sig.args = argList.map(function (rawArg) {
var arg = this._parseArg(rawArg);
if (!arg.literal) {
sig.static = false;
}
return arg;
}, this);
return sig;
},
_parseArg: function (rawArg) {
var arg = rawArg.trim().replace(/&comma;/g, ',').replace(/\\(.)/g, '$1');
var a = {
name: arg,
model: this._modelForPath(arg)
};
var fc = arg[0];
if (fc >= '0' && fc <= '9') {
fc = '#';
}
switch (fc) {
case '\'':
case '"':
a.value = arg.slice(1, -1);
a.literal = true;
break;
case '#':
a.value = Number(arg);
a.literal = true;
break;
}
if (!a.literal) {
a.structured = arg.indexOf('.') > 0;
if (a.structured) {
a.wildcard = arg.slice(-2) == '.*';
if (a.wildcard) {
a.name = arg.slice(0, -2);
}
}
}
return a;
},
_marshalInstanceEffects: function () {
Polymer.Bind.prepareInstance(this);
Polymer.Bind.setupBindListeners(this);
},
_applyEffectValue: function (value, info) {
var node = this._nodes[info.index];
var property = info.property || info.name || 'textContent';
if (info.kind == 'attribute') {
this.serializeValueToAttribute(value, property, node);
} else {
if (property === 'className') {
value = this._scopeElementClass(node, value);
}
if (property === 'textContent' || node.localName == 'input' && property == 'value') {
value = value == undefined ? '' : value;
}
return node[property] = value;
}
},
_executeStaticEffects: function () {
if (this._propertyEffects.__static__) {
this._effectEffects('__static__', null, this._propertyEffects.__static__);
}
}
});
Polymer.Base._addFeature({
_setupConfigure: function (initialConfig) {
this._config = initialConfig || {};
this._handlers = [];
},
_marshalAttributes: function () {
this._takeAttributesToModel(this._config);
},
_configValue: function (name, value) {
this._config[name] = value;
},
_beforeClientsReady: function () {
this._configure();
},
_configure: function () {
this._configureAnnotationReferences();
var config = {};
this.behaviors.forEach(function (b) {
this._configureProperties(b.properties, config);
}, this);
this._configureProperties(this.properties, config);
this._mixinConfigure(config, this._config);
this._config = config;
this._distributeConfig(this._config);
},
_configureProperties: function (properties, config) {
for (var i in properties) {
var c = properties[i];
if (c.value !== undefined) {
var value = c.value;
if (typeof value == 'function') {
value = value.call(this, this._config);
}
config[i] = value;
}
}
},
_mixinConfigure: function (a, b) {
for (var prop in b) {
if (!this.getPropertyInfo(prop).readOnly) {
a[prop] = b[prop];
}
}
},
_distributeConfig: function (config) {
var fx$ = this._propertyEffects;
if (fx$) {
for (var p in config) {
var fx = fx$[p];
if (fx) {
for (var i = 0, l = fx.length, x; i < l && (x = fx[i]); i++) {
if (x.kind === 'annotation') {
var node = this._nodes[x.effect.index];
if (node._configValue) {
var value = p === x.effect.value ? config[p] : this.get(x.effect.value, config);
node._configValue(x.effect.name, value);
}
}
}
}
}
}
},
_afterClientsReady: function () {
this._executeStaticEffects();
this._applyConfig(this._config);
this._flushHandlers();
},
_applyConfig: function (config) {
for (var n in config) {
if (this[n] === undefined) {
var effects = this._propertyEffects[n];
if (effects) {
this._propertySet(n, config[n], effects);
} else {
this[n] = config[n];
}
}
}
},
_notifyListener: function (fn, e) {
if (!this._clientsReadied) {
this._queueHandler([
fn,
e,
e.target
]);
} else {
return fn.call(this, e, e.target);
}
},
_queueHandler: function (args) {
this._handlers.push(args);
},
_flushHandlers: function () {
var h$ = this._handlers;
for (var i = 0, l = h$.length, h; i < l && (h = h$[i]); i++) {
h[0].call(this, h[1], h[2]);
}
}
});
(function () {
'use strict';
Polymer.Base._addFeature({
notifyPath: function (path, value, fromAbove) {
var old = this._propertySet(path, value);
if (old !== value && (old === old || value === value)) {
this._pathEffector(path, value);
if (!fromAbove) {
this._notifyPath(path, value);
}
}
},
_getPathParts: function (path) {
if (Array.isArray(path)) {
var parts = [];
for (var i = 0; i < path.length; i++) {
var args = path[i].toString().split('.');
for (var j = 0; j < args.length; j++) {
parts.push(args[j]);
}
}
return parts;
} else {
return path.toString().split('.');
}
},
set: function (path, value, root) {
var prop = root || this;
var parts = this._getPathParts(path);
var array;
var last = parts[parts.length - 1];
if (parts.length > 1) {
for (var i = 0; i < parts.length - 1; i++) {
prop = prop[parts[i]];
if (array) {
parts[i] = Polymer.Collection.get(array).getKey(prop);
}
if (!prop) {
return;
}
array = Array.isArray(prop) ? prop : null;
}
prop[last] = value;
if (!root) {
this.notifyPath(parts.join('.'), value);
}
} else {
prop[path] = value;
}
},
get: function (path, root) {
var prop = root || this;
var parts = this._getPathParts(path);
var last = parts.pop();
while (parts.length) {
prop = prop[parts.shift()];
if (!prop) {
return;
}
}
return prop[last];
},
_pathEffector: function (path, value) {
var model = this._modelForPath(path);
var fx$ = this._propertyEffects[model];
if (fx$) {
fx$.forEach(function (fx) {
var fxFn = this['_' + fx.kind + 'PathEffect'];
if (fxFn) {
fxFn.call(this, path, value, fx.effect);
}
}, this);
}
if (this._boundPaths) {
this._notifyBoundPaths(path, value);
}
},
_annotationPathEffect: function (path, value, effect) {
if (effect.value === path || effect.value.indexOf(path + '.') === 0) {
Polymer.Bind._annotationEffect.call(this, path, value, effect);
} else if (path.indexOf(effect.value + '.') === 0 && !effect.negate) {
var node = this._nodes[effect.index];
if (node && node.notifyPath) {
var p = this._fixPath(effect.name, effect.value, path);
node.notifyPath(p, value, true);
}
}
},
_complexObserverPathEffect: function (path, value, effect) {
if (this._pathMatchesEffect(path, effect)) {
Polymer.Bind._complexObserverEffect.call(this, path, value, effect);
}
},
_computePathEffect: function (path, value, effect) {
if (this._pathMatchesEffect(path, effect)) {
Polymer.Bind._computeEffect.call(this, path, value, effect);
}
},
_annotatedComputationPathEffect: function (path, value, effect) {
if (this._pathMatchesEffect(path, effect)) {
Polymer.Bind._annotatedComputationEffect.call(this, path, value, effect);
}
},
_pathMatchesEffect: function (path, effect) {
var effectArg = effect.trigger.name;
return effectArg == path || effectArg.indexOf(path + '.') === 0 || effect.trigger.wildcard && path.indexOf(effectArg) === 0;
},
linkPaths: function (to, from) {
this._boundPaths = this._boundPaths || {};
if (from) {
this._boundPaths[to] = from;
} else {
this.unbindPath(to);
}
},
unlinkPaths: function (path) {
if (this._boundPaths) {
delete this._boundPaths[path];
}
},
_notifyBoundPaths: function (path, value) {
var from, to;
for (var a in this._boundPaths) {
var b = this._boundPaths[a];
if (path.indexOf(a + '.') == 0) {
from = a;
to = b;
break;
}
if (path.indexOf(b + '.') == 0) {
from = b;
to = a;
break;
}
}
if (from && to) {
var p = this._fixPath(to, from, path);
this.notifyPath(p, value);
}
},
_fixPath: function (property, root, path) {
return property + path.slice(root.length);
},
_notifyPath: function (path, value) {
var rootName = this._modelForPath(path);
var dashCaseName = Polymer.CaseMap.camelToDashCase(rootName);
var eventName = dashCaseName + this._EVENT_CHANGED;
this.fire(eventName, {
path: path,
value: value
}, { bubbles: false });
},
_modelForPath: function (path) {
var dot = path.indexOf('.');
return dot < 0 ? path : path.slice(0, dot);
},
_EVENT_CHANGED: '-changed',
_notifySplice: function (array, path, index, added, removed) {
var splices = [{
index: index,
addedCount: added,
removed: removed,
object: array,
type: 'splice'
}];
var change = {
keySplices: Polymer.Collection.applySplices(array, splices),
indexSplices: splices
};
this.set(path + '.splices', change);
if (added != removed.length) {
this.notifyPath(path + '.length', array.length);
}
change.keySplices = null;
change.indexSplices = null;
},
push: function (path) {
var array = this.get(path);
var args = Array.prototype.slice.call(arguments, 1);
var len = array.length;
var ret = array.push.apply(array, args);
this._notifySplice(array, path, len, args.length, []);
return ret;
},
pop: function (path) {
var array = this.get(path);
var args = Array.prototype.slice.call(arguments, 1);
var rem = array.slice(-1);
var ret = array.pop.apply(array, args);
this._notifySplice(array, path, array.length, 0, rem);
return ret;
},
splice: function (path, start, deleteCount) {
var array = this.get(path);
var args = Array.prototype.slice.call(arguments, 1);
var rem = array.slice(start, start + deleteCount);
var ret = array.splice.apply(array, args);
this._notifySplice(array, path, start, args.length - 2, rem);
return ret;
},
shift: function (path) {
var array = this.get(path);
var args = Array.prototype.slice.call(arguments, 1);
var ret = array.shift.apply(array, args);
this._notifySplice(array, path, 0, 0, [ret]);
return ret;
},
unshift: function (path) {
var array = this.get(path);
var args = Array.prototype.slice.call(arguments, 1);
var ret = array.unshift.apply(array, args);
this._notifySplice(array, path, 0, args.length, []);
return ret;
}
});
}());
Polymer.Base._addFeature({
resolveUrl: function (url) {
var module = Polymer.DomModule.import(this.is);
var root = '';
if (module) {
var assetPath = module.getAttribute('assetpath') || '';
root = Polymer.ResolveUrl.resolveUrl(assetPath, module.ownerDocument.baseURI);
}
return Polymer.ResolveUrl.resolveUrl(url, root);
}
});
Polymer.CssParse = function () {
var api = {
parse: function (text) {
text = this._clean(text);
return this._parseCss(this._lex(text), text);
},
_clean: function (cssText) {
return cssText.replace(rx.comments, '').replace(rx.port, '');
},
_lex: function (text) {
var root = {
start: 0,
end: text.length
};
var n = root;
for (var i = 0, s = 0, l = text.length; i < l; i++) {
switch (text[i]) {
case this.OPEN_BRACE:
if (!n.rules) {
n.rules = [];
}
var p = n;
var previous = p.rules[p.rules.length - 1];
n = {
start: i + 1,
parent: p,
previous: previous
};
p.rules.push(n);
break;
case this.CLOSE_BRACE:
n.end = i + 1;
n = n.parent || root;
break;
}
}
return root;
},
_parseCss: function (node, text) {
var t = text.substring(node.start, node.end - 1);
node.parsedCssText = node.cssText = t.trim();
if (node.parent) {
var ss = node.previous ? node.previous.end : node.parent.start;
t = text.substring(ss, node.start - 1);
t = t.substring(t.lastIndexOf(';') + 1);
var s = node.parsedSelector = node.selector = t.trim();
node.atRule = s.indexOf(AT_START) === 0;
if (node.atRule) {
if (s.indexOf(MEDIA_START) === 0) {
node.type = this.types.MEDIA_RULE;
} else if (s.match(rx.keyframesRule)) {
node.type = this.types.KEYFRAMES_RULE;
}
} else {
if (s.indexOf(VAR_START) === 0) {
node.type = this.types.MIXIN_RULE;
} else {
node.type = this.types.STYLE_RULE;
}
}
}
var r$ = node.rules;
if (r$) {
for (var i = 0, l = r$.length, r; i < l && (r = r$[i]); i++) {
this._parseCss(r, text);
}
}
return node;
},
stringify: function (node, preserveProperties, text) {
text = text || '';
var cssText = '';
if (node.cssText || node.rules) {
var r$ = node.rules;
if (r$ && (preserveProperties || !hasMixinRules(r$))) {
for (var i = 0, l = r$.length, r; i < l && (r = r$[i]); i++) {
cssText = this.stringify(r, preserveProperties, cssText);
}
} else {
cssText = preserveProperties ? node.cssText : removeCustomProps(node.cssText);
cssText = cssText.trim();
if (cssText) {
cssText = ' ' + cssText + '\n';
}
}
}
if (cssText) {
if (node.selector) {
text += node.selector + ' ' + this.OPEN_BRACE + '\n';
}
text += cssText;
if (node.selector) {
text += this.CLOSE_BRACE + '\n\n';
}
}
return text;
},
types: {
STYLE_RULE: 1,
KEYFRAMES_RULE: 7,
MEDIA_RULE: 4,
MIXIN_RULE: 1000
},
OPEN_BRACE: '{',
CLOSE_BRACE: '}'
};
function hasMixinRules(rules) {
return rules[0].selector.indexOf(VAR_START) >= 0;
}
function removeCustomProps(cssText) {
return cssText.replace(rx.customProp, '').replace(rx.mixinProp, '').replace(rx.mixinApply, '').replace(rx.varApply, '');
}
var VAR_START = '--';
var MEDIA_START = '@media';
var AT_START = '@';
var rx = {
comments: /\/\*[^*]*\*+([^/*][^*]*\*+)*\//gim,
port: /@import[^;]*;/gim,
customProp: /(?:^|[\s;])--[^;{]*?:[^{};]*?;/gim,
mixinProp: /(?:^|[\s;])--[^;{]*?:[^{;]*?{[^}]*?};?/gim,
mixinApply: /@apply[\s]*\([^)]*?\)[\s]*;/gim,
varApply: /[^;:]*?:[^;]*var[^;]*;/gim,
keyframesRule: /^@[^\s]*keyframes/
};
return api;
}();
Polymer.StyleUtil = function () {
return {
MODULE_STYLES_SELECTOR: 'style, link[rel=import][type~=css]',
toCssText: function (rules, callback, preserveProperties) {
if (typeof rules === 'string') {
rules = this.parser.parse(rules);
}
if (callback) {
this.forEachStyleRule(rules, callback);
}
return this.parser.stringify(rules, preserveProperties);
},
forRulesInStyles: function (styles, callback) {
for (var i = 0, l = styles.length, s; i < l && (s = styles[i]); i++) {
this.forEachStyleRule(this.rulesForStyle(s), callback);
}
},
rulesForStyle: function (style) {
if (!style.__cssRules && style.textContent) {
style.__cssRules = this.parser.parse(style.textContent);
}
return style.__cssRules;
},
clearStyleRules: function (style) {
style.__cssRules = null;
},
forEachStyleRule: function (node, callback) {
var s = node.selector;
var skipRules = false;
if (node.type === this.ruleTypes.STYLE_RULE) {
callback(node);
} else if (node.type === this.ruleTypes.KEYFRAMES_RULE || node.type === this.ruleTypes.MIXIN_RULE) {
skipRules = true;
}
var r$ = node.rules;
if (r$ && !skipRules) {
for (var i = 0, l = r$.length, r; i < l && (r = r$[i]); i++) {
this.forEachStyleRule(r, callback);
}
}
},
applyCss: function (cssText, moniker, target, afterNode) {
var style = document.createElement('style');
if (moniker) {
style.setAttribute('scope', moniker);
}
style.textContent = cssText;
target = target || document.head;
if (!afterNode) {
var n$ = target.querySelectorAll('style[scope]');
afterNode = n$[n$.length - 1];
}
target.insertBefore(style, afterNode && afterNode.nextSibling || target.firstChild);
return style;
},
cssFromModule: function (moduleId) {
var m = Polymer.DomModule.import(moduleId);
if (m && !m._cssText) {
var cssText = '';
var e$ = Array.prototype.slice.call(m.querySelectorAll(this.MODULE_STYLES_SELECTOR));
for (var i = 0, e; i < e$.length; i++) {
e = e$[i];
if (e.localName === 'style') {
e = e.__appliedElement || e;
e.parentNode.removeChild(e);
} else {
e = e.import && e.import.body;
}
if (e) {
cssText += Polymer.ResolveUrl.resolveCss(e.textContent, e.ownerDocument);
}
}
m._cssText = cssText;
}
return m && m._cssText || '';
},
parser: Polymer.CssParse,
ruleTypes: Polymer.CssParse.types
};
}();
Polymer.StyleTransformer = function () {
var nativeShadow = Polymer.Settings.useNativeShadow;
var styleUtil = Polymer.StyleUtil;
var api = {
dom: function (node, scope, useAttr, shouldRemoveScope) {
this._transformDom(node, scope || '', useAttr, shouldRemoveScope);
},
_transformDom: function (node, selector, useAttr, shouldRemoveScope) {
if (node.setAttribute) {
this.element(node, selector, useAttr, shouldRemoveScope);
}
var c$ = Polymer.dom(node).childNodes;
for (var i = 0; i < c$.length; i++) {
this._transformDom(c$[i], selector, useAttr, shouldRemoveScope);
}
},
element: function (element, scope, useAttr, shouldRemoveScope) {
if (useAttr) {
if (shouldRemoveScope) {
element.removeAttribute(SCOPE_NAME);
} else {
element.setAttribute(SCOPE_NAME, scope);
}
} else {
if (scope) {
if (element.classList) {
if (shouldRemoveScope) {
element.classList.remove(SCOPE_NAME);
element.classList.remove(scope);
} else {
element.classList.add(SCOPE_NAME);
element.classList.add(scope);
}
} else if (element.getAttribute) {
var c = element.getAttribute(CLASS);
if (shouldRemoveScope) {
if (c) {
element.setAttribute(CLASS, c.replace(SCOPE_NAME, '').replace(scope, ''));
}
} else {
element.setAttribute(CLASS, c + (c ? ' ' : '') + SCOPE_NAME + ' ' + scope);
}
}
}
}
},
elementStyles: function (element, callback) {
var styles = element._styles;
var cssText = '';
for (var i = 0, l = styles.length, s, text; i < l && (s = styles[i]); i++) {
var rules = styleUtil.rulesForStyle(s);
cssText += nativeShadow ? styleUtil.toCssText(rules, callback) : this.css(rules, element.is, element.extends, callback, element._scopeCssViaAttr) + '\n\n';
}
return cssText.trim();
},
css: function (rules, scope, ext, callback, useAttr) {
var hostScope = this._calcHostScope(scope, ext);
scope = this._calcElementScope(scope, useAttr);
var self = this;
return styleUtil.toCssText(rules, function (rule) {
if (!rule.isScoped) {
self.rule(rule, scope, hostScope);
rule.isScoped = true;
}
if (callback) {
callback(rule, scope, hostScope);
}
});
},
_calcElementScope: function (scope, useAttr) {
if (scope) {
return useAttr ? CSS_ATTR_PREFIX + scope + CSS_ATTR_SUFFIX : CSS_CLASS_PREFIX + scope;
} else {
return '';
}
},
_calcHostScope: function (scope, ext) {
return ext ? '[is=' + scope + ']' : scope;
},
rule: function (rule, scope, hostScope) {
this._transformRule(rule, this._transformComplexSelector, scope, hostScope);
},
_transformRule: function (rule, transformer, scope, hostScope) {
var p$ = rule.selector.split(COMPLEX_SELECTOR_SEP);
for (var i = 0, l = p$.length, p; i < l && (p = p$[i]); i++) {
p$[i] = transformer.call(this, p, scope, hostScope);
}
rule.selector = p$.join(COMPLEX_SELECTOR_SEP);
},
_transformComplexSelector: function (selector, scope, hostScope) {
var stop = false;
var self = this;
selector = selector.replace(SIMPLE_SELECTOR_SEP, function (m, c, s) {
if (!stop) {
var o = self._transformCompoundSelector(s, c, scope, hostScope);
if (o.stop) {
stop = true;
}
c = o.combinator;
s = o.value;
} else {
s = s.replace(SCOPE_JUMP, ' ');
}
return c + s;
});
return selector;
},
_transformCompoundSelector: function (selector, combinator, scope, hostScope) {
var jumpIndex = selector.search(SCOPE_JUMP);
if (selector.indexOf(HOST) >= 0) {
selector = selector.replace(HOST_PAREN, function (m, host, paren) {
return hostScope + paren;
});
selector = selector.replace(HOST, hostScope);
} else if (jumpIndex !== 0) {
selector = scope ? this._transformSimpleSelector(selector, scope) : selector;
}
if (selector.indexOf(CONTENT) >= 0) {
combinator = '';
}
var stop;
if (jumpIndex >= 0) {
selector = selector.replace(SCOPE_JUMP, ' ');
stop = true;
}
return {
value: selector,
combinator: combinator,
stop: stop
};
},
_transformSimpleSelector: function (selector, scope) {
var p$ = selector.split(PSEUDO_PREFIX);
p$[0] += scope;
return p$.join(PSEUDO_PREFIX);
},
documentRule: function (rule) {
rule.selector = rule.parsedSelector;
this.normalizeRootSelector(rule);
if (!nativeShadow) {
this._transformRule(rule, this._transformDocumentSelector);
}
},
normalizeRootSelector: function (rule) {
if (rule.selector === ROOT) {
rule.selector = 'body';
}
},
_transformDocumentSelector: function (selector) {
return selector.match(SCOPE_JUMP) ? this._transformComplexSelector(selector, SCOPE_DOC_SELECTOR) : this._transformSimpleSelector(selector.trim(), SCOPE_DOC_SELECTOR);
},
SCOPE_NAME: 'style-scope'
};
var SCOPE_NAME = api.SCOPE_NAME;
var SCOPE_DOC_SELECTOR = ':not([' + SCOPE_NAME + '])' + ':not(.' + SCOPE_NAME + ')';
var COMPLEX_SELECTOR_SEP = ',';
var SIMPLE_SELECTOR_SEP = /(^|[\s>+~]+)([^\s>+~]+)/g;
var HOST = ':host';
var ROOT = ':root';
var HOST_PAREN = /(\:host)(?:\(((?:\([^)(]*\)|[^)(]*)+?)\))/g;
var CONTENT = '::content';
var SCOPE_JUMP = /\:\:content|\:\:shadow|\/deep\//;
var CSS_CLASS_PREFIX = '.';
var CSS_ATTR_PREFIX = '[' + SCOPE_NAME + '~=';
var CSS_ATTR_SUFFIX = ']';
var PSEUDO_PREFIX = ':';
var CLASS = 'class';
return api;
}();
Polymer.StyleExtends = function () {
var styleUtil = Polymer.StyleUtil;
return {
hasExtends: function (cssText) {
return Boolean(cssText.match(this.rx.EXTEND));
},
transform: function (style) {
var rules = styleUtil.rulesForStyle(style);
var self = this;
styleUtil.forEachStyleRule(rules, function (rule) {
var map = self._mapRule(rule);
if (rule.parent) {
var m;
while (m = self.rx.EXTEND.exec(rule.cssText)) {
var extend = m[1];
var extendor = self._findExtendor(extend, rule);
if (extendor) {
self._extendRule(rule, extendor);
}
}
}
rule.cssText = rule.cssText.replace(self.rx.EXTEND, '');
});
return styleUtil.toCssText(rules, function (rule) {
if (rule.selector.match(self.rx.STRIP)) {
rule.cssText = '';
}
}, true);
},
_mapRule: function (rule) {
if (rule.parent) {
var map = rule.parent.map || (rule.parent.map = {});
var parts = rule.selector.split(',');
for (var i = 0, p; i < parts.length; i++) {
p = parts[i];
map[p.trim()] = rule;
}
return map;
}
},
_findExtendor: function (extend, rule) {
return rule.parent && rule.parent.map && rule.parent.map[extend] || this._findExtendor(extend, rule.parent);
},
_extendRule: function (target, source) {
if (target.parent !== source.parent) {
this._cloneAndAddRuleToParent(source, target.parent);
}
target.extends = target.extends || (target.extends = []);
target.extends.push(source);
source.selector = source.selector.replace(this.rx.STRIP, '');
source.selector = (source.selector && source.selector + ',\n') + target.selector;
if (source.extends) {
source.extends.forEach(function (e) {
this._extendRule(target, e);
}, this);
}
},
_cloneAndAddRuleToParent: function (rule, parent) {
rule = Object.create(rule);
rule.parent = parent;
if (rule.extends) {
rule.extends = rule.extends.slice();
}
parent.rules.push(rule);
},
rx: {
EXTEND: /@extends\(([^)]*)\)\s*?;/gim,
STRIP: /%[^,]*$/
}
};
}();
(function () {
var prepElement = Polymer.Base._prepElement;
var nativeShadow = Polymer.Settings.useNativeShadow;
var styleUtil = Polymer.StyleUtil;
var styleTransformer = Polymer.StyleTransformer;
var styleExtends = Polymer.StyleExtends;
Polymer.Base._addFeature({
_prepElement: function (element) {
if (this._encapsulateStyle) {
styleTransformer.element(element, this.is, this._scopeCssViaAttr);
}
prepElement.call(this, element);
},
_prepStyles: function () {
if (this._encapsulateStyle === undefined) {
this._encapsulateStyle = !nativeShadow && Boolean(this._template);
}
this._styles = this._collectStyles();
var cssText = styleTransformer.elementStyles(this);
if (cssText && this._template) {
var style = styleUtil.applyCss(cssText, this.is, nativeShadow ? this._template.content : null);
if (!nativeShadow) {
this._scopeStyle = style;
}
}
},
_collectStyles: function () {
var styles = [];
var cssText = '', m$ = this.styleModules;
if (m$) {
for (var i = 0, l = m$.length, m; i < l && (m = m$[i]); i++) {
cssText += styleUtil.cssFromModule(m);
}
}
cssText += styleUtil.cssFromModule(this.is);
if (cssText) {
var style = document.createElement('style');
style.textContent = cssText;
if (styleExtends.hasExtends(style.textContent)) {
cssText = styleExtends.transform(style);
}
styles.push(style);
}
return styles;
},
_elementAdd: function (node) {
if (this._encapsulateStyle) {
if (node.__styleScoped) {
node.__styleScoped = false;
} else {
styleTransformer.dom(node, this.is, this._scopeCssViaAttr);
}
}
},
_elementRemove: function (node) {
if (this._encapsulateStyle) {
styleTransformer.dom(node, this.is, this._scopeCssViaAttr, true);
}
},
scopeSubtree: function (container, shouldObserve) {
if (nativeShadow) {
return;
}
var self = this;
var scopify = function (node) {
if (node.nodeType === Node.ELEMENT_NODE) {
node.className = self._scopeElementClass(node, node.className);
var n$ = node.querySelectorAll('*');
Array.prototype.forEach.call(n$, function (n) {
n.className = self._scopeElementClass(n, n.className);
});
}
};
scopify(container);
if (shouldObserve) {
var mo = new MutationObserver(function (mxns) {
mxns.forEach(function (m) {
if (m.addedNodes) {
for (var i = 0; i < m.addedNodes.length; i++) {
scopify(m.addedNodes[i]);
}
}
});
});
mo.observe(container, {
childList: true,
subtree: true
});
return mo;
}
}
});
}());
Polymer.StyleProperties = function () {
'use strict';
var nativeShadow = Polymer.Settings.useNativeShadow;
var matchesSelector = Polymer.DomApi.matchesSelector;
var styleUtil = Polymer.StyleUtil;
var styleTransformer = Polymer.StyleTransformer;
return {
decorateStyles: function (styles) {
var self = this, props = {};
styleUtil.forRulesInStyles(styles, function (rule) {
self.decorateRule(rule);
self.collectPropertiesInCssText(rule.propertyInfo.cssText, props);
});
var names = [];
for (var i in props) {
names.push(i);
}
return names;
},
decorateRule: function (rule) {
if (rule.propertyInfo) {
return rule.propertyInfo;
}
var info = {}, properties = {};
var hasProperties = this.collectProperties(rule, properties);
if (hasProperties) {
info.properties = properties;
rule.rules = null;
}
info.cssText = this.collectCssText(rule);
rule.propertyInfo = info;
return info;
},
collectProperties: function (rule, properties) {
var info = rule.propertyInfo;
if (info) {
if (info.properties) {
Polymer.Base.mixin(properties, info.properties);
return true;
}
} else {
var m, rx = this.rx.VAR_ASSIGN;
var cssText = rule.parsedCssText;
var any;
while (m = rx.exec(cssText)) {
properties[m[1]] = (m[2] || m[3]).trim();
any = true;
}
return any;
}
},
collectCssText: function (rule) {
var customCssText = '';
var cssText = rule.parsedCssText;
cssText = cssText.replace(this.rx.BRACKETED, '').replace(this.rx.VAR_ASSIGN, '');
var parts = cssText.split(';');
for (var i = 0, p; i < parts.length; i++) {
p = parts[i];
if (p.match(this.rx.MIXIN_MATCH) || p.match(this.rx.VAR_MATCH)) {
customCssText += p + ';\n';
}
}
return customCssText;
},
collectPropertiesInCssText: function (cssText, props) {
var m;
while (m = this.rx.VAR_CAPTURE.exec(cssText)) {
props[m[1]] = true;
var def = m[2];
if (def && def.match(this.rx.IS_VAR)) {
props[def] = true;
}
}
},
reify: function (props) {
var names = Object.getOwnPropertyNames(props);
for (var i = 0, n; i < names.length; i++) {
n = names[i];
props[n] = this.valueForProperty(props[n], props);
}
},
valueForProperty: function (property, props) {
if (property) {
if (property.indexOf(';') >= 0) {
property = this.valueForProperties(property, props);
} else {
var self = this;
var fn = function (all, prefix, value, fallback) {
var propertyValue = self.valueForProperty(props[value], props) || (props[fallback] ? self.valueForProperty(props[fallback], props) : fallback);
return prefix + (propertyValue || '');
};
property = property.replace(this.rx.VAR_MATCH, fn);
}
}
return property && property.trim() || '';
},
valueForProperties: function (property, props) {
var parts = property.split(';');
for (var i = 0, p, m; i < parts.length && (p = parts[i]); i++) {
m = p.match(this.rx.MIXIN_MATCH);
if (m) {
p = this.valueForProperty(props[m[1]], props);
} else {
var pp = p.split(':');
if (pp[1]) {
pp[1] = pp[1].trim();
pp[1] = this.valueForProperty(pp[1], props) || pp[1];
}
p = pp.join(':');
}
parts[i] = p && p.lastIndexOf(';') === p.length - 1 ? p.slice(0, -1) : p || '';
}
return parts.join(';');
},
applyProperties: function (rule, props) {
var output = '';
if (!rule.propertyInfo) {
this.decorateRule(rule);
}
if (rule.propertyInfo.cssText) {
output = this.valueForProperties(rule.propertyInfo.cssText, props);
}
rule.cssText = output;
},
propertyDataFromStyles: function (styles, element) {
var props = {}, self = this;
var o = [], i = 0;
styleUtil.forRulesInStyles(styles, function (rule) {
if (!rule.propertyInfo) {
self.decorateRule(rule);
}
if (element && rule.propertyInfo.properties && matchesSelector.call(element, rule.selector)) {
self.collectProperties(rule, props);
addToBitMask(i, o);
}
i++;
});
return {
properties: props,
key: o
};
},
scopePropertiesFromStyles: function (styles) {
if (!styles._scopeStyleProperties) {
styles._scopeStyleProperties = this.selectedPropertiesFromStyles(styles, this.SCOPE_SELECTORS);
}
return styles._scopeStyleProperties;
},
hostPropertiesFromStyles: function (styles) {
if (!styles._hostStyleProperties) {
styles._hostStyleProperties = this.selectedPropertiesFromStyles(styles, this.HOST_SELECTORS);
}
return styles._hostStyleProperties;
},
selectedPropertiesFromStyles: function (styles, selectors) {
var props = {}, self = this;
styleUtil.forRulesInStyles(styles, function (rule) {
if (!rule.propertyInfo) {
self.decorateRule(rule);
}
for (var i = 0; i < selectors.length; i++) {
if (rule.parsedSelector === selectors[i]) {
self.collectProperties(rule, props);
return;
}
}
});
return props;
},
transformStyles: function (element, properties, scopeSelector) {
var self = this;
var hostSelector = styleTransformer._calcHostScope(element.is, element.extends);
var rxHostSelector = element.extends ? '\\' + hostSelector.slice(0, -1) + '\\]' : hostSelector;
var hostRx = new RegExp(this.rx.HOST_PREFIX + rxHostSelector + this.rx.HOST_SUFFIX);
return styleTransformer.elementStyles(element, function (rule) {
self.applyProperties(rule, properties);
if (rule.cssText && !nativeShadow) {
self._scopeSelector(rule, hostRx, hostSelector, element._scopeCssViaAttr, scopeSelector);
}
});
},
_scopeSelector: function (rule, hostRx, hostSelector, viaAttr, scopeId) {
rule.transformedSelector = rule.transformedSelector || rule.selector;
var selector = rule.transformedSelector;
var scope = viaAttr ? '[' + styleTransformer.SCOPE_NAME + '~=' + scopeId + ']' : '.' + scopeId;
var parts = selector.split(',');
for (var i = 0, l = parts.length, p; i < l && (p = parts[i]); i++) {
parts[i] = p.match(hostRx) ? p.replace(hostSelector, hostSelector + scope) : scope + ' ' + p;
}
rule.selector = parts.join(',');
},
applyElementScopeSelector: function (element, selector, old, viaAttr) {
var c = viaAttr ? element.getAttribute(styleTransformer.SCOPE_NAME) : element.className;
var v = old ? c.replace(old, selector) : (c ? c + ' ' : '') + this.XSCOPE_NAME + ' ' + selector;
if (c !== v) {
if (viaAttr) {
element.setAttribute(styleTransformer.SCOPE_NAME, v);
} else {
element.className = v;
}
}
},
applyElementStyle: function (element, properties, selector, style) {
var cssText = style ? style.textContent || '' : this.transformStyles(element, properties, selector);
var s = element._customStyle;
if (s && !nativeShadow && s !== style) {
s._useCount--;
if (s._useCount <= 0) {
s.parentNode.removeChild(s);
}
}
if (nativeShadow || (!style || !style.parentNode)) {
if (nativeShadow && element._customStyle) {
element._customStyle.textContent = cssText;
style = element._customStyle;
} else if (cssText) {
style = styleUtil.applyCss(cssText, selector, nativeShadow ? element.root : null, element._scopeStyle);
}
}
if (style) {
style._useCount = style._useCount || 0;
if (element._customStyle != style) {
style._useCount++;
}
element._customStyle = style;
}
return style;
},
rx: {
VAR_ASSIGN: /(?:^|;\s*)(--[^\:;]*?):\s*?(?:([^;{]*?)|{([^}]*)})(?=;)/gim,
MIXIN_MATCH: /(?:^|\W+)@apply[\s]*\(([^)]*)\);?/im,
VAR_MATCH: /(^|\W+)var\([\s]*([^,)]*)[\s]*,?[\s]*((?:[^,)]*)|(?:[^;]*\([^;)]*\)))[\s]*?\)/gim,
VAR_CAPTURE: /\([\s]*(--[^,\s)]*)(?:,[\s]*(--[^,\s)]*))?(?:\)|,)/gim,
IS_VAR: /^--/,
BRACKETED: /\{[^}]*\}/g,
HOST_PREFIX: '(?:^|[^.])',
HOST_SUFFIX: '($|[.:[\\s>+~])'
},
HOST_SELECTORS: [':host'],
SCOPE_SELECTORS: [':root'],
XSCOPE_NAME: 'x-scope'
};
function addToBitMask(n, bits) {
var o = parseInt(n / 32);
var v = 1 << n % 32;
bits[o] = (bits[o] || 0) | v;
}
}();
Polymer.StyleDefaults = function () {
var styleProperties = Polymer.StyleProperties;
var styleUtil = Polymer.StyleUtil;
var api = {
_styles: [],
_properties: null,
addStyle: function (style) {
this._styles.push(style);
this._properties = null;
},
get _styleProperties() {
if (!this._properties) {
styleProperties.decorateStyles(this._styles);
this._styles._scopeStyleProperties = null;
this._properties = styleProperties.scopePropertiesFromStyles(this._styles);
styleProperties.reify(this._properties);
}
return this._properties;
},
_needsStyleProperties: function () {
},
_computeStyleProperties: function () {
return this._styleProperties;
},
updateStyles: function () {
this._styleCache.clear();
for (var i = 0, s; i < this._styles.length; i++) {
s = this._styles[i];
s = s.__importElement || s;
s._apply();
}
}
};
return api;
}();
(function () {
Polymer.StyleCache = function () {
this.cache = {};
};
Polymer.StyleCache.prototype = {
MAX: 100,
store: function (is, data, keyValues, keyStyles) {
data.keyValues = keyValues;
data.styles = keyStyles;
var s$ = this.cache[is] = this.cache[is] || [];
s$.push(data);
if (s$.length > this.MAX) {
s$.shift();
}
},
retrieve: function (is, keyValues, keyStyles) {
var cache = this.cache[is];
if (cache) {
for (var i = cache.length - 1, data; i >= 0; i--) {
data = cache[i];
if (keyStyles === data.styles && this._objectsEqual(keyValues, data.keyValues)) {
return data;
}
}
}
},
clear: function () {
this.cache = {};
},
_objectsEqual: function (target, source) {
for (var i in target) {
if (target[i] !== source[i]) {
return false;
}
}
if (Array.isArray(target)) {
return target.length === source.length;
}
return true;
}
};
}());
(function () {
'use strict';
var serializeValueToAttribute = Polymer.Base.serializeValueToAttribute;
var propertyUtils = Polymer.StyleProperties;
var styleTransformer = Polymer.StyleTransformer;
var styleUtil = Polymer.StyleUtil;
var styleDefaults = Polymer.StyleDefaults;
var nativeShadow = Polymer.Settings.useNativeShadow;
Polymer.Base._addFeature({
_prepStyleProperties: function () {
this._ownStylePropertyNames = this._styles ? propertyUtils.decorateStyles(this._styles) : [];
},
_setupStyleProperties: function () {
this.customStyle = {};
},
_needsStyleProperties: function () {
return Boolean(this._ownStylePropertyNames && this._ownStylePropertyNames.length);
},
_beforeAttached: function () {
if (!this._scopeSelector && this._needsStyleProperties()) {
this._updateStyleProperties();
}
},
_updateStyleProperties: function () {
var info, scope = this.domHost || styleDefaults;
if (!scope._styleCache) {
scope._styleCache = new Polymer.StyleCache();
}
var scopeData = propertyUtils.propertyDataFromStyles(scope._styles, this);
info = scope._styleCache.retrieve(this.is, scopeData.key, this._styles);
var scopeCached = Boolean(info);
if (scopeCached) {
this._styleProperties = info._styleProperties;
} else {
this._computeStyleProperties(scopeData.properties);
}
this._computeOwnStyleProperties();
if (!scopeCached) {
info = styleCache.retrieve(this.is, this._ownStyleProperties, this._styles);
}
var globalCached = Boolean(info) && !scopeCached;
var style = this._applyStyleProperties(info);
if (!scopeCached) {
var cacheableStyle = style;
if (nativeShadow) {
cacheableStyle = style.cloneNode ? style.cloneNode(true) : Object.create(style || null);
}
info = {
style: cacheableStyle,
_scopeSelector: this._scopeSelector,
_styleProperties: this._styleProperties
};
scope._styleCache.store(this.is, info, scopeData.key, this._styles);
if (!globalCached) {
styleCache.store(this.is, Object.create(info), this._ownStyleProperties, this._styles);
}
}
},
_computeStyleProperties: function (scopeProps) {
var scope = this.domHost || styleDefaults;
if (!scope._styleProperties) {
scope._computeStyleProperties();
}
var props = Object.create(scope._styleProperties);
this.mixin(props, propertyUtils.hostPropertiesFromStyles(this._styles));
scopeProps = scopeProps || propertyUtils.propertyDataFromStyles(scope._styles, this).properties;
this.mixin(props, scopeProps);
this.mixin(props, propertyUtils.scopePropertiesFromStyles(this._styles));
this.mixin(props, this.customStyle);
propertyUtils.reify(props);
this._styleProperties = props;
},
_computeOwnStyleProperties: function () {
var props = {};
for (var i = 0, n; i < this._ownStylePropertyNames.length; i++) {
n = this._ownStylePropertyNames[i];
props[n] = this._styleProperties[n];
}
this._ownStyleProperties = props;
},
_scopeCount: 0,
_applyStyleProperties: function (info) {
var oldScopeSelector = this._scopeSelector;
this._scopeSelector = info ? info._scopeSelector : this.is + '-' + this.__proto__._scopeCount++;
var style = propertyUtils.applyElementStyle(this, this._styleProperties, this._scopeSelector, info && info.style);
if ((style || oldScopeSelector) && !nativeShadow) {
propertyUtils.applyElementScopeSelector(this, this._scopeSelector, oldScopeSelector, this._scopeCssViaAttr);
}
return style || {};
},
serializeValueToAttribute: function (value, attribute, node) {
node = node || this;
if (attribute === 'class') {
var host = node === this ? this.domHost || this.dataHost : this;
if (host) {
value = host._scopeElementClass(node, value);
}
}
node = Polymer.dom(node);
serializeValueToAttribute.call(this, value, attribute, node);
},
_scopeElementClass: function (element, selector) {
if (!nativeShadow && !this._scopeCssViaAttr) {
selector += (selector ? ' ' : '') + SCOPE_NAME + ' ' + this.is + (element._scopeSelector ? ' ' + XSCOPE_NAME + ' ' + element._scopeSelector : '');
}
return selector;
},
updateStyles: function () {
if (this.isAttached) {
if (this._needsStyleProperties()) {
this._updateStyleProperties();
} else {
this._styleProperties = null;
}
if (this._styleCache) {
this._styleCache.clear();
}
this._updateRootStyles();
}
},
_updateRootStyles: function (root) {
root = root || this.root;
var c$ = Polymer.dom(root)._query(function (e) {
return e.shadyRoot || e.shadowRoot;
});
for (var i = 0, l = c$.length, c; i < l && (c = c$[i]); i++) {
if (c.updateStyles) {
c.updateStyles();
}
}
}
});
Polymer.updateStyles = function () {
styleDefaults.updateStyles();
Polymer.Base._updateRootStyles(document);
};
var styleCache = new Polymer.StyleCache();
Polymer.customStyleCache = styleCache;
var SCOPE_NAME = styleTransformer.SCOPE_NAME;
var XSCOPE_NAME = propertyUtils.XSCOPE_NAME;
}());
Polymer.Base._addFeature({
_registerFeatures: function () {
this._prepIs();
this._prepAttributes();
this._prepExtends();
this._prepConstructor();
this._prepTemplate();
this._prepStyles();
this._prepStyleProperties();
this._prepAnnotations();
this._prepEffects();
this._prepBehaviors();
this._prepBindings();
this._prepShady();
},
_prepBehavior: function (b) {
this._addPropertyEffects(b.properties);
this._addComplexObserverEffects(b.observers);
this._addHostAttributes(b.hostAttributes);
},
_initFeatures: function () {
this._poolContent();
this._setupConfigure();
this._setupStyleProperties();
this._pushHost();
this._stampTemplate();
this._popHost();
this._marshalAnnotationReferences();
this._marshalHostAttributes();
this._setupDebouncers();
this._marshalInstanceEffects();
this._marshalBehaviors();
this._marshalAttributes();
this._tryReady();
},
_marshalBehavior: function (b) {
this._listenListeners(b.listeners);
}
});
(function () {
var nativeShadow = Polymer.Settings.useNativeShadow;
var propertyUtils = Polymer.StyleProperties;
var styleUtil = Polymer.StyleUtil;
var styleDefaults = Polymer.StyleDefaults;
var styleTransformer = Polymer.StyleTransformer;
Polymer({
is: 'custom-style',
extends: 'style',
created: function () {
this._tryApply();
},
attached: function () {
this._tryApply();
},
_tryApply: function () {
if (!this._appliesToDocument) {
if (this.parentNode && this.parentNode.localName !== 'dom-module') {
this._appliesToDocument = true;
var e = this.__appliedElement || this;
styleDefaults.addStyle(e);
if (e.textContent) {
this._apply();
} else {
var observer = new MutationObserver(function () {
observer.disconnect();
this._apply();
}.bind(this));
observer.observe(e, { childList: true });
}
}
}
},
_apply: function () {
var e = this.__appliedElement || this;
this._computeStyleProperties();
var props = this._styleProperties;
var self = this;
e.textContent = styleUtil.toCssText(styleUtil.rulesForStyle(e), function (rule) {
var css = rule.cssText = rule.parsedCssText;
if (rule.propertyInfo && rule.propertyInfo.cssText) {
css = css.replace(propertyUtils.rx.VAR_ASSIGN, '');
rule.cssText = propertyUtils.valueForProperties(css, props);
}
styleTransformer.documentRule(rule);
});
}
});
}());
Polymer.Templatizer = {
properties: { _hideTemplateChildren: { observer: '_showHideChildren' } },
_templatizerStatic: {
count: 0,
callbacks: {},
debouncer: null
},
_instanceProps: Polymer.nob,
created: function () {
this._templatizerId = this._templatizerStatic.count++;
},
templatize: function (template) {
if (!template._content) {
template._content = template.content;
}
if (template._content._ctor) {
this.ctor = template._content._ctor;
this._prepParentProperties(this.ctor.prototype, template);
return;
}
var archetype = Object.create(Polymer.Base);
this._customPrepAnnotations(archetype, template);
archetype._prepEffects();
this._customPrepEffects(archetype);
archetype._prepBehaviors();
archetype._prepBindings();
this._prepParentProperties(archetype, template);
archetype._notifyPath = this._notifyPathImpl;
archetype._scopeElementClass = this._scopeElementClassImpl;
archetype.listen = this._listenImpl;
var _constructor = this._constructorImpl;
var ctor = function TemplateInstance(model, host) {
_constructor.call(this, model, host);
};
ctor.prototype = archetype;
archetype.constructor = ctor;
template._content._ctor = ctor;
this.ctor = ctor;
},
_getRootDataHost: function () {
return this.dataHost && this.dataHost._rootDataHost || this.dataHost;
},
_showHideChildren: function (hidden) {
},
_debounceTemplate: function (fn) {
this._templatizerStatic.callbacks[this._templatizerId] = fn.bind(this);
this._templatizerStatic.debouncer = Polymer.Debounce(this._templatizerStatic.debouncer, this._flushTemplates.bind(this, true));
},
_flushTemplates: function (debouncerExpired) {
var db = this._templatizerStatic.debouncer;
while (debouncerExpired || db && db.finish) {
db.stop();
var cbs = this._templatizerStatic.callbacks;
this._templatizerStatic.callbacks = {};
for (var id in cbs) {
cbs[id]();
}
debouncerExpired = false;
}
},
_customPrepEffects: function (archetype) {
var parentProps = archetype._parentProps;
for (var prop in parentProps) {
archetype._addPropertyEffect(prop, 'function', this._createHostPropEffector(prop));
}
},
_customPrepAnnotations: function (archetype, template) {
archetype._template = template;
var c = template._content;
if (!c._notes) {
var rootDataHost = archetype._rootDataHost;
if (rootDataHost) {
Polymer.Annotations.prepElement = rootDataHost._prepElement.bind(rootDataHost);
}
c._notes = Polymer.Annotations.parseAnnotations(template);
Polymer.Annotations.prepElement = null;
this._processAnnotations(c._notes);
}
archetype._notes = c._notes;
archetype._parentProps = c._parentProps;
},
_prepParentProperties: function (archetype, template) {
var parentProps = this._parentProps = archetype._parentProps;
if (this._forwardParentProp && parentProps) {
var proto = archetype._parentPropProto;
var prop;
if (!proto) {
for (prop in this._instanceProps) {
delete parentProps[prop];
}
proto = archetype._parentPropProto = Object.create(null);
if (template != this) {
Polymer.Bind.prepareModel(proto);
}
for (prop in parentProps) {
var parentProp = '_parent_' + prop;
var effects = [
{
kind: 'function',
effect: this._createForwardPropEffector(prop)
},
{ kind: 'notify' }
];
Polymer.Bind._createAccessors(proto, parentProp, effects);
}
}
if (template != this) {
Polymer.Bind.prepareInstance(template);
template._forwardParentProp = this._forwardParentProp.bind(this);
}
this._extendTemplate(template, proto);
}
},
_createForwardPropEffector: function (prop) {
return function (source, value) {
this._forwardParentProp(prop, value);
};
},
_createHostPropEffector: function (prop) {
return function (source, value) {
this.dataHost['_parent_' + prop] = value;
};
},
_extendTemplate: function (template, proto) {
Object.getOwnPropertyNames(proto).forEach(function (n) {
var val = template[n];
var pd = Object.getOwnPropertyDescriptor(proto, n);
Object.defineProperty(template, n, pd);
if (val !== undefined) {
template._propertySet(n, val);
}
});
},
_forwardInstancePath: function (inst, path, value) {
},
_notifyPathImpl: function (path, value) {
var dataHost = this.dataHost;
var dot = path.indexOf('.');
var root = dot < 0 ? path : path.slice(0, dot);
dataHost._forwardInstancePath.call(dataHost, this, path, value);
if (root in dataHost._parentProps) {
dataHost.notifyPath('_parent_' + path, value);
}
},
_pathEffector: function (path, value, fromAbove) {
if (this._forwardParentPath) {
if (path.indexOf('_parent_') === 0) {
this._forwardParentPath(path.substring(8), value);
}
}
Polymer.Base._pathEffector.apply(this, arguments);
},
_constructorImpl: function (model, host) {
this._rootDataHost = host._getRootDataHost();
this._setupConfigure(model);
this._pushHost(host);
this.root = this.instanceTemplate(this._template);
this.root.__styleScoped = true;
this._popHost();
this._marshalAnnotatedNodes();
this._marshalInstanceEffects();
this._marshalAnnotatedListeners();
var children = [];
for (var n = this.root.firstChild; n; n = n.nextSibling) {
children.push(n);
n._templateInstance = this;
}
this._children = children;
this._tryReady();
},
_listenImpl: function (node, eventName, methodName) {
var model = this;
var host = this._rootDataHost;
var handler = host._createEventHandler(node, eventName, methodName);
var decorated = function (e) {
e.model = model;
handler(e);
};
host._listen(node, eventName, decorated);
},
_scopeElementClassImpl: function (node, value) {
var host = this._rootDataHost;
if (host) {
return host._scopeElementClass(node, value);
}
},
stamp: function (model) {
model = model || {};
if (this._parentProps) {
for (var prop in this._parentProps) {
model[prop] = this['_parent_' + prop];
}
}
return new this.ctor(model, this);
}
};
Polymer({
is: 'dom-template',
extends: 'template',
behaviors: [Polymer.Templatizer],
ready: function () {
this.templatize(this);
}
});
Polymer._collections = new WeakMap();
Polymer.Collection = function (userArray) {
Polymer._collections.set(userArray, this);
this.userArray = userArray;
this.store = userArray.slice();
this.initMap();
};
Polymer.Collection.prototype = {
constructor: Polymer.Collection,
initMap: function () {
var omap = this.omap = new WeakMap();
var pmap = this.pmap = {};
var s = this.store;
for (var i = 0; i < s.length; i++) {
var item = s[i];
if (item && typeof item == 'object') {
omap.set(item, i);
} else {
pmap[item] = i;
}
}
},
add: function (item) {
var key = this.store.push(item) - 1;
if (item && typeof item == 'object') {
this.omap.set(item, key);
} else {
this.pmap[item] = key;
}
return key;
},
removeKey: function (key) {
this._removeFromMap(this.store[key]);
delete this.store[key];
},
_removeFromMap: function (item) {
if (typeof item == 'object') {
this.omap.delete(item);
} else {
delete this.pmap[item];
}
},
remove: function (item) {
var key = this.getKey(item);
this.removeKey(key);
return key;
},
getKey: function (item) {
if (typeof item == 'object') {
return this.omap.get(item);
} else {
return this.pmap[item];
}
},
getKeys: function () {
return Object.keys(this.store);
},
setItem: function (key, value) {
this.store[key] = value;
},
getItem: function (key) {
return this.store[key];
},
getItems: function () {
var items = [], store = this.store;
for (var key in store) {
items.push(store[key]);
}
return items;
},
_applySplices: function (splices) {
var keySplices = [];
for (var i = 0; i < splices.length; i++) {
var j, o, key, s = splices[i];
var removed = [];
for (j = 0; j < s.removed.length; j++) {
o = s.removed[j];
key = this.remove(o);
removed.push(key);
}
var added = [];
for (j = 0; j < s.addedCount; j++) {
o = this.userArray[s.index + j];
key = this.add(o);
added.push(key);
}
keySplices.push({
index: s.index,
removed: removed,
removedItems: s.removed,
added: added
});
}
return keySplices;
}
};
Polymer.Collection.get = function (userArray) {
return Polymer._collections.get(userArray) || new Polymer.Collection(userArray);
};
Polymer.Collection.applySplices = function (userArray, splices) {
var coll = Polymer._collections.get(userArray);
return coll ? coll._applySplices(splices) : null;
};
Polymer({
is: 'dom-repeat',
extends: 'template',
properties: {
items: { type: Array },
as: {
type: String,
value: 'item'
},
indexAs: {
type: String,
value: 'index'
},
sort: {
type: Function,
observer: '_sortChanged'
},
filter: {
type: Function,
observer: '_filterChanged'
},
observe: {
type: String,
observer: '_observeChanged'
},
delay: Number
},
behaviors: [Polymer.Templatizer],
observers: ['_itemsChanged(items.*)'],
detached: function () {
if (this.rows) {
for (var i = 0; i < this.rows.length; i++) {
this._detachRow(i);
}
}
},
attached: function () {
if (this.rows) {
var parentNode = Polymer.dom(this).parentNode;
for (var i = 0; i < this.rows.length; i++) {
Polymer.dom(parentNode).insertBefore(this.rows[i].root, this);
}
}
},
ready: function () {
this._instanceProps = { __key__: true };
this._instanceProps[this.as] = true;
this._instanceProps[this.indexAs] = true;
if (!this.ctor) {
this.templatize(this);
}
},
_sortChanged: function () {
var dataHost = this._getRootDataHost();
var sort = this.sort;
this._sortFn = sort && (typeof sort == 'function' ? sort : function () {
return dataHost[sort].apply(dataHost, arguments);
});
this._fullRefresh = true;
if (this.items) {
this._debounceTemplate(this._render);
}
},
_filterChanged: function () {
var dataHost = this._getRootDataHost();
var filter = this.filter;
this._filterFn = filter && (typeof filter == 'function' ? filter : function () {
return dataHost[filter].apply(dataHost, arguments);
});
this._fullRefresh = true;
if (this.items) {
this._debounceTemplate(this._render);
}
},
_observeChanged: function () {
this._observePaths = this.observe && this.observe.replace('.*', '.').split(' ');
},
_itemsChanged: function (change) {
if (change.path == 'items') {
if (Array.isArray(this.items)) {
this.collection = Polymer.Collection.get(this.items);
} else if (!this.items) {
this.collection = null;
} else {
this._error(this._logf('dom-repeat', 'expected array for `items`,' + ' found', this.items));
}
this._splices = [];
this._fullRefresh = true;
this._debounceTemplate(this._render);
} else if (change.path == 'items.splices') {
this._splices = this._splices.concat(change.value.keySplices);
this._debounceTemplate(this._render);
} else {
var subpath = change.path.slice(6);
this._forwardItemPath(subpath, change.value);
this._checkObservedPaths(subpath);
}
},
_checkObservedPaths: function (path) {
if (this._observePaths) {
path = path.substring(path.indexOf('.') + 1);
var paths = this._observePaths;
for (var i = 0; i < paths.length; i++) {
if (path.indexOf(paths[i]) === 0) {
this._fullRefresh = true;
if (this.delay) {
this.debounce('render', this._render, this.delay);
} else {
this._debounceTemplate(this._render);
}
return;
}
}
}
},
render: function () {
this._fullRefresh = true;
this.debounce('render', this._render);
this._flushTemplates();
},
_render: function () {
var c = this.collection;
if (!this._fullRefresh) {
if (this._sortFn) {
this._applySplicesViewSort(this._splices);
} else {
if (this._filterFn) {
this._fullRefresh = true;
} else {
this._applySplicesArraySort(this._splices);
}
}
}
if (this._fullRefresh) {
this._sortAndFilter();
this._fullRefresh = false;
}
this._splices = [];
var rowForKey = this._rowForKey = {};
var keys = this._orderedKeys;
this.rows = this.rows || [];
for (var i = 0; i < keys.length; i++) {
var key = keys[i];
var item = c.getItem(key);
var row = this.rows[i];
rowForKey[key] = i;
if (!row) {
this.rows.push(row = this._insertRow(i, null, item));
}
row[this.as] = item;
row.__key__ = key;
row[this.indexAs] = i;
}
for (; i < this.rows.length; i++) {
this._detachRow(i);
}
this.rows.splice(keys.length, this.rows.length - keys.length);
this.fire('dom-change');
},
_sortAndFilter: function () {
var c = this.collection;
if (!this._sortFn) {
this._orderedKeys = [];
var items = this.items;
if (items) {
for (var i = 0; i < items.length; i++) {
this._orderedKeys.push(c.getKey(items[i]));
}
}
} else {
this._orderedKeys = c ? c.getKeys() : [];
}
if (this._filterFn) {
this._orderedKeys = this._orderedKeys.filter(function (a) {
return this._filterFn(c.getItem(a));
}, this);
}
if (this._sortFn) {
this._orderedKeys.sort(function (a, b) {
return this._sortFn(c.getItem(a), c.getItem(b));
}.bind(this));
}
},
_keySort: function (a, b) {
return this.collection.getKey(a) - this.collection.getKey(b);
},
_applySplicesViewSort: function (splices) {
var c = this.collection;
var keys = this._orderedKeys;
var rows = this.rows;
var removedRows = [];
var addedKeys = [];
var pool = [];
var sortFn = this._sortFn || this._keySort.bind(this);
splices.forEach(function (s) {
for (var i = 0; i < s.removed.length; i++) {
var idx = this._rowForKey[s.removed[i]];
if (idx != null) {
removedRows.push(idx);
}
}
for (var i = 0; i < s.added.length; i++) {
addedKeys.push(s.added[i]);
}
}, this);
if (removedRows.length) {
removedRows.sort();
for (var i = removedRows.length - 1; i >= 0; i--) {
var idx = removedRows[i];
pool.push(this._detachRow(idx));
rows.splice(idx, 1);
keys.splice(idx, 1);
}
}
if (addedKeys.length) {
if (this._filterFn) {
addedKeys = addedKeys.filter(function (a) {
return this._filterFn(c.getItem(a));
}, this);
}
addedKeys.sort(function (a, b) {
return this._sortFn(c.getItem(a), c.getItem(b));
}.bind(this));
var start = 0;
for (var i = 0; i < addedKeys.length; i++) {
start = this._insertRowIntoViewSort(start, addedKeys[i], pool);
}
}
},
_insertRowIntoViewSort: function (start, key, pool) {
var c = this.collection;
var item = c.getItem(key);
var end = this.rows.length - 1;
var idx = -1;
var sortFn = this._sortFn || this._keySort.bind(this);
while (start <= end) {
var mid = start + end >> 1;
var midKey = this._orderedKeys[mid];
var cmp = sortFn(c.getItem(midKey), item);
if (cmp < 0) {
start = mid + 1;
} else if (cmp > 0) {
end = mid - 1;
} else {
idx = mid;
break;
}
}
if (idx < 0) {
idx = end + 1;
}
this._orderedKeys.splice(idx, 0, key);
this.rows.splice(idx, 0, this._insertRow(idx, pool, c.getItem(key)));
return idx;
},
_applySplicesArraySort: function (splices) {
var keys = this._orderedKeys;
var pool = [];
splices.forEach(function (s) {
for (var i = 0; i < s.removed.length; i++) {
pool.push(this._detachRow(s.index + i));
}
this.rows.splice(s.index, s.removed.length);
}, this);
var c = this.collection;
splices.forEach(function (s) {
var args = [
s.index,
s.removed.length
].concat(s.added);
keys.splice.apply(keys, args);
for (var i = 0; i < s.added.length; i++) {
var item = c.getItem(s.added[i]);
var row = this._insertRow(s.index + i, pool, item);
this.rows.splice(s.index + i, 0, row);
}
}, this);
},
_detachRow: function (idx) {
var row = this.rows[idx];
var parentNode = Polymer.dom(this).parentNode;
for (var i = 0; i < row._children.length; i++) {
var el = row._children[i];
Polymer.dom(row.root).appendChild(el);
}
return row;
},
_insertRow: function (idx, pool, item) {
var row = pool && pool.pop() || this._generateRow(idx, item);
var beforeRow = this.rows[idx];
var beforeNode = beforeRow ? beforeRow._children[0] : this;
var parentNode = Polymer.dom(this).parentNode;
Polymer.dom(parentNode).insertBefore(row.root, beforeNode);
return row;
},
_generateRow: function (idx, item) {
var model = { __key__: this.collection.getKey(item) };
model[this.as] = item;
model[this.indexAs] = idx;
var row = this.stamp(model);
return row;
},
_showHideChildren: function (hidden) {
if (this.rows) {
for (var i = 0; i < this.rows.length; i++) {
var c$ = this.rows[i]._children;
for (var j = 0; j < c$.length; j++) {
var c = c$[j];
if (c.style) {
c.style.display = hidden ? 'none' : '';
}
c._hideTemplateChildren = hidden;
}
}
}
},
_forwardInstancePath: function (row, path, value) {
if (path.indexOf(this.as + '.') === 0) {
this.notifyPath('items.' + row.__key__ + '.' + path.slice(this.as.length + 1), value);
return true;
}
},
_forwardParentProp: function (prop, value) {
if (this.rows) {
this.rows.forEach(function (row) {
row[prop] = value;
}, this);
}
},
_forwardParentPath: function (path, value) {
if (this.rows) {
this.rows.forEach(function (row) {
row.notifyPath(path, value, true);
}, this);
}
},
_forwardItemPath: function (path, value) {
if (this._rowForKey) {
var dot = path.indexOf('.');
var key = path.substring(0, dot < 0 ? path.length : dot);
var idx = this._rowForKey[key];
var row = this.rows[idx];
if (row) {
if (dot >= 0) {
path = this.as + '.' + path.substring(dot + 1);
row.notifyPath(path, value, true);
} else {
row[this.as] = value;
}
}
}
},
modelForElement: function (el) {
var model;
while (el) {
if (model = el._templateInstance) {
if (model.dataHost != this) {
el = model.dataHost;
} else {
return model;
}
} else {
el = el.parentNode;
}
}
},
itemForElement: function (el) {
var instance = this.modelForElement(el);
return instance && instance[this.as];
},
keyForElement: function (el) {
var instance = this.modelForElement(el);
return instance && instance.__key__;
},
indexForElement: function (el) {
var instance = this.modelForElement(el);
return instance && instance[this.indexAs];
}
});
Polymer({
is: 'array-selector',
properties: {
items: {
type: Array,
observer: '_itemsChanged'
},
selected: {
type: Object,
notify: true
},
toggle: Boolean,
multi: Boolean
},
_itemsChanged: function () {
if (Array.isArray(this.selected)) {
for (var i = 0; i < this.selected.length; i++) {
this.unlinkPaths('selected.' + i);
}
} else {
this.unlinkPaths('selected');
}
if (this.multi) {
this.selected = [];
} else {
this.selected = null;
}
},
deselect: function (item) {
if (this.multi) {
var scol = Polymer.Collection.get(this.selected);
var sidx = this.selected.indexOf(item);
if (sidx >= 0) {
var skey = scol.getKey(item);
this.splice('selected', sidx, 1);
this.unlinkPaths('selected.' + skey);
return true;
}
} else {
this.selected = null;
this.unlinkPaths('selected');
}
},
select: function (item) {
var icol = Polymer.Collection.get(this.items);
var key = icol.getKey(item);
if (this.multi) {
var scol = Polymer.Collection.get(this.selected);
var skey = scol.getKey(item);
if (skey >= 0) {
if (this.toggle) {
this.deselect(item);
}
} else {
this.push('selected', item);
this.async(function () {
skey = scol.getKey(item);
this.linkPaths('selected.' + skey, 'items.' + key);
});
}
} else {
if (this.toggle && item == this.selected) {
this.deselect();
} else {
this.linkPaths('selected', 'items.' + key);
this.selected = item;
}
}
}
});
Polymer({
is: 'dom-if',
extends: 'template',
properties: {
'if': {
type: Boolean,
value: false
},
restamp: {
type: Boolean,
value: false
}
},
behaviors: [Polymer.Templatizer],
observers: ['_queueRender(if, restamp)'],
_queueRender: function () {
this._debounceTemplate(this._render);
},
detached: function () {
this._teardownInstance();
},
attached: function () {
if (this.if && this.ctor) {
this.async(this._ensureInstance);
}
},
render: function () {
this._flushTemplates();
},
_render: function () {
if (this.if) {
if (!this.ctor) {
this._wrapTextNodes(this._content || this.content);
this.templatize(this);
}
this._ensureInstance();
this._showHideChildren();
} else if (this.restamp) {
this._teardownInstance();
}
if (!this.restamp && this._instance) {
this._showHideChildren();
}
if (this.if != this._lastIf) {
this.fire('dom-change');
this._lastIf = this.if;
}
},
_ensureInstance: function () {
if (!this._instance) {
this._instance = this.stamp();
var root = this._instance.root;
var parent = Polymer.dom(Polymer.dom(this).parentNode);
parent.insertBefore(root, this);
}
},
_teardownInstance: function () {
if (this._instance) {
var c = this._instance._children;
if (c) {
var parent = Polymer.dom(Polymer.dom(c[0]).parentNode);
c.forEach(function (n) {
parent.removeChild(n);
});
}
this._instance = null;
}
},
_wrapTextNodes: function (root) {
for (var n = root.firstChild; n; n = n.nextSibling) {
if (n.nodeType === Node.TEXT_NODE) {
var s = document.createElement('span');
root.insertBefore(s, n);
s.appendChild(n);
n = s;
}
}
},
_showHideChildren: function () {
var hidden = this._hideTemplateChildren || !this.if;
if (this._instance) {
var c$ = this._instance._children;
for (var i = 0; i < c$.length; i++) {
var c = c$[i];
c.style.display = hidden ? 'none' : '';
c._hideTemplateChildren = hidden;
}
}
},
_forwardParentProp: function (prop, value) {
if (this._instance) {
this._instance[prop] = value;
}
},
_forwardParentPath: function (path, value) {
if (this._instance) {
this._instance.notifyPath(path, value, true);
}
}
});
Polymer.ImportStatus = {
_ready: false,
_callbacks: [],
whenLoaded: function (cb) {
if (this._ready) {
cb();
} else {
this._callbacks.push(cb);
}
},
_importsLoaded: function () {
this._ready = true;
this._callbacks.forEach(function (cb) {
cb();
});
this._callbacks = [];
}
};
window.addEventListener('load', function () {
Polymer.ImportStatus._importsLoaded();
});
if (window.HTMLImports) {
HTMLImports.whenReady(function () {
Polymer.ImportStatus._importsLoaded();
});
}
Polymer({
is: 'dom-bind',
extends: 'template',
created: function () {
Polymer.ImportStatus.whenLoaded(this._readySelf.bind(this));
},
_registerFeatures: function () {
this._prepExtends();
this._prepConstructor();
},
_insertChildren: function () {
var parentDom = Polymer.dom(Polymer.dom(this).parentNode);
parentDom.insertBefore(this.root, this);
},
_removeChildren: function () {
if (this._children) {
for (var i = 0; i < this._children.length; i++) {
this.root.appendChild(this._children[i]);
}
}
},
_initFeatures: function () {
},
_scopeElementClass: function (element, selector) {
if (this.dataHost) {
return this.dataHost._scopeElementClass(element, selector);
} else {
return selector;
}
},
_prepConfigure: function () {
var config = {};
for (var prop in this._propertyEffects) {
config[prop] = this[prop];
}
this._setupConfigure = this._setupConfigure.bind(this, config);
},
attached: function () {
if (!this._children) {
this._template = this;
this._prepAnnotations();
this._prepEffects();
this._prepBehaviors();
this._prepConfigure();
this._prepBindings();
Polymer.Base._initFeatures.call(this);
this._children = Array.prototype.slice.call(this.root.childNodes);
}
this._insertChildren();
this.fire('dom-change');
},
detached: function () {
this._removeChildren();
}
});</script>
<style is="custom-style">
:root {
--shadow-transition: {
transition: box-shadow 0.28s cubic-bezier(0.4, 0, 0.2, 1);
};
/* from http://codepen.io/shyndman/pen/c5394ddf2e8b2a5c9185904b57421cdb */
--shadow-elevation-2dp: {
box-shadow: 0 2px 2px 0 rgba(0, 0, 0, 0.14),
0 1px 5px 0 rgba(0, 0, 0, 0.12),
0 3px 1px -2px rgba(0, 0, 0, 0.2);
};
--shadow-elevation-3dp: {
box-shadow: 0 3px 4px 0 rgba(0, 0, 0, 0.14),
0 1px 8px 0 rgba(0, 0, 0, 0.12),
0 3px 3px -2px rgba(0, 0, 0, 0.4);
};
--shadow-elevation-4dp: {
box-shadow: 0 4px 5px 0 rgba(0, 0, 0, 0.14),
0 1px 10px 0 rgba(0, 0, 0, 0.12),
0 2px 4px -1px rgba(0, 0, 0, 0.4);
};
--shadow-elevation-6dp: {
box-shadow: 0 6px 10px 0 rgba(0, 0, 0, 0.14),
0 1px 18px 0 rgba(0, 0, 0, 0.12),
0 3px 5px -1px rgba(0, 0, 0, 0.4);
};
--shadow-elevation-8dp: {
box-shadow: 0 8px 10px 1px rgba(0, 0, 0, 0.14),
0 3px 14px 2px rgba(0, 0, 0, 0.12),
0 5px 5px -3px rgba(0, 0, 0, 0.4);
};
--shadow-elevation-16dp: {
box-shadow: 0 16px 24px 2px rgba(0, 0, 0, 0.14),
0 6px 30px 5px rgba(0, 0, 0, 0.12),
0 8px 10px -5px rgba(0, 0, 0, 0.4);
};
}
</style>
<script>
(function() {
'use strict';
/**
* 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 = {
9: 'tab',
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: '*'
};
/**
* MODIFIER_KEYS maps the short name for modifier keys used in a key
* combo string to the property name that references those same keys
* in a KeyboardEvent instance.
*/
var MODIFIER_KEYS = {
shift: 'shiftKey',
ctrl: 'ctrlKey',
alt: 'altKey',
meta: 'metaKey'
};
/**
* 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*]/;
/**
* Matches a keyIdentifier string.
*/
var IDENT_CHAR = /U\+/;
/**
* Matches arrow keys in Gecko 27.0+
*/
var ARROW_KEY = /^arrow/;
/**
* Matches space keys everywhere (notably including IE10's exceptional name
* `spacebar`).
*/
var SPACE_KEY = /^space(bar)?/;
function transformKey(key) {
var validKey = '';
if (key) {
var lKey = key.toLowerCase();
if (lKey.length == 1) {
if (KEY_CHAR.test(lKey)) {
validKey = lKey;
}
} else if (ARROW_KEY.test(lKey)) {
validKey = lKey.replace('arrow', '');
} else if (SPACE_KEY.test(lKey)) {
validKey = 'space';
} else if (lKey == 'multiply') {
// numpad '*' can map to Multiply on IE/Windows
validKey = '*';
} else {
validKey = lKey;
}
}
return validKey;
}
function transformKeyIdentifier(keyIdent) {
var validKey = '';
if (keyIdent) {
if (IDENT_CHAR.test(keyIdent)) {
validKey = KEY_IDENTIFIER[keyIdent];
} else {
validKey = keyIdent.toLowerCase();
}
}
return validKey;
}
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 normalizedKeyForEvent(keyEvent) {
// fall back from .key, to .keyIdentifier, to .keyCode, and then to
// .detail.key to support artificial keyboard events
return transformKey(keyEvent.key) ||
transformKeyIdentifier(keyEvent.keyIdentifier) ||
transformKeyCode(keyEvent.keyCode) ||
transformKey(keyEvent.detail.key) || '';
}
function keyComboMatchesEvent(keyCombo, keyEvent) {
return normalizedKeyForEvent(keyEvent) === keyCombo.key &&
!!keyEvent.shiftKey === !!keyCombo.shiftKey &&
!!keyEvent.ctrlKey === !!keyCombo.ctrlKey &&
!!keyEvent.altKey === !!keyCombo.altKey &&
!!keyEvent.metaKey === !!keyCombo.metaKey;
}
function parseKeyComboString(keyComboString) {
return keyComboString.split('+').reduce(function(parsedKeyCombo, keyComboPart) {
var eventParts = keyComboPart.split(':');
var keyName = eventParts[0];
var event = eventParts[1];
if (keyName in MODIFIER_KEYS) {
parsedKeyCombo[MODIFIER_KEYS[keyName]] = true;
} else {
parsedKeyCombo.key = keyName;
parsedKeyCombo.event = event || 'keydown';
}
return parsedKeyCombo;
}, {
combo: keyComboString.split(':').shift()
});
}
function parseEventString(eventString) {
return eventString.split(' ').map(function(keyComboString) {
return parseKeyComboString(keyComboString);
});
}
/**
* `Polymer.IronA11yKeysBehavior` 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 `keyBindings` prototype property to express what combination of keys
* will trigger the event to fire.
*
* Use the `key-event-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` property is pressed.
*
* @demo demo/index.html
* @polymerBehavior IronA11yKeysBehavior
*/
Polymer.IronA11yKeysBehavior = {
properties: {
/**
* The HTMLElement that will be firing relevant KeyboardEvents.
*/
keyEventTarget: {
type: Object,
value: function() {
return this;
}
},
_boundKeyHandlers: {
type: Array,
value: function() {
return [];
}
},
// We use this due to a limitation in IE10 where instances will have
// own properties of everything on the "prototype".
_imperativeKeyBindings: {
type: Object,
value: function() {
return {};
}
}
},
observers: [
'_resetKeyEventListeners(keyEventTarget, _boundKeyHandlers)'
],
keyBindings: {},
registered: function() {
this._prepKeyBindings();
},
attached: function() {
this._listenKeyEventListeners();
},
detached: function() {
this._unlistenKeyEventListeners();
},
/**
* Can be used to imperatively add a key binding to the implementing
* element. This is the imperative equivalent of declaring a keybinding
* in the `keyBindings` prototype property.
*/
addOwnKeyBinding: function(eventString, handlerName) {
this._imperativeKeyBindings[eventString] = handlerName;
this._prepKeyBindings();
this._resetKeyEventListeners();
},
/**
* When called, will remove all imperatively-added key bindings.
*/
removeOwnKeyBindings: function() {
this._imperativeKeyBindings = {};
this._prepKeyBindings();
this._resetKeyEventListeners();
},
keyboardEventMatchesKeys: function(event, eventString) {
var keyCombos = parseEventString(eventString);
var index;
for (index = 0; index < keyCombos.length; ++index) {
if (keyComboMatchesEvent(keyCombos[index], event)) {
return true;
}
}
return false;
},
_collectKeyBindings: function() {
var keyBindings = this.behaviors.map(function(behavior) {
return behavior.keyBindings;
});
if (keyBindings.indexOf(this.keyBindings) === -1) {
keyBindings.push(this.keyBindings);
}
return keyBindings;
},
_prepKeyBindings: function() {
this._keyBindings = {};
this._collectKeyBindings().forEach(function(keyBindings) {
for (var eventString in keyBindings) {
this._addKeyBinding(eventString, keyBindings[eventString]);
}
}, this);
for (var eventString in this._imperativeKeyBindings) {
this._addKeyBinding(eventString, this._imperativeKeyBindings[eventString]);
}
},
_addKeyBinding: function(eventString, handlerName) {
parseEventString(eventString).forEach(function(keyCombo) {
this._keyBindings[keyCombo.event] =
this._keyBindings[keyCombo.event] || [];
this._keyBindings[keyCombo.event].push([
keyCombo,
handlerName
]);
}, this);
},
_resetKeyEventListeners: function() {
this._unlistenKeyEventListeners();
if (this.isAttached) {
this._listenKeyEventListeners();
}
},
_listenKeyEventListeners: function() {
Object.keys(this._keyBindings).forEach(function(eventName) {
var keyBindings = this._keyBindings[eventName];
var boundKeyHandler = this._onKeyBindingEvent.bind(this, keyBindings);
this._boundKeyHandlers.push([this.keyEventTarget, eventName, boundKeyHandler]);
this.keyEventTarget.addEventListener(eventName, boundKeyHandler);
}, this);
},
_unlistenKeyEventListeners: function() {
var keyHandlerTuple;
var keyEventTarget;
var eventName;
var boundKeyHandler;
while (this._boundKeyHandlers.length) {
// My kingdom for block-scope binding and destructuring assignment..
keyHandlerTuple = this._boundKeyHandlers.pop();
keyEventTarget = keyHandlerTuple[0];
eventName = keyHandlerTuple[1];
boundKeyHandler = keyHandlerTuple[2];
keyEventTarget.removeEventListener(eventName, boundKeyHandler);
}
},
_onKeyBindingEvent: function(keyBindings, event) {
keyBindings.forEach(function(keyBinding) {
var keyCombo = keyBinding[0];
var handlerName = keyBinding[1];
if (!event.defaultPrevented && keyComboMatchesEvent(keyCombo, event)) {
this._triggerKeyHandler(keyCombo, handlerName, event);
}
}, this);
},
_triggerKeyHandler: function(keyCombo, handlerName, keyboardEvent) {
var detail = Object.create(keyCombo);
detail.keyboardEvent = keyboardEvent;
this[handlerName].call(this, new CustomEvent(keyCombo.event, {
detail: detail
}));
}
};
})();
</script>
<script>
/**
* @demo demo/index.html
* @polymerBehavior
*/
Polymer.IronControlState = {
properties: {
/**
* If true, the element currently has focus.
*/
focused: {
type: Boolean,
value: false,
notify: true,
readOnly: true,
reflectToAttribute: true
},
/**
* If true, the user cannot interact with this element.
*/
disabled: {
type: Boolean,
value: false,
notify: true,
observer: '_disabledChanged',
reflectToAttribute: true
},
_oldTabIndex: {
type: Number
},
_boundFocusBlurHandler: {
type: Function,
value: function() {
return this._focusBlurHandler.bind(this);
}
}
},
observers: [
'_changedControlState(focused, disabled)'
],
ready: function() {
// TODO(sjmiles): ensure read-only property is valued so the compound
// observer will fire
if (this.focused === undefined) {
this._setFocused(false);
}
this.addEventListener('focus', this._boundFocusBlurHandler, true);
this.addEventListener('blur', this._boundFocusBlurHandler, true);
},
_focusBlurHandler: function(event) {
var target = event.path ? event.path[0] : event.target;
if (target === this) {
var focused = event.type === 'focus';
this._setFocused(focused);
} else if (!this.shadowRoot) {
event.stopPropagation();
this.fire(event.type, {sourceEvent: event}, {
node: this,
bubbles: event.bubbles,
cancelable: event.cancelable
});
}
},
_disabledChanged: function(disabled, old) {
this.setAttribute('aria-disabled', disabled ? 'true' : 'false');
this.style.pointerEvents = disabled ? 'none' : '';
if (disabled) {
this._oldTabIndex = this.tabIndex;
this.focused = false;
this.tabIndex = -1;
} else if (this._oldTabIndex !== undefined) {
this.tabIndex = this._oldTabIndex;
}
},
_changedControlState: function() {
// _controlStateChanged is abstract, follow-on behaviors may implement it
if (this._controlStateChanged) {
this._controlStateChanged();
}
}
};
</script>
<script>
/**
* @demo demo/index.html
* @polymerBehavior Polymer.IronButtonState
*/
Polymer.IronButtonStateImpl = {
properties: {
/**
* If true, the user is currently holding down the button.
*/
pressed: {
type: Boolean,
readOnly: true,
value: false,
reflectToAttribute: true,
observer: '_pressedChanged'
},
/**
* If true, the button toggles the active state with each tap or press
* of the spacebar.
*/
toggles: {
type: Boolean,
value: false,
reflectToAttribute: true
},
/**
* If true, the button is a toggle and is currently in the active state.
*/
active: {
type: Boolean,
value: false,
notify: true,
reflectToAttribute: true,
observer: '_activeChanged'
},
/**
* True if the element is currently being pressed by a "pointer," which
* is loosely defined as mouse or touch input (but specifically excluding
* keyboard input).
*/
pointerDown: {
type: Boolean,
readOnly: true,
value: false
},
/**
* True if the input device that caused the element to receive focus
* was a keyboard.
*/
receivedFocusFromKeyboard: {
type: Boolean,
readOnly: true
}
},
listeners: {
down: '_downHandler',
up: '_upHandler',
tap: '_tapHandler'
},
observers: [
'_detectKeyboardFocus(focused)'
],
keyBindings: {
'enter:keydown': '_asyncClick',
'space:keydown': '_spaceKeyDownHandler',
'space:keyup': '_spaceKeyUpHandler',
},
_tapHandler: function() {
if (this.toggles) {
// a tap is needed to toggle the active state
this._userActivate(!this.active);
} else {
this.active = false;
}
},
_detectKeyboardFocus: function(focused) {
this._setReceivedFocusFromKeyboard(!this.pointerDown && focused);
},
// to emulate native checkbox, (de-)activations from a user interaction fire
// 'change' events
_userActivate: function(active) {
this.active = active;
this.fire('change');
},
_downHandler: function() {
this._setPointerDown(true);
this._setPressed(true);
this._setReceivedFocusFromKeyboard(false);
},
_upHandler: function() {
this._setPointerDown(false);
this._setPressed(false);
},
_spaceKeyDownHandler: function(event) {
var keyboardEvent = event.detail.keyboardEvent;
keyboardEvent.preventDefault();
keyboardEvent.stopImmediatePropagation();
this._setPressed(true);
},
_spaceKeyUpHandler: function() {
if (this.pressed) {
this._asyncClick();
}
this._setPressed(false);
},
// trigger click asynchronously, the asynchrony is useful to allow one
// event handler to unwind before triggering another event
_asyncClick: function() {
this.async(function() {
this.click();
}, 1);
},
// any of these changes are considered a change to button state
_pressedChanged: function(pressed) {
this._changedButtonState();
},
_activeChanged: function(active) {
if (this.toggles) {
this.setAttribute('aria-pressed', active ? 'true' : 'false');
} else {
this.removeAttribute('aria-pressed');
}
this._changedButtonState();
},
_controlStateChanged: function() {
if (this.disabled) {
this._setPressed(false);
} else {
this._changedButtonState();
}
},
// provide hook for follow-on behaviors to react to button-state
_changedButtonState: function() {
if (this._buttonStateChanged) {
this._buttonStateChanged(); // abstract
}
}
};
/** @polymerBehavior */
Polymer.IronButtonState = [
Polymer.IronA11yKeysBehavior,
Polymer.IronButtonStateImpl
];
</script>
<script>
/** @polymerBehavior */
Polymer.PaperButtonBehaviorImpl = {
properties: {
_elevation: {
type: Number
}
},
observers: [
'_calculateElevation(focused, disabled, active, pressed, receivedFocusFromKeyboard)'
],
hostAttributes: {
role: 'button',
tabindex: '0'
},
_calculateElevation: function() {
var e = 1;
if (this.disabled) {
e = 0;
} else if (this.active || this.pressed) {
e = 4;
} else if (this.receivedFocusFromKeyboard) {
e = 3;
}
this._elevation = e;
}
};
/** @polymerBehavior */
Polymer.PaperButtonBehavior = [
Polymer.IronButtonState,
Polymer.IronControlState,
Polymer.PaperButtonBehaviorImpl
];
</script>
<style is="custom-style">
:root {
/* Shared Styles */
/*
Unfortunately, we can't make use of these yet - sibling properties aren't
evaluated. See https://github.com/Polymer/polymer/issues/1399
--paper-font-common-base: {
font-family: 'Roboto', 'Noto', sans-serif;
-webkit-font-smoothing: antialiased;
};
--paper-font-common-code: {
font-family: 'Inconsolata', 'Consolas', 'Source Code Pro', 'Monaco', 'Menlo', monospace;
-webkit-font-smoothing: antialiased;
};
--paper-font-common-expensive-kerning: {
text-rendering: optimizeLegibility;
};
--paper-font-common-nowrap: {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
};
*/
/* Material Font Styles */
--paper-font-display4: {
/* @apply(--paper-font-common-base) */
font-family: 'Roboto', 'Noto', sans-serif;
-webkit-font-smoothing: antialiased;
/* @apply(--paper-font-common-expensive-kerning); */
text-rendering: optimizeLegibility;
/* @apply(--paper-font-common-nowrap); */
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
font-size: 112px;
font-weight: 300;
letter-spacing: -.044em;
line-height: 120px;
};
--paper-font-display3: {
/* @apply(--paper-font-common-base) */
font-family: 'Roboto', 'Noto', sans-serif;
-webkit-font-smoothing: antialiased;
/* @apply(--paper-font-common-expensive-kerning); */
text-rendering: optimizeLegibility;
/* @apply(--paper-font-common-nowrap); */
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
font-size: 56px;
font-weight: 400;
letter-spacing: -.026em;
line-height: 60px;
};
--paper-font-display2: {
/* @apply(--paper-font-common-base) */
font-family: 'Roboto', 'Noto', sans-serif;
-webkit-font-smoothing: antialiased;
/* @apply(--paper-font-common-expensive-kerning); */
text-rendering: optimizeLegibility;
font-size: 45px;
font-weight: 400;
letter-spacing: -.018em;
line-height: 48px;
};
--paper-font-display1: {
/* @apply(--paper-font-common-base) */
font-family: 'Roboto', 'Noto', sans-serif;
-webkit-font-smoothing: antialiased;
/* @apply(--paper-font-common-expensive-kerning); */
text-rendering: optimizeLegibility;
font-size: 34px;
font-weight: 400;
letter-spacing: -.01em;
line-height: 40px;
};
--paper-font-headline: {
/* @apply(--paper-font-common-base) */
font-family: 'Roboto', 'Noto', sans-serif;
-webkit-font-smoothing: antialiased;
/* @apply(--paper-font-common-expensive-kerning); */
text-rendering: optimizeLegibility;
font-size: 24px;
font-weight: 400;
letter-spacing: -.012em;
line-height: 32px;
};
--paper-font-title: {
/* @apply(--paper-font-common-base) */
font-family: 'Roboto', 'Noto', sans-serif;
-webkit-font-smoothing: antialiased;
/* @apply(--paper-font-common-expensive-kerning); */
text-rendering: optimizeLegibility;
/* @apply(--paper-font-common-nowrap); */
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
font-size: 20px;
font-weight: 500;
line-height: 28px;
};
--paper-font-subhead: {
/* @apply(--paper-font-common-base) */
font-family: 'Roboto', 'Noto', sans-serif;
-webkit-font-smoothing: antialiased;
/* @apply(--paper-font-common-expensive-kerning); */
text-rendering: optimizeLegibility;
font-size: 16px;
font-weight: 400;
line-height: 24px;
};
--paper-font-body2: {
/* @apply(--paper-font-common-base) */
font-family: 'Roboto', 'Noto', sans-serif;
-webkit-font-smoothing: antialiased;
font-size: 14px;
font-weight: 500;
line-height: 24px;
};
--paper-font-body1: {
/* @apply(--paper-font-common-base) */
font-family: 'Roboto', 'Noto', sans-serif;
-webkit-font-smoothing: antialiased;
font-size: 14px;
font-weight: 400;
line-height: 20px;
};
--paper-font-caption: {
/* @apply(--paper-font-common-base) */
font-family: 'Roboto', 'Noto', sans-serif;
-webkit-font-smoothing: antialiased;
/* @apply(--paper-font-common-nowrap); */
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
font-size: 12px;
font-weight: 400;
letter-spacing: 0.011em;
line-height: 20px;
};
--paper-font-menu: {
/* @apply(--paper-font-common-base) */
font-family: 'Roboto', 'Noto', sans-serif;
-webkit-font-smoothing: antialiased;
/* @apply(--paper-font-common-expensive-kerning); */
text-rendering: optimizeLegibility;
/* @apply(--paper-font-common-nowrap); */
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
font-size: 13px;
font-weight: 500;
line-height: 24px;
};
--paper-font-button: {
/* @apply(--paper-font-common-base) */
font-family: 'Roboto', 'Noto', sans-serif;
-webkit-font-smoothing: antialiased;
/* @apply(--paper-font-common-expensive-kerning); */
text-rendering: optimizeLegibility;
/* @apply(--paper-font-common-nowrap); */
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
font-size: 14px;
font-weight: 500;
letter-spacing: 0.018em;
line-height: 24px;
text-transform: uppercase;
};
--paper-font-code2: {
/* @apply(--paper-font-common-code); */
font-family: 'Inconsolata', 'Consolas', 'Source Code Pro', 'Monaco', 'Menlo', monospace;
-webkit-font-smoothing: antialiased;
font-size: 14px;
font-weight: 700;
line-height: 20px;
};
--paper-font-code1: {
/* @apply(--paper-font-common-code); */
font-family: 'Inconsolata', 'Consolas', 'Source Code Pro', 'Monaco', 'Menlo', monospace;
-webkit-font-smoothing: antialiased;
font-size: 14px;
font-weight: 500;
line-height: 20px;
};
}
</style>
<style is="custom-style">
:root {
/* Material Design color palette for Google products */
--google-red-100: #f4c7c3;
--google-red-300: #e67c73;
--google-red-500: #db4437;
--google-red-700: #c53929;
--google-blue-100: #c6dafc;
--google-blue-300: #7baaf7;
--google-blue-500: #4285f4;
--google-blue-700: #3367d6;
--google-green-100: #b7e1cd;
--google-green-300: #57bb8a;
--google-green-500: #0f9d58;
--google-green-700: #0b8043;
--google-yellow-100: #fce8b2;
--google-yellow-300: #f7cb4d;
--google-yellow-500: #f4b400;
--google-yellow-700: #f09300;
--google-grey-100: #f5f5f5;
--google-grey-300: #e0e0e0;
--google-grey-500: #9e9e9e;
--google-grey-700: #616161;
/* Material Design color palette from online spec document */
--paper-red-50: #ffebee;
--paper-red-100: #ffcdd2;
--paper-red-200: #ef9a9a;
--paper-red-300: #e57373;
--paper-red-400: #ef5350;
--paper-red-500: #f44336;
--paper-red-600: #e53935;
--paper-red-700: #d32f2f;
--paper-red-800: #c62828;
--paper-red-900: #b71c1c;
--paper-red-a100: #ff8a80;
--paper-red-a200: #ff5252;
--paper-red-a400: #ff1744;
--paper-red-a700: #d50000;
--paper-pink-50: #fce4ec;
--paper-pink-100: #f8bbd0;
--paper-pink-200: #f48fb1;
--paper-pink-300: #f06292;
--paper-pink-400: #ec407a;
--paper-pink-500: #e91e63;
--paper-pink-600: #d81b60;
--paper-pink-700: #c2185b;
--paper-pink-800: #ad1457;
--paper-pink-900: #880e4f;
--paper-pink-a100: #ff80ab;
--paper-pink-a200: #ff4081;
--paper-pink-a400: #f50057;
--paper-pink-a700: #c51162;
--paper-purple-50: #f3e5f5;
--paper-purple-100: #e1bee7;
--paper-purple-200: #ce93d8;
--paper-purple-300: #ba68c8;
--paper-purple-400: #ab47bc;
--paper-purple-500: #9c27b0;
--paper-purple-600: #8e24aa;
--paper-purple-700: #7b1fa2;
--paper-purple-800: #6a1b9a;
--paper-purple-900: #4a148c;
--paper-purple-a100: #ea80fc;
--paper-purple-a200: #e040fb;
--paper-purple-a400: #d500f9;
--paper-purple-a700: #aa00ff;
--paper-deep-purple-50: #ede7f6;
--paper-deep-purple-100: #d1c4e9;
--paper-deep-purple-200: #b39ddb;
--paper-deep-purple-300: #9575cd;
--paper-deep-purple-400: #7e57c2;
--paper-deep-purple-500: #673ab7;
--paper-deep-purple-600: #5e35b1;
--paper-deep-purple-700: #512da8;
--paper-deep-purple-800: #4527a0;
--paper-deep-purple-900: #311b92;
--paper-deep-purple-a100: #b388ff;
--paper-deep-purple-a200: #7c4dff;
--paper-deep-purple-a400: #651fff;
--paper-deep-purple-a700: #6200ea;
--paper-indigo-50: #e8eaf6;
--paper-indigo-100: #c5cae9;
--paper-indigo-200: #9fa8da;
--paper-indigo-300: #7986cb;
--paper-indigo-400: #5c6bc0;
--paper-indigo-500: #3f51b5;
--paper-indigo-600: #3949ab;
--paper-indigo-700: #303f9f;
--paper-indigo-800: #283593;
--paper-indigo-900: #1a237e;
--paper-indigo-a100: #8c9eff;
--paper-indigo-a200: #536dfe;
--paper-indigo-a400: #3d5afe;
--paper-indigo-a700: #304ffe;
--paper-blue-50: #e3f2fd;
--paper-blue-100: #bbdefb;
--paper-blue-200: #90caf9;
--paper-blue-300: #64b5f6;
--paper-blue-400: #42a5f5;
--paper-blue-500: #2196f3;
--paper-blue-600: #1e88e5;
--paper-blue-700: #1976d2;
--paper-blue-800: #1565c0;
--paper-blue-900: #0d47a1;
--paper-blue-a100: #82b1ff;
--paper-blue-a200: #448aff;
--paper-blue-a400: #2979ff;
--paper-blue-a700: #2962ff;
--paper-light-blue-50: #e1f5fe;
--paper-light-blue-100: #b3e5fc;
--paper-light-blue-200: #81d4fa;
--paper-light-blue-300: #4fc3f7;
--paper-light-blue-400: #29b6f6;
--paper-light-blue-500: #03a9f4;
--paper-light-blue-600: #039be5;
--paper-light-blue-700: #0288d1;
--paper-light-blue-800: #0277bd;
--paper-light-blue-900: #01579b;
--paper-light-blue-a100: #80d8ff;
--paper-light-blue-a200: #40c4ff;
--paper-light-blue-a400: #00b0ff;
--paper-light-blue-a700: #0091ea;
--paper-cyan-50: #e0f7fa;
--paper-cyan-100: #b2ebf2;
--paper-cyan-200: #80deea;
--paper-cyan-300: #4dd0e1;
--paper-cyan-400: #26c6da;
--paper-cyan-500: #00bcd4;
--paper-cyan-600: #00acc1;
--paper-cyan-700: #0097a7;
--paper-cyan-800: #00838f;
--paper-cyan-900: #006064;
--paper-cyan-a100: #84ffff;
--paper-cyan-a200: #18ffff;
--paper-cyan-a400: #00e5ff;
--paper-cyan-a700: #00b8d4;
--paper-teal-50: #e0f2f1;
--paper-teal-100: #b2dfdb;
--paper-teal-200: #80cbc4;
--paper-teal-300: #4db6ac;
--paper-teal-400: #26a69a;
--paper-teal-500: #009688;
--paper-teal-600: #00897b;
--paper-teal-700: #00796b;
--paper-teal-800: #00695c;
--paper-teal-900: #004d40;
--paper-teal-a100: #a7ffeb;
--paper-teal-a200: #64ffda;
--paper-teal-a400: #1de9b6;
--paper-teal-a700: #00bfa5;
--paper-green-50: #e8f5e9;
--paper-green-100: #c8e6c9;
--paper-green-200: #a5d6a7;
--paper-green-300: #81c784;
--paper-green-400: #66bb6a;
--paper-green-500: #4caf50;
--paper-green-600: #43a047;
--paper-green-700: #388e3c;
--paper-green-800: #2e7d32;
--paper-green-900: #1b5e20;
--paper-green-a100: #b9f6ca;
--paper-green-a200: #69f0ae;
--paper-green-a400: #00e676;
--paper-green-a700: #00c853;
--paper-light-green-50: #f1f8e9;
--paper-light-green-100: #dcedc8;
--paper-light-green-200: #c5e1a5;
--paper-light-green-300: #aed581;
--paper-light-green-400: #9ccc65;
--paper-light-green-500: #8bc34a;
--paper-light-green-600: #7cb342;
--paper-light-green-700: #689f38;
--paper-light-green-800: #558b2f;
--paper-light-green-900: #33691e;
--paper-light-green-a100: #ccff90;
--paper-light-green-a200: #b2ff59;
--paper-light-green-a400: #76ff03;
--paper-light-green-a700: #64dd17;
--paper-lime-50: #f9fbe7;
--paper-lime-100: #f0f4c3;
--paper-lime-200: #e6ee9c;
--paper-lime-300: #dce775;
--paper-lime-400: #d4e157;
--paper-lime-500: #cddc39;
--paper-lime-600: #c0ca33;
--paper-lime-700: #afb42b;
--paper-lime-800: #9e9d24;
--paper-lime-900: #827717;
--paper-lime-a100: #f4ff81;
--paper-lime-a200: #eeff41;
--paper-lime-a400: #c6ff00;
--paper-lime-a700: #aeea00;
--paper-yellow-50: #fffde7;
--paper-yellow-100: #fff9c4;
--paper-yellow-200: #fff59d;
--paper-yellow-300: #fff176;
--paper-yellow-400: #ffee58;
--paper-yellow-500: #ffeb3b;
--paper-yellow-600: #fdd835;
--paper-yellow-700: #fbc02d;
--paper-yellow-800: #f9a825;
--paper-yellow-900: #f57f17;
--paper-yellow-a100: #ffff8d;
--paper-yellow-a200: #ffff00;
--paper-yellow-a400: #ffea00;
--paper-yellow-a700: #ffd600;
--paper-amber-50: #fff8e1;
--paper-amber-100: #ffecb3;
--paper-amber-200: #ffe082;
--paper-amber-300: #ffd54f;
--paper-amber-400: #ffca28;
--paper-amber-500: #ffc107;
--paper-amber-600: #ffb300;
--paper-amber-700: #ffa000;
--paper-amber-800: #ff8f00;
--paper-amber-900: #ff6f00;
--paper-amber-a100: #ffe57f;
--paper-amber-a200: #ffd740;
--paper-amber-a400: #ffc400;
--paper-amber-a700: #ffab00;
--paper-orange-50: #fff3e0;
--paper-orange-100: #ffe0b2;
--paper-orange-200: #ffcc80;
--paper-orange-300: #ffb74d;
--paper-orange-400: #ffa726;
--paper-orange-500: #ff9800;
--paper-orange-600: #fb8c00;
--paper-orange-700: #f57c00;
--paper-orange-800: #ef6c00;
--paper-orange-900: #e65100;
--paper-orange-a100: #ffd180;
--paper-orange-a200: #ffab40;
--paper-orange-a400: #ff9100;
--paper-orange-a700: #ff6500;
--paper-deep-orange-50: #ff5722;
--paper-deep-orange-100: #fbe9e7;
--paper-deep-orange-200: #ffccbc;
--paper-deep-orange-300: #ff8a65;
--paper-deep-orange-400: #ff7043;
--paper-deep-orange-500: #ff5722;
--paper-deep-orange-600: #f4511e;
--paper-deep-orange-700: #e64a19;
--paper-deep-orange-800: #d84315;
--paper-deep-orange-900: #bf360c;
--paper-deep-orange-a100: #ff9e80;
--paper-deep-orange-a200: #ff6e40;
--paper-deep-orange-a400: #ff3d00;
--paper-deep-orange-a700: #dd2c00;
--paper-brown-50: #efebe9;
--paper-brown-100: #d7ccc8;
--paper-brown-200: #bcaaa4;
--paper-brown-300: #a1887f;
--paper-brown-400: #8d6e63;
--paper-brown-500: #795548;
--paper-brown-600: #6d4c41;
--paper-brown-700: #5d4037;
--paper-brown-800: #4e342e;
--paper-brown-900: #3e2723;
--paper-grey-50: #fafafa;
--paper-grey-100: #f5f5f5;
--paper-grey-200: #eeeeee;
--paper-grey-300: #e0e0e0;
--paper-grey-400: #bdbdbd;
--paper-grey-500: #9e9e9e;
--paper-grey-600: #757575;
--paper-grey-700: #616161;
--paper-grey-800: #424242;
--paper-grey-900: #212121;
--paper-blue-grey-50: #eceff1;
--paper-blue-grey-100: #cfd8dc;
--paper-blue-grey-200: #b0bec5;
--paper-blue-grey-300: #90a4ae;
--paper-blue-grey-400: #78909c;
--paper-blue-grey-500: #607d8b;
--paper-blue-grey-600: #546e7a;
--paper-blue-grey-700: #455a64;
--paper-blue-grey-800: #37474f;
--paper-blue-grey-900: #263238;
/* opacity for dark text on a light background */
--dark-divider-opacity: 0.12;
--dark-disabled-opacity: 0.26; /* or hint text */
--dark-secondary-opacity: 0.54; /* or icon */
--dark-primary-opacity: 0.87;
/* opacity for light text on a dark background */
--light-divider-opacity: 0.12;
--light-disabled-opacity: 0.3; /* or hint text */
--light-secondary-opacity: 0.7; /* or icon */
--light-primary-opacity: 1.0;
}
</style>
<style is="custom-style">
:root {
--layout: {
display: -ms-flexbox;
display: -webkit-flex;
display: flex;
};
--layout-inline: {
display: -ms-inline-flexbox;
display: -webkit-inline-flex;
display: inline-flex;
};
--layout-horizontal: {
/* @apply(--layout); */
display: -ms-flexbox;
display: -webkit-flex;
display: flex;
-ms-flex-direction: row;
-webkit-flex-direction: row;
flex-direction: row;
};
--layout-horizontal-reverse: {
-ms-flex-direction: row-reverse;
-webkit-flex-direction: row-reverse;
flex-direction: row-reverse;
};
--layout-vertical: {
/* @apply(--layout); */
display: -ms-flexbox;
display: -webkit-flex;
display: flex;
-ms-flex-direction: column;
-webkit-flex-direction: column;
flex-direction: column;
};
--layout-vertical-reverse: {
-ms-flex-direction: column-reverse;
-webkit-flex-direction: column-reverse;
flex-direction: column-reverse;
};
--layout-wrap: {
-ms-flex-wrap: wrap;
-webkit-flex-wrap: wrap;
flex-wrap: wrap;
};
--layout-wrap-reverse: {
-ms-flex-wrap: wrap-reverse;
-webkit-flex-wrap: wrap-reverse;
flex-wrap: wrap-reverse;
};
--layout-flex-auto: {
-ms-flex: 1 1 auto;
-webkit-flex: 1 1 auto;
flex: 1 1 auto;
};
--layout-flex-none: {
-ms-flex: none;
-webkit-flex: none;
flex: none;
};
--layout-flex: {
-ms-flex: 1 1 0.000000001px;
-webkit-flex: 1;
flex: 1;
-webkit-flex-basis: 0.000000001px;
flex-basis: 0.000000001px;
};
--layout-flex-2: {
-ms-flex: 2;
-webkit-flex: 2;
flex: 2;
};
--layout-flex-3: {
-ms-flex: 3;
-webkit-flex: 3;
flex: 3;
};
--layout-flex-4: {
-ms-flex: 4;
-webkit-flex: 4;
flex: 4;
};
--layout-flex-5: {
-ms-flex: 5;
-webkit-flex: 5;
flex: 5;
};
--layout-flex-6: {
-ms-flex: 6;
-webkit-flex: 6;
flex: 6;
};
--layout-flex-7: {
-ms-flex: 7;
-webkit-flex: 7;
flex: 7;
};
--layout-flex-8: {
-ms-flex: 8;
-webkit-flex: 8;
flex: 8;
};
--layout-flex-9: {
-ms-flex: 9;
-webkit-flex: 9;
flex: 9;
};
--layout-flex-10: {
-ms-flex: 10;
-webkit-flex: 10;
flex: 10;
};
--layout-flex-11: {
-ms-flex: 11;
-webkit-flex: 11;
flex: 11;
};
--layout-flex-12: {
-ms-flex: 12;
-webkit-flex: 12;
flex: 12;
};
/* alignment in cross axis */
--layout-start: {
-ms-flex-align: start;
-webkit-align-items: flex-start;
align-items: flex-start;
};
--layout-center: {
-ms-flex-align: center;
-webkit-align-items: center;
align-items: center;
};
--layout-end: {
-ms-flex-align: end;
-webkit-align-items: flex-end;
align-items: flex-end;
};
/* alignment in main axis */
--layout-start-justified: {
-ms-flex-pack: start;
-webkit-justify-content: flex-start;
justify-content: flex-start;
};
--layout-center-justified: {
-ms-flex-pack: center;
-webkit-justify-content: center;
justify-content: center;
};
--layout-end-justified: {
-ms-flex-pack: end;
-webkit-justify-content: flex-end;
justify-content: flex-end;
};
--layout-around-justified: {
-ms-flex-pack: around;
-webkit-justify-content: space-around;
justify-content: space-around;
};
--layout-justified: {
-ms-flex-pack: justify;
-webkit-justify-content: space-between;
justify-content: space-between;
};
--layout-center-center: {
/* @apply(--layout-center --layout-center-justified); */
-ms-flex-align: center;
-webkit-align-items: center;
align-items: center;
-ms-flex-pack: center;
-webkit-justify-content: center;
justify-content: center;
};
/* self alignment */
--layout-self-start: {
-ms-align-self: flex-start;
-webkit-align-self: flex-start;
align-self: flex-start;
};
--layout-self-center: {
-ms-align-self: center;
-webkit-align-self: center;
align-self: center;
};
--layout-self-end: {
-ms-align-self: flex-end;
-webkit-align-self: flex-end;
align-self: flex-end;
};
--layout-self-stretch: {
-ms-align-self: stretch;
-webkit-align-self: stretch;
align-self: stretch;
};
/*******************************
Other Layout
*******************************/
--layout-block: {
display: block;
};
--layout-invisible: {
visibility: hidden !important;
};
--layout-relative: {
position: relative;
};
--layout-fit: {
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
};
--layout-scroll: {
-webkit-overflow-scrolling: touch;
overflow: auto;
};
/* fixed position */
--layout-fixed-bottom:,
--layout-fixed-left:,
--layout-fixed-right:,
--layout-fixed-top: {
position: fixed;
};
--layout-fixed-top: {
top: 0;
left: 0;
right: 0;
};
--layout-fixed-right: {
top: 0;
right: 0;
bottom: 0;
};
--layout-fixed-bottom: {
right: 0;
bottom: 0;
left: 0;
};
--layout-fixed-left: {
top: 0;
bottom: 0;
left: 0;
};
}
</style>
<script>
(function() {
// monostate data
var metaDatas = {};
var metaArrays = {};
Polymer.IronMeta = Polymer({
is: 'iron-meta',
properties: {
/**
* The type of meta-data. All meta-data of the same type is stored
* together.
*/
type: {
type: String,
value: 'default',
observer: '_typeChanged'
},
/**
* The key used to store `value` under the `type` namespace.
*/
key: {
type: String,
observer: '_keyChanged'
},
/**
* The meta-data to store or retrieve.
*/
value: {
type: Object,
notify: true,
observer: '_valueChanged'
},
/**
* If true, `value` is set to the iron-meta instance itself.
*/
self: {
type: Boolean,
observer: '_selfChanged'
},
/**
* Array of all meta-data values for the given type.
*/
list: {
type: Array,
notify: true
}
},
/**
* Only runs if someone invokes the factory/constructor directly
* e.g. `new Polymer.IronMeta()`
*/
factoryImpl: function(config) {
if (config) {
for (var n in config) {
switch(n) {
case 'type':
case 'key':
case 'value':
this[n] = config[n];
break;
}
}
}
},
created: function() {
// TODO(sjmiles): good for debugging?
this._metaDatas = metaDatas;
this._metaArrays = metaArrays;
},
_keyChanged: function(key, old) {
this._resetRegistration(old);
},
_valueChanged: function(value) {
this._resetRegistration(this.key);
},
_selfChanged: function(self) {
if (self) {
this.value = this;
}
},
_typeChanged: function(type) {
this._unregisterKey(this.key);
if (!metaDatas[type]) {
metaDatas[type] = {};
}
this._metaData = metaDatas[type];
if (!metaArrays[type]) {
metaArrays[type] = [];
}
this.list = metaArrays[type];
this._registerKeyValue(this.key, this.value);
},
/**
* Retrieves meta data value by key.
*
* @method byKey
* @param {String} key The key of the meta-data to be returned.
* @returns *
*/
byKey: function(key) {
return this._metaData && this._metaData[key];
},
_resetRegistration: function(oldKey) {
this._unregisterKey(oldKey);
this._registerKeyValue(this.key, this.value);
},
_unregisterKey: function(key) {
this._unregister(key, this._metaData, this.list);
},
_registerKeyValue: function(key, value) {
this._register(key, value, this._metaData, this.list);
},
_register: function(key, value, data, list) {
if (key && data && value !== undefined) {
data[key] = value;
list.push(value);
}
},
_unregister: function(key, data, list) {
if (key && data) {
if (key in data) {
var value = data[key];
delete data[key];
this.arrayDelete(list, value);
}
}
}
});
/**
`iron-meta-query` can be used to access infomation stored in `iron-meta`.
Examples:
If I create an instance like this:
<iron-meta key="info" value="foo/bar"></iron-meta>
Note that value="foo/bar" is the metadata I've defined. I could define more
attributes or use child nodes to define additional metadata.
Now I can access that element (and it's metadata) from any `iron-meta-query` instance:
var value = new Polymer.IronMetaQuery({key: 'info'}).value;
@group Polymer Iron Elements
@element iron-meta-query
*/
Polymer.IronMetaQuery = Polymer({
is: 'iron-meta-query',
properties: {
/**
* The type of meta-data. All meta-data of the same type is stored
* together.
*/
type: {
type: String,
value: 'default',
observer: '_typeChanged'
},
/**
* Specifies a key to use for retrieving `value` from the `type`
* namespace.
*/
key: {
type: String,
observer: '_keyChanged'
},
/**
* The meta-data to store or retrieve.
*/
value: {
type: Object,
notify: true,
readOnly: true
},
/**
* Array of all meta-data values for the given type.
*/
list: {
type: Array,
notify: true
}
},
/**
* Actually a factory method, not a true constructor. Only runs if
* someone invokes it directly (via `new Polymer.IronMeta()`);
*/
factoryImpl: function(config) {
if (config) {
for (var n in config) {
switch(n) {
case 'type':
case 'key':
this[n] = config[n];
break;
}
}
}
},
created: function() {
// TODO(sjmiles): good for debugging?
this._metaDatas = metaDatas;
this._metaArrays = metaArrays;
},
_keyChanged: function(key) {
this._setValue(this._metaData && this._metaData[key]);
},
_typeChanged: function(type) {
this._metaData = metaDatas[type];
this.list = metaArrays[type];
if (this.key) {
this._keyChanged(this.key);
}
},
/**
* Retrieves meta data value by key.
*/
byKey: function(key) {
return this._metaData && this._metaData[key];
}
});
})();
</script>
<style>
/*******************************
Flex Layout
*******************************/
html /deep/ .layout.horizontal,
html /deep/ .layout.horizontal-reverse,
html /deep/ .layout.vertical,
html /deep/ .layout.vertical-reverse {
display: -ms-flexbox;
display: -webkit-flex;
display: flex;
}
html /deep/ .layout.inline {
display: -ms-inline-flexbox;
display: -webkit-inline-flex;
display: inline-flex;
}
html /deep/ .layout.horizontal {
-ms-flex-direction: row;
-webkit-flex-direction: row;
flex-direction: row;
}
html /deep/ .layout.horizontal-reverse {
-ms-flex-direction: row-reverse;
-webkit-flex-direction: row-reverse;
flex-direction: row-reverse;
}
html /deep/ .layout.vertical {
-ms-flex-direction: column;
-webkit-flex-direction: column;
flex-direction: column;
}
html /deep/ .layout.vertical-reverse {
-ms-flex-direction: column-reverse;
-webkit-flex-direction: column-reverse;
flex-direction: column-reverse;
}
html /deep/ .layout.wrap {
-ms-flex-wrap: wrap;
-webkit-flex-wrap: wrap;
flex-wrap: wrap;
}
html /deep/ .layout.wrap-reverse {
-ms-flex-wrap: wrap-reverse;
-webkit-flex-wrap: wrap-reverse;
flex-wrap: wrap-reverse;
}
html /deep/ .flex-auto {
-ms-flex: 1 1 auto;
-webkit-flex: 1 1 auto;
flex: 1 1 auto;
}
html /deep/ .flex-none {
-ms-flex: none;
-webkit-flex: none;
flex: none;
}
html /deep/ .flex,
html /deep/ .flex-1 {
-ms-flex: 1;
-webkit-flex: 1;
flex: 1;
}
html /deep/ .flex-2 {
-ms-flex: 2;
-webkit-flex: 2;
flex: 2;
}
html /deep/ .flex-3 {
-ms-flex: 3;
-webkit-flex: 3;
flex: 3;
}
html /deep/ .flex-4 {
-ms-flex: 4;
-webkit-flex: 4;
flex: 4;
}
html /deep/ .flex-5 {
-ms-flex: 5;
-webkit-flex: 5;
flex: 5;
}
html /deep/ .flex-6 {
-ms-flex: 6;
-webkit-flex: 6;
flex: 6;
}
html /deep/ .flex-7 {
-ms-flex: 7;
-webkit-flex: 7;
flex: 7;
}
html /deep/ .flex-8 {
-ms-flex: 8;
-webkit-flex: 8;
flex: 8;
}
html /deep/ .flex-9 {
-ms-flex: 9;
-webkit-flex: 9;
flex: 9;
}
html /deep/ .flex-10 {
-ms-flex: 10;
-webkit-flex: 10;
flex: 10;
}
html /deep/ .flex-11 {
-ms-flex: 11;
-webkit-flex: 11;
flex: 11;
}
html /deep/ .flex-12 {
-ms-flex: 12;
-webkit-flex: 12;
flex: 12;
}
/* alignment in cross axis */
html /deep/ .layout.start {
-ms-flex-align: start;
-webkit-align-items: flex-start;
align-items: flex-start;
}
html /deep/ .layout.center,
html /deep/ .layout.center-center {
-ms-flex-align: center;
-webkit-align-items: center;
align-items: center;
}
html /deep/ .layout.end {
-ms-flex-align: end;
-webkit-align-items: flex-end;
align-items: flex-end;
}
/* alignment in main axis */
html /deep/ .layout.start-justified {
-ms-flex-pack: start;
-webkit-justify-content: flex-start;
justify-content: flex-start;
}
html /deep/ .layout.center-justified,
html /deep/ .layout.center-center {
-ms-flex-pack: center;
-webkit-justify-content: center;
justify-content: center;
}
html /deep/ .layout.end-justified {
-ms-flex-pack: end;
-webkit-justify-content: flex-end;
justify-content: flex-end;
}
html /deep/ .layout.around-justified {
-ms-flex-pack: around;
-webkit-justify-content: space-around;
justify-content: space-around;
}
html /deep/ .layout.justified {
-ms-flex-pack: justify;
-webkit-justify-content: space-between;
justify-content: space-between;
}
/* self alignment */
html /deep/ .self-start {
-ms-align-self: flex-start;
-webkit-align-self: flex-start;
align-self: flex-start;
}
html /deep/ .self-center {
-ms-align-self: center;
-webkit-align-self: center;
align-self: center;
}
html /deep/ .self-end {
-ms-align-self: flex-end;
-webkit-align-self: flex-end;
align-self: flex-end;
}
html /deep/ .self-stretch {
-ms-align-self: stretch;
-webkit-align-self: stretch;
align-self: stretch;
}
/*******************************
Other Layout
*******************************/
html /deep/ .block {
display: block;
}
/* IE 10 support for HTML5 hidden attr */
html /deep/ [hidden] {
display: none !important;
}
html /deep/ .invisible {
visibility: hidden !important;
}
html /deep/ .relative {
position: relative;
}
html /deep/ .fit {
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
}
body.fullbleed {
margin: 0;
height: 100vh;
}
html /deep/ .scroll {
-webkit-overflow-scrolling: touch;
overflow: auto;
}
.fixed-bottom,
.fixed-left,
.fixed-right,
.fixed-top {
position: fixed;
}
html /deep/ .fixed-top {
top: 0;
left: 0;
right: 0;
}
html /deep/ .fixed-right {
top: 0;
right: 0;
botttom: 0;
}
html /deep/ .fixed-bottom {
right: 0;
bottom: 0;
left: 0;
}
html /deep/ .fixed-left {
top: 0;
botttom: 0;
left: 0;
}
</style>
<style>
/*******************************
Flex Layout
*******************************/
.layout.horizontal,
.layout.horizontal-reverse,
.layout.vertical,
.layout.vertical-reverse {
display: -ms-flexbox;
display: -webkit-flex;
display: flex;
}
.layout.inline {
display: -ms-inline-flexbox;
display: -webkit-inline-flex;
display: inline-flex;
}
.layout.horizontal {
-ms-flex-direction: row;
-webkit-flex-direction: row;
flex-direction: row;
}
.layout.horizontal-reverse {
-ms-flex-direction: row-reverse;
-webkit-flex-direction: row-reverse;
flex-direction: row-reverse;
}
.layout.vertical {
-ms-flex-direction: column;
-webkit-flex-direction: column;
flex-direction: column;
}
.layout.vertical-reverse {
-ms-flex-direction: column-reverse;
-webkit-flex-direction: column-reverse;
flex-direction: column-reverse;
}
.layout.wrap {
-ms-flex-wrap: wrap;
-webkit-flex-wrap: wrap;
flex-wrap: wrap;
}
.layout.wrap-reverse {
-ms-flex-wrap: wrap-reverse;
-webkit-flex-wrap: wrap-reverse;
flex-wrap: wrap-reverse;
}
.flex-auto {
-ms-flex: 1 1 auto;
-webkit-flex: 1 1 auto;
flex: 1 1 auto;
}
.flex-none {
-ms-flex: none;
-webkit-flex: none;
flex: none;
}
.flex,
.flex-1 {
-ms-flex: 1;
-webkit-flex: 1;
flex: 1;
}
.flex-2 {
-ms-flex: 2;
-webkit-flex: 2;
flex: 2;
}
.flex-3 {
-ms-flex: 3;
-webkit-flex: 3;
flex: 3;
}
.flex-4 {
-ms-flex: 4;
-webkit-flex: 4;
flex: 4;
}
.flex-5 {
-ms-flex: 5;
-webkit-flex: 5;
flex: 5;
}
.flex-6 {
-ms-flex: 6;
-webkit-flex: 6;
flex: 6;
}
.flex-7 {
-ms-flex: 7;
-webkit-flex: 7;
flex: 7;
}
.flex-8 {
-ms-flex: 8;
-webkit-flex: 8;
flex: 8;
}
.flex-9 {
-ms-flex: 9;
-webkit-flex: 9;
flex: 9;
}
.flex-10 {
-ms-flex: 10;
-webkit-flex: 10;
flex: 10;
}
.flex-11 {
-ms-flex: 11;
-webkit-flex: 11;
flex: 11;
}
.flex-12 {
-ms-flex: 12;
-webkit-flex: 12;
flex: 12;
}
/* alignment in cross axis */
.layout.start {
-ms-flex-align: start;
-webkit-align-items: flex-start;
align-items: flex-start;
}
.layout.center,
.layout.center-center {
-ms-flex-align: center;
-webkit-align-items: center;
align-items: center;
}
.layout.end {
-ms-flex-align: end;
-webkit-align-items: flex-end;
align-items: flex-end;
}
/* alignment in main axis */
.layout.start-justified {
-ms-flex-pack: start;
-webkit-justify-content: flex-start;
justify-content: flex-start;
}
.layout.center-justified,
.layout.center-center {
-ms-flex-pack: center;
-webkit-justify-content: center;
justify-content: center;
}
.layout.end-justified {
-ms-flex-pack: end;
-webkit-justify-content: flex-end;
justify-content: flex-end;
}
.layout.around-justified {
-ms-flex-pack: around;
-webkit-justify-content: space-around;
justify-content: space-around;
}
.layout.justified {
-ms-flex-pack: justify;
-webkit-justify-content: space-between;
justify-content: space-between;
}
/* self alignment */
.self-start {
-ms-align-self: flex-start;
-webkit-align-self: flex-start;
align-self: flex-start;
}
.self-center {
-ms-align-self: center;
-webkit-align-self: center;
align-self: center;
}
.self-end {
-ms-align-self: flex-end;
-webkit-align-self: flex-end;
align-self: flex-end;
}
.self-stretch {
-ms-align-self: stretch;
-webkit-align-self: stretch;
align-self: stretch;
}
/*******************************
Other Layout
*******************************/
.block {
display: block;
}
/* IE 10 support for HTML5 hidden attr */
[hidden] {
display: none !important;
}
.invisible {
visibility: hidden !important;
}
.relative {
position: relative;
}
.fit {
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
}
body.fullbleed {
margin: 0;
height: 100vh;
}
.scroll {
-webkit-overflow-scrolling: touch;
overflow: auto;
}
/* fixed position */
.fixed-bottom,
.fixed-left,
.fixed-right,
.fixed-top {
position: fixed;
}
.fixed-top {
top: 0;
left: 0;
right: 0;
}
.fixed-right {
top: 0;
right: 0;
bottom: 0;
}
.fixed-bottom {
right: 0;
bottom: 0;
left: 0;
}
.fixed-left {
top: 0;
bottom: 0;
left: 0;
}
</style>
<style is="custom-style">
:root {
--dark-primary-color: #303f9f;
--default-primary-color: #3f51b5;
--light-primary-color: #c5cae9;
--text-primary-color: #ffffff;
--accent-color: #ff4081;
--primary-background-color: #ffffff;
--primary-text-color: #212121;
--secondary-text-color: #757575;
--disabled-text-color: #bdbdbd;
--divider-color: #e0e0e0;
}
</style>
<script>
/**
* Use `Polymer.NeonAnimationBehavior` to implement an animation.
* @polymerBehavior
*/
Polymer.NeonAnimationBehavior = {
properties: {
/**
* Defines the animation timing.
*/
animationTiming: {
type: Object,
value: function() {
return {
duration: 500,
easing: 'cubic-bezier(0.4, 0, 0.2, 1)',
fill: 'both'
}
}
}
},
registered: function() {
new Polymer.IronMeta({type: 'animation', key: this.is, value: this.constructor});
},
/**
* Do any animation configuration here.
*/
// configure: function(config) {
// },
/**
* Returns the animation timing by mixing in properties from `config` to the defaults defined
* by the animation.
*/
timingFromConfig: function(config) {
if (config.timing) {
for (var property in config.timing) {
this.animationTiming[property] = config.timing[property];
}
}
return this.animationTiming;
},
/**
* Sets `transform` and `transformOrigin` properties along with the prefixed versions.
*/
setPrefixedProperty: function(node, property, value) {
var map = {
'transform': ['webkitTransform'],
'transformOrigin': ['mozTransformOrigin', 'webkitTransformOrigin']
};
var prefixes = map[property];
for (var prefix, index = 0; prefix = prefixes[index]; index++) {
node.style[prefix] = value;
}
node.style[property] = value;
},
/**
* Called when the animation finishes.
*/
complete: function() {
// FIXME not sure about non-bubbling event
this.fire(this.animationEndEvent, null, {bubbles: false});
}
};
</script>
<script>// Copyright 2014 Google Inc. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
!function(a,b){b["true"]=a;var c={},d={},e={},f=null;!function(a){function b(a){if("number"==typeof a)return a;var b={};for(var c in a)b[c]=a[c];return b}function c(b,c){var d={delay:0,endDelay:0,fill:c?"both":"none",iterationStart:0,iterations:1,duration:c?"auto":0,playbackRate:1,direction:"normal",easing:"linear"};return"number"!=typeof b||isNaN(b)?void 0!==b&&Object.getOwnPropertyNames(b).forEach(function(c){if("auto"!=b[c]){if(("number"==typeof d[c]||"duration"==c)&&("number"!=typeof b[c]||isNaN(b[c])))return;if("fill"==c&&-1==q.indexOf(b[c]))return;if("direction"==c&&-1==r.indexOf(b[c]))return;if("playbackRate"==c&&1!==b[c]&&a.isDeprecated("AnimationEffectTiming.playbackRate","2014-11-28","Use Animation.playbackRate instead."))return;d[c]=b[c]}}):d.duration=b,d}function d(a,b){var d=c(a,b);return d.easing=g(d.easing),d}function e(a,b,c,d){return 0>a||a>1||0>c||c>1?z:function(e){function f(a,b,c){return 3*a*(1-c)*(1-c)*c+3*b*(1-c)*c*c+c*c*c}if(0==e||1==e)return e;for(var g=0,h=1;;){var i=(g+h)/2,j=f(a,c,i);if(Math.abs(e-j)<.001)return f(b,d,i);e>j?g=i:h=i}}}function f(a,b){return function(c){if(c>=1)return 1;var d=1/a;return c+=b*d,c-c%d}}function g(a){var b=x.exec(a);if(b)return e.apply(this,b.slice(1).map(Number));var c=y.exec(a);if(c)return f(Number(c[1]),{start:s,middle:t,end:u}[c[2]]);var d=v[a];return d?d:z}function h(a){return Math.abs(i(a)/a.playbackRate)}function i(a){return a.duration*a.iterations}function j(a,b,c){return null==b?A:b<c.delay?B:b>=c.delay+a?C:D}function k(a,b,c,d,e){switch(d){case B:return"backwards"==b||"both"==b?0:null;case D:return c-e;case C:return"forwards"==b||"both"==b?a:null;case A:return null}}function l(a,b,c,d){return(d.playbackRate<0?b-a:b)*d.playbackRate+c}function m(a,b,c,d,e){return 1/0===c||c===-1/0||c-d==b&&e.iterations&&(e.iterations+e.iterationStart)%1==0?a:c%a}function n(a,b,c,d){return 0===c?0:b==a?d.iterationStart+d.iterations-1:Math.floor(c/a)}function o(a,b,c,d){var e=a%2>=1,f="normal"==d.direction||d.direction==(e?"alternate-reverse":"alternate"),g=f?c:b-c,h=g/b;return b*d.easing(h)}function p(a,b,c){var d=j(a,b,c),e=k(a,c.fill,b,d,c.delay);if(null===e)return null;if(0===a)return d===B?0:1;var f=c.iterationStart*c.duration,g=l(a,e,f,c),h=m(c.duration,i(c),g,f,c),p=n(c.duration,h,g,c);return o(p,c.duration,h,c)/c.duration}var q="backwards|forwards|both|none".split("|"),r="reverse|alternate|alternate-reverse".split("|"),s=1,t=.5,u=0,v={ease:e(.25,.1,.25,1),"ease-in":e(.42,0,1,1),"ease-out":e(0,0,.58,1),"ease-in-out":e(.42,0,.58,1),"step-start":f(1,s),"step-middle":f(1,t),"step-end":f(1,u)},w="\\s*(-?\\d+\\.?\\d*|-?\\.\\d+)\\s*",x=new RegExp("cubic-bezier\\("+w+","+w+","+w+","+w+"\\)"),y=/steps\(\s*(\d+)\s*,\s*(start|middle|end)\s*\)/,z=function(a){return a},A=0,B=1,C=2,D=3;a.cloneTimingInput=b,a.makeTiming=c,a.normalizeTimingInput=d,a.calculateActiveDuration=h,a.calculateTimeFraction=p,a.calculatePhase=j,a.toTimingFunction=g}(c,f),function(a){function b(a,b){return a in h?h[a][b]||b:b}function c(a,c,d){var g=e[a];if(g){f.style[a]=c;for(var h in g){var i=g[h],j=f.style[i];d[i]=b(i,j)}}else d[a]=b(a,c)}function d(b){function d(){var a=e.length;null==e[a-1].offset&&(e[a-1].offset=1),a>1&&null==e[0].offset&&(e[0].offset=0);for(var b=0,c=e[0].offset,d=1;a>d;d++){var f=e[d].offset;if(null!=f){for(var g=1;d-b>g;g++)e[b+g].offset=c+(f-c)*g/(d-b);b=d,c=f}}}if(!Array.isArray(b)&&null!==b)throw new TypeError("Keyframes must be null or an array of keyframes");if(null==b)return[];for(var e=b.map(function(b){var d={};for(var e in b){var f=b[e];if("offset"==e){if(null!=f&&(f=Number(f),!isFinite(f)))throw new TypeError("keyframe offsets must be numbers.")}else{if("composite"==e)throw{type:DOMException.NOT_SUPPORTED_ERR,name:"NotSupportedError",message:"add compositing is not supported"};f="easing"==e?a.toTimingFunction(f):""+f}c(e,f,d)}return void 0==d.offset&&(d.offset=null),void 0==d.easing&&(d.easing=a.toTimingFunction("linear")),d}),f=!0,g=-1/0,h=0;h<e.length;h++){var i=e[h].offset;if(null!=i){if(g>i)throw{code:DOMException.INVALID_MODIFICATION_ERR,name:"InvalidModificationError",message:"Keyframes are not loosely sorted by offset. Sort or specify offsets."};g=i}else f=!1}return e=e.filter(function(a){return a.offset>=0&&a.offset<=1}),f||d(),e}var e={background:["backgroundImage","backgroundPosition","backgroundSize","backgroundRepeat","backgroundAttachment","backgroundOrigin","backgroundClip","backgroundColor"],border:["borderTopColor","borderTopStyle","borderTopWidth","borderRightColor","borderRightStyle","borderRightWidth","borderBottomColor","borderBottomStyle","borderBottomWidth","borderLeftColor","borderLeftStyle","borderLeftWidth"],borderBottom:["borderBottomWidth","borderBottomStyle","borderBottomColor"],borderColor:["borderTopColor","borderRightColor","borderBottomColor","borderLeftColor"],borderLeft:["borderLeftWidth","borderLeftStyle","borderLeftColor"],borderRadius:["borderTopLeftRadius","borderTopRightRadius","borderBottomRightRadius","borderBottomLeftRadius"],borderRight:["borderRightWidth","borderRightStyle","borderRightColor"],borderTop:["borderTopWidth","borderTopStyle","borderTopColor"],borderWidth:["borderTopWidth","borderRightWidth","borderBottomWidth","borderLeftWidth"],flex:["flexGrow","flexShrink","flexBasis"],font:["fontFamily","fontSize","fontStyle","fontVariant","fontWeight","lineHeight"],margin:["marginTop","marginRight","marginBottom","marginLeft"],outline:["outlineColor","outlineStyle","outlineWidth"],padding:["paddingTop","paddingRight","paddingBottom","paddingLeft"]},f=document.createElementNS("http://www.w3.org/1999/xhtml","div"),g={thin:"1px",medium:"3px",thick:"5px"},h={borderBottomWidth:g,borderLeftWidth:g,borderRightWidth:g,borderTopWidth:g,fontSize:{"xx-small":"60%","x-small":"75%",small:"89%",medium:"100%",large:"120%","x-large":"150%","xx-large":"200%"},fontWeight:{normal:"400",bold:"700"},outlineWidth:g,textShadow:{none:"0px 0px 0px transparent"},boxShadow:{none:"0px 0px 0px 0px transparent"}};a.normalizeKeyframes=d}(c,f),function(a){var b={};a.isDeprecated=function(a,c,d,e){var f=e?"are":"is",g=new Date,h=new Date(c);return h.setMonth(h.getMonth()+3),h>g?(a in b||console.warn("Web Animations: "+a+" "+f+" deprecated and will stop working on "+h.toDateString()+". "+d),b[a]=!0,!1):!0},a.deprecated=function(b,c,d,e){var f=e?"are":"is";if(a.isDeprecated(b,c,d,e))throw new Error(b+" "+f+" no longer supported. "+d)}}(c),function(){if(document.documentElement.animate){var a=document.documentElement.animate([],0),b=!0;if(a&&(b=!1,"play|currentTime|pause|reverse|playbackRate|cancel|finish|startTime|playState".split("|").forEach(function(c){void 0===a[c]&&(b=!0)})),!b)return}!function(a,b){function c(a){for(var b={},c=0;c<a.length;c++)for(var d in a[c])if("offset"!=d&&"easing"!=d&&"composite"!=d){var e={offset:a[c].offset,easing:a[c].easing,value:a[c][d]};b[d]=b[d]||[],b[d].push(e)}for(var f in b){var g=b[f];if(0!=g[0].offset||1!=g[g.length-1].offset)throw{type:DOMException.NOT_SUPPORTED_ERR,name:"NotSupportedError",message:"Partial keyframes are not supported"}}return b}function d(a){var c=[];for(var d in a)for(var e=a[d],f=0;f<e.length-1;f++){var g=e[f].offset,h=e[f+1].offset,i=e[f].value,j=e[f+1].value;g==h&&(1==h?i=j:j=i),c.push({startTime:g,endTime:h,easing:e[f].easing,property:d,interpolation:b.propertyInterpolation(d,i,j)})}return c.sort(function(a,b){return a.startTime-b.startTime}),c}b.convertEffectInput=function(e){var f=a.normalizeKeyframes(e),g=c(f),h=d(g);return function(a,c){if(null!=c)h.filter(function(a){return 0>=c&&0==a.startTime||c>=1&&1==a.endTime||c>=a.startTime&&c<=a.endTime}).forEach(function(d){var e=c-d.startTime,f=d.endTime-d.startTime,g=0==f?0:d.easing(e/f);b.apply(a,d.property,d.interpolation(g))});else for(var d in g)"offset"!=d&&"easing"!=d&&"composite"!=d&&b.clear(a,d)}}}(c,d,f),function(a){function b(a,b,c){e[c]=e[c]||[],e[c].push([a,b])}function c(a,c,d){for(var e=0;e<d.length;e++){var f=d[e];b(a,c,f),/-/.test(f)&&b(a,c,f.replace(/-(.)/g,function(a,b){return b.toUpperCase()}))}}function d(b,c,d){if("initial"==c||"initial"==d){var g=b.replace(/-(.)/g,function(a,b){return b.toUpperCase()});"initial"==c&&(c=f[g]),"initial"==d&&(d=f[g])}for(var h=c==d?[]:e[b],i=0;h&&i<h.length;i++){var j=h[i][0](c),k=h[i][0](d);if(void 0!==j&&void 0!==k){var l=h[i][1](j,k);if(l){var m=a.Interpolation.apply(null,l);return function(a){return 0==a?c:1==a?d:m(a)}}}}return a.Interpolation(!1,!0,function(a){return a?d:c})}var e={};a.addPropertiesHandler=c;var f={backgroundColor:"transparent",backgroundPosition:"0% 0%",borderBottomColor:"currentColor",borderBottomLeftRadius:"0px",borderBottomRightRadius:"0px",borderBottomWidth:"3px",borderLeftColor:"currentColor",borderLeftWidth:"3px",borderRightColor:"currentColor",borderRightWidth:"3px",borderSpacing:"2px",borderTopColor:"currentColor",borderTopLeftRadius:"0px",borderTopRightRadius:"0px",borderTopWidth:"3px",bottom:"auto",clip:"rect(0px, 0px, 0px, 0px)",color:"black",fontSize:"100%",fontWeight:"400",height:"auto",left:"auto",letterSpacing:"normal",lineHeight:"120%",marginBottom:"0px",marginLeft:"0px",marginRight:"0px",marginTop:"0px",maxHeight:"none",maxWidth:"none",minHeight:"0px",minWidth:"0px",opacity:"1.0",outlineColor:"invert",outlineOffset:"0px",outlineWidth:"3px",paddingBottom:"0px",paddingLeft:"0px",paddingRight:"0px",paddingTop:"0px",right:"auto",textIndent:"0px",textShadow:"0px 0px 0px transparent",top:"auto",transform:"",verticalAlign:"0px",visibility:"visible",width:"auto",wordSpacing:"normal",zIndex:"auto"};a.propertyInterpolation=d}(d,f),function(a,b){function c(b){var c=a.calculateActiveDuration(b),d=function(d){return a.calculateTimeFraction(c,d,b)};return d._totalDuration=b.delay+c+b.endDelay,d._isCurrent=function(d){var e=a.calculatePhase(c,d,b);return e===PhaseActive||e===PhaseBefore},d}b.KeyframeEffect=function(d,e,f){var g,h=c(a.normalizeTimingInput(f)),i=b.convertEffectInput(e),j=function(){i(d,g)};return j._update=function(a){return g=h(a),null!==g},j._clear=function(){i(d,null)},j._hasSameTarget=function(a){return d===a},j._isCurrent=h._isCurrent,j._totalDuration=h._totalDuration,j},b.NullEffect=function(a){var b=function(){a&&(a(),a=null)};return b._update=function(){return null},b._totalDuration=0,b._isCurrent=function(){return!1},b._hasSameTarget=function(){return!1},b}}(c,d,f),function(a){a.apply=function(b,c,d){b.style[a.propertyName(c)]=d},a.clear=function(b,c){b.style[a.propertyName(c)]=""}}(d,f),function(a){window.Element.prototype.animate=function(b,c){return a.timeline._play(a.KeyframeEffect(this,b,c))}}(d),function(a){function b(a,c,d){if("number"==typeof a&&"number"==typeof c)return a*(1-d)+c*d;if("boolean"==typeof a&&"boolean"==typeof c)return.5>d?a:c;if(a.length==c.length){for(var e=[],f=0;f<a.length;f++)e.push(b(a[f],c[f],d));return e}throw"Mismatched interpolation arguments "+a+":"+c}a.Interpolation=function(a,c,d){return function(e){return d(b(a,c,e))}}}(d,f),function(a,b){a.sequenceNumber=0;var c=function(a,b,c){this.target=a,this.currentTime=b,this.timelineTime=c,this.type="finish",this.bubbles=!1,this.cancelable=!1,this.currentTarget=a,this.defaultPrevented=!1,this.eventPhase=Event.AT_TARGET,this.timeStamp=Date.now()};b.Animation=function(b){this._sequenceNumber=a.sequenceNumber++,this._currentTime=0,this._startTime=null,this._paused=!1,this._playbackRate=1,this._inTimeline=!0,this._finishedFlag=!1,this.onfinish=null,this._finishHandlers=[],this._effect=b,this._inEffect=this._effect._update(0),this._idle=!0,this._currentTimePending=!1},b.Animation.prototype={_ensureAlive:function(){this._inEffect=this._effect._update(this.playbackRate<0&&0===this.currentTime?-1:this.currentTime),this._inTimeline||!this._inEffect&&this._finishedFlag||(this._inTimeline=!0,b.timeline._animations.push(this))},_tickCurrentTime:function(a,b){a!=this._currentTime&&(this._currentTime=a,this._isFinished&&!b&&(this._currentTime=this._playbackRate>0?this._totalDuration:0),this._ensureAlive())},get currentTime(){return this._idle||this._currentTimePending?null:this._currentTime},set currentTime(a){a=+a,isNaN(a)||(b.restart(),this._paused||null==this._startTime||(this._startTime=this._timeline.currentTime-a/this._playbackRate),this._currentTimePending=!1,this._currentTime!=a&&(this._tickCurrentTime(a,!0),b.invalidateEffects()))},get startTime(){return this._startTime},set startTime(a){a=+a,isNaN(a)||this._paused||this._idle||(this._startTime=a,this._tickCurrentTime((this._timeline.currentTime-this._startTime)*this.playbackRate),b.invalidateEffects())},get playbackRate(){return this._playbackRate},set playbackRate(a){if(a!=this._playbackRate){var b=this.currentTime;this._playbackRate=a,this._startTime=null,"paused"!=this.playState&&"idle"!=this.playState&&this.play(),null!=b&&(this.currentTime=b)}},get _isFinished(){return!this._idle&&(this._playbackRate>0&&this._currentTime>=this._totalDuration||this._playbackRate<0&&this._currentTime<=0)},get _totalDuration(){return this._effect._totalDuration},get playState(){return this._idle?"idle":null==this._startTime&&!this._paused&&0!=this.playbackRate||this._currentTimePending?"pending":this._paused?"paused":this._isFinished?"finished":"running"},play:function(){this._paused=!1,(this._isFinished||this._idle)&&(this._currentTime=this._playbackRate>0?0:this._totalDuration,this._startTime=null,b.invalidateEffects()),this._finishedFlag=!1,b.restart(),this._idle=!1,this._ensureAlive()},pause:function(){this._isFinished||this._paused||this._idle||(this._currentTimePending=!0),this._startTime=null,this._paused=!0},finish:function(){this._idle||(this.currentTime=this._playbackRate>0?this._totalDuration:0,this._startTime=this._totalDuration-this.currentTime,this._currentTimePending=!1)},cancel:function(){this._inEffect&&(this._inEffect=!1,this._idle=!0,this.currentTime=0,this._startTime=null,this._effect._update(null),b.invalidateEffects(),b.restart())},reverse:function(){this.playbackRate*=-1,this.play()},addEventListener:function(a,b){"function"==typeof b&&"finish"==a&&this._finishHandlers.push(b)},removeEventListener:function(a,b){if("finish"==a){var c=this._finishHandlers.indexOf(b);c>=0&&this._finishHandlers.splice(c,1)}},_fireEvents:function(a){var b=this._isFinished;if((b||this._idle)&&!this._finishedFlag){var d=new c(this,this._currentTime,a),e=this._finishHandlers.concat(this.onfinish?[this.onfinish]:[]);setTimeout(function(){e.forEach(function(a){a.call(d.target,d)})},0)}this._finishedFlag=b},_tick:function(a){return this._idle||this._paused||(null==this._startTime?this.startTime=a-this._currentTime/this.playbackRate:this._isFinished||this._tickCurrentTime((a-this._startTime)*this.playbackRate)),this._currentTimePending=!1,this._fireEvents(a),!this._idle&&(this._inEffect||!this._finishedFlag)}}}(c,d,f),function(a,b){function c(a){var b=i;i=[],a<s.currentTime&&(a=s.currentTime),g(a),b.forEach(function(b){b[1](a)}),o&&g(a),f(),l=void 0}function d(a,b){return a._sequenceNumber-b._sequenceNumber}function e(){this._animations=[],this.currentTime=window.performance&&performance.now?performance.now():0}function f(){p.forEach(function(a){a()}),p.length=0}function g(a){n=!1;var c=b.timeline;c.currentTime=a,c._animations.sort(d),m=!1;var e=c._animations;c._animations=[];var f=[],g=[];e=e.filter(function(b){return b._inTimeline=b._tick(a),b._inEffect?g.push(b._effect):f.push(b._effect),b._isFinished||b._paused||b._idle||(m=!0),b._inTimeline}),p.push.apply(p,f),p.push.apply(p,g),c._animations.push.apply(c._animations,e),o=!1,m&&requestAnimationFrame(function(){})}var h=window.requestAnimationFrame,i=[],j=0;window.requestAnimationFrame=function(a){var b=j++;return 0==i.length&&h(c),i.push([b,a]),b},window.cancelAnimationFrame=function(a){i.forEach(function(b){b[0]==a&&(b[1]=function(){})})},e.prototype={_play:function(c){c._timing=a.normalizeTimingInput(c.timing);var d=new b.Animation(c);return d._idle=!1,d._timeline=this,this._animations.push(d),b.restart(),b.invalidateEffects(),d}};var k,l=void 0,k=function(){return void 0==l&&(l=performance.now()),l},m=!1,n=!1;b.restart=function(){return m||(m=!0,requestAnimationFrame(function(){}),n=!0),n};var o=!1;b.invalidateEffects=function(){o=!0};var p=[],q=1e3/60,r=window.getComputedStyle;Object.defineProperty(window,"getComputedStyle",{configurable:!0,enumerable:!0,value:function(){if(o){var a=k();a-s.currentTime>0&&(s.currentTime+=q*(Math.floor((a-s.currentTime)/q)+1)),g(s.currentTime)}return f(),r.apply(this,arguments)}});var s=new e;b.timeline=s}(c,d,f),function(a){function b(a,b){var c=a.exec(b);return c?(c=a.ignoreCase?c[0].toLowerCase():c[0],[c,b.substr(c.length)]):void 0}function c(a,b){b=b.replace(/^\s*/,"");var c=a(b);return c?[c[0],c[1].replace(/^\s*/,"")]:void 0}function d(a,d,e){a=c.bind(null,a);for(var f=[];;){var g=a(e);if(!g)return[f,e];if(f.push(g[0]),e=g[1],g=b(d,e),!g||""==g[1])return[f,e];e=g[1]}}function e(a,b){for(var c=0,d=0;d<b.length&&(!/\s|,/.test(b[d])||0!=c);d++)if("("==b[d])c++;else if(")"==b[d]&&(c--,0==c&&d++,0>=c))break;var e=a(b.substr(0,d));return void 0==e?void 0:[e,b.substr(d)]}function f(a,b){for(var c=a,d=b;c&&d;)c>d?c%=d:d%=c;return c=a*b/(c+d)}function g(a){return function(b){var c=a(b);return c&&(c[0]=void 0),c}}function h(a,b){return function(c){var d=a(c);return d?d:[b,c]}}function i(b,c){for(var d=[],e=0;e<b.length;e++){var f=a.consumeTrimmed(b[e],c);if(!f||""==f[0])return;void 0!==f[0]&&d.push(f[0]),c=f[1]}return""==c?d:void 0}function j(a,b,c,d,e){for(var g=[],h=[],i=[],j=f(d.length,e.length),k=0;j>k;k++){var l=b(d[k%d.length],e[k%e.length]);if(!l)return;g.push(l[0]),h.push(l[1]),i.push(l[2])}return[g,h,function(b){var d=b.map(function(a,b){return i[b](a)}).join(c);return a?a(d):d}]}function k(a,b,c){for(var d=[],e=[],f=[],g=0,h=0;h<c.length;h++)if("function"==typeof c[h]){var i=c[h](a[g],b[g++]);d.push(i[0]),e.push(i[1]),f.push(i[2])}else!function(a){d.push(!1),e.push(!1),f.push(function(){return c[a]})}(h);return[d,e,function(a){for(var b="",c=0;c<a.length;c++)b+=f[c](a[c]);return b}]}a.consumeToken=b,a.consumeTrimmed=c,a.consumeRepeated=d,a.consumeParenthesised=e,a.ignore=g,a.optional=h,a.consumeList=i,a.mergeNestedRepeated=j.bind(null,null),a.mergeWrappedNestedRepeated=j,a.mergeList=k}(d),function(a){function b(b){function c(b){var c=a.consumeToken(/^inset/i,b);if(c)return d.inset=!0,c;var c=a.consumeLengthOrPercent(b);if(c)return d.lengths.push(c[0]),c;var c=a.consumeColor(b);return c?(d.color=c[0],c):void 0}var d={inset:!1,lengths:[],color:null},e=a.consumeRepeated(c,/^/,b);return e&&e[0].length?[d,e[1]]:void 0}function c(c){var d=a.consumeRepeated(b,/^,/,c);return d&&""==d[1]?d[0]:void 0}function d(b,c){for(;b.lengths.length<Math.max(b.lengths.length,c.lengths.length);)b.lengths.push({px:0});for(;c.lengths.length<Math.max(b.lengths.length,c.lengths.length);)c.lengths.push({px:0});if(b.inset==c.inset&&!!b.color==!!c.color){for(var d,e=[],f=[[],0],g=[[],0],h=0;h<b.lengths.length;h++){var i=a.mergeDimensions(b.lengths[h],c.lengths[h],2==h);f[0].push(i[0]),g[0].push(i[1]),e.push(i[2])}if(b.color&&c.color){var j=a.mergeColors(b.color,c.color);f[1]=j[0],g[1]=j[1],d=j[2]}return[f,g,function(a){for(var c=b.inset?"inset ":" ",f=0;f<e.length;f++)c+=e[f](a[0][f])+" ";return d&&(c+=d(a[1])),c}]}}function e(b,c,d,e){function f(a){return{inset:a,color:[0,0,0,0],lengths:[{px:0},{px:0},{px:0},{px:0}]}}for(var g=[],h=[],i=0;i<d.length||i<e.length;i++){var j=d[i]||f(e[i].inset),k=e[i]||f(d[i].inset);g.push(j),h.push(k)}return a.mergeNestedRepeated(b,c,g,h)}var f=e.bind(null,d,", ");a.addPropertiesHandler(c,f,["box-shadow","text-shadow"])}(d),function(a){function b(a){return a.toFixed(3).replace(".000","")}function c(a,b,c){return Math.min(b,Math.max(a,c))}function d(a){return/^\s*[-+]?(\d*\.)?\d+\s*$/.test(a)?Number(a):void 0}function e(a,c){return[a,c,b]}function f(a,b){return 0!=a?h(0,1/0)(a,b):void 0}function g(a,b){return[a,b,function(a){return Math.round(c(1,1/0,a))}]}function h(a,d){return function(e,f){return[e,f,function(e){return b(c(a,d,e))}]}}function i(a,b){return[a,b,Math.round]}a.clamp=c,a.addPropertiesHandler(d,h(0,1/0),["border-image-width","line-height"]),a.addPropertiesHandler(d,h(0,1),["opacity","shape-image-threshold"]),a.addPropertiesHandler(d,f,["flex-grow","flex-shrink"]),a.addPropertiesHandler(d,g,["orphans","widows"]),a.addPropertiesHandler(d,i,["z-index"]),a.parseNumber=d,a.mergeNumbers=e,a.numberToString=b}(d,f),function(a){function b(a,b){return"visible"==a||"visible"==b?[0,1,function(c){return 0>=c?a:c>=1?b:"visible"}]:void 0}a.addPropertiesHandler(String,b,["visibility"])}(d),function(a){function b(a){a=a.trim(),e.fillStyle="#000",e.fillStyle=a;var b=e.fillStyle;if(e.fillStyle="#fff",e.fillStyle=a,b==e.fillStyle){e.fillRect(0,0,1,1);var c=e.getImageData(0,0,1,1).data;e.clearRect(0,0,1,1);var d=c[3]/255;return[c[0]*d,c[1]*d,c[2]*d,d]}}function c(b,c){return[b,c,function(b){function c(a){return Math.max(0,Math.min(255,a))}if(b[3])for(var d=0;3>d;d++)b[d]=Math.round(c(b[d]/b[3]));return b[3]=a.numberToString(a.clamp(0,1,b[3])),"rgba("+b.join(",")+")"}]}var d=document.createElementNS("http://www.w3.org/1999/xhtml","canvas");d.width=d.height=1;var e=d.getContext("2d");a.addPropertiesHandler(b,c,["background-color","border-bottom-color","border-left-color","border-right-color","border-top-color","color","outline-color","text-decoration-color"]),a.consumeColor=a.consumeParenthesised.bind(null,b),a.mergeColors=c}(d,f),function(a,b){function c(a,b){if(b=b.trim().toLowerCase(),"0"==b&&"px".search(a)>=0)return{px:0};if(/^[^(]*$|^calc/.test(b)){b=b.replace(/calc\(/g,"(");var c={};b=b.replace(a,function(a){return c[a]=null,"U"+a});for(var d="U("+a.source+")",e=b.replace(/[-+]?(\d*\.)?\d+/g,"N").replace(new RegExp("N"+d,"g"),"D").replace(/\s[+-]\s/g,"O").replace(/\s/g,""),f=[/N\*(D)/g,/(N|D)[*/]N/g,/(N|D)O\1/g,/\((N|D)\)/g],g=0;g<f.length;)f[g].test(e)?(e=e.replace(f[g],"$1"),g=0):g++;if("D"==e){for(var h in c){var i=eval(b.replace(new RegExp("U"+h,"g"),"").replace(new RegExp(d,"g"),"*0"));if(!isFinite(i))return;c[h]=i}return c}}}function d(a,b){return e(a,b,!0)}function e(b,c,d){var e,f=[];for(e in b)f.push(e);for(e in c)f.indexOf(e)<0&&f.push(e);return b=f.map(function(a){return b[a]||0}),c=f.map(function(a){return c[a]||0}),[b,c,function(b){var c=b.map(function(c,e){return 1==b.length&&d&&(c=Math.max(c,0)),a.numberToString(c)+f[e]}).join(" + ");return b.length>1?"calc("+c+")":c}]}var f="px|em|ex|ch|rem|vw|vh|vmin|vmax|cm|mm|in|pt|pc",g=c.bind(null,new RegExp(f,"g")),h=c.bind(null,new RegExp(f+"|%","g")),i=c.bind(null,/deg|rad|grad|turn/g);a.parseLength=g,a.parseLengthOrPercent=h,a.consumeLengthOrPercent=a.consumeParenthesised.bind(null,h),a.parseAngle=i,a.mergeDimensions=e;var j=a.consumeParenthesised.bind(null,g),k=a.consumeRepeated.bind(void 0,j,/^/),l=a.consumeRepeated.bind(void 0,k,/^,/);a.consumeSizePairList=l;var m=function(a){var b=l(a);return b&&""==b[1]?b[0]:void 0},n=a.mergeNestedRepeated.bind(void 0,d," "),o=a.mergeNestedRepeated.bind(void 0,n,",");a.mergeNonNegativeSizePair=n,a.addPropertiesHandler(m,o,["background-size"]),a.addPropertiesHandler(h,d,["border-bottom-width","border-image-width","border-left-width","border-right-width","border-top-width","flex-basis","font-size","height","line-height","max-height","max-width","outline-width","width"]),a.addPropertiesHandler(h,e,["border-bottom-left-radius","border-bottom-right-radius","border-top-left-radius","border-top-right-radius","bottom","left","letter-spacing","margin-bottom","margin-left","margin-right","margin-top","min-height","min-width","outline-offset","padding-bottom","padding-left","padding-right","padding-top","perspective","right","shape-margin","text-indent","top","vertical-align","word-spacing"])}(d,f),function(a){function b(b){return a.consumeLengthOrPercent(b)||a.consumeToken(/^auto/,b)}function c(c){var d=a.consumeList([a.ignore(a.consumeToken.bind(null,/^rect/)),a.ignore(a.consumeToken.bind(null,/^\(/)),a.consumeRepeated.bind(null,b,/^,/),a.ignore(a.consumeToken.bind(null,/^\)/))],c);return d&&4==d[0].length?d[0]:void 0}function d(b,c){return"auto"==b||"auto"==c?[!0,!1,function(d){var e=d?b:c;if("auto"==e)return"auto";var f=a.mergeDimensions(e,e);return f[2](f[0])}]:a.mergeDimensions(b,c)}function e(a){return"rect("+a+")"}var f=a.mergeWrappedNestedRepeated.bind(null,e,d,", ");a.parseBox=c,a.mergeBoxes=f,a.addPropertiesHandler(c,f,["clip"])}(d,f),function(a){function b(a){return function(b){var c=0;return a.map(function(a){return a===j?b[c++]:a})}}function c(a){return a}function d(b){if(b=b.toLowerCase().trim(),"none"==b)return[];for(var c,d=/\s*(\w+)\(([^)]*)\)/g,e=[],f=0;c=d.exec(b);){if(c.index!=f)return;f=c.index+c[0].length;var g=c[1],h=m[g];if(!h)return;var i=c[2].split(","),j=h[0];if(j.length<i.length)return;for(var n=[],o=0;o<j.length;o++){var p,q=i[o],r=j[o];if(p=q?{A:function(b){return"0"==b.trim()?l:a.parseAngle(b)},N:a.parseNumber,T:a.parseLengthOrPercent,L:a.parseLength}[r.toUpperCase()](q):{a:l,n:n[0],t:k}[r],void 0===p)return;n.push(p)}if(e.push({t:g,d:n}),d.lastIndex==b.length)return e}}function e(a){return a.toFixed(6).replace(".000000","")}function f(b,c){if(b.decompositionPair!==c){b.decompositionPair=c;var d=a.makeMatrixDecomposition(b)}if(c.decompositionPair!==b){c.decompositionPair=b;var f=a.makeMatrixDecomposition(c)}return null==d[0]||null==f[0]?[[!1],[!0],function(a){return a?c[0].d:b[0].d}]:(d[0].push(0),f[0].push(1),[d,f,function(b){var c=a.quat(d[0][3],f[0][3],b[5]),g=a.composeMatrix(b[0],b[1],b[2],c,b[4]),h=g.map(e).join(",");return h}])}function g(a){return a.replace(/[xy]/,"")}function h(a){return a.replace(/(x|y|z|3d)?$/,"3d")}function i(b,c){var d=a.makeMatrixDecomposition&&!0,e=!1;if(!b.length||!c.length){b.length||(e=!0,b=c,c=[]);for(var i=0;i<b.length;i++){var j=b[i].t,k=b[i].d,l="scale"==j.substr(0,5)?1:0;c.push({t:j,d:k.map(function(a){if("number"==typeof a)return l;var b={};for(var c in a)b[c]=l;return b})})}}var n=function(a,b){return"perspective"==a&&"perspective"==b||("matrix"==a||"matrix3d"==a)&&("matrix"==b||"matrix3d"==b)},o=[],p=[],q=[];if(b.length!=c.length){if(!d)return;var r=f(b,c);o=[r[0]],p=[r[1]],q=[["matrix",[r[2]]]]}else for(var i=0;i<b.length;i++){var j,s=b[i].t,t=c[i].t,u=b[i].d,v=c[i].d,w=m[s],x=m[t];if(n(s,t)){if(!d)return;var r=f([b[i]],[c[i]]);o.push(r[0]),p.push(r[1]),q.push(["matrix",[r[2]]])}else{if(s==t)j=s;else if(w[2]&&x[2]&&g(s)==g(t))j=g(s),u=w[2](u),v=x[2](v);else{if(!w[1]||!x[1]||h(s)!=h(t)){if(!d)return;var r=f(b,c);o=[r[0]],p=[r[1]],q=[["matrix",[r[2]]]];break}j=h(s),u=w[1](u),v=x[1](v)}for(var y=[],z=[],A=[],B=0;B<u.length;B++){var C="number"==typeof u[B]?a.mergeNumbers:a.mergeDimensions,r=C(u[B],v[B]);y[B]=r[0],z[B]=r[1],A.push(r[2])}o.push(y),p.push(z),q.push([j,A])}}if(e){var D=o;o=p,p=D}return[o,p,function(a){return a.map(function(a,b){var c=a.map(function(a,c){return q[b][1][c](a)}).join(",");return"matrix"==q[b][0]&&16==c.split(",").length&&(q[b][0]="matrix3d"),q[b][0]+"("+c+")"}).join(" ")}]}var j=null,k={px:0},l={deg:0},m={matrix:["NNNNNN",[j,j,0,0,j,j,0,0,0,0,1,0,j,j,0,1],c],matrix3d:["NNNNNNNNNNNNNNNN",c],rotate:["A"],rotatex:["A"],rotatey:["A"],rotatez:["A"],rotate3d:["NNNA"],perspective:["L"],scale:["Nn",b([j,j,1]),c],scalex:["N",b([j,1,1]),b([j,1])],scaley:["N",b([1,j,1]),b([1,j])],scalez:["N",b([1,1,j])],scale3d:["NNN",c],skew:["Aa",null,c],skewx:["A",null,b([j,l])],skewy:["A",null,b([l,j])],translate:["Tt",b([j,j,k]),c],translatex:["T",b([j,k,k]),b([j,k])],translatey:["T",b([k,j,k]),b([k,j])],translatez:["L",b([k,k,j])],translate3d:["TTL",c]};a.addPropertiesHandler(d,i,["transform"])}(d,f),function(a){function b(a,b){b.concat([a]).forEach(function(b){b in document.documentElement.style&&(c[a]=b)})}var c={};b("transform",["webkitTransform","msTransform"]),b("transformOrigin",["webkitTransformOrigin"]),b("perspective",["webkitPerspective"]),b("perspectiveOrigin",["webkitPerspectiveOrigin"]),a.propertyName=function(a){return c[a]||a}}(d,f)}(),!function(a,b){function c(a){var b=window.document.timeline;b.currentTime=a,b._discardAnimations(),0==b._animations.length?e=!1:requestAnimationFrame(c)}var d=window.requestAnimationFrame;window.requestAnimationFrame=function(a){return d(function(b){window.document.timeline._updateAnimationsPromises(),a(b),window.document.timeline._updateAnimationsPromises()})},b.AnimationTimeline=function(){this._animations=[],this.currentTime=void 0},b.AnimationTimeline.prototype={getAnimations:function(){return this._discardAnimations(),this._animations.slice()},getAnimationPlayers:function(){return a.deprecated("AnimationTimeline.getAnimationPlayers","2015-03-23","Use AnimationTimeline.getAnimations instead."),this.getAnimations()},_updateAnimationsPromises:function(){b.animationsWithPromises=b.animationsWithPromises.filter(function(a){return a._updatePromises()})},_discardAnimations:function(){this._updateAnimationsPromises(),this._animations=this._animations.filter(function(a){return"finished"!=a.playState&&"idle"!=a.playState})},_play:function(a){var c=new b.Animation(a);return this._animations.push(c),b.restartWebAnimationsNextTick(),c._updatePromises(),c._animation.play(),c._updatePromises(),c},play:function(a){return a&&a.remove(),this._play(a)}};var e=!1;b.restartWebAnimationsNextTick=function(){e||(e=!0,requestAnimationFrame(c))};var f=new b.AnimationTimeline;b.timeline=f;try{Object.defineProperty(window.document,"timeline",{configurable:!0,get:function(){return f}})}catch(g){}try{window.document.timeline=f}catch(g){}}(c,e,f),function(a,b){b.animationsWithPromises=[],b.Animation=function(b){this.effect=b,b&&(b._animation=this),this._sequenceNumber=a.sequenceNumber++,this._holdTime=0,this._paused=!1,this._isGroup=!1,this._animation=null,this._childAnimations=[],this._callback=null,this._oldPlayState="idle",this._rebuildUnderlyingAnimation(),this._animation.cancel(),this._updatePromises()},b.Animation.prototype={_updatePromises:function(){var a=this._oldPlayState,b=this.playState;return this._readyPromise&&b!==a&&("idle"==b?(this._rejectReadyPromise(),this._readyPromise=void 0):"pending"==a?this._resolveReadyPromise():"pending"==b&&(this._readyPromise=void 0)),this._finishedPromise&&b!==a&&("idle"==b?(this._rejectFinishedPromise(),this._finishedPromise=void 0):"finished"==b?this._resolveFinishedPromise():"finished"==a&&(this._finishedPromise=void 0)),this._oldPlayState=this.playState,this._readyPromise||this._finishedPromise},_rebuildUnderlyingAnimation:function(){this._updatePromises();var a,c,d,e,f=this._animation?!0:!1;f&&(a=this.playbackRate,c=this._paused,d=this.startTime,e=this.currentTime,this._animation.cancel(),this._animation._wrapper=null,this._animation=null),(!this.effect||this.effect instanceof window.KeyframeEffect)&&(this._animation=b.newUnderlyingAnimationForKeyframeEffect(this.effect),b.bindAnimationForKeyframeEffect(this)),(this.effect instanceof window.SequenceEffect||this.effect instanceof window.GroupEffect)&&(this._animation=b.newUnderlyingAnimationForGroup(this.effect),b.bindAnimationForGroup(this)),f&&(1!=a&&(this.playbackRate=a),null!==d?this.startTime=d:null!==e?this.currentTime=e:null!==this._holdTime&&(this.currentTime=this._holdTime),c&&this.pause()),this._updatePromises()},_updateChildren:function(){if(this.effect&&"idle"!=this.playState){var a=this.effect._timing.delay;this._childAnimations.forEach(function(c){this._arrangeChildren(c,a),this.effect instanceof window.SequenceEffect&&(a+=b.groupChildDuration(c.effect))}.bind(this))}},_setExternalAnimation:function(a){if(this.effect&&this._isGroup)for(var b=0;b<this.effect.children.length;b++)this.effect.children[b]._animation=a,this._childAnimations[b]._setExternalAnimation(a)},_constructChildAnimations:function(){if(this.effect&&this._isGroup){var a=this.effect._timing.delay;this._removeChildAnimations(),this.effect.children.forEach(function(c){var d=window.document.timeline._play(c);this._childAnimations.push(d),d.playbackRate=this.playbackRate,this._paused&&d.pause(),c._animation=this.effect._animation,this._arrangeChildren(d,a),this.effect instanceof window.SequenceEffect&&(a+=b.groupChildDuration(c))
}.bind(this))}},_arrangeChildren:function(a,b){null===this.startTime?a.currentTime=this.currentTime-b/this.playbackRate:a.startTime!==this.startTime+b/this.playbackRate&&(a.startTime=this.startTime+b/this.playbackRate)},get playState(){return this._animation?this._animation.playState:"idle"},get finished(){return window.Promise?(this._finishedPromise||(-1==b.animationsWithPromises.indexOf(this)&&b.animationsWithPromises.push(this),this._finishedPromise=new Promise(function(a,b){this._resolveFinishedPromise=function(){a(this)},this._rejectFinishedPromise=function(){b({type:DOMException.ABORT_ERR,name:"AbortError"})}}.bind(this)),"finished"==this.playState&&this._resolveFinishedPromise()),this._finishedPromise):(console.warn("Animation Promises require JavaScript Promise constructor"),null)},get ready(){return window.Promise?(this._readyPromise||(-1==b.animationsWithPromises.indexOf(this)&&b.animationsWithPromises.push(this),this._readyPromise=new Promise(function(a,b){this._resolveReadyPromise=function(){a(this)},this._rejectReadyPromise=function(){b({type:DOMException.ABORT_ERR,name:"AbortError"})}}.bind(this)),"pending"!==this.playState&&this._resolveReadyPromise()),this._readyPromise):(console.warn("Animation Promises require JavaScript Promise constructor"),null)},get onfinish(){return this._onfinish},set onfinish(a){"function"==typeof a?(this._onfinish=a,this._animation.onfinish=function(b){b.target=this,a.call(this,b)}.bind(this)):(this._animation.onfinish=a,this.onfinish=this._animation.onfinish)},get currentTime(){this._updatePromises();var a=this._animation.currentTime;return this._updatePromises(),a},set currentTime(a){this._updatePromises(),this._animation.currentTime=isFinite(a)?a:Math.sign(a)*Number.MAX_VALUE,this._register(),this._forEachChild(function(b,c){b.currentTime=a-c}),this._updatePromises()},get startTime(){return this._animation.startTime},set startTime(a){this._updatePromises(),this._animation.startTime=isFinite(a)?a:Math.sign(a)*Number.MAX_VALUE,this._register(),this._forEachChild(function(b,c){b.startTime=a+c}),this._updatePromises()},get playbackRate(){return this._animation.playbackRate},set playbackRate(a){this._updatePromises();var b=this.currentTime;this._animation.playbackRate=a,this._forEachChild(function(b){b.playbackRate=a}),"paused"!=this.playState&&"idle"!=this.playState&&this.play(),null!==b&&(this.currentTime=b),this._updatePromises()},get source(){return a.deprecated("Animation.source","2015-03-23","Use Animation.effect instead."),this.effect},play:function(){this._updatePromises(),this._paused=!1,this._animation.play(),-1==document.timeline._animations.indexOf(this)&&document.timeline._animations.push(this),this._register(),b.awaitStartTime(this),this._forEachChild(function(a){var b=a.currentTime;a.play(),a.currentTime=b}),this._updatePromises()},pause:function(){this._updatePromises(),this.currentTime&&(this._holdTime=this.currentTime),this._animation.pause(),this._register(),this._forEachChild(function(a){a.pause()}),this._paused=!0,this._updatePromises()},finish:function(){this._updatePromises(),this._animation.finish(),this._register(),this._updatePromises()},cancel:function(){this._updatePromises(),this._animation.cancel(),this._register(),this._removeChildAnimations(),this._updatePromises()},reverse:function(){this._updatePromises();var a=this.currentTime;this._animation.reverse(),this._forEachChild(function(a){a.reverse()}),null!==a&&(this.currentTime=a),this._updatePromises()},addEventListener:function(a,b){var c=b;"function"==typeof b&&(c=function(a){a.target=this,b.call(this,a)}.bind(this),b._wrapper=c),this._animation.addEventListener(a,c)},removeEventListener:function(a,b){this._animation.removeEventListener(a,b&&b._wrapper||b)},_removeChildAnimations:function(){for(;this._childAnimations.length;)this._childAnimations.pop().cancel()},_forEachChild:function(b){var c=0;if(this.effect.children&&this._childAnimations.length<this.effect.children.length&&this._constructChildAnimations(),this._childAnimations.forEach(function(a){b.call(this,a,c),this.effect instanceof window.SequenceEffect&&(c+=a.effect.activeDuration)}.bind(this)),"pending"!=this.playState){var d=this.effect._timing,e=this.currentTime;null!==e&&(e=a.calculateTimeFraction(a.calculateActiveDuration(d),e,d)),(null==e||isNaN(e))&&this._removeChildAnimations()}}}}(c,e,f),function(a,b){function c(b){this._frames=a.normalizeKeyframes(b)}function d(){for(var a=!1;h.length;){var b=h.shift();b._updateChildren(),a=!0}return a}var e=function(a){if(a._animation=void 0,a instanceof window.SequenceEffect||a instanceof window.GroupEffect)for(var b=0;b<a.children.length;b++)e(a.children[b])};b.removeMulti=function(a){for(var b=[],c=0;c<a.length;c++){var d=a[c];d._parent?(-1==b.indexOf(d._parent)&&b.push(d._parent),d._parent.children.splice(d._parent.children.indexOf(d),1),d._parent=null,e(d)):d._animation&&d._animation.effect==d&&(d._animation.cancel(),d._animation.effect=new KeyframeEffect(null,[]),d._animation._callback&&(d._animation._callback._animation=null),d._animation._rebuildUnderlyingAnimation(),e(d))}for(c=0;c<b.length;c++)b[c]._rebuild()},b.KeyframeEffect=function(b,d,e){return this.target=b,this._timingInput=a.cloneTimingInput(e),this._timing=a.normalizeTimingInput(e),this.timing=a.makeTiming(e),this._normalizedKeyframes="function"==typeof d?d:new c(d),this._keyframes=d,this.activeDuration=a.calculateActiveDuration(this._timing),this},b.KeyframeEffect.prototype={getFrames:function(){return"function"==typeof this._normalizedKeyframes?this._normalizedKeyframes:this._normalizedKeyframes._frames},get effect(){return a.deprecated("KeyframeEffect.effect","2015-03-23","Use KeyframeEffect.getFrames() instead."),this._normalizedKeyframes},clone:function(){if("function"==typeof this.getFrames())throw new Error("Cloning custom effects is not supported.");var b=new KeyframeEffect(this.target,[],a.cloneTimingInput(this._timingInput));return b._normalizedKeyframes=this._normalizedKeyframes,b._keyframes=this._keyframes,b},remove:function(){b.removeMulti([this])}};var f=Element.prototype.animate;Element.prototype.animate=function(a,c){return b.timeline._play(new b.KeyframeEffect(this,a,c))};var g=document.createElementNS("http://www.w3.org/1999/xhtml","div");b.newUnderlyingAnimationForKeyframeEffect=function(a){if(a){var b=a.target||g,c=a._keyframes;"function"==typeof c&&(c=[]);var d=a._timingInput}else var b=g,c=[],d=0;return f.apply(b,[c,d])},b.bindAnimationForKeyframeEffect=function(a){a.effect&&"function"==typeof a.effect._normalizedKeyframes&&b.bindAnimationForCustomEffect(a)};var h=[];b.awaitStartTime=function(a){null===a.startTime&&a._isGroup&&(0==h.length&&requestAnimationFrame(d),h.push(a))};var i=window.getComputedStyle;Object.defineProperty(window,"getComputedStyle",{configurable:!0,enumerable:!0,value:function(){window.document.timeline._updateAnimationsPromises();var a=i.apply(this,arguments);return d()&&(a=i.apply(this,arguments)),window.document.timeline._updateAnimationsPromises(),a}}),window.KeyframeEffect=b.KeyframeEffect,window.Element.prototype.getAnimations=function(){return document.timeline.getAnimations().filter(function(a){return null!==a.effect&&a.effect.target==this}.bind(this))},window.Element.prototype.getAnimationPlayers=function(){return a.deprecated("Element.getAnimationPlayers","2015-03-23","Use Element.getAnimations instead."),this.getAnimations()},window.Animation=function(){a.deprecated("window.Animation","2015-03-23","Use window.KeyframeEffect instead."),window.KeyframeEffect.apply(this,arguments)},window.Animation.prototype=Object.create(window.KeyframeEffect.prototype),window.Animation.prototype.constructor=window.Animation}(c,e,f),function(a,b){function c(a){a._registered||(a._registered=!0,f.push(a),g||(g=!0,requestAnimationFrame(d)))}function d(){var a=f;f=[],a.sort(function(a,b){return a._sequenceNumber-b._sequenceNumber}),a=a.filter(function(a){a();var b=a._animation?a._animation.playState:"idle";return"running"!=b&&"pending"!=b&&(a._registered=!1),a._registered}),f.push.apply(f,a),f.length?(g=!0,requestAnimationFrame(d)):g=!1}var e=(document.createElementNS("http://www.w3.org/1999/xhtml","div"),0);b.bindAnimationForCustomEffect=function(b){var d=b.effect.target,f=b.effect._normalizedKeyframes,g=b.effect.timing,h=null;g=a.normalizeTimingInput(g);var i=function(){var c=i._animation?i._animation.currentTime:null;null!==c&&(c=a.calculateTimeFraction(a.calculateActiveDuration(g),c,g),isNaN(c)&&(c=null)),c!==h&&f(c,d,b.effect),h=c};i._animation=b,i._registered=!1,i._sequenceNumber=e++,b._callback=i,c(i)};var f=[],g=!1;b.Animation.prototype._register=function(){this._callback&&c(this._callback)}}(c,e,f),function(a,b){function c(a){return a._timing.delay+a.activeDuration+a._timing.endDelay}function d(b,c){this._parent=null,this.children=b||[],this._reparent(this.children),this._timingInput=a.cloneTimingInput(c),this._timing=a.normalizeTimingInput(c,!0),this.timing=a.makeTiming(c,!0),"auto"===this._timing.duration&&(this._timing.duration=this.activeDuration)}window.SequenceEffect=function(){d.apply(this,arguments)},window.GroupEffect=function(){d.apply(this,arguments)},d.prototype={_isAncestor:function(a){for(var b=this;null!==b;){if(b==a)return!0;b=b._parent}return!1},_rebuild:function(){for(var a=this;a;)"auto"===a.timing.duration&&(a._timing.duration=a.activeDuration),a=a._parent;this._animation&&this._animation._rebuildUnderlyingAnimation()},_reparent:function(a){b.removeMulti(a);for(var c=0;c<a.length;c++)a[c]._parent=this},_putChild:function(a,b){for(var c=b?"Cannot append an ancestor or self":"Cannot prepend an ancestor or self",d=0;d<a.length;d++)if(this._isAncestor(a[d]))throw{type:DOMException.HIERARCHY_REQUEST_ERR,name:"HierarchyRequestError",message:c};for(var d=0;d<a.length;d++)b?this.children.push(a[d]):this.children.unshift(a[d]);this._reparent(a),this._rebuild()},append:function(){this._putChild(arguments,!0)},prepend:function(){this._putChild(arguments,!1)},get firstChild(){return this.children.length?this.children[0]:null},get lastChild(){return this.children.length?this.children[this.children.length-1]:null},clone:function(){for(var b=a.cloneTimingInput(this._timingInput),c=[],d=0;d<this.children.length;d++)c.push(this.children[d].clone());return this instanceof GroupEffect?new GroupEffect(c,b):new SequenceEffect(c,b)},remove:function(){b.removeMulti([this])}},window.SequenceEffect.prototype=Object.create(d.prototype),Object.defineProperty(window.SequenceEffect.prototype,"activeDuration",{get:function(){var a=0;return this.children.forEach(function(b){a+=c(b)}),Math.max(a,0)}}),window.GroupEffect.prototype=Object.create(d.prototype),Object.defineProperty(window.GroupEffect.prototype,"activeDuration",{get:function(){var a=0;return this.children.forEach(function(b){a=Math.max(a,c(b))}),a}}),b.newUnderlyingAnimationForGroup=function(c){var d,e=null,f=function(b){var c=d._wrapper;return c&&"pending"!=c.playState&&c.effect?null==b?void c._removeChildAnimations():0==b&&c.playbackRate<0&&(e||(e=a.normalizeTimingInput(c.effect.timing)),b=a.calculateTimeFraction(a.calculateActiveDuration(e),-1,e),isNaN(b)||null==b)?(c._forEachChild(function(a){a.currentTime=-1}),void c._removeChildAnimations()):void 0:void 0};return d=b.timeline._play(new b.KeyframeEffect(null,f,c._timing))},b.bindAnimationForGroup=function(a){a._animation._wrapper=a,a._isGroup=!0,b.awaitStartTime(a),a._constructChildAnimations(),a._setExternalAnimation(a)},b.groupChildDuration=c,window.AnimationSequence=function(){a.deprecated("window.AnimationSequence","2015-03-23","Use window.SequenceEffect instead."),window.SequenceEffect.apply(this,arguments)},window.AnimationSequence.prototype=Object.create(window.SequenceEffect.prototype),window.AnimationSequence.prototype.constructor=window.AnimationSequence,window.AnimationGroup=function(){a.deprecated("window.AnimationGroup","2015-03-23","Use window.GroupEffect instead."),window.GroupEffect.apply(this,arguments)},window.AnimationGroup.prototype=Object.create(window.GroupEffect.prototype),window.AnimationGroup.prototype.constructor=window.AnimationGroup}(c,e,f)}({},function(){return this}());
//# sourceMappingURL=web-animations-next-lite.min.js.map</script>
<script>
Polymer({
is: 'opaque-animation',
behaviors: [
Polymer.NeonAnimationBehavior
],
configure: function(config) {
var node = config.node;
node.style.opacity = '0';
this._effect = new KeyframeEffect(node, [
{'opacity': '1'},
{'opacity': '1'}
], this.timingFromConfig(config));
return this._effect;
},
complete: function(config) {
config.node.style.opacity = '';
}
});
</script>
<script>
/**
* `Polymer.NeonAnimatableBehavior` is implemented by elements containing animations for use with
* elements implementing `Polymer.NeonAnimationRunnerBehavior`.
* @polymerBehavior
*/
Polymer.NeonAnimatableBehavior = {
properties: {
/**
* Animation configuration. See README for more info.
*/
animationConfig: {
type: Object
},
/**
* Convenience property for setting an 'entry' animation. Do not set `animationConfig.entry`
* manually if using this. The animated node is set to `this` if using this property.
*/
entryAnimation: {
observer: '_entryAnimationChanged',
type: String
},
/**
* Convenience property for setting an 'exit' animation. Do not set `animationConfig.exit`
* manually if using this. The animated node is set to `this` if using this property.
*/
exitAnimation: {
observer: '_exitAnimationChanged',
type: String
}
},
_entryAnimationChanged: function() {
this.animationConfig = this.animationConfig || {};
if (this.entryAnimation !== 'fade-in-animation') {
// insert polyfill hack
this.animationConfig['entry'] = [{
name: 'opaque-animation',
node: this
}, {
name: this.entryAnimation,
node: this
}];
} else {
this.animationConfig['entry'] = [{
name: this.entryAnimation,
node: this
}];
}
},
_exitAnimationChanged: function() {
this.animationConfig = this.animationConfig || {};
this.animationConfig['exit'] = [{
name: this.exitAnimation,
node: this
}];
},
_copyProperties: function(config1, config2) {
// shallowly copy properties from config2 to config1
for (var property in config2) {
config1[property] = config2[property];
}
},
_cloneConfig: function(config) {
var clone = {
isClone: true
};
this._copyProperties(clone, config);
return clone;
},
_getAnimationConfigRecursive: function(type, map, allConfigs) {
if (!this.animationConfig) {
return;
}
// type is optional
var thisConfig;
if (type) {
thisConfig = this.animationConfig[type];
} else {
thisConfig = this.animationConfig;
}
if (!Array.isArray(thisConfig)) {
thisConfig = [thisConfig];
}
// iterate animations and recurse to process configurations from child nodes
if (thisConfig) {
for (var config, index = 0; config = thisConfig[index]; index++) {
if (config.animatable) {
config.animatable._getAnimationConfigRecursive(config.type || type, map, allConfigs);
} else {
if (config.id) {
var cachedConfig = map[config.id];
if (cachedConfig) {
// merge configurations with the same id, making a clone lazily
if (!cachedConfig.isClone) {
map[config.id] = this._cloneConfig(cachedConfig)
cachedConfig = map[config.id];
}
this._copyProperties(cachedConfig, config);
} else {
// put any configs with an id into a map
map[config.id] = config;
}
} else {
allConfigs.push(config);
}
}
}
}
},
/**
* An element implementing `Polymer.NeonAnimationRunnerBehavior` calls this method to configure
* an animation with an optional type. Elements implementing `Polymer.NeonAnimatableBehavior`
* should define the property `animationConfig`, which is either a configuration object
* or a map of animation type to array of configuration objects.
*/
getAnimationConfig: function(type) {
var map = [];
var allConfigs = [];
this._getAnimationConfigRecursive(type, map, allConfigs);
// append the configurations saved in the map to the array
for (var key in map) {
allConfigs.push(map[key]);
}
return allConfigs;
}
};
</script>
<script>
/**
* `Polymer.NeonAnimationRunnerBehavior` adds a method to run animations.
* @polymerBehavior
*/
Polymer.NeonAnimationRunnerBehavior = [Polymer.NeonAnimatableBehavior, {
properties: {
_animationMeta: {
type: Object,
value: function() {
return new Polymer.IronMeta({type: 'animation'});
}
},
_player: {
type: Object
}
},
_configureAnimationEffects: function(allConfigs) {
var allAnimations = [];
if (allConfigs.length > 0) {
for (var config, index = 0; config = allConfigs[index]; index++) {
var animationConstructor = this._animationMeta.byKey(config.name);
if (animationConstructor) {
var animation = animationConstructor && new animationConstructor();
var effect = animation.configure(config);
if (effect) {
allAnimations.push({
animation: animation,
config: config,
effect: effect
});
}
} else {
console.warn(this.is + ':', config.name, 'not found!');
}
}
}
return allAnimations;
},
_runAnimationEffects: function(allEffects) {
return player = document.timeline.play(new GroupEffect(allEffects));
},
_completeAnimations: function(allAnimations) {
for (var animation, index = 0; animation = allAnimations[index]; index++) {
animation.animation.complete(animation.config);
}
},
/**
* Plays an animation with an optional `type`.
*/
playAnimation: function(type, cookie) {
var allConfigs = this.getAnimationConfig(type);
if (!allConfigs) {
return;
}
var allAnimations = this._configureAnimationEffects(allConfigs);
var allEffects = allAnimations.map(function(animation) {
return animation.effect;
});
if (allEffects.length > 0) {
this._player = this._runAnimationEffects(allEffects);
this._player.onfinish = function() {
this._completeAnimations(allAnimations);
if (this._player) {
this._player.cancel();
this._player = null;
}
this.fire('neon-animation-finish', cookie, {bubbles: false});
}.bind(this);
} else {
this.fire('neon-animation-finish', cookie, {bubbles: false});
}
},
/**
* Cancels the currently running animation.
*/
cancelAnimation: function() {
if (this._player) {
this._player.cancel();
}
}
}];
</script>
<script>
/**
Polymer.IronFitBehavior fits an element in another element using `max-height` and `max-width`, and
optionally centers it in the window or another element.
The element will only be sized and/or positioned if it has not already been sized and/or positioned
by CSS.
CSS properties | Action
-----------------------------|-------------------------------------------
`position` set | Element is not centered horizontally or vertically
`top` or `bottom` set | Element is not vertically centered
`left` or `right` set | Element is not horizontally centered
`max-height` or `height` set | Element respects `max-height` or `height`
`max-width` or `width` set | Element respects `max-width` or `width`
@demo demo/index.html
@polymerBehavior
*/
Polymer.IronFitBehavior = {
properties: {
/**
* The element that will receive a `max-height`/`width`. By default it is the same as `this`,
* but it can be set to a child element. This is useful, for example, for implementing a
* scrolling region inside the element.
*/
sizingTarget: {
type: Object,
value: function() {
return this;
}
},
/**
* The element to fit `this` into.
*/
fitInto: {
type: Object,
value: window
},
/**
* Set to true to auto-fit on attach.
*/
autoFitOnAttach: {
type: Boolean,
value: false
},
_fitInfo: {
type: Object
}
},
get _fitWidth() {
var fitWidth;
if (this.fitInto === window) {
fitWidth = this.fitInto.innerWidth;
} else {
fitWidth = this.fitInto.getBoundingClientRect().width;
}
return fitWidth;
},
get _fitHeight() {
var fitHeight;
if (this.fitInto === window) {
fitHeight = this.fitInto.innerHeight;
} else {
fitHeight = this.fitInto.getBoundingClientRect().height;
}
return fitHeight;
},
attached: function() {
if (this.autoFitOnAttach) {
if (window.getComputedStyle(this).display === 'none') {
setTimeout(function() {
this.fit();
}.bind(this));
} else {
this.fit();
}
}
},
/**
* Fits and optionally centers the element into the window, or `fitInfo` if specified.
*/
fit: function() {
this._discoverInfo();
this.constrain();
this.center();
},
/**
* Memoize information needed to position and size the target element.
*/
_discoverInfo: function() {
if (this._fitInfo) {
return;
}
var target = window.getComputedStyle(this);
var sizer = window.getComputedStyle(this.sizingTarget);
this._fitInfo = {
positionedBy: {
vertically: target.top !== 'auto' ? 'top' : (target.bottom !== 'auto' ?
'bottom' : null),
horizontally: target.left !== 'auto' ? 'left' : (target.right !== 'auto' ?
'right' : null),
css: target.position
},
sizedBy: {
height: sizer.maxHeight !== 'none',
width: sizer.maxWidth !== 'none'
},
margin: {
top: parseInt(target.marginTop, 10) || 0,
right: parseInt(target.marginRight, 10) || 0,
bottom: parseInt(target.marginBottom, 10) || 0,
left: parseInt(target.marginLeft, 10) || 0
}
};
},
/**
* Resets the target element's position and size constraints, and clear
* the memoized data.
*/
resetFit: function() {
if (!this._fitInfo || !this._fitInfo.sizedBy.height) {
this.sizingTarget.style.maxHeight = '';
this.style.top = '';
}
if (!this._fitInfo || !this._fitInfo.sizedBy.width) {
this.sizingTarget.style.maxWidth = '';
this.style.left = '';
}
if (this._fitInfo) {
this.style.position = this._fitInfo.positionedBy.css;
}
this._fitInfo = null;
},
/**
* Equivalent to calling `resetFit()` and `fit()`. Useful to call this after the element,
* the window, or the `fitInfo` element has been resized.
*/
refit: function() {
this.resetFit();
this.fit();
},
/**
* Constrains the size of the element to the window or `fitInfo` by setting `max-height`
* and/or `max-width`.
*/
constrain: function() {
var info = this._fitInfo;
// position at (0px, 0px) if not already positioned, so we can measure the natural size.
if (!this._fitInfo.positionedBy.vertically) {
this.style.top = '0px';
}
if (!this._fitInfo.positionedBy.horizontally) {
this.style.left = '0px';
}
// need border-box for margin/padding
this.sizingTarget.style.boxSizing = 'border-box';
// constrain the width and height if not already set
var rect = this.getBoundingClientRect();
if (!info.sizedBy.height) {
this._sizeDimension(rect, info.positionedBy.vertically, 'top', 'bottom', 'Height');
}
if (!info.sizedBy.width) {
this._sizeDimension(rect, info.positionedBy.horizontally, 'left', 'right', 'Width');
}
},
_sizeDimension: function(rect, positionedBy, start, end, extent) {
var info = this._fitInfo;
var max = extent === 'Width' ? this._fitWidth : this._fitHeight;
var flip = (positionedBy === end);
var offset = flip ? max - rect[end] : rect[start];
var margin = info.margin[flip ? start : end];
var offsetExtent = 'offset' + extent;
var sizingOffset = this[offsetExtent] - this.sizingTarget[offsetExtent];
this.sizingTarget.style['max' + extent] = (max - margin - offset - sizingOffset) + 'px';
},
/**
* Centers horizontally and vertically if not already positioned. This also sets
* `position:fixed`.
*/
center: function() {
if (!this._fitInfo.positionedBy.vertically || !this._fitInfo.positionedBy.horizontally) {
// need position:fixed to center
this.style.position = 'fixed';
}
if (!this._fitInfo.positionedBy.vertically) {
var top = (this._fitHeight - this.offsetHeight) / 2;
top -= this._fitInfo.margin.top;
this.style.top = top + 'px';
}
if (!this._fitInfo.positionedBy.horizontally) {
var left = (this._fitWidth - this.offsetWidth) / 2;
left -= this._fitInfo.margin.left;
this.style.left = left + 'px';
}
}
};
</script>
<script>
/**
* `IronResizableBehavior` is a behavior that can be used in Polymer elements to
* coordinate the flow of resize events between "resizers" (elements that control the
* size or hidden state of their children) and "resizables" (elements that need to be
* notified when they are resized or un-hidden by their parents in order to take
* action on their new measurements).
* Elements that perform measurement should add the `IronResizableBehavior` behavior to
* their element definition and listen for the `iron-resize` event on themselves.
* This event will be fired when they become showing after having been hidden,
* when they are resized explicitly by another resizable, or when the window has been
* resized.
* Note, the `iron-resize` event is non-bubbling.
*
* @polymerBehavior Polymer.IronResizableBehavior
* @demo demo/index.html
**/
Polymer.IronResizableBehavior = {
properties: {
_parentResizable: {
type: Object,
observer: '_parentResizableChanged'
}
},
listeners: {
'iron-request-resize-notifications': '_onIronRequestResizeNotifications'
},
created: function() {
// We don't really need property effects on these, and also we want them
// to be created before the `_parentResizable` observer fires:
this._interestedResizables = [];
this._boundNotifyResize = this.notifyResize.bind(this);
},
attached: function() {
this.fire('iron-request-resize-notifications', null, {
node: this,
bubbles: true
});
if (!this._parentResizable) {
window.addEventListener('resize', this._boundNotifyResize);
this.notifyResize();
}
},
detached: function() {
if (this._parentResizable) {
this._parentResizable.stopResizeNotificationsFor(this);
} else {
window.removeEventListener('resize', this._boundNotifyResize);
}
this._parentResizable = null;
},
/**
* Can be called to manually notify a resizable and its descendant
* resizables of a resize change.
*/
notifyResize: function() {
if (!this.isAttached) {
return;
}
this._interestedResizables.forEach(function(resizable) {
// TODO(cdata): Currently behaviors cannot define "abstract" methods..
if (!this.resizerShouldNotify || this.resizerShouldNotify(resizable)) {
resizable.notifyResize();
}
}, this);
this.fire('iron-resize', null, {
node: this,
bubbles: false
});
},
/**
* Used to assign the closest resizable ancestor to this resizable
* if the ancestor detects a request for notifications.
*/
assignParentResizable: function(parentResizable) {
this._parentResizable = parentResizable;
},
/**
* Used to remove a resizable descendant from the list of descendants
* that should be notified of a resize change.
*/
stopResizeNotificationsFor: function(target) {
var index = this._interestedResizables.indexOf(target);
if (index > -1) {
this._interestedResizables.splice(index, 1);
}
},
// TODO(cdata): Currently behaviors cannot define "abstract" methods.
// resizerShouldNotify: function(el) { return true; },
_parentResizableChanged: function(parentResizable) {
if (parentResizable) {
window.removeEventListener('resize', this._boundNotifyResize);
}
},
_onIronRequestResizeNotifications: function(event) {
var target = event.path ? event.path[0] : event.target;
if (target === this) {
return;
}
if (this._interestedResizables.indexOf(target) === -1) {
this._interestedResizables.push(target);
}
target.assignParentResizable(this);
event.stopPropagation();
}
};
</script>
<script>
Polymer.IronOverlayManager = (function() {
var overlays = [];
var DEFAULT_Z = 10;
var backdrops = [];
// track overlays for z-index and focus managemant
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, aboveZ + 2);
}
function setZ(element, z) {
element.style.zIndex = z;
}
function currentOverlay() {
return overlays[overlays.length-1];
}
function currentOverlayZ() {
var z;
var current = currentOverlay();
if (current) {
var z1 = window.getComputedStyle(current).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();
}
}
function trackBackdrop(element) {
// backdrops contains the overlays with a backdrop that are currently
// visible
if (element.opened) {
backdrops.push(element);
} else {
var index = backdrops.indexOf(element);
if (index >= 0) {
backdrops.splice(index, 1);
}
}
}
function getBackdrops() {
return backdrops;
}
return {
addOverlay: addOverlay,
removeOverlay: removeOverlay,
currentOverlay: currentOverlay,
currentOverlayZ: currentOverlayZ,
focusOverlay: focusOverlay,
trackBackdrop: trackBackdrop,
getBackdrops: getBackdrops
};
})();
</script>
<script>
/**
Use `Polymer.IronOverlayBehavior` to implement an element that can be hidden or shown, and displays
on top of other content. It includes an optional backdrop, and can be used to implement a variety
of UI controls including dialogs and drop downs. Multiple overlays may be displayed at once.
### Closing and canceling
A dialog may be hidden by closing or canceling. The difference between close and cancel is user
intent. Closing generally implies that the user acknowledged the content on the overlay. By default,
it will cancel whenever the user taps outside it or presses the escape key. This behavior is
configurable with the `no-cancel-on-esc-key` and the `no-cancel-on-outside-click` properties.
`close()` should be called explicitly by the implementer when the user interacts with a control
in the overlay element.
### Positioning
By default the element is sized and positioned to fit and centered inside the window. You can
position and size it manually using CSS. See `Polymer.IronFitBehavior`.
### Backdrop
Set the `with-backdrop` attribute to display a backdrop behind the overlay. The backdrop is
appended to `<body>` and is of type `<iron-overlay-backdrop>`. See its doc page for styling
options.
### Limitations
The element is styled to appear on top of other content by setting its `z-index` property. You
must ensure no element has a stacking context with a higher `z-index` than its parent stacking
context. You should place this element as a child of `<body>` whenever possible.
@demo demo/index.html
@polymerBehavior Polymer.IronOverlayBehavior
*/
Polymer.IronOverlayBehaviorImpl = {
properties: {
/**
* True if the overlay is currently displayed.
*/
opened: {
observer: '_openedChanged',
type: Boolean,
value: false
},
/**
* True if the overlay was canceled when it was last closed.
*/
canceled: {
observer: '_canceledChanged',
readOnly: true,
type: Boolean,
value: false
},
/**
* Set to true to display a backdrop behind the overlay.
*/
withBackdrop: {
type: Boolean,
value: false
},
/**
* Set to true to disable auto-focusing the overlay or child nodes with
* the `autofocus` attribute` when the overlay is opened.
*/
noAutoFocus: {
type: Boolean,
value: false
},
/**
* Set to true to disable canceling the overlay with the ESC key.
*/
noCancelOnEscKey: {
type: Boolean,
value: false
},
/**
* Set to true to disable canceling the overlay by clicking outside it.
*/
noCancelOnOutsideClick: {
type: Boolean,
value: false
},
/**
* Returns the reason this dialog was last closed.
*/
closingReason: {
// was a getter before, but needs to be a property so other
// behaviors can override this.
type: Object
},
_manager: {
type: Object,
value: Polymer.IronOverlayManager
},
_boundOnCaptureClick: {
type: Function,
value: function() {
return this._onCaptureClick.bind(this);
}
},
_boundOnCaptureKeydown: {
type: Function,
value: function() {
return this._onCaptureKeydown.bind(this);
}
}
},
/**
* Fired after the `iron-overlay` opens.
* @event iron-overlay-opened
*/
/**
* Fired after the `iron-overlay` closes.
* @event iron-overlay-closed {{canceled: boolean}} detail -
* canceled: True if the overlay was canceled.
*/
listeners: {
'click': '_onClick',
'iron-resize': '_onIronResize'
},
/**
* The backdrop element.
* @type Node
*/
get backdropElement() {
return this._backdrop;
},
get _focusNode() {
return Polymer.dom(this).querySelector('[autofocus]') || this;
},
registered: function() {
this._backdrop = document.createElement('iron-overlay-backdrop');
},
ready: function() {
this._ensureSetup();
if (this._callOpenedWhenReady) {
this._openedChanged();
}
},
detached: function() {
this.opened = false;
this._completeBackdrop();
this._manager.removeOverlay(this);
},
/**
* Toggle the opened state of the overlay.
*/
toggle: function() {
this.opened = !this.opened;
},
/**
* Open the overlay.
*/
open: function() {
this.opened = true;
this.closingReason = {canceled: false};
},
/**
* Close the overlay.
*/
close: function() {
this.opened = false;
this._setCanceled(false);
},
/**
* Cancels the overlay.
*/
cancel: function() {
this.opened = false,
this._setCanceled(true);
},
_ensureSetup: function() {
if (this._overlaySetup) {
return;
}
this._overlaySetup = true;
this.style.outline = 'none';
this.style.display = 'none';
},
_openedChanged: function() {
if (this.opened) {
this.removeAttribute('aria-hidden');
} else {
this.setAttribute('aria-hidden', 'true');
}
// wait to call after ready only if we're initially open
if (!this._overlaySetup) {
this._callOpenedWhenReady = this.opened;
return;
}
if (this._openChangedAsync) {
this.cancelAsync(this._openChangedAsync);
}
this._toggleListeners();
if (this.opened) {
this._prepareRenderOpened();
}
// async here to allow overlay layer to become visible.
this._openChangedAsync = this.async(function() {
// overlay becomes visible here
this.style.display = '';
// force layout to ensure transitions will go
this.offsetWidth;
if (this.opened) {
this._renderOpened();
} else {
this._renderClosed();
}
this._openChangedAsync = null;
});
},
_canceledChanged: function() {
this.closingReason = this.closingReason || {};
this.closingReason.canceled = this.canceled;
},
_toggleListener: function(enable, node, event, boundListener, capture) {
if (enable) {
node.addEventListener(event, boundListener, capture);
} else {
node.removeEventListener(event, boundListener, capture);
}
},
_toggleListeners: function() {
if (this._toggleListenersAsync) {
this.cancelAsync(this._toggleListenersAsync);
}
// async so we don't auto-close immediately via a click.
this._toggleListenersAsync = this.async(function() {
this._toggleListener(this.opened, document, 'click', this._boundOnCaptureClick, true);
this._toggleListener(this.opened, document, 'keydown', this._boundOnCaptureKeydown, true);
this._toggleListenersAsync = null;
});
},
// tasks which must occur before opening; e.g. making the element visible
_prepareRenderOpened: function() {
this._manager.addOverlay(this);
if (this.withBackdrop) {
this.backdropElement.prepare();
this._manager.trackBackdrop(this);
}
this._preparePositioning();
this.fit();
this._finishPositioning();
},
// tasks which cause the overlay to actually open; typically play an
// animation
_renderOpened: function() {
if (this.withBackdrop) {
this.backdropElement.open();
}
this._finishRenderOpened();
},
_renderClosed: function() {
if (this.withBackdrop) {
this.backdropElement.close();
}
this._finishRenderClosed();
},
_onTransitionend: function(event) {
// make sure this is our transition event.
if (event && event.target !== this) {
return;
}
if (this.opened) {
this._finishRenderOpened();
} else {
this._finishRenderClosed();
}
},
_finishRenderOpened: function() {
// focus the child node with [autofocus]
if (!this.noAutoFocus) {
this._focusNode.focus();
}
this.fire('iron-overlay-opened');
this._squelchNextResize = true;
this.async(this.notifyResize);
},
_finishRenderClosed: function() {
// hide the overlay and remove the backdrop
this.resetFit();
this.style.display = 'none';
this._completeBackdrop();
this._manager.removeOverlay(this);
this._focusNode.blur();
// focus the next overlay, if there is one
this._manager.focusOverlay();
this.fire('iron-overlay-closed', this.closingReason);
this._squelchNextResize = true;
this.async(this.notifyResize);
},
_completeBackdrop: function() {
if (this.withBackdrop) {
this._manager.trackBackdrop(this);
this.backdropElement.complete();
}
},
_preparePositioning: function() {
this.style.transition = this.style.webkitTransition = 'none';
this.style.transform = this.style.webkitTransform = 'none';
this.style.display = '';
},
_finishPositioning: function(target) {
this.style.display = 'none';
this.style.transform = this.style.webkitTransform = '';
// force layout to avoid application of transform
this.offsetWidth;
this.style.transition = this.style.webkitTransition = '';
},
_applyFocus: function() {
if (this.opened) {
if (!this.noAutoFocus) {
this._focusNode.focus();
}
} else {
this._focusNode.blur();
this._manager.focusOverlay();
}
},
_onCaptureClick: function(event) {
// attempt to close asynchronously and prevent the close of a tap event is immediately heard
// on target. This is because in shadow dom due to event retargetting event.target is not
// useful.
if (!this.noCancelOnOutsideClick && (this._manager.currentOverlay() == this)) {
this._cancelJob = this.async(function() {
this.cancel();
}, 10);
}
},
_onClick: function(event) {
if (this._cancelJob) {
this.cancelAsync(this._cancelJob);
this._cancelJob = null;
}
},
_onCaptureKeydown: function(event) {
var ESC = 27;
if (!this.noCancelOnEscKey && (event.keyCode === ESC)) {
this.cancel();
event.stopPropagation();
}
},
_onIronResize: function() {
if (this._squelchNextResize) {
this._squelchNextResize = false;
return;
}
if (this.opened) {
this.refit();
}
}
};
/** @polymerBehavior */
Polymer.IronOverlayBehavior = [Polymer.IronFitBehavior, Polymer.IronResizableBehavior, Polymer.IronOverlayBehaviorImpl];
</script>
<script>
/**
Use `Polymer.PaperDialogBehavior` and `paper-dialog-common.css` to implement a Material Design
dialog.
For example, if `<paper-dialog-impl>` implements this behavior:
<paper-dialog-impl>
<h2>Header</h2>
<div>Dialog body</div>
<div class="buttons">
<paper-button dialog-dismiss>Cancel</paper-button>
<paper-button dialog-confirm>Accept</paper-button>
</div>
</paper-dialog-impl>
`paper-dialog-common.css` provide styles for a header, content area, and an action area for buttons.
Use the `<h2>` tag for the header and the `buttons` class for the action area. You can use the
`paper-dialog-scrollable` element (in its own repository) if you need a scrolling content area.
Use the `dialog-dismiss` and `dialog-confirm` attributes on interactive controls to close the
dialog. If the user dismisses the dialog with `dialog-confirm`, the `closingReason` will update
to include `confirmed: true`.
### Styling
The following custom properties and mixins are available for styling.
Custom property | Description | Default
----------------|-------------|----------
`--paper-dialog-background-color` | Dialog background color | `--primary-background-color`
`--paper-dialog-color` | Dialog foreground color | `--primary-text-color`
`--paper-dialog` | Mixin applied to the dialog | `{}`
`--paper-dialog-title` | Mixin applied to the title (`<h2>`) element | `{}`
`--paper-dialog-button-color` | Button area foreground color | `--default-primary-color`
### Accessibility
This element has `role="dialog"` by default. Depending on the context, it may be more appropriate
to override this attribute with `role="alertdialog"`. The header (a `<h2>` element) will
If `modal` is set, the element will set `aria-modal` and prevent the focus from exiting the element.
It will also ensure that focus remains in the dialog.
The `aria-labelledby` attribute will be set to the header element, if one exists.
@hero hero.svg
@demo demo/index.html
@polymerBehavior Polymer.PaperDialogBehavior
*/
Polymer.PaperDialogBehaviorImpl = {
hostAttributes: {
'role': 'dialog',
'tabindex': '-1'
},
properties: {
/**
* If `modal` is true, this implies `no-cancel-on-outside-click` and `with-backdrop`.
*/
modal: {
observer: '_modalChanged',
type: Boolean,
value: false
},
/** @type {?Node} */
_lastFocusedElement: {
type: Object
},
_boundOnFocus: {
type: Function,
value: function() {
return this._onFocus.bind(this);
}
},
_boundOnBackdropClick: {
type: Function,
value: function() {
return this._onBackdropClick.bind(this);
}
}
},
listeners: {
'click': '_onDialogClick',
'iron-overlay-opened': '_onIronOverlayOpened',
'iron-overlay-closed': '_onIronOverlayClosed'
},
attached: function() {
this._observer = this._observe(this);
this._updateAriaLabelledBy();
},
detached: function() {
if (this._observer) {
this._observer.disconnect();
}
},
_observe: function(node) {
var observer = new MutationObserver(function() {
this._updateAriaLabelledBy();
}.bind(this));
observer.observe(node, {
childList: true,
subtree: true
});
return observer;
},
_modalChanged: function() {
if (this.modal) {
this.setAttribute('aria-modal', 'true');
} else {
this.setAttribute('aria-modal', 'false');
}
// modal implies noCancelOnOutsideClick and withBackdrop if true, don't overwrite
// those properties otherwise.
if (this.modal) {
this.noCancelOnOutsideClick = true;
this.withBackdrop = true;
}
},
_updateAriaLabelledBy: function() {
var header = Polymer.dom(this).querySelector('h2');
if (!header) {
this.removeAttribute('aria-labelledby');
return;
}
var headerId = header.getAttribute('id');
if (headerId && this.getAttribute('aria-labelledby') === headerId) {
return;
}
// set aria-describedBy to the header element
var labelledById;
if (headerId) {
labelledById = headerId;
} else {
labelledById = 'paper-dialog-header-' + new Date().getUTCMilliseconds();
header.setAttribute('id', labelledById);
}
this.setAttribute('aria-labelledby', labelledById);
},
_updateClosingReasonConfirmed: function(confirmed) {
this.closingReason = this.closingReason || {};
this.closingReason.confirmed = confirmed;
},
_onDialogClick: function(event) {
var target = event.target;
while (target !== this) {
if (target.hasAttribute('dialog-dismiss')) {
this._updateClosingReasonConfirmed(false);
this.close();
break;
} else if (target.hasAttribute('dialog-confirm')) {
this._updateClosingReasonConfirmed(true);
this.close();
break;
}
target = target.parentNode;
}
},
_onIronOverlayOpened: function() {
if (this.modal) {
document.body.addEventListener('focus', this._boundOnFocus, true);
this.backdropElement.addEventListener('click', this._boundOnBackdropClick);
}
},
_onIronOverlayClosed: function() {
document.body.removeEventListener('focus', this._boundOnFocus, true);
this.backdropElement.removeEventListener('click', this._boundOnBackdropClick);
},
_onFocus: function(event) {
if (this.modal) {
var target = event.target;
while (target && target !== this && target !== document.body) {
target = target.parentNode;
}
if (target) {
if (target === document.body) {
if (this._lastFocusedElement) {
this._lastFocusedElement.focus();
} else {
this._focusNode.focus();
}
} else {
this._lastFocusedElement = event.target;
}
}
}
},
_onBackdropClick: function() {
if (this.modal) {
if (this._lastFocusedElement) {
this._lastFocusedElement.focus();
} else {
this._focusNode.focus();
}
}
}
};
/** @polymerBehavior */
Polymer.PaperDialogBehavior = [Polymer.IronOverlayBehavior, Polymer.PaperDialogBehaviorImpl];
</script>
<script>
Polymer({
is: 'scale-up-animation',
behaviors: [
Polymer.NeonAnimationBehavior
],
configure: function(config) {
var node = config.node;
if (config.transformOrigin) {
this.setPrefixedProperty(node, 'transformOrigin', config.transformOrigin);
}
this._effect = new KeyframeEffect(node, [
{'transform': 'scale(0)'},
{'transform': 'scale(1)'}
], this.timingFromConfig(config));
return this._effect;
}
});
</script>
<script>
Polymer({
is: 'fade-out-animation',
behaviors: [
Polymer.NeonAnimationBehavior
],
configure: function(config) {
var node = config.node;
this._effect = new KeyframeEffect(node, [
{'opacity': '1'},
{'opacity': '0'}
], this.timingFromConfig(config));
return this._effect;
}
});
</script>
<script>
Polymer({
is: 'fade-in-animation',
behaviors: [
Polymer.NeonAnimationBehavior
],
configure: function(config) {
var node = config.node;
this._effect = new KeyframeEffect(node, [
{'opacity': '0'},
{'opacity': '1'}
], this.timingFromConfig(config));
return this._effect;
}
});
</script>
<script>
/**
* `Polymer.PaperInkyFocusBehavior` implements a ripple when the element has keyboard focus.
*
* @polymerBehavior Polymer.PaperInkyFocusBehavior
*/
Polymer.PaperInkyFocusBehaviorImpl = {
observers: [
'_focusedChanged(receivedFocusFromKeyboard)'
],
_focusedChanged: function(receivedFocusFromKeyboard) {
if (!this.$.ink) {
return;
}
this.$.ink.holdDown = receivedFocusFromKeyboard;
}
};
/** @polymerBehavior Polymer.PaperInkyFocusBehavior */
Polymer.PaperInkyFocusBehavior = [
Polymer.IronButtonState,
Polymer.IronControlState,
Polymer.PaperInkyFocusBehaviorImpl
];
</script>
<script>
Polymer({
is: 'iron-media-query',
properties: {
/**
* The Boolean return value of the media query.
*/
queryMatches: {
type: Boolean,
value: false,
readOnly: true,
notify: true
},
/**
* The CSS media query to evaluate.
*/
query: {
type: String,
observer: 'queryChanged'
}
},
created: function() {
this._mqHandler = this.queryHandler.bind(this);
},
queryChanged: function(query) {
if (this._mq) {
this._mq.removeListener(this._mqHandler);
}
if (query[0] !== '(') {
query = '(' + query + ')';
}
this._mq = window.matchMedia(query);
this._mq.addListener(this._mqHandler);
this.queryHandler(this._mq);
},
queryHandler: function(mq) {
this._setQueryMatches(mq.matches);
}
});
</script>
<script>
/**
* @param {!Function} selectCallback
* @constructor
*/
Polymer.IronSelection = function(selectCallback) {
this.selection = [];
this.selectCallback = selectCallback;
};
Polymer.IronSelection.prototype = {
/**
* Retrieves the selected item(s).
*
* @method get
* @returns Returns the selected item(s). If the multi property is true,
* `get` will return an array, otherwise it will return
* the selected item or undefined if there is no selection.
*/
get: function() {
return this.multi ? this.selection : this.selection[0];
},
/**
* Clears all the selection except the ones indicated.
*
* @method clear
* @param {Array} excludes items to be excluded.
*/
clear: function(excludes) {
this.selection.slice().forEach(function(item) {
if (!excludes || excludes.indexOf(item) < 0) {
this.setItemSelected(item, false);
}
}, this);
},
/**
* Indicates if a given item is selected.
*
* @method isSelected
* @param {*} 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;
},
/**
* Sets the selection state for a given item to either selected or deselected.
*
* @method setItemSelected
* @param {*} item The item to select.
* @param {boolean} isSelected True for selected, false for deselected.
*/
setItemSelected: function(item, isSelected) {
if (item != null) {
if (isSelected) {
this.selection.push(item);
} else {
var i = this.selection.indexOf(item);
if (i >= 0) {
this.selection.splice(i, 1);
}
}
if (this.selectCallback) {
this.selectCallback(item, isSelected);
}
}
},
/**
* Sets 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 {*} item The item to select.
*/
select: function(item) {
if (this.multi) {
this.toggle(item);
} else if (this.get() !== item) {
this.setItemSelected(this.get(), false);
this.setItemSelected(item, true);
}
},
/**
* Toggles the selection state for `item`.
*
* @method toggle
* @param {*} item The item to toggle.
*/
toggle: function(item) {
this.setItemSelected(item, !this.isSelected(item));
}
};
</script>
<script>
/** @polymerBehavior */
Polymer.IronSelectableBehavior = {
properties: {
/**
* If you want to use the attribute value of an element for `selected` instead of the index,
* set this to the name of the attribute.
*
* @attribute attrForSelected
* @type {string}
*/
attrForSelected: {
type: String,
value: null
},
/**
* Gets or sets the selected element. The default is to use the index of the item.
*
* @attribute selected
* @type {string}
*/
selected: {
type: String,
notify: true
},
/**
* Returns the currently selected item.
*
* @attribute selectedItem
* @type {Object}
*/
selectedItem: {
type: Object,
readOnly: true,
notify: true
},
/**
* The event that fires from items when they are selected. Selectable
* will listen for this event from items and update the selection state.
* Set to empty string to listen to no events.
*
* @attribute activateEvent
* @type {string}
* @default 'tap'
*/
activateEvent: {
type: String,
value: 'tap',
observer: '_activateEventChanged'
},
/**
* This is a CSS selector sting. If this is set, only items that matches the CSS selector
* are selectable.
*
* @attribute selectable
* @type {string}
*/
selectable: String,
/**
* The class to set on elements when selected.
*
* @attribute selectedClass
* @type {string}
*/
selectedClass: {
type: String,
value: 'iron-selected'
},
/**
* The attribute to set on elements when selected.
*
* @attribute selectedAttribute
* @type {string}
*/
selectedAttribute: {
type: String,
value: null
}
},
observers: [
'_updateSelected(attrForSelected, selected)'
],
excludedLocalNames: {
'template': 1
},
created: function() {
this._bindFilterItem = this._filterItem.bind(this);
this._selection = new Polymer.IronSelection(this._applySelection.bind(this));
},
attached: function() {
this._observer = this._observeItems(this);
this._contentObserver = this._observeContent(this);
},
detached: function() {
if (this._observer) {
this._observer.disconnect();
}
if (this._contentObserver) {
this._contentObserver.disconnect();
}
this._removeListener(this.activateEvent);
},
/**
* Returns an array of selectable items.
*
* @property items
* @type Array
*/
get items() {
var nodes = Polymer.dom(this).queryDistributedElements(this.selectable || '*');
return Array.prototype.filter.call(nodes, this._bindFilterItem);
},
/**
* Returns the index of the given item.
*
* @method indexOf
* @param {Object} item
* @returns Returns the index of the item
*/
indexOf: function(item) {
return this.items.indexOf(item);
},
/**
* Selects the given value.
*
* @method select
* @param {string} value the value to select.
*/
select: function(value) {
this.selected = value;
},
/**
* Selects the previous item.
*
* @method selectPrevious
*/
selectPrevious: function() {
var length = this.items.length;
var index = (Number(this._valueToIndex(this.selected)) - 1 + length) % length;
this.selected = this._indexToValue(index);
},
/**
* Selects the next item.
*
* @method selectNext
*/
selectNext: function() {
var index = (Number(this._valueToIndex(this.selected)) + 1) % this.items.length;
this.selected = this._indexToValue(index);
},
_addListener: function(eventName) {
this.listen(this, eventName, '_activateHandler');
},
_removeListener: function(eventName) {
// There is no unlisten yet...
// https://github.com/Polymer/polymer/issues/1639
//this.removeEventListener(eventName, this._bindActivateHandler);
},
_activateEventChanged: function(eventName, old) {
this._removeListener(old);
this._addListener(eventName);
},
_updateSelected: function() {
this._selectSelected(this.selected);
},
_selectSelected: function(selected) {
this._selection.select(this._valueToItem(this.selected));
},
_filterItem: function(node) {
return !this.excludedLocalNames[node.localName];
},
_valueToItem: function(value) {
return (value == null) ? null : this.items[this._valueToIndex(value)];
},
_valueToIndex: function(value) {
if (this.attrForSelected) {
for (var i = 0, item; item = this.items[i]; i++) {
if (this._valueForItem(item) == value) {
return i;
}
}
} else {
return Number(value);
}
},
_indexToValue: function(index) {
if (this.attrForSelected) {
var item = this.items[index];
if (item) {
return this._valueForItem(item);
}
} else {
return index;
}
},
_valueForItem: function(item) {
return item[this.attrForSelected] || item.getAttribute(this.attrForSelected);
},
_applySelection: function(item, isSelected) {
if (this.selectedClass) {
this.toggleClass(this.selectedClass, isSelected, item);
}
if (this.selectedAttribute) {
this.toggleAttribute(this.selectedAttribute, isSelected, item);
}
this._selectionChange();
this.fire('iron-' + (isSelected ? 'select' : 'deselect'), {item: item});
},
_selectionChange: function() {
this._setSelectedItem(this._selection.get());
},
// observe content changes under the given node.
_observeContent: function(node) {
var content = node.querySelector('content');
if (content && content.parentElement === node) {
return this._observeItems(node.domHost);
}
},
// observe items change under the given node.
_observeItems: function(node) {
var observer = new MutationObserver(function() {
if (this.selected != null) {
this._updateSelected();
}
}.bind(this));
observer.observe(node, {
childList: true,
subtree: true
});
return observer;
},
_activateHandler: function(e) {
// TODO: remove this when https://github.com/Polymer/polymer/issues/1639 is fixed so we
// can just remove the old event listener.
if (e.type !== this.activateEvent) {
return;
}
var t = e.target;
var items = this.items;
while (t && t != this) {
var i = items.indexOf(t);
if (i >= 0) {
var value = this._indexToValue(i);
this._itemActivate(value, t);
return;
}
t = t.parentNode;
}
},
_itemActivate: function(value, item) {
if (!this.fire('iron-activate',
{selected: value, item: item}, {cancelable: true}).defaultPrevented) {
this.select(value);
}
}
};
</script>
<script>
/** @polymerBehavior Polymer.IronMultiSelectableBehavior */
Polymer.IronMultiSelectableBehaviorImpl = {
properties: {
/**
* If true, multiple selections are allowed.
*/
multi: {
type: Boolean,
value: false,
observer: 'multiChanged'
},
/**
* Gets or sets the selected elements. This is used instead of `selected` when `multi`
* is true.
*/
selectedValues: {
type: Array,
notify: true
},
/**
* Returns an array of currently selected items.
*/
selectedItems: {
type: Array,
readOnly: true,
notify: true
},
},
observers: [
'_updateSelected(attrForSelected, selectedValues)'
],
/**
* Selects the given value. If the `multi` property is true, then the selected state of the
* `value` will be toggled; otherwise the `value` will be selected.
*
* @method select
* @param {string} value the value to select.
*/
select: function(value) {
if (this.multi) {
if (this.selectedValues) {
this._toggleSelected(value);
} else {
this.selectedValues = [value];
}
} else {
this.selected = value;
}
},
multiChanged: function(multi) {
this._selection.multi = multi;
},
_updateSelected: function() {
if (this.multi) {
this._selectMulti(this.selectedValues);
} else {
this._selectSelected(this.selected);
}
},
_selectMulti: function(values) {
this._selection.clear();
if (values) {
for (var i = 0; i < values.length; i++) {
this._selection.setItemSelected(this._valueToItem(values[i]), true);
}
}
},
_selectionChange: function() {
var s = this._selection.get();
if (this.multi) {
this._setSelectedItems(s);
} else {
this._setSelectedItems([s]);
this._setSelectedItem(s);
}
},
_toggleSelected: function(value) {
var i = this.selectedValues.indexOf(value);
var unselected = i < 0;
if (unselected) {
this.selectedValues.push(value);
} else {
this.selectedValues.splice(i, 1);
}
this._selection.setItemSelected(this._valueToItem(value), unselected);
}
};
/** @polymerBehavior */
Polymer.IronMultiSelectableBehavior = [
Polymer.IronSelectableBehavior,
Polymer.IronMultiSelectableBehaviorImpl
];
</script>
<script>
/**
`iron-selector` is an element which can be used to manage a list of elements
that can be selected. Tapping on the item will make the item selected. The `selected` indicates
which item is being selected. The default is to use the index of the item.
Example:
<iron-selector selected="0">
<div>Item 1</div>
<div>Item 2</div>
<div>Item 3</div>
</iron-selector>
If you want to use the attribute value of an element for `selected` instead of the index,
set `attrForSelected` to the name of the attribute. For example, if you want to select item by
`name`, set `attrForSelected` to `name`.
Example:
<iron-selector attr-for-selected="name" selected="foo">
<div name="foo">Foo</div>
<div name="bar">Bar</div>
<div name="zot">Zot</div>
</iron-selector>
`iron-selector` is not styled. Use the `iron-selected` CSS class to style the selected element.
Example:
<style>
.iron-selected {
background: #eee;
}
</style>
...
<iron-selector selected="0">
<div>Item 1</div>
<div>Item 2</div>
<div>Item 3</div>
</iron-selector>
@demo demo/index.html
*/
Polymer({
is: 'iron-selector',
behaviors: [
Polymer.IronMultiSelectableBehavior
]
});
</script>
<script>
/**
* The `iron-iconset-svg` element allows users to define their own icon sets
* that contain svg icons. The svg icon elements should be children of the
* `iron-iconset-svg` element. Multiple icons should be given distinct id's.
*
* Using svg elements to create icons has a few advantages over traditional
* bitmap graphics like jpg or png. Icons that use svg are vector based so they
* are resolution independent and should look good on any device. They are
* stylable via css. Icons can be themed, colorized, and even animated.
*
* Example:
*
* <iron-iconset-svg name="my-svg-icons" size="24">
* <svg>
* <defs>
* <g id="shape">
* <rect x="50" y="50" width="50" height="50" />
* <circle cx="50" cy="50" r="50" />
* </g>
* </defs>
* </svg>
* </iron-iconset-svg>
*
* This will automatically register the icon set "my-svg-icons" to the iconset
* database. To use these icons from within another element, make a
* `iron-iconset` element and call the `byId` method
* to retrieve a given iconset. To apply a particular icon inside an
* element use the `applyIcon` method. For example:
*
* iconset.applyIcon(iconNode, 'car');
*
* @element iron-iconset-svg
* @demo demo/index.html
*/
Polymer({
is: 'iron-iconset-svg',
properties: {
/**
* The name of the iconset.
*
* @attribute name
* @type string
*/
name: {
type: String,
observer: '_nameChanged'
},
/**
* The size of an individual icon. Note that icons must be square.
*
* @attribute iconSize
* @type number
* @default 24
*/
size: {
type: Number,
value: 24
}
},
/**
* Construct an array of all icon names in this iconset.
*
* @return {!Array} Array of icon names.
*/
getIconNames: function() {
this._icons = this._createIconMap();
return Object.keys(this._icons).map(function(n) {
return this.name + ':' + n;
}, this);
},
/**
* Applies an icon to the given element.
*
* An svg icon is prepended to the element's shadowRoot if it exists,
* otherwise to the element itself.
*
* @method applyIcon
* @param {Element} element Element to which the icon is applied.
* @param {string} iconName Name of the icon to apply.
* @return {Element} The svg element which renders the icon.
*/
applyIcon: function(element, iconName) {
// insert svg element into shadow root, if it exists
element = element.root || element;
// Remove old svg element
this.removeIcon(element);
// install new svg element
var svg = this._cloneIcon(iconName);
if (svg) {
var pde = Polymer.dom(element);
pde.insertBefore(svg, pde.childNodes[0]);
return element._svgIcon = svg;
}
return null;
},
/**
* Remove an icon from the given element by undoing the changes effected
* by `applyIcon`.
*
* @param {Element} element The element from which the icon is removed.
*/
removeIcon: function(element) {
// Remove old svg element
if (element._svgIcon) {
Polymer.dom(element).removeChild(element._svgIcon);
element._svgIcon = null;
}
},
/**
*
* When name is changed, register iconset metadata
*
*/
_nameChanged: function() {
new Polymer.IronMeta({type: 'iconset', key: this.name, value: this});
},
/**
* Create a map of child SVG elements by id.
*
* @return {!Object} Map of id's to SVG elements.
*/
_createIconMap: function() {
// Objects chained to Object.prototype (`{}`) have members. Specifically,
// on FF there is a `watch` method that confuses the icon map, so we
// need to use a null-based object here.
var icons = Object.create(null);
Polymer.dom(this).querySelectorAll('[id]')
.forEach(function(icon) {
icons[icon.id] = icon;
});
return icons;
},
/**
* Produce installable clone of the SVG element matching `id` in this
* iconset, or `undefined` if there is no matching element.
*
* @return {Element} Returns an installable clone of the SVG element
* matching `id`.
*/
_cloneIcon: function(id) {
// create the icon map on-demand, since the iconset itself has no discrete
// signal to know when it's children are fully parsed
this._icons = this._icons || this._createIconMap();
return this._prepareSvgClone(this._icons[id], this.size);
},
/**
* @param {Element} sourceSvg
* @param {number} size
* @return {Element}
*/
_prepareSvgClone: function(sourceSvg, size) {
if (sourceSvg) {
var svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
svg.setAttribute('viewBox', ['0', '0', size, size].join(' '));
svg.setAttribute('preserveAspectRatio', 'xMidYMid meet');
// TODO(dfreedm): `pointer-events: none` works around https://crbug.com/370136
// TODO(sjmiles): inline style may not be ideal, but avoids requiring a shadow-root
svg.style.cssText = 'pointer-events: none; display: block; width: 100%; height: 100%;';
svg.appendChild(sourceSvg.cloneNode(true)).removeAttribute('id');
return svg;
}
return null;
}
});
</script>
</head><body><div hidden="" by-vulcanize=""><dom-module id="paper-material" assetpath="bower_components/paper-material/">
<style>
:host {
display: block;
position: relative;
@apply(--shadow-transition);
}
:host([elevation="1"]) {
@apply(--shadow-elevation-2dp);
}
:host([elevation="2"]) {
@apply(--shadow-elevation-4dp);
}
:host([elevation="3"]) {
@apply(--shadow-elevation-6dp);
}
:host([elevation="4"]) {
@apply(--shadow-elevation-8dp);
}
:host([elevation="5"]) {
@apply(--shadow-elevation-16dp);
}
</style>
<template>
<content></content>
</template>
</dom-module>
<script>
Polymer({
is: 'paper-material',
properties: {
/**
* The z-depth of this element, from 0-5. Setting to 0 will remove the
* shadow, and each increasing number greater than 0 will be "deeper"
* than the last.
*
* @attribute elevation
* @type number
* @default 1
*/
elevation: {
type: Number,
reflectToAttribute: true,
value: 1
},
/**
* Set this to true to animate the shadow when setting a new
* `elevation` value.
*
* @attribute animated
* @type boolean
* @default false
*/
animated: {
type: Boolean,
reflectToAttribute: true,
value: false
}
}
});
</script>
<dom-module id="paper-ripple" assetpath="bower_components/paper-ripple/">
<style>
:host {
display: block;
position: absolute;
border-radius: inherit;
overflow: hidden;
top: 0;
left: 0;
right: 0;
bottom: 0;
}
:host([animating]) {
/* This resolves a rendering issue in Chrome (as of 40) where the
ripple is not properly clipped by its parent (which may have
rounded corners). See: http://jsbin.com/temexa/4
Note: We only apply this style conditionally. Otherwise, the browser
will create a new compositing layer for every ripple element on the
page, and that would be bad. */
-webkit-transform: translate(0, 0);
transform: translate3d(0, 0, 0);
}
:host([noink]) {
pointer-events: none;
}
#background,
#waves,
.wave-container,
.wave {
pointer-events: none;
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
}
#background,
.wave {
opacity: 0;
}
#waves,
.wave {
overflow: hidden;
}
.wave-container,
.wave {
border-radius: 50%;
}
:host(.circle) #background,
:host(.circle) #waves {
border-radius: 50%;
}
:host(.circle) .wave-container {
overflow: hidden;
}
</style>
<template>
<div id="background"></div>
<div id="waves"></div>
</template>
</dom-module>
<script>
(function() {
var Utility = {
cssColorWithAlpha: function(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 + ')';
},
distance: function(x1, y1, x2, y2) {
var xDelta = (x1 - x2);
var yDelta = (y1 - y2);
return Math.sqrt(xDelta * xDelta + yDelta * yDelta);
},
now: (function() {
if (window.performance && window.performance.now) {
return window.performance.now.bind(window.performance);
}
return Date.now;
})()
};
/**
* @param {HTMLElement} element
* @constructor
*/
function ElementMetrics(element) {
this.element = element;
this.width = this.boundingRect.width;
this.height = this.boundingRect.height;
this.size = Math.max(this.width, this.height);
}
ElementMetrics.prototype = {
get boundingRect () {
return this.element.getBoundingClientRect();
},
furthestCornerDistanceFrom: function(x, y) {
var topLeft = Utility.distance(x, y, 0, 0);
var topRight = Utility.distance(x, y, this.width, 0);
var bottomLeft = Utility.distance(x, y, 0, this.height);
var bottomRight = Utility.distance(x, y, this.width, this.height);
return Math.max(topLeft, topRight, bottomLeft, bottomRight);
}
};
/**
* @param {HTMLElement} element
* @constructor
*/
function Ripple(element) {
this.element = element;
this.color = window.getComputedStyle(element).color;
this.wave = document.createElement('div');
this.waveContainer = document.createElement('div');
this.wave.style.backgroundColor = this.color;
this.wave.classList.add('wave');
this.waveContainer.classList.add('wave-container');
Polymer.dom(this.waveContainer).appendChild(this.wave);
this.resetInteractionState();
}
Ripple.MAX_RADIUS = 300;
Ripple.prototype = {
get recenters() {
return this.element.recenters;
},
get center() {
return this.element.center;
},
get mouseDownElapsed() {
var elapsed;
if (!this.mouseDownStart) {
return 0;
}
elapsed = Utility.now() - this.mouseDownStart;
if (this.mouseUpStart) {
elapsed -= this.mouseUpElapsed;
}
return elapsed;
},
get mouseUpElapsed() {
return this.mouseUpStart ?
Utility.now () - this.mouseUpStart : 0;
},
get mouseDownElapsedSeconds() {
return this.mouseDownElapsed / 1000;
},
get mouseUpElapsedSeconds() {
return this.mouseUpElapsed / 1000;
},
get mouseInteractionSeconds() {
return this.mouseDownElapsedSeconds + this.mouseUpElapsedSeconds;
},
get initialOpacity() {
return this.element.initialOpacity;
},
get opacityDecayVelocity() {
return this.element.opacityDecayVelocity;
},
get radius() {
var width2 = this.containerMetrics.width * this.containerMetrics.width;
var height2 = this.containerMetrics.height * this.containerMetrics.height;
var waveRadius = Math.min(
Math.sqrt(width2 + height2),
Ripple.MAX_RADIUS
) * 1.1 + 5;
var duration = 1.1 - 0.2 * (waveRadius / Ripple.MAX_RADIUS);
var timeNow = this.mouseInteractionSeconds / duration;
var size = waveRadius * (1 - Math.pow(80, -timeNow));
return Math.abs(size);
},
get opacity() {
if (!this.mouseUpStart) {
return this.initialOpacity;
}
return Math.max(
0,
this.initialOpacity - this.mouseUpElapsedSeconds * this.opacityDecayVelocity
);
},
get outerOpacity() {
// Linear increase in background opacity, capped at the opacity
// of the wavefront (waveOpacity).
var outerOpacity = this.mouseUpElapsedSeconds * 0.3;
var waveOpacity = this.opacity;
return Math.max(
0,
Math.min(outerOpacity, waveOpacity)
);
},
get isOpacityFullyDecayed() {
return this.opacity < 0.01 &&
this.radius >= Math.min(this.maxRadius, Ripple.MAX_RADIUS);
},
get isRestingAtMaxRadius() {
return this.opacity >= this.initialOpacity &&
this.radius >= Math.min(this.maxRadius, Ripple.MAX_RADIUS);
},
get isAnimationComplete() {
return this.mouseUpStart ?
this.isOpacityFullyDecayed : this.isRestingAtMaxRadius;
},
get translationFraction() {
return Math.min(
1,
this.radius / this.containerMetrics.size * 2 / Math.sqrt(2)
);
},
get xNow() {
if (this.xEnd) {
return this.xStart + this.translationFraction * (this.xEnd - this.xStart);
}
return this.xStart;
},
get yNow() {
if (this.yEnd) {
return this.yStart + this.translationFraction * (this.yEnd - this.yStart);
}
return this.yStart;
},
get isMouseDown() {
return this.mouseDownStart && !this.mouseUpStart;
},
resetInteractionState: function() {
this.maxRadius = 0;
this.mouseDownStart = 0;
this.mouseUpStart = 0;
this.xStart = 0;
this.yStart = 0;
this.xEnd = 0;
this.yEnd = 0;
this.slideDistance = 0;
this.containerMetrics = new ElementMetrics(this.element);
},
draw: function() {
var scale;
var translateString;
var dx;
var dy;
this.wave.style.opacity = this.opacity;
scale = this.radius / (this.containerMetrics.size / 2);
dx = this.xNow - (this.containerMetrics.width / 2);
dy = this.yNow - (this.containerMetrics.height / 2);
// 2d transform for safari because of border-radius and overflow:hidden clipping bug.
// https://bugs.webkit.org/show_bug.cgi?id=98538
this.waveContainer.style.webkitTransform = 'translate(' + dx + 'px, ' + dy + 'px)';
this.waveContainer.style.transform = 'translate3d(' + dx + 'px, ' + dy + 'px, 0)';
this.wave.style.webkitTransform = 'scale(' + scale + ',' + scale + ')';
this.wave.style.transform = 'scale3d(' + scale + ',' + scale + ',1)';
},
/** @param {Event=} event */
downAction: function(event) {
var xCenter = this.containerMetrics.width / 2;
var yCenter = this.containerMetrics.height / 2;
this.resetInteractionState();
this.mouseDownStart = Utility.now();
if (this.center) {
this.xStart = xCenter;
this.yStart = yCenter;
this.slideDistance = Utility.distance(
this.xStart, this.yStart, this.xEnd, this.yEnd
);
} else {
this.xStart = event ?
event.detail.x - this.containerMetrics.boundingRect.left :
this.containerMetrics.width / 2;
this.yStart = event ?
event.detail.y - this.containerMetrics.boundingRect.top :
this.containerMetrics.height / 2;
}
if (this.recenters) {
this.xEnd = xCenter;
this.yEnd = yCenter;
this.slideDistance = Utility.distance(
this.xStart, this.yStart, this.xEnd, this.yEnd
);
}
this.maxRadius = this.containerMetrics.furthestCornerDistanceFrom(
this.xStart,
this.yStart
);
this.waveContainer.style.top =
(this.containerMetrics.height - this.containerMetrics.size) / 2 + 'px';
this.waveContainer.style.left =
(this.containerMetrics.width - this.containerMetrics.size) / 2 + 'px';
this.waveContainer.style.width = this.containerMetrics.size + 'px';
this.waveContainer.style.height = this.containerMetrics.size + 'px';
},
/** @param {Event=} event */
upAction: function(event) {
if (!this.isMouseDown) {
return;
}
this.mouseUpStart = Utility.now();
},
remove: function() {
Polymer.dom(this.waveContainer.parentNode).removeChild(
this.waveContainer
);
}
};
Polymer({
is: 'paper-ripple',
behaviors: [
Polymer.IronA11yKeysBehavior
],
properties: {
/**
* The initial opacity set on the wave.
*
* @attribute initialOpacity
* @type number
* @default 0.25
*/
initialOpacity: {
type: Number,
value: 0.25
},
/**
* How fast (opacity per second) the wave fades out.
*
* @attribute opacityDecayVelocity
* @type number
* @default 0.8
*/
opacityDecayVelocity: {
type: Number,
value: 0.8
},
/**
* If true, ripples will exhibit a gravitational pull towards
* the center of their container as they fade away.
*
* @attribute recenters
* @type boolean
* @default false
*/
recenters: {
type: Boolean,
value: false
},
/**
* If true, ripples will center inside its container
*
* @attribute recenters
* @type boolean
* @default false
*/
center: {
type: Boolean,
value: false
},
/**
* A list of the visual ripples.
*
* @attribute ripples
* @type Array
* @default []
*/
ripples: {
type: Array,
value: function() {
return [];
}
},
/**
* True when there are visible ripples animating within the
* element.
*/
animating: {
type: Boolean,
readOnly: true,
reflectToAttribute: true,
value: false
},
/**
* If true, the ripple will remain in the "down" state until `holdDown`
* is set to false again.
*/
holdDown: {
type: Boolean,
value: false,
observer: '_holdDownChanged'
},
_animating: {
type: Boolean
},
_boundAnimate: {
type: Function,
value: function() {
return this.animate.bind(this);
}
}
},
get target () {
var ownerRoot = Polymer.dom(this).getOwnerRoot();
var target;
if (this.parentNode.nodeType == 11) { // DOCUMENT_FRAGMENT_NODE
target = ownerRoot.host;
} else {
target = this.parentNode;
}
return target;
},
keyBindings: {
'enter:keydown': '_onEnterKeydown',
'space:keydown': '_onSpaceKeydown',
'space:keyup': '_onSpaceKeyup'
},
attached: function() {
this.listen(this.target, 'up', 'upAction');
this.listen(this.target, 'down', 'downAction');
if (!this.target.hasAttribute('noink')) {
this.keyEventTarget = this.target;
}
},
get shouldKeepAnimating () {
for (var index = 0; index < this.ripples.length; ++index) {
if (!this.ripples[index].isAnimationComplete) {
return true;
}
}
return false;
},
simulatedRipple: function() {
this.downAction(null);
// Please see polymer/polymer#1305
this.async(function() {
this.upAction();
}, 1);
},
/** @param {Event=} event */
downAction: function(event) {
if (this.holdDown && this.ripples.length > 0) {
return;
}
var ripple = this.addRipple();
ripple.downAction(event);
if (!this._animating) {
this.animate();
}
},
/** @param {Event=} event */
upAction: function(event) {
if (this.holdDown) {
return;
}
this.ripples.forEach(function(ripple) {
ripple.upAction(event);
});
this.animate();
},
onAnimationComplete: function() {
this._animating = false;
this.$.background.style.backgroundColor = null;
this.fire('transitionend');
},
addRipple: function() {
var ripple = new Ripple(this);
Polymer.dom(this.$.waves).appendChild(ripple.waveContainer);
this.$.background.style.backgroundColor = ripple.color;
this.ripples.push(ripple);
this._setAnimating(true);
return ripple;
},
removeRipple: function(ripple) {
var rippleIndex = this.ripples.indexOf(ripple);
if (rippleIndex < 0) {
return;
}
this.ripples.splice(rippleIndex, 1);
ripple.remove();
if (!this.ripples.length) {
this._setAnimating(false);
}
},
animate: function() {
var index;
var ripple;
this._animating = true;
for (index = 0; index < this.ripples.length; ++index) {
ripple = this.ripples[index];
ripple.draw();
this.$.background.style.opacity = ripple.outerOpacity;
if (ripple.isOpacityFullyDecayed && !ripple.isRestingAtMaxRadius) {
this.removeRipple(ripple);
}
}
if (!this.shouldKeepAnimating && this.ripples.length === 0) {
this.onAnimationComplete();
} else {
window.requestAnimationFrame(this._boundAnimate);
}
},
_onEnterKeydown: function() {
this.downAction();
this.async(this.upAction, 1);
},
_onSpaceKeydown: function() {
this.downAction();
},
_onSpaceKeyup: function() {
this.upAction();
},
_holdDownChanged: function(holdDown) {
if (holdDown) {
this.downAction();
} else {
this.upAction();
}
}
});
})();
</script>
<dom-module id="paper-button" assetpath="bower_components/paper-button/">
<style>
:host {
display: inline-block;
position: relative;
box-sizing: border-box;
min-width: 5.14em;
margin: 0 0.29em;
background: transparent;
text-align: center;
font: inherit;
text-transform: uppercase;
outline: none;
border-radius: 3px;
-moz-user-select: none;
-ms-user-select: none;
-webkit-user-select: none;
user-select: none;
cursor: pointer;
z-index: 0;
@apply(--paper-button);
}
.keyboard-focus {
font-weight: bold;
}
:host([disabled]) {
background: #eaeaea;
color: #a8a8a8;
cursor: auto;
pointer-events: none;
@apply(--paper-button-disabled);
}
:host([noink]) paper-ripple {
display: none;
}
paper-material {
border-radius: inherit;
}
.content > ::content * {
text-transform: inherit;
}
.content {
padding: 0.7em 0.57em
}
</style>
<template>
<paper-ripple></paper-ripple>
<paper-material class$="[[_computeContentClass(receivedFocusFromKeyboard)]]" elevation="[[_elevation]]" animated="">
<content></content>
</paper-material>
</template>
</dom-module>
<script>
Polymer({
is: 'paper-button',
behaviors: [
Polymer.PaperButtonBehavior
],
properties: {
/**
* If true, the button should be styled with a shadow.
*/
raised: {
type: Boolean,
reflectToAttribute: true,
value: false,
observer: '_calculateElevation'
}
},
_calculateElevation: function() {
if (!this.raised) {
this._elevation = 0;
} else {
Polymer.PaperButtonBehaviorImpl._calculateElevation.apply(this);
}
},
_computeContentClass: function(receivedFocusFromKeyboard) {
var className = 'content ';
if (receivedFocusFromKeyboard) {
className += ' keyboard-focus';
}
return className;
}
});
</script>
<dom-module id="iron-a11y-announcer" assetpath="bower_components/iron-a11y-announcer/">
<style>
:host {
display: inline-block;
position: fixed;
clip: rect(0px,0px,0px,0px);
}
</style>
<template>
<span aria-live$="[[mode]]">[[_text]]</span>
</template>
<script>
(function() {
'use strict';
Polymer.IronA11yAnnouncer = Polymer({
is: 'iron-a11y-announcer',
properties: {
/**
* The value of mode is used to set the `aria-live` attribute
* for the element that will be announced. Valid values are: `off`,
* `polite` and `assertive`.
*/
mode: {
type: String,
value: 'polite'
},
_text: {
type: String,
value: ''
}
},
created: function() {
if (!Polymer.IronA11yAnnouncer.instance) {
Polymer.IronA11yAnnouncer.instance = this;
}
document.body.addEventListener('iron-announce', this._onIronAnnounce.bind(this));
},
/**
* Cause a text string to be announced by screen readers.
*
* @param {string} text The text that should be announced.
*/
announce: function(text) {
this._text = '';
this.async(function() {
this._text = text;
}, 100);
},
_onIronAnnounce: function(event) {
if (event.detail && event.detail.text) {
this.announce(event.detail.text);
}
}
});
Polymer.IronA11yAnnouncer.instance = null;
Polymer.IronA11yAnnouncer.requestAvailability = function() {
if (!Polymer.IronA11yAnnouncer.instance) {
document.createElement('iron-a11y-announcer');
}
document.body.appendChild(Polymer.IronA11yAnnouncer.instance);
};
})();
</script>
</dom-module>
<dom-module id="paper-toast" assetpath="bower_components/paper-toast/">
<style>
:host {
display: inline-block;
position: fixed;
background: #323232;
color: #f1f1f1;
min-height: 48px;
min-width: 288px;
padding: 16px 24px 12px;
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;
-webkit-transition: visibility 0.3s, -webkit-transform 0.3s;
transition: visibility 0.3s, transform 0.3s;
-webkit-transform: translateY(100px);
transform: translateY(100px);
visibility: hidden;
}
:host(.capsule) {
border-radius: 24px;
}
:host(.fit-bottom) {
bottom: 0;
left: 0;
width: 100%;
min-width: 0;
border-radius: 0;
}
:host(.paper-toast-open){
visibility: visible;
-webkit-transform: translateY(0px);
transform: translateY(0px);
}
</style>
<template>
<span id="label">{{text}}</span>
<content></content>
</template>
</dom-module>
<script>
(function() {
var PaperToast = Polymer({
is: 'paper-toast',
properties: {
/**
* The duration in milliseconds to show the toast.
*/
duration: {
type: Number,
value: 3000
},
/**
* The text to display in the toast.
*/
text: {
type: String,
value: ""
},
/**
* True if the toast is currently visible.
*/
visible: {
type: Boolean,
readOnly: true,
value: false,
observer: '_visibleChanged'
}
},
created: function() {
Polymer.IronA11yAnnouncer.requestAvailability();
},
ready: function() {
this.async(function() {
this.hide();
});
},
/**
* Show the toast.
* @method show
*/
show: function() {
if (PaperToast.currentToast) {
PaperToast.currentToast.hide();
}
PaperToast.currentToast = this;
this.removeAttribute('aria-hidden');
this._setVisible(true);
this.fire('iron-announce', {
text: this.text
});
this.debounce('hide', this.hide, this.duration);
},
/**
* Hide the toast
*/
hide: function() {
this.setAttribute('aria-hidden', 'true');
this._setVisible(false);
},
/**
* Toggle the opened state of the toast.
* @method toggle
*/
toggle: function() {
if (!this.visible) {
this.show();
} else {
this.hide();
}
},
_visibleChanged: function(visible) {
this.toggleClass('paper-toast-open', visible);
}
});
PaperToast.currentToast = null;
})();
</script>
<dom-module id="paper-spinner" assetpath="bower_components/paper-spinner/">
<style>
/**
@license
Copyright (c) 2015 The Polymer Project Authors. All rights reserved.
This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
Code distributed by Google as part of the polymer project is also
subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
*/
/**************************/
/* STYLES FOR THE SPINNER */
/**************************/
/*
* Constants:
* STROKEWIDTH = 3px
* ARCSIZE = 270 degrees (amount of circle the arc takes up)
* ARCTIME = 1333ms (time it takes to expand and contract arc)
* ARCSTARTROT = 216 degrees (how much the start location of the arc
* should rotate each time, 216 gives us a
* 5 pointed star shape (it's 360/5 * 3).
* For a 7 pointed star, we might do
* 360/7 * 3 = 154.286)
* CONTAINERWIDTH = 28px
* SHRINK_TIME = 400ms
*/
:host {
display: inline-block;
position: relative;
width: 28px; /* CONTAINERWIDTH */
height: 28px; /* CONTAINERWIDTH */
}
#spinnerContainer {
width: 100%;
height: 100%;
}
#spinnerContainer.active {
/* duration: 360 * ARCTIME / (ARCSTARTROT + (360-ARCSIZE)) */
-webkit-animation: container-rotate 1568ms linear infinite;
animation: container-rotate 1568ms linear infinite;
}
@-webkit-keyframes container-rotate {
to { -webkit-transform: rotate(360deg) }
}
@keyframes container-rotate {
to { transform: rotate(360deg) }
}
.spinner-layer {
position: absolute;
width: 100%;
height: 100%;
opacity: 0;
}
.layer-1 {
border-color: var(--paper-spinner-layer-1-color, --google-blue-500);
}
.layer-2 {
border-color: var(--paper-spinner-layer-2-color, --google-red-500);
}
.layer-3 {
border-color: var(--paper-spinner-layer-3-color, --google-yellow-500);
}
.layer-4 {
border-color: var(--paper-spinner-layer-4-color, --google-blue-500);
}
/**
* IMPORTANT NOTE ABOUT CSS ANIMATION PROPERTIES (keanulee):
*
* iOS Safari (tested on iOS 8.1) does not handle animation-delay very well - it doesn't
* guarantee that the animation will start _exactly_ after that value. So we avoid using
* animation-delay and instead set custom keyframes for each color (as layer-2undant as it
* seems).
*
* We write out each animation in full (instead of separating animation-name,
* animation-duration, etc.) because under the polyfill, Safari does not recognize those
* specific properties properly, treats them as -webkit-animation, and overrides the
* other animation rules. See https://github.com/Polymer/platform/issues/53.
*/
.active .spinner-layer.layer-1 {
/* durations: 4 * ARCTIME */
-webkit-animation: fill-unfill-rotate 5332ms cubic-bezier(0.4, 0.0, 0.2, 1) infinite both, layer-1-fade-in-out 5332ms cubic-bezier(0.4, 0.0, 0.2, 1) infinite both;
animation: fill-unfill-rotate 5332ms cubic-bezier(0.4, 0.0, 0.2, 1) infinite both, layer-1-fade-in-out 5332ms cubic-bezier(0.4, 0.0, 0.2, 1) infinite both;
}
.active .spinner-layer.layer-2 {
/* durations: 4 * ARCTIME */
-webkit-animation: fill-unfill-rotate 5332ms cubic-bezier(0.4, 0.0, 0.2, 1) infinite both, layer-2-fade-in-out 5332ms cubic-bezier(0.4, 0.0, 0.2, 1) infinite both;
animation: fill-unfill-rotate 5332ms cubic-bezier(0.4, 0.0, 0.2, 1) infinite both, layer-2-fade-in-out 5332ms cubic-bezier(0.4, 0.0, 0.2, 1) infinite both;
}
.active .spinner-layer.layer-3 {
/* durations: 4 * ARCTIME */
-webkit-animation: fill-unfill-rotate 5332ms cubic-bezier(0.4, 0.0, 0.2, 1) infinite both, layer-3-fade-in-out 5332ms cubic-bezier(0.4, 0.0, 0.2, 1) infinite both;
animation: fill-unfill-rotate 5332ms cubic-bezier(0.4, 0.0, 0.2, 1) infinite both, layer-3-fade-in-out 5332ms cubic-bezier(0.4, 0.0, 0.2, 1) infinite both;
}
.active .spinner-layer.layer-4 {
/* durations: 4 * ARCTIME */
-webkit-animation: fill-unfill-rotate 5332ms cubic-bezier(0.4, 0.0, 0.2, 1) infinite both, layer-4-fade-in-out 5332ms cubic-bezier(0.4, 0.0, 0.2, 1) infinite both;
animation: fill-unfill-rotate 5332ms cubic-bezier(0.4, 0.0, 0.2, 1) infinite both, layer-4-fade-in-out 5332ms cubic-bezier(0.4, 0.0, 0.2, 1) infinite both;
}
@-webkit-keyframes fill-unfill-rotate {
12.5% { -webkit-transform: rotate(135deg); } /* 0.5 * ARCSIZE */
25% { -webkit-transform: rotate(270deg); } /* 1 * ARCSIZE */
37.5% { -webkit-transform: rotate(405deg); } /* 1.5 * ARCSIZE */
50% { -webkit-transform: rotate(540deg); } /* 2 * ARCSIZE */
62.5% { -webkit-transform: rotate(675deg); } /* 2.5 * ARCSIZE */
75% { -webkit-transform: rotate(810deg); } /* 3 * ARCSIZE */
87.5% { -webkit-transform: rotate(945deg); } /* 3.5 * ARCSIZE */
to { -webkit-transform: rotate(1080deg); } /* 4 * ARCSIZE */
}
@keyframes fill-unfill-rotate {
12.5% { transform: rotate(135deg); } /* 0.5 * ARCSIZE */
25% { transform: rotate(270deg); } /* 1 * ARCSIZE */
37.5% { transform: rotate(405deg); } /* 1.5 * ARCSIZE */
50% { transform: rotate(540deg); } /* 2 * ARCSIZE */
62.5% { transform: rotate(675deg); } /* 2.5 * ARCSIZE */
75% { transform: rotate(810deg); } /* 3 * ARCSIZE */
87.5% { transform: rotate(945deg); } /* 3.5 * ARCSIZE */
to { transform: rotate(1080deg); } /* 4 * ARCSIZE */
}
/**
* HACK: Even though the intention is to have the current .spinner-layer at
* `opacity: 1`, we set it to `opacity: 0.99` instead since this forces Chrome
* to do proper subpixel rendering for the elements being animated. This is
* especially visible in Chrome 39 on Ubuntu 14.04. See:
*
* - https://github.com/Polymer/paper-spinner/issues/9
* - https://code.google.com/p/chromium/issues/detail?id=436255
*/
@-webkit-keyframes layer-1-fade-in-out {
from { opacity: 0.99; }
25% { opacity: 0.99; }
26% { opacity: 0; }
89% { opacity: 0; }
90% { opacity: 0.99; }
100% { opacity: 0.99; }
}
@keyframes layer-1-fade-in-out {
from { opacity: 0.99; }
25% { opacity: 0.99; }
26% { opacity: 0; }
89% { opacity: 0; }
90% { opacity: 0.99; }
100% { opacity: 0.99; }
}
@-webkit-keyframes layer-2-fade-in-out {
from { opacity: 0; }
15% { opacity: 0; }
25% { opacity: 0.99; }
50% { opacity: 0.99; }
51% { opacity: 0; }
}
@keyframes layer-2-fade-in-out {
from { opacity: 0; }
15% { opacity: 0; }
25% { opacity: 0.99; }
50% { opacity: 0.99; }
51% { opacity: 0; }
}
@-webkit-keyframes layer-3-fade-in-out {
from { opacity: 0; }
40% { opacity: 0; }
50% { opacity: 0.99; }
75% { opacity: 0.99; }
76% { opacity: 0; }
}
@keyframes layer-3-fade-in-out {
from { opacity: 0; }
40% { opacity: 0; }
50% { opacity: 0.99; }
75% { opacity: 0.99; }
76% { opacity: 0; }
}
@-webkit-keyframes layer-4-fade-in-out {
from { opacity: 0; }
65% { opacity: 0; }
75% { opacity: 0.99; }
90% { opacity: 0.99; }
100% { opacity: 0; }
}
@keyframes layer-4-fade-in-out {
from { opacity: 0; }
65% { opacity: 0; }
75% { opacity: 0.99; }
90% { opacity: 0.99; }
100% { opacity: 0; }
}
/**
* Patch the gap that appear between the two adjacent div.circle-clipper while the
* spinner is rotating (appears on Chrome 38, Safari 7.1, and IE 11).
*
* Update: the gap no longer appears on Chrome when .spinner-layer's opacity is 0.99,
* but still does on Safari and IE.
*/
.gap-patch {
position: absolute;
box-sizing: border-box;
top: 0;
left: 45%;
width: 10%;
height: 100%;
overflow: hidden;
border-color: inherit;
}
.gap-patch .circle {
width: 1000%;
left: -450%;
}
.circle-clipper {
display: inline-block;
position: relative;
width: 50%;
height: 100%;
overflow: hidden;
border-color: inherit;
}
.circle-clipper .circle {
width: 200%;
}
.circle {
box-sizing: border-box;
height: 100%;
border-width: 3px; /* STROKEWIDTH */
border-style: solid;
border-color: inherit;
border-bottom-color: transparent !important;
border-radius: 50%;
-webkit-animation: none;
animation: none;
@apply(--layout-fit);
}
.circle-clipper.left .circle {
border-right-color: transparent !important;
-webkit-transform: rotate(129deg);
transform: rotate(129deg);
}
.circle-clipper.right .circle {
left: -100%;
border-left-color: transparent !important;
-webkit-transform: rotate(-129deg);
transform: rotate(-129deg);
}
.active .circle-clipper.left .circle {
/* duration: ARCTIME */
-webkit-animation: left-spin 1333ms cubic-bezier(0.4, 0.0, 0.2, 1) infinite both;
animation: left-spin 1333ms cubic-bezier(0.4, 0.0, 0.2, 1) infinite both;
}
.active .circle-clipper.right .circle {
/* duration: ARCTIME */
-webkit-animation: right-spin 1333ms cubic-bezier(0.4, 0.0, 0.2, 1) infinite both;
animation: right-spin 1333ms cubic-bezier(0.4, 0.0, 0.2, 1) infinite both;
}
@-webkit-keyframes left-spin {
from { -webkit-transform: rotate(130deg); }
50% { -webkit-transform: rotate(-5deg); }
to { -webkit-transform: rotate(130deg); }
}
@keyframes left-spin {
from { transform: rotate(130deg); }
50% { transform: rotate(-5deg); }
to { transform: rotate(130deg); }
}
@-webkit-keyframes right-spin {
from { -webkit-transform: rotate(-130deg); }
50% { -webkit-transform: rotate(5deg); }
to { -webkit-transform: rotate(-130deg); }
}
@keyframes right-spin {
from { transform: rotate(-130deg); }
50% { transform: rotate(5deg); }
to { transform: rotate(-130deg); }
}
#spinnerContainer.cooldown {
/* duration: SHRINK_TIME */
-webkit-animation: container-rotate 1568ms linear infinite, fade-out 400ms cubic-bezier(0.4, 0.0, 0.2, 1);
animation: container-rotate 1568ms linear infinite, fade-out 400ms cubic-bezier(0.4, 0.0, 0.2, 1);
}
@-webkit-keyframes fade-out {
from { opacity: 0.99; }
to { opacity: 0; }
}
@keyframes fade-out {
from { opacity: 0.99; }
to { opacity: 0; }
}
</style>
<template>
<div id="spinnerContainer" class-name="[[_spinnerContainerClassName]]">
<div class="spinner-layer layer-1">
<div class="circle-clipper left">
<div class="circle"></div>
</div><div class="gap-patch">
<div class="circle"></div>
</div><div class="circle-clipper right">
<div class="circle"></div>
</div>
</div>
<div class="spinner-layer layer-2">
<div class="circle-clipper left">
<div class="circle"></div>
</div><div class="gap-patch">
<div class="circle"></div>
</div><div class="circle-clipper right">
<div class="circle"></div>
</div>
</div>
<div class="spinner-layer layer-3">
<div class="circle-clipper left">
<div class="circle"></div>
</div><div class="gap-patch">
<div class="circle"></div>
</div><div class="circle-clipper right">
<div class="circle"></div>
</div>
</div>
<div class="spinner-layer layer-4">
<div class="circle-clipper left">
<div class="circle"></div>
</div><div class="gap-patch">
<div class="circle"></div>
</div><div class="circle-clipper right">
<div class="circle"></div>
</div>
</div>
</div>
</template>
<script>
(function() {
'use strict';
function classNames(obj) {
var classNames = [];
for (var key in obj) {
if (obj.hasOwnProperty(key) && obj[key]) {
classNames.push(key);
}
}
return classNames.join(' ');
}
Polymer({
is: 'paper-spinner',
listeners: {
'animationend': 'reset',
'webkitAnimationEnd': 'reset'
},
properties: {
/**
* Displays the spinner.
*
* @attribute active
* @type boolean
* @default false
*/
active: {
observer: '_activeChanged',
type: Boolean,
value: false
},
/**
* Alternative text content for accessibility support.
* If alt is present, it will add an aria-label whose content matches alt when active.
* If alt is not present, it will default to 'loading' as the alt value.
*
* @attribute alt
* @type string
* @default 'loading'
*/
alt: {
observer: '_altChanged',
type: String,
value: 'loading'
},
/**
* True when the spinner is going from active to inactive. This is represented by a fade
* to 0% opacity to the user.
*/
_coolingDown: {
type: Boolean,
value: false
},
_spinnerContainerClassName: {
type: String,
computed: '_computeSpinnerContainerClassName(active, _coolingDown)'
}
},
_computeSpinnerContainerClassName: function(active, _coolingDown) {
return classNames({
active: active || _coolingDown,
cooldown: _coolingDown
});
},
ready: function() {
// Allow user-provided `aria-label` take preference to any other text alternative.
if (this.hasAttribute('aria-label')) {
this.alt = this.getAttribute('aria-label');
} else {
this.setAttribute('aria-label', this.alt);
}
if (!this.active) {
this.setAttribute('aria-hidden', 'true');
}
},
_activeChanged: function() {
if (this.active) {
this.removeAttribute('aria-hidden');
} else {
this._coolingDown = true;
this.setAttribute('aria-hidden', 'true');
}
},
_altChanged: function() {
if (this.alt === '') {
this.setAttribute('aria-hidden', 'true');
} else {
this.removeAttribute('aria-hidden');
}
this.setAttribute('aria-label', this.alt);
},
reset: function() {
this.active = false;
this._coolingDown = false;
}
});
}());
</script>
</dom-module>
<dom-module id="iron-icon" assetpath="bower_components/iron-icon/">
<style>
:host {
@apply(--layout-inline);
@apply(--layout-center-center);
position: relative;
vertical-align: middle;
fill: currentcolor;
width: var(--iron-icon-width, 24px);
height: var(--iron-icon-height, 24px);
}
</style>
<template>
<iron-meta id="meta" type="iconset"></iron-meta>
</template>
<script>
Polymer({
is: 'iron-icon',
properties: {
/**
* The name of the icon to use. The name should be of the form:
* `iconset_name:icon_name`.
*/
icon: {
type: String,
observer: '_iconChanged'
},
/**
* The name of the theme to used, if one is specified by the
* iconset.
*/
theme: {
type: String,
observer: '_updateIcon'
},
/**
* If using iron-icon without an iconset, you can set the src to be
* the URL of an individual icon image file. Note that this will take
* precedence over a given icon attribute.
*/
src: {
type: String,
observer: '_srcChanged'
}
},
_DEFAULT_ICONSET: 'icons',
_iconChanged: function(icon) {
var parts = (icon || '').split(':');
this._iconName = parts.pop();
this._iconsetName = parts.pop() || this._DEFAULT_ICONSET;
this._updateIcon();
},
_srcChanged: function(src) {
this._updateIcon();
},
_usesIconset: function() {
return this.icon || !this.src;
},
_updateIcon: function() {
if (this._usesIconset()) {
if (this._iconsetName) {
this._iconset = this.$.meta.byKey(this._iconsetName);
if (this._iconset) {
this._iconset.applyIcon(this, this._iconName, this.theme);
} else {
this._warn(this._logf('_updateIcon', 'could not find iconset `'
+ this._iconsetName + '`, did you import the iconset?'));
}
}
} else {
if (!this._img) {
this._img = document.createElement('img');
this._img.style.width = '100%';
this._img.style.height = '100%';
}
this._img.src = this.src;
Polymer.dom(this.root).appendChild(this._img);
}
}
});
</script>
</dom-module>
<dom-module id="paper-fab" assetpath="bower_components/paper-fab/">
<style>
:host {
display: inline-block;
position: relative;
outline: none;
-moz-user-select: none;
-ms-user-select: none;
-webkit-user-select: none;
user-select: none;
cursor: pointer;
box-sizing: border-box;
min-width: 0;
width: 56px;
height: 56px;
background: var(--paper-fab-background, --accent-color);
color: var(--text-primary-color);
border-radius: 50%;
padding: 16px;
z-index: 0;
@apply(--paper-fab);
}
:host([mini]) {
width: 40px;
height: 40px;
padding: 8px;
@apply(--paper-fab-mini);
}
:host([disabled]) {
color: var(--paper-fab-disabled-text, --paper-grey-500);
background: var(--paper-fab-disabled-background, --paper-grey-300);
@apply(--paper-fab-disabled);
}
paper-material {
border-radius: inherit;
@apply(--layout-fit);
@apply(--layout-vertical);
@apply(--layout-center-center);
}
.keyboard-focus {
background: var(--paper-fab-keyboard-focus-background, --paper-pink-900);
}
</style>
<template>
<paper-ripple></paper-ripple>
<paper-material class$="[[_computeContentClass(receivedFocusFromKeyboard)]]" elevation="[[_elevation]]" animated="">
<iron-icon id="icon" src="[[src]]" icon="[[icon]]"></iron-icon>
</paper-material>
</template>
</dom-module>
<script>
Polymer({
is: 'paper-fab',
behaviors: [
Polymer.PaperButtonBehavior
],
properties: {
/**
* 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: {
type: String,
value: ''
},
/**
* 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: {
type: String,
value: ''
},
/**
* Set this to true to style this is a "mini" FAB.
*
* @attribute mini
* @type boolean
* @default false
*/
mini: {
type: Boolean,
value: false
}
},
_computeContentClass: function(receivedFocusFromKeyboard) {
var className = 'content';
if (receivedFocusFromKeyboard) {
className += ' keyboard-focus';
}
return className;
}
});
</script>
<dom-module id="iron-overlay-backdrop" assetpath="bower_components/iron-overlay-behavior/">
<style>
:host {
position: fixed;
top: 0;
left: 0;
width: 100vw;
height: 100vh;
background-color: var(--iron-overlay-backdrop-background-color, #000);
opacity: 0;
transition: opacity 0.2s;
@apply(--iron-overlay-backdrop);
}
:host([opened]) {
opacity: var(--iron-overlay-backdrop-opacity, 0.6);
@apply(--iron-overlay-backdrop-opened);
}
</style>
<template>
<content></content>
</template>
</dom-module>
<script>
(function() {
Polymer({
is: 'iron-overlay-backdrop',
properties: {
/**
* Returns true if the backdrop is opened.
*/
opened: {
readOnly: true,
reflectToAttribute: true,
type: Boolean,
value: false
},
_manager: {
type: Object,
value: Polymer.IronOverlayManager
}
},
/**
* Appends the backdrop to document body and sets its `z-index` to be below the latest overlay.
*/
prepare: function() {
if (!this.parentNode) {
Polymer.dom(document.body).appendChild(this);
this.style.zIndex = this._manager.currentOverlayZ() - 1;
}
},
/**
* Shows the backdrop if needed.
*/
open: function() {
// only need to make the backdrop visible if this is called by the first overlay with a backdrop
if (this._manager.getBackdrops().length < 2) {
this._setOpened(true);
}
},
/**
* Hides the backdrop if needed.
*/
close: function() {
// only need to make the backdrop invisible if this is called by the last overlay with a backdrop
if (this._manager.getBackdrops().length < 2) {
this._setOpened(false);
}
},
/**
* Removes the backdrop from document body if needed.
*/
complete: function() {
// only remove the backdrop if there are no more overlays with backdrops
if (this._manager.getBackdrops().length === 0 && this.parentNode) {
Polymer.dom(this.parentNode).removeChild(this);
}
}
});
})();
</script>
<dom-module id="paper-dialog" assetpath="bower_components/paper-dialog/">
<style>
/*
@license
Copyright (c) 2015 The Polymer Project Authors. All rights reserved.
This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
Code distributed by Google as part of the polymer project is also
subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
*/
:host {
display: block;
margin: 24px 40px;
background: var(--paper-dialog-background-color, --primary-background-color);
color: var(--paper-dialog-color, --primary-text-color);
@apply(--layout-scroll);
@apply(--paper-font-body1);
@apply(--shadow-elevation-16dp);
@apply(--paper-dialog);
}
:host > ::content > * {
margin-top: 20px;
padding: 0 24px;
}
:host > ::content > .no-padding {
padding: 0;
};
:host > ::content > *:first-child {
margin-top: 24px;
}
:host > ::content > *:last-child {
margin-bottom: 24px;
}
:host > ::content h2 {
position: relative;
margin: 0;
@apply(--paper-font-title);
@apply(--paper-dialog-title);
}
:host > ::content .buttons {
position: relative;
padding: 8px 8px 8px 24px;
margin: 0;
color: var(--paper-dialog-button-color, --default-primary-color);
@apply(--layout-horizontal);
@apply(--layout-end-justified);
}
</style>
<template>
<content></content>
</template>
</dom-module>
<script>
(function() {
Polymer({
is: 'paper-dialog',
behaviors: [
Polymer.PaperDialogBehavior,
Polymer.NeonAnimationRunnerBehavior
],
listeners: {
'neon-animation-finish': '_onNeonAnimationFinish'
},
_renderOpened: function() {
if (this.withBackdrop) {
this.backdropElement.open();
}
this.playAnimation('entry');
},
_renderClosed: function() {
if (this.withBackdrop) {
this.backdropElement.close();
}
this.playAnimation('exit');
},
_onNeonAnimationFinish: function() {
if (this.opened) {
this._finishRenderOpened();
} else {
this._finishRenderClosed();
}
}
});
})();
</script>
<dom-module id="paper-dialog-scrollable" assetpath="bower_components/paper-dialog-scrollable/">
<style>
:host {
display: block;
position: relative;
}
:host(.is-scrolled:not(:first-child))::before {
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
height: 1px;
background: var(--divider-color);
}
:host(.can-scroll:not(.scrolled-to-bottom):not(:last-child))::after {
content: '';
position: absolute;
bottom: 0;
left: 0;
right: 0;
height: 1px;
background: var(--divider-color);
}
.scrollable {
padding: 0 24px;
@apply(--layout-scroll);
@apply(--paper-dialog-scrollable);
}
</style>
<template>
<div id="scrollable" class="scrollable">
<content></content>
</div>
</template>
</dom-module>
<script>
(function() {
Polymer({
is: 'paper-dialog-scrollable',
properties: {
/**
* The dialog element that implements `Polymer.PaperDialogBehavior` containing this element.
* @type {?Node}
*/
dialogElement: {
type: Object,
value: function() {
return this.parentNode;
}
}
},
listeners: {
'scrollable.scroll': '_onScroll',
'iron-resize': '_onIronResize'
},
/**
* Returns the scrolling element.
*/
get scrollTarget() {
return this.$.scrollable;
},
attached: function() {
this.classList.add('no-padding');
// Set itself to the overlay sizing target
this.dialogElement.sizingTarget = this.scrollTarget;
// If the host is sized, fit the scrollable area to the container. Otherwise let it be
// its natural size.
requestAnimationFrame(function() {
if (this.offsetHeight > 0) {
this.$.scrollable.classList.add('fit');
}
this._scroll();
}.bind(this));
},
_scroll: function() {
this.toggleClass('is-scrolled', this.scrollTarget.scrollTop > 0);
this.toggleClass('can-scroll', this.scrollTarget.offsetHeight < this.scrollTarget.scrollHeight);
this.toggleClass('scrolled-to-bottom',
this.scrollTarget.scrollTop + this.scrollTarget.offsetHeight >= this.scrollTarget.scrollHeight);
},
_onScroll: function() {
this._scroll();
}
})
})();
</script>
<dom-module id="paper-icon-button" assetpath="bower_components/paper-icon-button/">
<style>
:host {
display: inline-block;
position: relative;
padding: 8px;
outline: none;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
cursor: pointer;
z-index: 0;
@apply(--paper-icon-button);
}
:host #ink {
color: var(--paper-icon-button-ink-color, --primary-text-color);
opacity: 0.6;
}
:host([disabled]) {
color: var(--paper-icon-button-disabled-text, --disabled-text-color);
pointer-events: none;
cursor: auto;
@apply(--paper-icon-button-disabled);
}
</style>
<template>
<paper-ripple id="ink" class="circle" center=""></paper-ripple>
<iron-icon id="icon" src="[[src]]" icon="[[icon]]" alt$="[[alt]]"></iron-icon>
</template>
</dom-module>
<script>
Polymer({
is: 'paper-icon-button',
hostAttributes: {
role: 'button',
tabindex: '0'
},
behaviors: [
Polymer.PaperInkyFocusBehavior
],
properties: {
/**
* The URL of an image for the icon. If the src property is specified,
* the icon property should not be.
*/
src: {
type: String
},
/**
* 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.
*/
icon: {
type: String
},
/**
* Specifies the alternate text for the button, for accessibility.
*/
alt: {
type: String,
observer: "_altChanged"
}
},
_altChanged: function(newValue, oldValue) {
var label = this.getAttribute('aria-label');
// Don't stomp over a user-set aria-label.
if (!label || oldValue == label) {
this.setAttribute('aria-label', newValue);
}
}
});
</script>
<dom-module id="paper-drawer-panel" assetpath="bower_components/paper-drawer-panel/">
<style>
/**
@license
Copyright (c) 2015 The Polymer Project Authors. All rights reserved.
This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
Code distributed by Google as part of the polymer project is also
subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
*/
:host {
display: block;
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
overflow: hidden;
}
iron-selector > #drawer {
position: absolute;
top: 0;
left: 0;
height: 100%;
background-color: white;
will-change: transform;
box-sizing: border-box;
-moz-box-sizing: border-box;
@apply(--paper-drawer-panel-drawer-container);
}
.transition > #drawer {
transition: -webkit-transform ease-in-out 0.3s, width ease-in-out 0.3s;
transition: transform ease-in-out 0.3s, width ease-in-out 0.3s;
}
.left-drawer > #drawer {
@apply(--paper-drawer-panel-left-drawer-container);
}
.right-drawer > #drawer {
left: auto;
right: 0;
@apply(--paper-drawer-panel-right-drawer-container);
}
iron-selector > #main {
position: absolute;
top: 0;
right: 0;
bottom: 0;
@apply(--paper-drawer-panel-main-container);
}
.transition > #main {
transition: left ease-in-out 0.3s, padding ease-in-out 0.3s;
}
.right-drawer > #main {
left: 0;
}
.right-drawer.transition > #main {
transition: right ease-in-out 0.3s, padding ease-in-out 0.3s;
}
#main > ::content > [main] {
height: 100%;
}
#drawer > ::content > [drawer] {
height: 100%;
}
#scrim {
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
visibility: hidden;
opacity: 0;
transition: opacity ease-in-out 0.38s, visibility ease-in-out 0.38s;
background-color: rgba(0, 0, 0, 0.3);
}
.narrow-layout > #drawer.iron-selected {
box-shadow: 2px 2px 4px rgba(0, 0, 0, 0.15);
}
.right-drawer.narrow-layout > #drawer.iron-selected {
box-shadow: -2px 2px 4px rgba(0, 0, 0, 0.15);
}
.narrow-layout > #drawer > ::content > [drawer] {
border: 0;
}
.left-drawer.narrow-layout > #drawer:not(.iron-selected) {
-webkit-transform: translateX(-100%);
transform: translateX(-100%);
}
.right-drawer.narrow-layout > #drawer:not(.iron-selected) {
left: auto;
-webkit-transform: translateX(100%);
transform: translateX(100%);
}
.narrow-layout > #main {
left: 0 !important;
padding: 0;
}
.right-drawer.narrow-layout > #main {
left: 0;
right: 0;
padding: 0;
}
.narrow-layout > #main:not(.iron-selected) > #scrim,
.dragging > #main > #scrim {
visibility: visible;
opacity: var(--paper-drawer-panel-scrim-opacity, 1);
}
.narrow-layout > #main > * {
margin: 0;
min-height: 100%;
left: 0;
right: 0;
box-sizing: border-box;
-moz-box-sizing: border-box;
}
iron-selector:not(.narrow-layout) #main ::content [paper-drawer-toggle] {
display: none;
}
</style>
<template>
<iron-media-query id="mq" on-query-matches-changed="_onQueryMatchesChanged" query="[[_computeMediaQuery(forceNarrow, responsiveWidth)]]">
</iron-media-query>
<iron-selector attr-for-selected="id" class$="[[_computeIronSelectorClass(narrow, transition, dragging, rightDrawer)]]" activate-event="" selected="[[selected]]">
<div id="main" style$="[[_computeMainStyle(narrow, rightDrawer, drawerWidth)]]">
<content select="[main]"></content>
<div id="scrim" on-tap="closeDrawer"></div>
</div>
<div id="drawer" style$="[[_computeDrawerStyle(drawerWidth)]]">
<content select="[drawer]"></content>
</div>
</iron-selector>
</template>
</dom-module>
<script>
(function() {
'use strict';
// this would be the only `paper-drawer-panel` in
// the whole app that can be in `dragging` state
var sharedPanel = null;
function classNames(obj) {
var classes = [];
for (var key in obj) {
if (obj.hasOwnProperty(key) && obj[key]) {
classes.push(key);
}
}
return classes.join(' ');
}
Polymer({
is: 'paper-drawer-panel',
/**
* Fired when the narrow layout changes.
*
* @event paper-responsive-change {{narrow: boolean}} detail -
* narrow: true if the panel is in narrow layout.
*/
/**
* Fired when the selected panel changes.
*
* Listening for this event is an alternative to observing changes in the `selected` attribute.
* This event is fired both when a panel is selected and deselected.
* The `isSelected` detail property contains the selection state.
*
* @event paper-select {{isSelected: boolean, item: Object}} detail -
* isSelected: True for selection and false for deselection.
* item: The panel that the event refers to.
*/
properties: {
/**
* The panel to be selected when `paper-drawer-panel` changes to narrow
* layout.
*/
defaultSelected: {
type: String,
value: 'main'
},
/**
* If true, swipe from the edge is disable.
*/
disableEdgeSwipe: {
type: Boolean,
value: false
},
/**
* If true, swipe to open/close the drawer is disabled.
*/
disableSwipe: {
type: Boolean,
value: false
},
/**
* Whether the user is dragging the drawer interactively.
*/
dragging: {
type: Boolean,
value: false,
readOnly: true,
notify: true
},
/**
* Width of the drawer panel.
*/
drawerWidth: {
type: String,
value: '256px'
},
/**
* How many pixels on the side of the screen are sensitive to edge
* swipes and peek.
*/
edgeSwipeSensitivity: {
type: Number,
value: 30
},
/**
* If true, ignore `responsiveWidth` setting and force the narrow layout.
*/
forceNarrow: {
type: Boolean,
value: false
},
/**
* Whether the browser has support for the transform CSS property.
*/
hasTransform: {
type: Boolean,
value: function() {
return 'transform' in this.style;
}
},
/**
* Whether the browser has support for the will-change CSS property.
*/
hasWillChange: {
type: Boolean,
value: function() {
return 'willChange' in this.style;
}
},
/**
* Returns true if the panel is in narrow layout. This is useful if you
* need to show/hide elements based on the layout.
*/
narrow: {
reflectToAttribute: true,
type: Boolean,
value: false,
readOnly: true,
notify: true
},
/**
* Whether the drawer is peeking out from the edge.
*/
peeking: {
type: Boolean,
value: false,
readOnly: true,
notify: true
},
/**
* Max-width when the panel changes to narrow layout.
*/
responsiveWidth: {
type: String,
value: '640px'
},
/**
* If true, position the drawer to the right.
*/
rightDrawer: {
type: Boolean,
value: false
},
/**
* The panel that is being selected. `drawer` for the drawer panel and
* `main` for the main panel.
*/
selected: {
reflectToAttribute: true,
notify: true,
type: String,
value: null
},
/**
* The attribute on elements that should toggle the drawer on tap, also elements will
* automatically be hidden in wide layout.
*/
drawerToggleAttribute: {
type: String,
value: 'paper-drawer-toggle'
},
/**
* Whether the transition is enabled.
*/
transition: {
type: Boolean,
value: false
},
},
listeners: {
tap: '_onTap',
track: '_onTrack',
down: '_downHandler',
up: '_upHandler'
},
observers: [
'_forceNarrowChanged(forceNarrow, defaultSelected)'
],
/**
* Toggles the panel open and closed.
*
* @method togglePanel
*/
togglePanel: function() {
if (this._isMainSelected()) {
this.openDrawer();
} else {
this.closeDrawer();
}
},
/**
* Opens the drawer.
*
* @method openDrawer
*/
openDrawer: function() {
this.selected = 'drawer';
},
/**
* Closes the drawer.
*
* @method closeDrawer
*/
closeDrawer: function() {
this.selected = 'main';
},
ready: function() {
// Avoid transition at the beginning e.g. page loads and enable
// transitions only after the element is rendered and ready.
this.transition = true;
},
_computeIronSelectorClass: function(narrow, transition, dragging, rightDrawer) {
return classNames({
dragging: dragging,
'narrow-layout': narrow,
'right-drawer': rightDrawer,
'left-drawer': !rightDrawer,
transition: transition
});
},
_computeDrawerStyle: function(drawerWidth) {
return 'width:' + drawerWidth + ';';
},
_computeMainStyle: function(narrow, rightDrawer, drawerWidth) {
var style = '';
style += 'left:' + ((narrow || rightDrawer) ? '0' : drawerWidth) + ';';
if (rightDrawer) {
style += 'right:' + (narrow ? '' : drawerWidth) + ';';
} else {
style += 'right:;';
}
return style;
},
_computeMediaQuery: function(forceNarrow, responsiveWidth) {
return forceNarrow ? '' : '(max-width: ' + responsiveWidth + ')';
},
_computeSwipeOverlayHidden: function(narrow, disableEdgeSwipe) {
return !narrow || disableEdgeSwipe;
},
_onTrack: function(e) {
if (sharedPanel && this !== sharedPanel) {
return;
}
switch (e.detail.state) {
case 'start':
this._trackStart(e);
break;
case 'track':
this._trackX(e);
break;
case 'end':
this._trackEnd(e);
break;
}
},
_responsiveChange: function(narrow) {
this._setNarrow(narrow);
if (this.narrow) {
this.selected = this.defaultSelected;
}
this.setScrollDirection(this._swipeAllowed() ? 'y' : 'all');
this.fire('paper-responsive-change', {narrow: this.narrow});
},
_onQueryMatchesChanged: function(e) {
this._responsiveChange(e.detail.value);
},
_forceNarrowChanged: function() {
// set the narrow mode only if we reached the `responsiveWidth`
this._responsiveChange(this.forceNarrow || this.$.mq.queryMatches);
},
_swipeAllowed: function() {
return this.narrow && !this.disableSwipe;
},
_isMainSelected: function() {
return this.selected === 'main';
},
_startEdgePeek: function() {
this.width = this.$.drawer.offsetWidth;
this._moveDrawer(this._translateXForDeltaX(this.rightDrawer ?
-this.edgeSwipeSensitivity : this.edgeSwipeSensitivity));
this._setPeeking(true);
},
_stopEdgePeek: function() {
if (this.peeking) {
this._setPeeking(false);
this._moveDrawer(null);
}
},
_downHandler: function(e) {
if (!this.dragging && this._isMainSelected() && this._isEdgeTouch(e) && !sharedPanel) {
this._startEdgePeek();
// grab this panel
sharedPanel = this;
}
},
_upHandler: function() {
this._stopEdgePeek();
// release the panel
sharedPanel = null;
},
_onTap: function(e) {
var targetElement = Polymer.dom(e).localTarget;
var isTargetToggleElement = targetElement &&
this.drawerToggleAttribute &&
targetElement.hasAttribute(this.drawerToggleAttribute);
if (isTargetToggleElement) {
this.togglePanel();
}
},
_isEdgeTouch: function(e) {
var x = e.detail.x;
return !this.disableEdgeSwipe && this._swipeAllowed() &&
(this.rightDrawer ?
x >= this.offsetWidth - this.edgeSwipeSensitivity :
x <= this.edgeSwipeSensitivity);
},
_trackStart: function(event) {
if (this._swipeAllowed()) {
sharedPanel = this;
this._setDragging(true);
if (this._isMainSelected()) {
this._setDragging(this.peeking || this._isEdgeTouch(event));
}
if (this.dragging) {
this.width = this.$.drawer.offsetWidth;
this.transition = false;
}
}
},
_translateXForDeltaX: function(deltaX) {
var isMain = this._isMainSelected();
if (this.rightDrawer) {
return Math.max(0, isMain ? this.width + deltaX : deltaX);
} else {
return Math.min(0, isMain ? deltaX - this.width : deltaX);
}
},
_trackX: function(e) {
if (this.dragging) {
var dx = e.detail.dx;
if (this.peeking) {
if (Math.abs(dx) <= this.edgeSwipeSensitivity) {
// Ignore trackx until we move past the edge peek.
return;
}
this._setPeeking(false);
}
this._moveDrawer(this._translateXForDeltaX(dx));
}
},
_trackEnd: function(e) {
if (this.dragging) {
var xDirection = e.detail.dx > 0;
this._setDragging(false);
this.transition = true;
sharedPanel = null;
this._moveDrawer(null);
if (this.rightDrawer) {
this[xDirection ? 'closeDrawer' : 'openDrawer']();
} else {
this[xDirection ? 'openDrawer' : 'closeDrawer']();
}
}
},
_transformForTranslateX: function(translateX) {
if (translateX === null) {
return '';
}
return this.hasWillChange ? 'translateX(' + translateX + 'px)' :
'translate3d(' + translateX + 'px, 0, 0)';
},
_moveDrawer: function(translateX) {
var s = this.$.drawer.style;
if (this.hasTransform) {
s.transform = this._transformForTranslateX(translateX);
} else {
s.webkitTransform = this._transformForTranslateX(translateX);
}
}
});
}());
</script>
<iron-iconset-svg name="icons" size="24">
<svg>
<defs>
<g id="add"><path d="M19 13h-6v6h-2v-6H5v-2h6V5h2v6h6v2z"></path></g>
<g id="airplay"><defs><path id="a" d="M0 0h24v24H0V0z"></path></defs><defs><path id="c" d="M0 0h24v24H0V0z"></path></defs><clipPath id="b"><use xlink:href="#a" overflow="visible"></use></clipPath><clipPath id="d" clip-path="url(#b)"><use xlink:href="#c" overflow="visible"></use></clipPath><path d="M6 22h12l-6-6zM21 3H3c-1.1 0-2 .9-2 2v12c0 1.1.9 2 2 2h4v-2H3V5h18v12h-4v2h4c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2z" clip-path="url(#d)"></path></g>
<g id="album"><path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm0 14.5c-2.49 0-4.5-2.01-4.5-4.5S9.51 7.5 12 7.5s4.5 2.01 4.5 4.5-2.01 4.5-4.5 4.5zm0-5.5c-.55 0-1 .45-1 1s.45 1 1 1 1-.45 1-1-.45-1-1-1z"></path></g>
<g id="check"><path d="M9 16.17L4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41z"></path></g>
<g id="close"><path d="M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z"></path></g>
<g id="add"><path d="M19 13h-6v6h-2v-6H5v-2h6V5h2v6h6v2z"></path></g>
<g id="arrow-back"><path d="M20 11H7.83l5.59-5.59L12 4l-8 8 8 8 1.41-1.41L7.83 13H20v-2z"></path></g>
<g id="arrow-forward"><path d="M12 4l-1.41 1.41L16.17 11H4v2h12.17l-5.58 5.59L12 20l8-8z"></path></g>
<g id="delete"><path d="M6 19c0 1.1.9 2 2 2h8c1.1 0 2-.9 2-2V7H6v12zM19 4h-3.5l-1-1h-5l-1 1H5v2h14V4z"></path></g>
<g id="file-download"><path d="M19 9h-4V3H9v6H5l7 7 7-7zM5 18v2h14v-2H5z"></path></g>
<g id="info"><path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm1 15h-2v-6h2v6zm0-8h-2V7h2v2z"></path></g>
<g id="lock"><path d="M18 8h-1V6c0-2.76-2.24-5-5-5S7 3.24 7 6v2H6c-1.1 0-2 .9-2 2v10c0 1.1.9 2 2 2h12c1.1 0 2-.9 2-2V10c0-1.1-.9-2-2-2zm-6 9c-1.1 0-2-.9-2-2s.9-2 2-2 2 .9 2 2-.9 2-2 2zm3.1-9H8.9V6c0-1.71 1.39-3.1 3.1-3.1 1.71 0 3.1 1.39 3.1 3.1v2z"></path></g>
<g id="settings"><path d="M19.43 12.98c.04-.32.07-.64.07-.98s-.03-.66-.07-.98l2.11-1.65c.19-.15.24-.42.12-.64l-2-3.46c-.12-.22-.39-.3-.61-.22l-2.49 1c-.52-.4-1.08-.73-1.69-.98l-.38-2.65C14.46 2.18 14.25 2 14 2h-4c-.25 0-.46.18-.49.42l-.38 2.65c-.61.25-1.17.59-1.69.98l-2.49-1c-.23-.09-.49 0-.61.22l-2 3.46c-.13.22-.07.49.12.64l2.11 1.65c-.04.32-.07.65-.07.98s.03.66.07.98l-2.11 1.65c-.19.15-.24.42-.12.64l2 3.46c.12.22.39.3.61.22l2.49-1c.52.4 1.08.73 1.69.98l.38 2.65c.03.24.24.42.49.42h4c.25 0 .46-.18.49-.42l.38-2.65c.61-.25 1.17-.59 1.69-.98l2.49 1c.23.09.49 0 .61-.22l2-3.46c.12-.22.07-.49-.12-.64l-2.11-1.65zM12 15.5c-1.93 0-3.5-1.57-3.5-3.5s1.57-3.5 3.5-3.5 3.5 1.57 3.5 3.5-1.57 3.5-3.5 3.5z"></path></g>
<g id="refresh"><path d="M17.65 6.35C16.2 4.9 14.21 4 12 4c-4.42 0-7.99 3.58-7.99 8s3.57 8 7.99 8c3.73 0 6.84-2.55 7.73-6h-2.08c-.82 2.33-3.04 4-5.65 4-3.31 0-6-2.69-6-6s2.69-6 6-6c1.66 0 3.14.69 4.22 1.78L13 11h7V4l-2.35 2.35z"></path></g>
<g id="person"><path d="M12 12c2.21 0 4-1.79 4-4s-1.79-4-4-4-4 1.79-4 4 1.79 4 4 4zm0 2c-2.67 0-8 1.34-8 4v2h16v-2c0-2.66-5.33-4-8-4z"></path></g>
<g id="play-arrow"><path d="M8 5v14l11-7z"></path></g>
<g id="folder-open"><path d="M20 6h-8l-2-2H4c-1.1 0-1.99.9-1.99 2L2 18c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V8c0-1.1-.9-2-2-2zm0 12H4V8h16v10z"></path></g>
<g id="mode-edit"><path d="M3 17.25V21h3.75L17.81 9.94l-3.75-3.75L3 17.25zM20.71 7.04c.39-.39.39-1.02 0-1.41l-2.34-2.34c-.39-.39-1.02-.39-1.41 0l-1.83 1.83 3.75 3.75 1.83-1.83z"></path></g>
<g id="more-vert"><path d="M12 8c1.1 0 2-.9 2-2s-.9-2-2-2-2 .9-2 2 .9 2 2 2zm0 2c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2zm0 6c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2z"></path></g>
<g id="playlist-add"><path d="M14 10H2v2h12v-2zm0-4H2v2h12V6zm4 8v-4h-2v4h-4v2h4v4h2v-4h4v-2h-4zM2 16h8v-2H2v2z"></path></g>
<g id="remove"><path d="M19 13H5v-2h14v2z"></path></g>
<g id="cast"><path d="M21 3H3c-1.1 0-2 .9-2 2v3h2V5h18v14h-7v2h7c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zM1 18v3h3c0-1.66-1.34-3-3-3zm0-4v2c2.76 0 5 2.24 5 5h2c0-3.87-3.13-7-7-7zm0-4v2c4.97 0 9 4.03 9 9h2c0-6.08-4.93-11-11-11z"></path></g>
<g id="cast-connected"><path d="M1 18v3h3c0-1.66-1.34-3-3-3zm0-4v2c2.76 0 5 2.24 5 5h2c0-3.87-3.13-7-7-7zm18-7H5v1.63c3.96 1.28 7.09 4.41 8.37 8.37H19V7zM1 10v2c4.97 0 9 4.03 9 9h2c0-6.08-4.93-11-11-11zm20-7H3c-1.1 0-2 .9-2 2v3h2V5h18v14h-7v2h7c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2z"></path></g>
<g id="today"><path d="M19 3h-1V1h-2v2H8V1H6v2H5c-1.11 0-1.99.9-1.99 2L3 19c0 1.1.89 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm0 16H5V8h14v11zM7 10h5v5H7z"></path></g>
<g id="shuffle"><path d="M10.59 9.17L5.41 4 4 5.41l5.17 5.17 1.42-1.41zM14.5 4l2.04 2.04L4 18.59 5.41 20 17.96 7.46 20 9.5V4h-5.5zm.33 9.41l-1.41 1.41 3.13 3.13L14.5 20H20v-5.5l-2.04 2.04-3.13-3.13z"></path></g>
<g id="tablet-android"><path d="M18 0H6C4.34 0 3 1.34 3 3v18c0 1.66 1.34 3 3 3h12c1.66 0 3-1.34 3-3V3c0-1.66-1.34-3-3-3zm-4 22h-4v-1h4v1zm5.25-3H4.75V3h14.5v16z"></path></g>
<g id="view-comfy"><path d="M3 9h4V5H3v4zm0 5h4v-4H3v4zm5 0h4v-4H8v4zm5 0h4v-4h-4v4zM8 9h4V5H8v4zm5-4v4h4V5h-4zm5 9h4v-4h-4v4zM3 19h4v-4H3v4zm5 0h4v-4H8v4zm5 0h4v-4h-4v4zm5 0h4v-4h-4v4zm0-14v4h4V5h-4z"></path></g>
<g id="videocam"><path d="M17 10.5V7c0-.55-.45-1-1-1H4c-.55 0-1 .45-1 1v10c0 .55.45 1 1 1h12c.55 0 1-.45 1-1v-3.5l4 4v-11l-4 4z"></path></g>
</defs>
</svg>
</iron-iconset-svg>
</div></body></html>