UNPKG

npm-polymer-elements

Version:

Polymer Elements package for npm

2,085 lines (2,082 loc) 118 kB
<!-- @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 --><link rel="import" href="polymer-mini.html"> <script>Polymer.nar = []; Polymer.Annotations = { parseAnnotations: function (template) { var list = []; var content = template._content || template.content; this._parseNodeAnnotations(content, list, template.hasAttribute('strip-whitespace')); return list; }, _parseNodeAnnotations: function (node, list, stripWhiteSpace) { return node.nodeType === Node.TEXT_NODE ? this._parseTextNodeAnnotation(node, list) : this._parseElementAnnotations(node, list, stripWhiteSpace); }, _bindingRegex: function () { var IDENT = '(?:' + '[a-zA-Z_$][\\w.:$-*]*' + ')'; var NUMBER = '(?:' + '[-+]?[0-9]*\\.?[0-9]+(?:[eE][-+]?[0-9]+)?' + ')'; var SQUOTE_STRING = '(?:' + '\'(?:[^\'\\\\]|\\\\.)*\'' + ')'; var DQUOTE_STRING = '(?:' + '"(?:[^"\\\\]|\\\\.)*"' + ')'; var STRING = '(?:' + SQUOTE_STRING + '|' + DQUOTE_STRING + ')'; var ARGUMENT = '(?:' + IDENT + '|' + NUMBER + '|' + STRING + '\\s*' + ')'; var ARGUMENTS = '(?:' + ARGUMENT + '(?:,\\s*' + ARGUMENT + ')*' + ')'; var ARGUMENT_LIST = '(?:' + '\\(\\s*' + '(?:' + ARGUMENTS + '?' + ')' + '\\)\\s*' + ')'; var BINDING = '(' + IDENT + '\\s*' + ARGUMENT_LIST + '?' + ')'; var OPEN_BRACKET = '(\\[\\[|{{)' + '\\s*'; var CLOSE_BRACKET = '(?:]]|}})'; var NEGATE = '(?:(!)\\s*)?'; var EXPRESSION = OPEN_BRACKET + NEGATE + BINDING + CLOSE_BRACKET; return new RegExp(EXPRESSION, 'g'); }(), _parseBindings: function (text) { var re = this._bindingRegex; var parts = []; var lastIndex = 0; var m; while ((m = re.exec(text)) !== null) { if (m.index > lastIndex) { parts.push({ literal: text.slice(lastIndex, m.index) }); } var mode = m[1][0]; var negate = Boolean(m[2]); var value = m[3].trim(); var customEvent, notifyEvent, colon; if (mode == '{' && (colon = value.indexOf('::')) > 0) { notifyEvent = value.substring(colon + 2); value = value.substring(0, colon); customEvent = true; } parts.push({ compoundIndex: parts.length, value: value, mode: mode, negate: negate, event: notifyEvent, customEvent: customEvent }); lastIndex = re.lastIndex; } if (lastIndex && lastIndex < text.length) { var literal = text.substring(lastIndex); if (literal) { parts.push({ literal: literal }); } } if (parts.length) { return parts; } }, _literalFromParts: function (parts) { var s = ''; for (var i = 0; i < parts.length; i++) { var literal = parts[i].literal; s += literal || ''; } return s; }, _parseTextNodeAnnotation: function (node, list) { var parts = this._parseBindings(node.textContent); if (parts) { node.textContent = this._literalFromParts(parts) || ' '; var annote = { bindings: [{ kind: 'text', name: 'textContent', parts: parts, isCompound: parts.length !== 1 }] }; list.push(annote); return annote; } }, _parseElementAnnotations: function (element, list, stripWhiteSpace) { var annote = { bindings: [], events: [] }; if (element.localName === 'content') { list._hasContent = true; } this._parseChildNodesAnnotations(element, annote, list, stripWhiteSpace); 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, stripWhiteSpace) { if (root.firstChild) { var node = root.firstChild; var i = 0; while (node) { var next = node.nextSibling; if (node.localName === 'template' && !node.hasAttribute('preserve-content')) { this._parseTemplate(node, i, list, annote); } if (node.nodeType === Node.TEXT_NODE) { var n = next; while (n && n.nodeType === Node.TEXT_NODE) { node.textContent += n.textContent; next = n.nextSibling; root.removeChild(n); n = next; } if (stripWhiteSpace && !node.textContent.trim()) { root.removeChild(node); i--; } } if (node.parentNode) { var childAnnotation = this._parseNodeAnnotations(node, list, stripWhiteSpace); if (childAnnotation) { childAnnotation.parent = annote; childAnnotation.index = i; } } node = next; 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) { var attrs = Array.prototype.slice.call(node.attributes); for (var i = attrs.length - 1, a; a = attrs[i]; i--) { var n = a.name; var v = a.value; var b; if (n.slice(0, 3) === 'on-') { node.removeAttribute(n); annotation.events.push({ name: n.slice(3), value: v }); } else if (b = this._parseNodeAttributeAnnotation(node, n, v)) { annotation.bindings.push(b); } else if (n === 'id') { annotation.id = v; } } }, _parseNodeAttributeAnnotation: function (node, name, value) { var parts = this._parseBindings(value); if (parts) { var origName = name; var kind = 'property'; if (name[name.length - 1] == '$') { name = name.slice(0, -1); kind = 'attribute'; } var literal = this._literalFromParts(parts); if (literal && kind == 'attribute') { node.setAttribute(name, literal); } if (node.localName === 'input' && origName === 'value') { node.setAttribute(origName, ''); } node.removeAttribute(origName); if (kind === 'property') { name = Polymer.CaseMap.dashToCamelCase(name); } return { kind: kind, name: name, parts: parts, literal: literal, isCompound: parts.length !== 1 }; } }, findAnnotatedNode: function (root, annote) { var parent = annote.parent && Polymer.Annotations.findAnnotatedNode(root, annote.parent); if (parent) { for (var n = parent.firstChild, i = 0; n; n = n.nextSibling) { if (annote.index === i++) { return n; } } } else { return root; } } }; (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 { var self = this; Polymer.Annotations.prepElement = function (element) { self._prepElement(element); }; if (this._template._content && this._template._content._notes) { this._notes = this._template._content._notes; } else { 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]; for (var k = 0; k < b.parts.length; k++) { var p = b.parts[k]; if (!p.literal) { p.signature = this._parseMethod(p.value); if (!p.signature) { p.model = this._modelForPath(p.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', name: '_parent_' + prop, parts: [{ mode: '{', model: prop, value: prop }] }); } note.bindings = note.bindings.concat(bindings); } } }, _discoverTemplateParentProps: function (notes) { var pp = {}; for (var i = 0, n; i < notes.length && (n = notes[i]); i++) { for (var j = 0, b$ = n.bindings, b; j < b$.length && (b = b$[j]); j++) { for (var k = 0, p$ = b.parts, p; k < p$.length && (p = p$[k]); k++) { if (p.signature) { var args = p.signature.args; for (var kk = 0; kk < args.length; kk++) { var model = args[kk].model; if (model) { pp[model] = true; } } } else { if (p.model) { pp[p.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 (config) { var notes = this._notes; var nodes = this._nodes; for (var i = 0; i < notes.length; i++) { var note = notes[i]; var node = nodes[i]; this._configureTemplateContent(note, node); this._configureCompoundBindings(note, node); } }, _configureTemplateContent: function (note, node) { if (note.templateContent) { node._content = note.templateContent; } }, _configureCompoundBindings: function (note, node) { var bindings = note.bindings; for (var i = 0; i < bindings.length; i++) { var binding = bindings[i]; if (binding.isCompound) { var storage = node.__compoundStorage__ || (node.__compoundStorage__ = {}); var parts = binding.parts; var literals = new Array(parts.length); for (var j = 0; j < parts.length; j++) { literals[j] = parts[j].literal; } var name = binding.name; storage[name] = literals; if (binding.literal && binding.kind == 'property') { if (node._configValue) { node._configValue(name, binding.literal); } else { node[name] = binding.literal; } } } } }, _marshalIdNodes: function () { this.$ = {}; for (var i = 0, l = this._notes.length, a; i < l && (a = this._notes[i]); i++) { if (a.id) { this.$[a.id] = this._findAnnotatedNode(this.root, a); } } }, _marshalAnnotatedNodes: function () { if (this._notes && this._notes.length) { var r = new Array(this._notes.length); for (var i = 0; i < this._notes.length; i++) { r[i] = this._findAnnotatedNode(this.root, this._notes[i]); } this._nodes = r; } }, _marshalAnnotatedListeners: function () { for (var i = 0, l = this._notes.length, a; i < l && (a = this._notes[i]); i++) { if (a.events && a.events.length) { var node = this._findAnnotatedNode(this.root, a); for (var j = 0, e$ = a.events, e; j < e$.length && (e = e$[j]); j++) { this.listen(node, e.name, e.value); } } } } }); Polymer.Base._addFeature({ listeners: {}, _listenListeners: function (listeners) { var node, name, eventName; for (eventName in listeners) { if (eventName.indexOf('.') < 0) { node = this; name = eventName; } else { name = eventName.split('.'); node = this.$[name[0]]; name = name[1]; } this.listen(node, name, listeners[eventName]); } }, listen: function (node, eventName, methodName) { var handler = this._recallEventHandler(this, eventName, node, methodName); if (!handler) { handler = this._createEventHandler(node, eventName, methodName); } if (handler._listening) { return; } this._listen(node, eventName, handler); handler._listening = true; }, _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')); } }; handler._listening = false; 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); handler._listening = false; } }, _listen: function (node, eventName, handler) { node.addEventListener(eventName, handler); }, _unlisten: function (node, eventName, handler) { node.removeEventListener(eventName, handler); } }); (function () { 'use strict'; var wrap = Polymer.DomApi.wrap; 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 MOUSE_WHICH_TO_BUTTONS = [ 0, 1, 4, 2 ]; var MOUSE_HAS_BUTTONS = function () { try { return new MouseEvent('test', { buttons: 1 }).buttons === 1; } catch (e) { return false; } }(); var IS_TOUCH_ONLY = navigator.userAgent.match(/iP(?:[oa]d|hone)|Android/); 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 (IS_TOUCH_ONLY) { return; } 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); } function hasLeftMouseButton(ev) { var type = ev.type; if (MOUSE_EVENTS.indexOf(type) === -1) { return false; } if (type === 'mousemove') { var buttons = ev.buttons === undefined ? 1 : ev.buttons; if (ev instanceof window.MouseEvent && !MOUSE_HAS_BUTTONS) { buttons = MOUSE_WHICH_TO_BUTTONS[ev.which] || 0; } return Boolean(buttons & 1); } else { var button = ev.button === undefined ? 0 : ev.button; return button === 0; } } function isSyntheticClick(ev) { if (ev.type === 'click') { if (ev.detail === 0) { return true; } var t = Gestures.findOriginalTarget(ev); var bcr = t.getBoundingClientRect(); var x = ev.pageX, y = ev.pageY; return !(x >= bcr.left && x <= bcr.right && (y >= bcr.top && y <= bcr.bottom)); } return false; } 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; } function trackDocument(stateObj, movefn, upfn) { stateObj.movefn = movefn; stateObj.upfn = upfn; document.addEventListener('mousemove', movefn); document.addEventListener('mouseup', upfn); } function untrackDocument(stateObj) { document.removeEventListener('mousemove', stateObj.movefn); document.removeEventListener('mouseup', stateObj.upfn); stateObj.movefn = null; stateObj.upfn = null; } 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; }, findOriginalTarget: function (ev) { if (ev.path) { return ev.path[0]; } return ev.target; }, handleNative: function (ev) { var handled; var type = ev.type; var node = wrap(ev.currentTarget); var gobj = node[GESTURE_KEY]; if (!gobj) { return; } 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]) { if (r.flow && r.flow.start.indexOf(ev.type) > -1) { if (r.reset) { r.reset(); } } } } 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(); } else { Gestures.prevent('track'); } } }, add: function (node, evType, handler) { node = wrap(node); 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]; if (IS_TOUCH_ONLY && MOUSE_EVENTS.indexOf(dep) > -1) { continue; } gd = gobj[dep]; if (!gd) { gobj[dep] = gd = { _count: 0 }; } if (gd._count === 0) { node.addEventListener(dep, this.handleNative); } gd[name] = (gd[name] || 0) + 1; gd._count = (gd._count || 0) + 1; } node.addEventListener(evType, handler); if (recognizer.touchAction) { this.setTouchAction(node, recognizer.touchAction); } }, remove: function (node, evType, handler) { node = wrap(node); 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; gd._count = (gd._count || 1) - 1; if (gd._count === 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' ], flow: { start: [ 'mousedown', 'touchstart' ], end: [ 'mouseup', 'touchend' ] }, emits: [ 'down', 'up' ], info: { movefn: null, upfn: null }, reset: function () { untrackDocument(this.info); }, mousedown: function (e) { if (!hasLeftMouseButton(e)) { return; } var t = Gestures.findOriginalTarget(e); var self = this; var movefn = function movefn(e) { if (!hasLeftMouseButton(e)) { self.fire('up', t, e); untrackDocument(self.info); } }; var upfn = function upfn(e) { if (hasLeftMouseButton(e)) { self.fire('up', t, e); } untrackDocument(self.info); }; trackDocument(this.info, movefn, upfn); this.fire('down', t, e); }, touchstart: function (e) { this.fire('down', Gestures.findOriginalTarget(e), e.changedTouches[0]); }, touchend: function (e) { this.fire('up', Gestures.findOriginalTarget(e), e.changedTouches[0]); }, fire: function (type, target, event) { Gestures.fire(target, type, { x: event.clientX, y: event.clientY, sourceEvent: event, prevent: function (e) { return Gestures.prevent(e); } }); } }); Gestures.register({ name: 'track', touchAction: 'none', deps: [ 'mousedown', 'touchstart', 'touchmove', 'touchend' ], flow: { start: [ 'mousedown', 'touchstart' ], end: [ 'mouseup', '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); }, movefn: null, upfn: null, prevent: false }, reset: function () { this.info.state = 'start'; this.info.started = false; this.info.moves = []; this.info.x = 0; this.info.y = 0; this.info.prevent = false; untrackDocument(this.info); }, 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) { if (!hasLeftMouseButton(e)) { return; } var t = Gestures.findOriginalTarget(e); 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 }); if (!hasLeftMouseButton(e)) { self.info.state = 'end'; untrackDocument(self.info); } self.fire(t, e); self.info.started = true; } }; var upfn = function upfn(e) { if (self.info.started) { Gestures.prevent('tap'); movefn(e); } untrackDocument(self.info); }; trackDocument(this.info, movefn, 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 = Gestures.findOriginalTarget(e); 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 = Gestures.findOriginalTarget(e); 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); } }, 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' ], flow: { start: [ 'mousedown', 'touchstart' ], end: [ 'click', '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) { if (hasLeftMouseButton(e)) { this.save(e); } }, click: function (e) { if (hasLeftMouseButton(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); var t = Gestures.findOriginalTarget(e); if (isNaN(dx) || isNaN(dy) || dx <= TAP_DISTANCE && dy <= TAP_DISTANCE || isSyntheticClick(e)) { if (!this.info.prevent) { Gestures.fire(t, 'tap', { x: e.clientX, y: e.clientY, sourceEvent: e }); } } } }); var DIRECTION_MAP = { x: 'pan-x', y: 'pan-y', none: 'none', all: 'auto' }; Polymer.Base._addFeature({ _setupGestures: function () { this.__polymerGestures = null; }, _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.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, ''); } }, getEffectiveChildNodes: function () { return Polymer.dom(this).getEffectiveChildNodes(); }, getEffectiveChildren: function () { var list = Polymer.dom(this).getEffectiveChildNodes(); return list.filter(function (n) { return n.nodeType === Node.ELEMENT_NODE; }); }, getEffectiveTextContent: function () { var cn = this.getEffectiveChildNodes(); var tc = []; for (var i = 0, c; c = cn[i]; i++) { if (c.nodeType !== Node.COMMENT_NODE) { tc.push(Polymer.dom(c).textContent); } } return tc.join(''); }, queryEffectiveChildren: function (slctr) { var e$ = Polymer.dom(this).queryDistributedElements(slctr); return e$ && e$[0]; }, queryAllEffectiveChildren: function (slctr) { return Polymer.dom(this).queryDistributedElements(slctr); }, getContentChildNodes: function (slctr) { var content = Polymer.dom(this.root).querySelector(slctr || 'content'); return content ? Polymer.dom(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 ? {} : detail; var bubbles = options.bubbles === undefined ? true : options.bubbles; var cancelable = Boolean(options.cancelable); var useCache = options._useCache; var event = this._getEvent(type, bubbles, cancelable, useCache); event.detail = detail; if (useCache) { this.__eventCache[type] = null; } node.dispatchEvent(event); if (useCache) { this.__eventCache[type] = event; } return event; }, __eventCache: {}, _getEvent: function (type, bubbles, cancelable, useCache) { var event = useCache && this.__eventCache[type]; if (!event || (event.bubbles != bubbles || event.cancelable != cancelable)) { event = new Event(type, { bubbles: Boolean(bubbles), cancelable: cancelable }); } return event; }, async: function (callback, waitTime) { var self = this; return Polymer.Async.run(function () { callback.call(self); }, 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, optAsync) { var l = document.createElement('link'); l.rel = 'import'; l.href = href; optAsync = Boolean(optAsync); if (optAsync) { l.setAttribute('async', ''); } var self = this; if (onload) { l.onload = function (e) { return onload.call(self, e); }; } if (onerror) { l.onerror = function (e) { return onerror.call(self, e); }; } 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; }, isLightDescendant: function (node) { return this !== node && this.contains(node) && Polymer.dom(this).getOwnerRoot() === Polymer.dom(node).getOwnerRoot(); }, isLocalDescendant: function (node) { return this.root === Polymer.dom(node).getOwnerRoot(); } }); Polymer.Bind = { _dataEventCache: {}, prepareModel: function (model) { Polymer.Base.mixin(model, this._modelApi); }, _modelApi: { _notifyChange: function (source, event, value) { value = value === undefined ? this[source] : value; event = event || Polymer.CaseMap.camelToDashCase(source) + '-changed'; this.fire(event, { value: value }, { bubbles: false, cancelable: false, _useCache: true }); }, _propertySetter: function (property, value, effects, fromAbove) { 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, fromAbove); } } return old; }, __setProperty: function (property, value, quiet, node) { node = node || this; var effects = node._propertyEffects && node._propertyEffects[property]; if (effects) { node._propertySetter(property, value, effects, quiet); } else { node[property] = value; } }, _effectEffects: function (property, value, effects, old, fromAbove) { for (var i = 0, l = effects.length, fx; i < l && (fx = effects[i]); i++) { fx.fn.call(this, property, value, fx.effect, old, fromAbove); } }, _clearPath: function (path) { for (var prop in this.__data__) { if (prop.indexOf(path + '.') === 0) { this.__data__[prop] = undefined; } } } }, ensurePropertyEffects: function (model, property) { if (!model._propertyEffects) { model._propertyEffects = {}; } 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); var propEffect = { kind: kind, effect: effect, fn: Polymer.Bind['_' + kind + 'Effect'] }; fx.push(propEffect); return propEffect; }, 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._propertySetter(property, value, effects); }; var info = model.getPropertyInfo && model.getPropertyInfo(property); if (info && info.readOnly) { if (!info.computed) { 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) { if (!model._bindListeners) { model._bindListeners = []; } var fn = this._notedListenerFactory(property, path, this._isStructured(path)); 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) { return function (target, value, targetPath) { if (targetPath) { this._notifyPath(this._fixPath(path, property, targetPath), value); } else { value = target[property]; if (!isStructured) { this[path] = value; } else { if (this.__data__[path] != value) { this.set(path, value); } } } }; }, prepareInstance: function (inst) { inst.__data__ = Object.create(null); }, setupBindListeners: function (inst) { var b$ = inst._bindListeners; for (var i = 0, l = b$.length, info; i < l && (info = b$[i]); i++) { var node = inst._nodes[info.index]; this._addNotifyListener(node, inst, info.event, info.changedFn); } ; }, _addNotifyListener: function (element, context, event, changedFn) { element.addEventListener(event, function (e) { return context._notifyListener(changedFn, e); }); } }; Polymer.Base.extend(Polymer.Bind, { _shouldAddListener: function (effect) { return effect.name && effect.kind != 'attribute' && effect.kind != 'text' && !effect.isCompound && effect.parts[0].mode === '{' && !effect.parts[0].negate; }, _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(effect, calc); } }, _reflectEffect: function (source, value, effect) { this.reflectPropertyToAttribute(source, effect.attribute, value); }, _notifyEffect: function (source, value, effect, old, fromAbove) { if (!fromAbove) { this._notifyChange(source, effect.event, value); } }, _functionEffect: function (source, value, fn, old, fromAbove) { fn.call(this, source, value, old, fromAbove); }, _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.__setProperty(effect.name, 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(effect, computedvalue); } } 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) { var prop = Polymer.Bind.addPropertyEffect(this, property, kind, effect); prop.pathFn = this['_' + prop.kind + 'PathEffect']; }, _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) { prop.readOnly = true; this._addComputedEffect(p, prop.computed); } if (prop.notify) { this._addPropertyEffect(p, 'notify', { event: Polymer.CaseMap.camelToDashCase(p) + '-changed' }); } if (prop.reflectToAttribute) { this._addPropertyEffect(p, 'reflect', { attribute: Polymer.CaseMap.camelToDashCase(p) }); } if (prop.readOnly) { Polymer.Bind.ensurePropertyEffects(this, p); } } } }, _addComputedEffect: function (name, expression) { var sig = this._parseMethod(expression); for (var i = 0, arg; i < sig.args.length && (arg = sig.args[i]); i++) { this._addPropertyEffect(arg.model, 'compute', { method: sig.method, args: sig.args, trigger: arg, name: name }); } }, _addObserverEffect: function (property, observer) { this._addPropertyEffect(property, 'observer', { method: observer, property: property }); }, _addComplexObserverEffects: function (observers) { if (observers) { for (var i = 0, o; i < observers.length && (o = observers[i]); i++) { this._addComplexObserverEffect(o); } } }, _addComplexObserverEffect: function (observer) { var sig = this._parseMethod(observer); if (!sig) { throw new Error('Malformed observer expression \'' + observer + '\''); } for (var i = 0, arg; i < sig.args.length && (arg = sig.args[i]); i++) { this._addPropertyEffect(arg.model, 'complexObserver', { method: sig.method, args: sig.args, trigger: arg }); } }, _addAnnotationEffects: function (notes) { for (var i = 0, note; i < notes.length && (note = notes[i]); i++) { var b$ = note.bindings; for (var j = 0, binding; j < b$.length && (binding = b$[j]); j++) { this._addAnnotationEffect(binding, i); } } }, _addAnnotationEffect: function (note, index) { if (Polymer.Bind._shouldAddListener(note)) { Polymer.Bind._addAnnotatedListener(this, index, note.name, note.parts[0].value, note.parts[0].event); } for (var i = 0; i < note.parts.length; i++) { var part = note.parts[i]; if (part.signature) { this._addAnnotatedComputationEffect(note, part, index); } else if (!part.literal) { this._addPropertyEffect(part.model, 'annotation', { kind: note.kind, index: index, name: note.name, value: part.value, isCompound: note.isCompound, compoundIndex: part.compoundIndex, event: part.event, customEvent: part.customEvent, negate: part.negate }); } } }, _addAnnotatedComputationEffect: function (note, part, index) { var sig = part.signature; if (sig.static) { this.__addAnnotatedComputationEffect('__static__', index, note, part, null); } else { for (var i = 0, arg; i < sig.args.length && (arg = sig.args[i]); i++) { if (!arg.literal) { this.__addAnnotatedComputationEffect(arg.model, index, note, part, arg); } } } }, __addAnnotatedComputationEffect: function (property, index, note, part, trigger) { this._addPropertyEffect(property, 'annotatedComputation', { index: index, isCompound: note.isCompound, compoundIndex: part.compoundIndex, kind: note.kind, name: note.name, negate: part.negate, method: part.signature.method, args: part.signature.args, trigger: trigger }); }, _parseMethod: function (expression) { var m = expression.match(/([^\s]+?)\((.*)\)/); 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 }; var fc = arg[0]; if (fc === '-') { fc = arg[1]; } 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.model = this._modelForPath(arg); 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); if (this._bindListeners) { Polymer.Bind.setupBindListeners(this); } }, _applyEffectValue: function (info, value) { var node = this._nodes[info.index]; var property = info.name; if (info.isCompound) { var storage = node.__compoundStorage__[property]; storage[info.compoundIndex] = value; value = storage.join(''); } 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; } var pinfo; if (!node._propertyInfo || !(pinfo = node._propertyInfo[property]) || !pinfo.readOnly) { this.__setProperty(property, value, false, node); } } }, _executeStaticEffects: function () { if (this._propertyEffects && this._propertyEffects.__static__) { this._effectEffects('__static__', null, this._propertyEffects.__static__); } } }); Polymer.Base._addFeature({ _setupConfigure: function (initialConfig) { this._config = {}; this._handlers = []; this._aboveConfig = null; if (initialConfig) { for (var i in initialConfig) { if (initialConfig[i] !== undefined) { this._config[i] = initialConfig[i]; } } } }, _marshalAttributes: function () { this._takeAttributesToModel(this._config); }, _attributeChangedImpl: function (name) { var model = this._clientsReadied ? this : this._config; this._setAttributeToProperty(model, name); }, _configValue: function (name, value) { var info = this._propertyInfo[name]; if (!info || !info.readOnly) { this._config[name] = value; } }, _beforeClientsReady: function () { this._configure(); }, _configure: function () { this._configureAnnotationReferences(); this._aboveConfig = this.mixin({}, this._config); var config = {}; for (var i = 0; i < this.behaviors.length; i++) { this._configureProperties(this.behaviors[i].properties, config); } this._configureProperties(this.properties, config); this.mixin(config, this._aboveConfig); this._config = config; if (this._clients && this._clients.length) { 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; } } }, _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' && !x.isCompound) { 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._aboveConfig); this._flushHandlers(); }, _applyConfig: function (config, aboveConfig) { for (var n in config) { if (this[n] === undefined) { this.__setProperty(n, config[n], n in aboveConfig); } } }, _notifyListener: function (fn, e) { if (!Polymer.Bind._isEventBogus(e, e.target)) { var value, path; if (e.detail) { value = e.detail.value; path = e.detail.path; } if (!this._clientsReadied) { this._queueHandler([ fn, e.target, value, path ]); } else { return fn.call(this, e.target, value, path); } } }, _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], h[3]); } this._handlers = []; } }); (function () { 'use strict'; Polymer.Base._addFeature({ notifyPath: function (path, value, fromAbove) { var info = {}; this._get(path, this, info); if (info.path) { this._notifyPath(info.path, value, fromAbove); } }, _notifyPath: function (path, value, fromAbove) { var old = this._propertySetter(path, value); if (old !== value && (old === old || value === value)) { this._pathEffector(path, value); if (!fromAbove) { this._notifyPathUp(path, value); } return true; } }, _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++) { var part = parts[i]; if (array && part[0] == '#') { prop = Polymer.Collection.get(array).getItem(part); } else { prop = prop[part]; if (array && parseInt(part, 10) == part) { parts[i] = Polymer.Collection.get(array).getKey(prop); } } if (!prop) { return; } array = Array.isArray(prop) ? prop : null; } if (array) { var coll = Polymer.Collection.get(array); if (last[0] == '#') { var key = last; var old = coll.getItem(key); last = array.indexOf(old); coll.setItem(key, value); } else if (parseInt(last, 10) == last) { var old = prop[last]; var key = coll.getKey(old); parts[i] = key; coll.setItem(key, value); } } prop[last] = value; if (!root) { this._notifyPath(parts.join('.'), value); } } else { prop[path] = value; } }, get: function (path, root) { return this._get(path, root); }, _get: function (path, root, info) { var prop = root || this; var parts = this._getPathParts(path); var array; for (var i = 0; i < parts.length; i++) { if (!prop) { return; } var part = parts[i]; if (array && part[0] == '#') { prop = Polymer.Collection.get(array).getItem(part); } else { prop = prop[part]; if (info && array && parseInt(part, 10) == part) { parts[i] = Polymer.Collection.get(array).getKey(prop); } } array = Array.isArray(prop) ? prop : null; } if (info) { info.path = parts.join('.'); } return prop; }, _pathEffector: function (path, value) { var model = this._modelForPath(path); var fx$ = this._propertyEffects && this._propertyEffects[model]; if (fx$) { for (var i = 0, fx; i < fx$.length && (fx = fx$[i]); i++) { var fxFn = fx.pathFn; if (fxFn) { fxFn.call(this, path, value, fx.effect); } } } 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.