Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(16)

Side by Side Diff: third_party/polymer/v1_0/components/polymer/polymer.html

Issue 1269803005: Remove third_party/polymer from .gitignore (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 5 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 <!--
2 @license
3 Copyright (c) 2015 The Polymer Project Authors. All rights reserved.
4 This code may only be used under the BSD style license found at http://polymer.g ithub.io/LICENSE.txt
5 The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
6 The complete set of contributors may be found at http://polymer.github.io/CONTRI BUTORS.txt
7 Code distributed by Google as part of the polymer project is also
8 subject to an additional IP rights grant found at http://polymer.github.io/PATEN TS.txt
9 --><!--
10 @license
11 Copyright (c) 2014 The Polymer Project Authors. All rights reserved.
12 This code may only be used under the BSD style license found at http://polymer.g ithub.io/LICENSE.txt
13 The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
14 The complete set of contributors may be found at http://polymer.github.io/CONTRI BUTORS.txt
15 Code distributed by Google as part of the polymer project is also
16 subject to an additional IP rights grant found at http://polymer.github.io/PATEN TS.txt
17 --><link rel="import" href="polymer-mini.html">
18
19 <script>Polymer.nar = [];
20 Polymer.Annotations = {
21 parseAnnotations: function (template) {
22 var list = [];
23 var content = template._content || template.content;
24 this._parseNodeAnnotations(content, list);
25 return list;
26 },
27 _parseNodeAnnotations: function (node, list) {
28 return node.nodeType === Node.TEXT_NODE ? this._parseTextNodeAnnotation(node, li st) : this._parseElementAnnotations(node, list);
29 },
30 _testEscape: function (value) {
31 var escape = value.slice(0, 2);
32 if (escape === '{{' || escape === '[[') {
33 return escape;
34 }
35 },
36 _parseTextNodeAnnotation: function (node, list) {
37 var v = node.textContent;
38 var escape = this._testEscape(v);
39 if (escape) {
40 node.textContent = ' ';
41 var annote = {
42 bindings: [{
43 kind: 'text',
44 mode: escape[0],
45 value: v.slice(2, -2).trim()
46 }]
47 };
48 list.push(annote);
49 return annote;
50 }
51 },
52 _parseElementAnnotations: function (element, list) {
53 var annote = {
54 bindings: [],
55 events: []
56 };
57 if (element.localName === 'content') {
58 list._hasContent = true;
59 }
60 this._parseChildNodesAnnotations(element, annote, list);
61 if (element.attributes) {
62 this._parseNodeAttributeAnnotations(element, annote, list);
63 if (this.prepElement) {
64 this.prepElement(element);
65 }
66 }
67 if (annote.bindings.length || annote.events.length || annote.id) {
68 list.push(annote);
69 }
70 return annote;
71 },
72 _parseChildNodesAnnotations: function (root, annote, list, callback) {
73 if (root.firstChild) {
74 for (var i = 0, node = root.firstChild; node; node = node.nextSibling, i++) {
75 if (node.localName === 'template' && !node.hasAttribute('preserve-content')) {
76 this._parseTemplate(node, i, list, annote);
77 }
78 if (node.nodeType === Node.TEXT_NODE) {
79 var n = node.nextSibling;
80 while (n && n.nodeType === Node.TEXT_NODE) {
81 node.textContent += n.textContent;
82 root.removeChild(n);
83 n = n.nextSibling;
84 }
85 }
86 var childAnnotation = this._parseNodeAnnotations(node, list, callback);
87 if (childAnnotation) {
88 childAnnotation.parent = annote;
89 childAnnotation.index = i;
90 }
91 }
92 }
93 },
94 _parseTemplate: function (node, index, list, parent) {
95 var content = document.createDocumentFragment();
96 content._notes = this.parseAnnotations(node);
97 content.appendChild(node.content);
98 list.push({
99 bindings: Polymer.nar,
100 events: Polymer.nar,
101 templateContent: content,
102 parent: parent,
103 index: index
104 });
105 },
106 _parseNodeAttributeAnnotations: function (node, annotation) {
107 for (var i = node.attributes.length - 1, a; a = node.attributes[i]; i--) {
108 var n = a.name, v = a.value;
109 if (n === 'id' && !this._testEscape(v)) {
110 annotation.id = v;
111 } else if (n.slice(0, 3) === 'on-') {
112 node.removeAttribute(n);
113 annotation.events.push({
114 name: n.slice(3),
115 value: v
116 });
117 } else {
118 var b = this._parseNodeAttributeAnnotation(node, n, v);
119 if (b) {
120 annotation.bindings.push(b);
121 }
122 }
123 }
124 },
125 _parseNodeAttributeAnnotation: function (node, n, v) {
126 var escape = this._testEscape(v);
127 if (escape) {
128 var customEvent;
129 var name = n;
130 var mode = escape[0];
131 v = v.slice(2, -2).trim();
132 var not = false;
133 if (v[0] == '!') {
134 v = v.substring(1);
135 not = true;
136 }
137 var kind = 'property';
138 if (n[n.length - 1] == '$') {
139 name = n.slice(0, -1);
140 kind = 'attribute';
141 }
142 var notifyEvent, colon;
143 if (mode == '{' && (colon = v.indexOf('::')) > 0) {
144 notifyEvent = v.substring(colon + 2);
145 v = v.substring(0, colon);
146 customEvent = true;
147 }
148 if (node.localName == 'input' && n == 'value') {
149 node.setAttribute(n, '');
150 }
151 node.removeAttribute(n);
152 if (kind === 'property') {
153 name = Polymer.CaseMap.dashToCamelCase(name);
154 }
155 return {
156 kind: kind,
157 mode: mode,
158 name: name,
159 value: v,
160 negate: not,
161 event: notifyEvent,
162 customEvent: customEvent
163 };
164 }
165 },
166 _localSubTree: function (node, host) {
167 return node === host ? node.childNodes : node._lightChildren || node.childNodes;
168 },
169 findAnnotatedNode: function (root, annote) {
170 var parent = annote.parent && Polymer.Annotations.findAnnotatedNode(root, annote .parent);
171 return !parent ? root : Polymer.Annotations._localSubTree(parent, root)[annote.i ndex];
172 }
173 };
174 (function () {
175 function resolveCss(cssText, ownerDocument) {
176 return cssText.replace(CSS_URL_RX, function (m, pre, url, post) {
177 return pre + '\'' + resolve(url.replace(/["']/g, ''), ownerDocument) + '\'' + po st;
178 });
179 }
180 function resolveAttrs(element, ownerDocument) {
181 for (var name in URL_ATTRS) {
182 var a$ = URL_ATTRS[name];
183 for (var i = 0, l = a$.length, a, at, v; i < l && (a = a$[i]); i++) {
184 if (name === '*' || element.localName === name) {
185 at = element.attributes[a];
186 v = at && at.value;
187 if (v && v.search(BINDING_RX) < 0) {
188 at.value = a === 'style' ? resolveCss(v, ownerDocument) : resolve(v, ownerDocume nt);
189 }
190 }
191 }
192 }
193 }
194 function resolve(url, ownerDocument) {
195 if (url && url[0] === '#') {
196 return url;
197 }
198 var resolver = getUrlResolver(ownerDocument);
199 resolver.href = url;
200 return resolver.href || url;
201 }
202 var tempDoc;
203 var tempDocBase;
204 function resolveUrl(url, baseUri) {
205 if (!tempDoc) {
206 tempDoc = document.implementation.createHTMLDocument('temp');
207 tempDocBase = tempDoc.createElement('base');
208 tempDoc.head.appendChild(tempDocBase);
209 }
210 tempDocBase.href = baseUri;
211 return resolve(url, tempDoc);
212 }
213 function getUrlResolver(ownerDocument) {
214 return ownerDocument.__urlResolver || (ownerDocument.__urlResolver = ownerDocume nt.createElement('a'));
215 }
216 var CSS_URL_RX = /(url\()([^)]*)(\))/g;
217 var URL_ATTRS = {
218 '*': [
219 'href',
220 'src',
221 'style',
222 'url'
223 ],
224 form: ['action']
225 };
226 var BINDING_RX = /\{\{|\[\[/;
227 Polymer.ResolveUrl = {
228 resolveCss: resolveCss,
229 resolveAttrs: resolveAttrs,
230 resolveUrl: resolveUrl
231 };
232 }());
233 Polymer.Base._addFeature({
234 _prepAnnotations: function () {
235 if (!this._template) {
236 this._notes = [];
237 } else {
238 Polymer.Annotations.prepElement = this._prepElement.bind(this);
239 this._notes = Polymer.Annotations.parseAnnotations(this._template);
240 this._processAnnotations(this._notes);
241 Polymer.Annotations.prepElement = null;
242 }
243 },
244 _processAnnotations: function (notes) {
245 for (var i = 0; i < notes.length; i++) {
246 var note = notes[i];
247 for (var j = 0; j < note.bindings.length; j++) {
248 var b = note.bindings[j];
249 b.signature = this._parseMethod(b.value);
250 if (!b.signature) {
251 b.model = this._modelForPath(b.value);
252 }
253 }
254 if (note.templateContent) {
255 this._processAnnotations(note.templateContent._notes);
256 var pp = note.templateContent._parentProps = this._discoverTemplateParentProps(n ote.templateContent._notes);
257 var bindings = [];
258 for (var prop in pp) {
259 bindings.push({
260 index: note.index,
261 kind: 'property',
262 mode: '{',
263 name: '_parent_' + prop,
264 model: prop,
265 value: prop
266 });
267 }
268 note.bindings = note.bindings.concat(bindings);
269 }
270 }
271 },
272 _discoverTemplateParentProps: function (notes) {
273 var pp = {};
274 notes.forEach(function (n) {
275 n.bindings.forEach(function (b) {
276 if (b.signature) {
277 var args = b.signature.args;
278 for (var k = 0; k < args.length; k++) {
279 pp[args[k].model] = true;
280 }
281 } else {
282 pp[b.model] = true;
283 }
284 });
285 if (n.templateContent) {
286 var tpp = n.templateContent._parentProps;
287 Polymer.Base.mixin(pp, tpp);
288 }
289 });
290 return pp;
291 },
292 _prepElement: function (element) {
293 Polymer.ResolveUrl.resolveAttrs(element, this._template.ownerDocument);
294 },
295 _findAnnotatedNode: Polymer.Annotations.findAnnotatedNode,
296 _marshalAnnotationReferences: function () {
297 if (this._template) {
298 this._marshalIdNodes();
299 this._marshalAnnotatedNodes();
300 this._marshalAnnotatedListeners();
301 }
302 },
303 _configureAnnotationReferences: function () {
304 this._configureTemplateContent();
305 },
306 _configureTemplateContent: function () {
307 this._notes.forEach(function (note, i) {
308 if (note.templateContent) {
309 this._nodes[i]._content = note.templateContent;
310 }
311 }, this);
312 },
313 _marshalIdNodes: function () {
314 this.$ = {};
315 this._notes.forEach(function (a) {
316 if (a.id) {
317 this.$[a.id] = this._findAnnotatedNode(this.root, a);
318 }
319 }, this);
320 },
321 _marshalAnnotatedNodes: function () {
322 if (this._nodes) {
323 this._nodes = this._nodes.map(function (a) {
324 return this._findAnnotatedNode(this.root, a);
325 }, this);
326 }
327 },
328 _marshalAnnotatedListeners: function () {
329 this._notes.forEach(function (a) {
330 if (a.events && a.events.length) {
331 var node = this._findAnnotatedNode(this.root, a);
332 a.events.forEach(function (e) {
333 this.listen(node, e.name, e.value);
334 }, this);
335 }
336 }, this);
337 }
338 });
339 Polymer.Base._addFeature({
340 listeners: {},
341 _listenListeners: function (listeners) {
342 var node, name, key;
343 for (key in listeners) {
344 if (key.indexOf('.') < 0) {
345 node = this;
346 name = key;
347 } else {
348 name = key.split('.');
349 node = this.$[name[0]];
350 name = name[1];
351 }
352 this.listen(node, name, listeners[key]);
353 }
354 },
355 listen: function (node, eventName, methodName) {
356 this._listen(node, eventName, this._createEventHandler(node, eventName, methodNa me));
357 },
358 _boundListenerKey: function (eventName, methodName) {
359 return eventName + ':' + methodName;
360 },
361 _recordEventHandler: function (host, eventName, target, methodName, handler) {
362 var hbl = host.__boundListeners;
363 if (!hbl) {
364 hbl = host.__boundListeners = new WeakMap();
365 }
366 var bl = hbl.get(target);
367 if (!bl) {
368 bl = {};
369 hbl.set(target, bl);
370 }
371 var key = this._boundListenerKey(eventName, methodName);
372 bl[key] = handler;
373 },
374 _recallEventHandler: function (host, eventName, target, methodName) {
375 var hbl = host.__boundListeners;
376 if (!hbl) {
377 return;
378 }
379 var bl = hbl.get(target);
380 if (!bl) {
381 return;
382 }
383 var key = this._boundListenerKey(eventName, methodName);
384 return bl[key];
385 },
386 _createEventHandler: function (node, eventName, methodName) {
387 var host = this;
388 var handler = function (e) {
389 if (host[methodName]) {
390 host[methodName](e, e.detail);
391 } else {
392 host._warn(host._logf('_createEventHandler', 'listener method `' + methodName + '` not defined'));
393 }
394 };
395 this._recordEventHandler(host, eventName, node, methodName, handler);
396 return handler;
397 },
398 unlisten: function (node, eventName, methodName) {
399 var handler = this._recallEventHandler(this, eventName, node, methodName);
400 if (handler) {
401 this._unlisten(node, eventName, handler);
402 }
403 },
404 _listen: function (node, eventName, handler) {
405 node.addEventListener(eventName, handler);
406 },
407 _unlisten: function (node, eventName, handler) {
408 node.removeEventListener(eventName, handler);
409 }
410 });
411 (function () {
412 'use strict';
413 var HAS_NATIVE_TA = typeof document.head.style.touchAction === 'string';
414 var GESTURE_KEY = '__polymerGestures';
415 var HANDLED_OBJ = '__polymerGesturesHandled';
416 var TOUCH_ACTION = '__polymerGesturesTouchAction';
417 var TAP_DISTANCE = 25;
418 var TRACK_DISTANCE = 5;
419 var TRACK_LENGTH = 2;
420 var MOUSE_TIMEOUT = 2500;
421 var MOUSE_EVENTS = [
422 'mousedown',
423 'mousemove',
424 'mouseup',
425 'click'
426 ];
427 var IS_TOUCH_ONLY = navigator.userAgent.match(/iP(?:[oa]d|hone)|Android/);
428 var mouseCanceller = function (mouseEvent) {
429 mouseEvent[HANDLED_OBJ] = { skip: true };
430 if (mouseEvent.type === 'click') {
431 var path = Polymer.dom(mouseEvent).path;
432 for (var i = 0; i < path.length; i++) {
433 if (path[i] === POINTERSTATE.mouse.target) {
434 return;
435 }
436 }
437 mouseEvent.preventDefault();
438 mouseEvent.stopPropagation();
439 }
440 };
441 function setupTeardownMouseCanceller(setup) {
442 for (var i = 0, en; i < MOUSE_EVENTS.length; i++) {
443 en = MOUSE_EVENTS[i];
444 if (setup) {
445 document.addEventListener(en, mouseCanceller, true);
446 } else {
447 document.removeEventListener(en, mouseCanceller, true);
448 }
449 }
450 }
451 function ignoreMouse() {
452 if (IS_TOUCH_ONLY) {
453 return;
454 }
455 if (!POINTERSTATE.mouse.mouseIgnoreJob) {
456 setupTeardownMouseCanceller(true);
457 }
458 var unset = function () {
459 setupTeardownMouseCanceller();
460 POINTERSTATE.mouse.target = null;
461 POINTERSTATE.mouse.mouseIgnoreJob = null;
462 };
463 POINTERSTATE.mouse.mouseIgnoreJob = Polymer.Debounce(POINTERSTATE.mouse.mouseIgn oreJob, unset, MOUSE_TIMEOUT);
464 }
465 var POINTERSTATE = {
466 mouse: {
467 target: null,
468 mouseIgnoreJob: null
469 },
470 touch: {
471 x: 0,
472 y: 0,
473 id: -1,
474 scrollDecided: false
475 }
476 };
477 function firstTouchAction(ev) {
478 var path = Polymer.dom(ev).path;
479 var ta = 'auto';
480 for (var i = 0, n; i < path.length; i++) {
481 n = path[i];
482 if (n[TOUCH_ACTION]) {
483 ta = n[TOUCH_ACTION];
484 break;
485 }
486 }
487 return ta;
488 }
489 var Gestures = {
490 gestures: {},
491 recognizers: [],
492 deepTargetFind: function (x, y) {
493 var node = document.elementFromPoint(x, y);
494 var next = node;
495 while (next && next.shadowRoot) {
496 next = next.shadowRoot.elementFromPoint(x, y);
497 if (next) {
498 node = next;
499 }
500 }
501 return node;
502 },
503 findOriginalTarget: function (ev) {
504 if (ev.path) {
505 return ev.path[0];
506 }
507 return ev.target;
508 },
509 handleNative: function (ev) {
510 var handled;
511 var type = ev.type;
512 var node = ev.currentTarget;
513 var gobj = node[GESTURE_KEY];
514 var gs = gobj[type];
515 if (!gs) {
516 return;
517 }
518 if (!ev[HANDLED_OBJ]) {
519 ev[HANDLED_OBJ] = {};
520 if (type.slice(0, 5) === 'touch') {
521 var t = ev.changedTouches[0];
522 if (type === 'touchstart') {
523 if (ev.touches.length === 1) {
524 POINTERSTATE.touch.id = t.identifier;
525 }
526 }
527 if (POINTERSTATE.touch.id !== t.identifier) {
528 return;
529 }
530 if (!HAS_NATIVE_TA) {
531 if (type === 'touchstart' || type === 'touchmove') {
532 Gestures.handleTouchAction(ev);
533 }
534 }
535 if (type === 'touchend') {
536 POINTERSTATE.mouse.target = Polymer.dom(ev).rootTarget;
537 ignoreMouse(true);
538 }
539 }
540 }
541 handled = ev[HANDLED_OBJ];
542 if (handled.skip) {
543 return;
544 }
545 var recognizers = Gestures.recognizers;
546 for (var i = 0, r; i < recognizers.length; i++) {
547 r = recognizers[i];
548 if (gs[r.name] && !handled[r.name]) {
549 handled[r.name] = true;
550 r[type](ev);
551 }
552 }
553 },
554 handleTouchAction: function (ev) {
555 var t = ev.changedTouches[0];
556 var type = ev.type;
557 if (type === 'touchstart') {
558 POINTERSTATE.touch.x = t.clientX;
559 POINTERSTATE.touch.y = t.clientY;
560 POINTERSTATE.touch.scrollDecided = false;
561 } else if (type === 'touchmove') {
562 if (POINTERSTATE.touch.scrollDecided) {
563 return;
564 }
565 POINTERSTATE.touch.scrollDecided = true;
566 var ta = firstTouchAction(ev);
567 var prevent = false;
568 var dx = Math.abs(POINTERSTATE.touch.x - t.clientX);
569 var dy = Math.abs(POINTERSTATE.touch.y - t.clientY);
570 if (!ev.cancelable) {
571 } else if (ta === 'none') {
572 prevent = true;
573 } else if (ta === 'pan-x') {
574 prevent = dy > dx;
575 } else if (ta === 'pan-y') {
576 prevent = dx > dy;
577 }
578 if (prevent) {
579 ev.preventDefault();
580 }
581 }
582 },
583 add: function (node, evType, handler) {
584 var recognizer = this.gestures[evType];
585 var deps = recognizer.deps;
586 var name = recognizer.name;
587 var gobj = node[GESTURE_KEY];
588 if (!gobj) {
589 node[GESTURE_KEY] = gobj = {};
590 }
591 for (var i = 0, dep, gd; i < deps.length; i++) {
592 dep = deps[i];
593 if (IS_TOUCH_ONLY && MOUSE_EVENTS.indexOf(dep) > -1) {
594 continue;
595 }
596 gd = gobj[dep];
597 if (!gd) {
598 gobj[dep] = gd = { _count: 0 };
599 }
600 if (gd._count === 0) {
601 node.addEventListener(dep, this.handleNative);
602 }
603 gd[name] = (gd[name] || 0) + 1;
604 gd._count = (gd._count || 0) + 1;
605 }
606 node.addEventListener(evType, handler);
607 if (recognizer.touchAction) {
608 this.setTouchAction(node, recognizer.touchAction);
609 }
610 },
611 remove: function (node, evType, handler) {
612 var recognizer = this.gestures[evType];
613 var deps = recognizer.deps;
614 var name = recognizer.name;
615 var gobj = node[GESTURE_KEY];
616 if (gobj) {
617 for (var i = 0, dep, gd; i < deps.length; i++) {
618 dep = deps[i];
619 gd = gobj[dep];
620 if (gd && gd[name]) {
621 gd[name] = (gd[name] || 1) - 1;
622 gd._count = (gd._count || 1) - 1;
623 }
624 if (gd._count === 0) {
625 node.removeEventListener(dep, this.handleNative);
626 }
627 }
628 }
629 node.removeEventListener(evType, handler);
630 },
631 register: function (recog) {
632 this.recognizers.push(recog);
633 for (var i = 0; i < recog.emits.length; i++) {
634 this.gestures[recog.emits[i]] = recog;
635 }
636 },
637 findRecognizerByEvent: function (evName) {
638 for (var i = 0, r; i < this.recognizers.length; i++) {
639 r = this.recognizers[i];
640 for (var j = 0, n; j < r.emits.length; j++) {
641 n = r.emits[j];
642 if (n === evName) {
643 return r;
644 }
645 }
646 }
647 return null;
648 },
649 setTouchAction: function (node, value) {
650 if (HAS_NATIVE_TA) {
651 node.style.touchAction = value;
652 }
653 node[TOUCH_ACTION] = value;
654 },
655 fire: function (target, type, detail) {
656 var ev = Polymer.Base.fire(type, detail, {
657 node: target,
658 bubbles: true,
659 cancelable: true
660 });
661 if (ev.defaultPrevented) {
662 var se = detail.sourceEvent;
663 if (se && se.preventDefault) {
664 se.preventDefault();
665 }
666 }
667 },
668 prevent: function (evName) {
669 var recognizer = this.findRecognizerByEvent(evName);
670 if (recognizer.info) {
671 recognizer.info.prevent = true;
672 }
673 }
674 };
675 Gestures.register({
676 name: 'downup',
677 deps: [
678 'mousedown',
679 'touchstart',
680 'touchend'
681 ],
682 emits: [
683 'down',
684 'up'
685 ],
686 mousedown: function (e) {
687 var t = Gestures.findOriginalTarget(e);
688 var self = this;
689 var upfn = function upfn(e) {
690 self.fire('up', t, e);
691 document.removeEventListener('mouseup', upfn);
692 };
693 document.addEventListener('mouseup', upfn);
694 this.fire('down', t, e);
695 },
696 touchstart: function (e) {
697 this.fire('down', Gestures.findOriginalTarget(e), e.changedTouches[0]);
698 },
699 touchend: function (e) {
700 this.fire('up', Gestures.findOriginalTarget(e), e.changedTouches[0]);
701 },
702 fire: function (type, target, event) {
703 var self = this;
704 Gestures.fire(target, type, {
705 x: event.clientX,
706 y: event.clientY,
707 sourceEvent: event,
708 prevent: Gestures.prevent.bind(Gestures)
709 });
710 }
711 });
712 Gestures.register({
713 name: 'track',
714 touchAction: 'none',
715 deps: [
716 'mousedown',
717 'touchstart',
718 'touchmove',
719 'touchend'
720 ],
721 emits: ['track'],
722 info: {
723 x: 0,
724 y: 0,
725 state: 'start',
726 started: false,
727 moves: [],
728 addMove: function (move) {
729 if (this.moves.length > TRACK_LENGTH) {
730 this.moves.shift();
731 }
732 this.moves.push(move);
733 },
734 prevent: false
735 },
736 clearInfo: function () {
737 this.info.state = 'start';
738 this.info.started = false;
739 this.info.moves = [];
740 this.info.x = 0;
741 this.info.y = 0;
742 this.info.prevent = false;
743 },
744 hasMovedEnough: function (x, y) {
745 if (this.info.prevent) {
746 return false;
747 }
748 if (this.info.started) {
749 return true;
750 }
751 var dx = Math.abs(this.info.x - x);
752 var dy = Math.abs(this.info.y - y);
753 return dx >= TRACK_DISTANCE || dy >= TRACK_DISTANCE;
754 },
755 mousedown: function (e) {
756 var t = Gestures.findOriginalTarget(e);
757 var self = this;
758 var movefn = function movefn(e) {
759 var x = e.clientX, y = e.clientY;
760 if (self.hasMovedEnough(x, y)) {
761 self.info.state = self.info.started ? e.type === 'mouseup' ? 'end' : 'track' : ' start';
762 self.info.addMove({
763 x: x,
764 y: y
765 });
766 self.fire(t, e);
767 self.info.started = true;
768 }
769 };
770 var upfn = function upfn(e) {
771 if (self.info.started) {
772 Gestures.prevent('tap');
773 movefn(e);
774 }
775 self.clearInfo();
776 document.removeEventListener('mousemove', movefn);
777 document.removeEventListener('mouseup', upfn);
778 };
779 document.addEventListener('mousemove', movefn);
780 document.addEventListener('mouseup', upfn);
781 this.info.x = e.clientX;
782 this.info.y = e.clientY;
783 },
784 touchstart: function (e) {
785 var ct = e.changedTouches[0];
786 this.info.x = ct.clientX;
787 this.info.y = ct.clientY;
788 },
789 touchmove: function (e) {
790 var t = Gestures.findOriginalTarget(e);
791 var ct = e.changedTouches[0];
792 var x = ct.clientX, y = ct.clientY;
793 if (this.hasMovedEnough(x, y)) {
794 this.info.addMove({
795 x: x,
796 y: y
797 });
798 this.fire(t, ct);
799 this.info.state = 'track';
800 this.info.started = true;
801 }
802 },
803 touchend: function (e) {
804 var t = Gestures.findOriginalTarget(e);
805 var ct = e.changedTouches[0];
806 if (this.info.started) {
807 Gestures.prevent('tap');
808 this.info.state = 'end';
809 this.info.addMove({
810 x: ct.clientX,
811 y: ct.clientY
812 });
813 this.fire(t, ct);
814 }
815 this.clearInfo();
816 },
817 fire: function (target, touch) {
818 var secondlast = this.info.moves[this.info.moves.length - 2];
819 var lastmove = this.info.moves[this.info.moves.length - 1];
820 var dx = lastmove.x - this.info.x;
821 var dy = lastmove.y - this.info.y;
822 var ddx, ddy = 0;
823 if (secondlast) {
824 ddx = lastmove.x - secondlast.x;
825 ddy = lastmove.y - secondlast.y;
826 }
827 return Gestures.fire(target, 'track', {
828 state: this.info.state,
829 x: touch.clientX,
830 y: touch.clientY,
831 dx: dx,
832 dy: dy,
833 ddx: ddx,
834 ddy: ddy,
835 sourceEvent: touch,
836 hover: function () {
837 return Gestures.deepTargetFind(touch.clientX, touch.clientY);
838 }
839 });
840 }
841 });
842 Gestures.register({
843 name: 'tap',
844 deps: [
845 'mousedown',
846 'click',
847 'touchstart',
848 'touchend'
849 ],
850 emits: ['tap'],
851 info: {
852 x: NaN,
853 y: NaN,
854 prevent: false
855 },
856 reset: function () {
857 this.info.x = NaN;
858 this.info.y = NaN;
859 this.info.prevent = false;
860 },
861 save: function (e) {
862 this.info.x = e.clientX;
863 this.info.y = e.clientY;
864 },
865 mousedown: function (e) {
866 this.save(e);
867 },
868 click: function (e) {
869 this.forward(e);
870 },
871 touchstart: function (e) {
872 this.save(e.changedTouches[0]);
873 },
874 touchend: function (e) {
875 this.forward(e.changedTouches[0]);
876 },
877 forward: function (e) {
878 var dx = Math.abs(e.clientX - this.info.x);
879 var dy = Math.abs(e.clientY - this.info.y);
880 var t = Gestures.findOriginalTarget(e);
881 if (isNaN(dx) || isNaN(dy) || dx <= TAP_DISTANCE && dy <= TAP_DISTANCE) {
882 if (!this.info.prevent) {
883 Gestures.fire(t, 'tap', {
884 x: e.clientX,
885 y: e.clientY,
886 sourceEvent: e
887 });
888 }
889 }
890 this.reset();
891 }
892 });
893 var DIRECTION_MAP = {
894 x: 'pan-x',
895 y: 'pan-y',
896 none: 'none',
897 all: 'auto'
898 };
899 Polymer.Base._addFeature({
900 _listen: function (node, eventName, handler) {
901 if (Gestures.gestures[eventName]) {
902 Gestures.add(node, eventName, handler);
903 } else {
904 node.addEventListener(eventName, handler);
905 }
906 },
907 _unlisten: function (node, eventName, handler) {
908 if (Gestures.gestures[eventName]) {
909 Gestures.remove(node, eventName, handler);
910 } else {
911 node.removeEventListener(eventName, handler);
912 }
913 },
914 setScrollDirection: function (direction, node) {
915 node = node || this;
916 Gestures.setTouchAction(node, DIRECTION_MAP[direction] || 'auto');
917 }
918 });
919 Polymer.Gestures = Gestures;
920 }());
921 Polymer.Async = {
922 _currVal: 0,
923 _lastVal: 0,
924 _callbacks: [],
925 _twiddleContent: 0,
926 _twiddle: document.createTextNode(''),
927 run: function (callback, waitTime) {
928 if (waitTime > 0) {
929 return ~setTimeout(callback, waitTime);
930 } else {
931 this._twiddle.textContent = this._twiddleContent++;
932 this._callbacks.push(callback);
933 return this._currVal++;
934 }
935 },
936 cancel: function (handle) {
937 if (handle < 0) {
938 clearTimeout(~handle);
939 } else {
940 var idx = handle - this._lastVal;
941 if (idx >= 0) {
942 if (!this._callbacks[idx]) {
943 throw 'invalid async handle: ' + handle;
944 }
945 this._callbacks[idx] = null;
946 }
947 }
948 },
949 _atEndOfMicrotask: function () {
950 var len = this._callbacks.length;
951 for (var i = 0; i < len; i++) {
952 var cb = this._callbacks[i];
953 if (cb) {
954 try {
955 cb();
956 } catch (e) {
957 i++;
958 this._callbacks.splice(0, i);
959 this._lastVal += i;
960 this._twiddle.textContent = this._twiddleContent++;
961 throw e;
962 }
963 }
964 }
965 this._callbacks.splice(0, len);
966 this._lastVal += len;
967 }
968 };
969 new (window.MutationObserver || JsMutationObserver)(Polymer.Async._atEndOfMicrot ask.bind(Polymer.Async)).observe(Polymer.Async._twiddle, { characterData: true } );
970 Polymer.Debounce = function () {
971 var Async = Polymer.Async;
972 var Debouncer = function (context) {
973 this.context = context;
974 this.boundComplete = this.complete.bind(this);
975 };
976 Debouncer.prototype = {
977 go: function (callback, wait) {
978 var h;
979 this.finish = function () {
980 Async.cancel(h);
981 };
982 h = Async.run(this.boundComplete, wait);
983 this.callback = callback;
984 },
985 stop: function () {
986 if (this.finish) {
987 this.finish();
988 this.finish = null;
989 }
990 },
991 complete: function () {
992 if (this.finish) {
993 this.stop();
994 this.callback.call(this.context);
995 }
996 }
997 };
998 function debounce(debouncer, callback, wait) {
999 if (debouncer) {
1000 debouncer.stop();
1001 } else {
1002 debouncer = new Debouncer(this);
1003 }
1004 debouncer.go(callback, wait);
1005 return debouncer;
1006 }
1007 return debounce;
1008 }();
1009 Polymer.Base._addFeature({
1010 $$: function (slctr) {
1011 return Polymer.dom(this.root).querySelector(slctr);
1012 },
1013 toggleClass: function (name, bool, node) {
1014 node = node || this;
1015 if (arguments.length == 1) {
1016 bool = !node.classList.contains(name);
1017 }
1018 if (bool) {
1019 Polymer.dom(node).classList.add(name);
1020 } else {
1021 Polymer.dom(node).classList.remove(name);
1022 }
1023 },
1024 toggleAttribute: function (name, bool, node) {
1025 node = node || this;
1026 if (arguments.length == 1) {
1027 bool = !node.hasAttribute(name);
1028 }
1029 if (bool) {
1030 Polymer.dom(node).setAttribute(name, '');
1031 } else {
1032 Polymer.dom(node).removeAttribute(name);
1033 }
1034 },
1035 classFollows: function (name, toElement, fromElement) {
1036 if (fromElement) {
1037 Polymer.dom(fromElement).classList.remove(name);
1038 }
1039 if (toElement) {
1040 Polymer.dom(toElement).classList.add(name);
1041 }
1042 },
1043 attributeFollows: function (name, toElement, fromElement) {
1044 if (fromElement) {
1045 Polymer.dom(fromElement).removeAttribute(name);
1046 }
1047 if (toElement) {
1048 Polymer.dom(toElement).setAttribute(name, '');
1049 }
1050 },
1051 getContentChildNodes: function (slctr) {
1052 var content = Polymer.dom(this.root).querySelector(slctr || 'content');
1053 return content ? Polymer.dom(content).getDistributedNodes() : [];
1054 },
1055 getContentChildren: function (slctr) {
1056 return this.getContentChildNodes(slctr).filter(function (n) {
1057 return n.nodeType === Node.ELEMENT_NODE;
1058 });
1059 },
1060 fire: function (type, detail, options) {
1061 options = options || Polymer.nob;
1062 var node = options.node || this;
1063 var detail = detail === null || detail === undefined ? Polymer.nob : detail;
1064 var bubbles = options.bubbles === undefined ? true : options.bubbles;
1065 var cancelable = Boolean(options.cancelable);
1066 var event = new CustomEvent(type, {
1067 bubbles: Boolean(bubbles),
1068 cancelable: cancelable,
1069 detail: detail
1070 });
1071 node.dispatchEvent(event);
1072 return event;
1073 },
1074 async: function (callback, waitTime) {
1075 return Polymer.Async.run(callback.bind(this), waitTime);
1076 },
1077 cancelAsync: function (handle) {
1078 Polymer.Async.cancel(handle);
1079 },
1080 arrayDelete: function (path, item) {
1081 var index;
1082 if (Array.isArray(path)) {
1083 index = path.indexOf(item);
1084 if (index >= 0) {
1085 return path.splice(index, 1);
1086 }
1087 } else {
1088 var arr = this.get(path);
1089 index = arr.indexOf(item);
1090 if (index >= 0) {
1091 return this.splice(path, index, 1);
1092 }
1093 }
1094 },
1095 transform: function (transform, node) {
1096 node = node || this;
1097 node.style.webkitTransform = transform;
1098 node.style.transform = transform;
1099 },
1100 translate3d: function (x, y, z, node) {
1101 node = node || this;
1102 this.transform('translate3d(' + x + ',' + y + ',' + z + ')', node);
1103 },
1104 importHref: function (href, onload, onerror) {
1105 var l = document.createElement('link');
1106 l.rel = 'import';
1107 l.href = href;
1108 if (onload) {
1109 l.onload = onload.bind(this);
1110 }
1111 if (onerror) {
1112 l.onerror = onerror.bind(this);
1113 }
1114 document.head.appendChild(l);
1115 return l;
1116 },
1117 create: function (tag, props) {
1118 var elt = document.createElement(tag);
1119 if (props) {
1120 for (var n in props) {
1121 elt[n] = props[n];
1122 }
1123 }
1124 return elt;
1125 }
1126 });
1127 Polymer.Bind = {
1128 prepareModel: function (model) {
1129 model._propertyEffects = {};
1130 model._bindListeners = [];
1131 Polymer.Base.mixin(model, this._modelApi);
1132 },
1133 _modelApi: {
1134 _notifyChange: function (property) {
1135 var eventName = Polymer.CaseMap.camelToDashCase(property) + '-changed';
1136 Polymer.Base.fire(eventName, { value: this[property] }, {
1137 bubbles: false,
1138 node: this
1139 });
1140 },
1141 _propertySetter: function (property, value, effects, fromAbove) {
1142 var old = this.__data__[property];
1143 if (old !== value && (old === old || value === value)) {
1144 this.__data__[property] = value;
1145 if (typeof value == 'object') {
1146 this._clearPath(property);
1147 }
1148 if (this._propertyChanged) {
1149 this._propertyChanged(property, value, old);
1150 }
1151 if (effects) {
1152 this._effectEffects(property, value, effects, old, fromAbove);
1153 }
1154 }
1155 return old;
1156 },
1157 __setProperty: function (property, value, quiet, node) {
1158 node = node || this;
1159 var effects = node._propertyEffects && node._propertyEffects[property];
1160 if (effects) {
1161 node._propertySetter(property, value, effects, quiet);
1162 } else {
1163 node[property] = value;
1164 }
1165 },
1166 _effectEffects: function (property, value, effects, old, fromAbove) {
1167 effects.forEach(function (fx) {
1168 var fn = Polymer.Bind['_' + fx.kind + 'Effect'];
1169 if (fn) {
1170 fn.call(this, property, value, fx.effect, old, fromAbove);
1171 }
1172 }, this);
1173 },
1174 _clearPath: function (path) {
1175 for (var prop in this.__data__) {
1176 if (prop.indexOf(path + '.') === 0) {
1177 this.__data__[prop] = undefined;
1178 }
1179 }
1180 }
1181 },
1182 ensurePropertyEffects: function (model, property) {
1183 var fx = model._propertyEffects[property];
1184 if (!fx) {
1185 fx = model._propertyEffects[property] = [];
1186 }
1187 return fx;
1188 },
1189 addPropertyEffect: function (model, property, kind, effect) {
1190 var fx = this.ensurePropertyEffects(model, property);
1191 fx.push({
1192 kind: kind,
1193 effect: effect
1194 });
1195 },
1196 createBindings: function (model) {
1197 var fx$ = model._propertyEffects;
1198 if (fx$) {
1199 for (var n in fx$) {
1200 var fx = fx$[n];
1201 fx.sort(this._sortPropertyEffects);
1202 this._createAccessors(model, n, fx);
1203 }
1204 }
1205 },
1206 _sortPropertyEffects: function () {
1207 var EFFECT_ORDER = {
1208 'compute': 0,
1209 'annotation': 1,
1210 'computedAnnotation': 2,
1211 'reflect': 3,
1212 'notify': 4,
1213 'observer': 5,
1214 'complexObserver': 6,
1215 'function': 7
1216 };
1217 return function (a, b) {
1218 return EFFECT_ORDER[a.kind] - EFFECT_ORDER[b.kind];
1219 };
1220 }(),
1221 _createAccessors: function (model, property, effects) {
1222 var defun = {
1223 get: function () {
1224 return this.__data__[property];
1225 }
1226 };
1227 var setter = function (value) {
1228 this._propertySetter(property, value, effects);
1229 };
1230 var info = model.getPropertyInfo && model.getPropertyInfo(property);
1231 if (info && info.readOnly) {
1232 if (!info.computed) {
1233 model['_set' + this.upper(property)] = setter;
1234 }
1235 } else {
1236 defun.set = setter;
1237 }
1238 Object.defineProperty(model, property, defun);
1239 },
1240 upper: function (name) {
1241 return name[0].toUpperCase() + name.substring(1);
1242 },
1243 _addAnnotatedListener: function (model, index, property, path, event) {
1244 var fn = this._notedListenerFactory(property, path, this._isStructured(path), th is._isEventBogus);
1245 var eventName = event || Polymer.CaseMap.camelToDashCase(property) + '-changed';
1246 model._bindListeners.push({
1247 index: index,
1248 property: property,
1249 path: path,
1250 changedFn: fn,
1251 event: eventName
1252 });
1253 },
1254 _isStructured: function (path) {
1255 return path.indexOf('.') > 0;
1256 },
1257 _isEventBogus: function (e, target) {
1258 return e.path && e.path[0] !== target;
1259 },
1260 _notedListenerFactory: function (property, path, isStructured, bogusTest) {
1261 return function (e, target) {
1262 if (!bogusTest(e, target)) {
1263 if (e.detail && e.detail.path) {
1264 this.notifyPath(this._fixPath(path, property, e.detail.path), e.detail.value);
1265 } else {
1266 var value = target[property];
1267 if (!isStructured) {
1268 this[path] = target[property];
1269 } else {
1270 if (this.__data__[path] != value) {
1271 this.set(path, value);
1272 }
1273 }
1274 }
1275 }
1276 };
1277 },
1278 prepareInstance: function (inst) {
1279 inst.__data__ = Object.create(null);
1280 },
1281 setupBindListeners: function (inst) {
1282 inst._bindListeners.forEach(function (info) {
1283 var node = inst._nodes[info.index];
1284 node.addEventListener(info.event, inst._notifyListener.bind(inst, info.changedFn ));
1285 });
1286 }
1287 };
1288 Polymer.Base.extend(Polymer.Bind, {
1289 _shouldAddListener: function (effect) {
1290 return effect.name && effect.mode === '{' && !effect.negate && effect.kind != 'a ttribute';
1291 },
1292 _annotationEffect: function (source, value, effect) {
1293 if (source != effect.value) {
1294 value = this.get(effect.value);
1295 this.__data__[effect.value] = value;
1296 }
1297 var calc = effect.negate ? !value : value;
1298 if (!effect.customEvent || this._nodes[effect.index][effect.name] !== calc) {
1299 return this._applyEffectValue(calc, effect);
1300 }
1301 },
1302 _reflectEffect: function (source) {
1303 this.reflectPropertyToAttribute(source);
1304 },
1305 _notifyEffect: function (source, value, effect, old, fromAbove) {
1306 if (!fromAbove) {
1307 this._notifyChange(source);
1308 }
1309 },
1310 _functionEffect: function (source, value, fn, old, fromAbove) {
1311 fn.call(this, source, value, old, fromAbove);
1312 },
1313 _observerEffect: function (source, value, effect, old) {
1314 var fn = this[effect.method];
1315 if (fn) {
1316 fn.call(this, value, old);
1317 } else {
1318 this._warn(this._logf('_observerEffect', 'observer method `' + effect.method + ' ` not defined'));
1319 }
1320 },
1321 _complexObserverEffect: function (source, value, effect) {
1322 var fn = this[effect.method];
1323 if (fn) {
1324 var args = Polymer.Bind._marshalArgs(this.__data__, effect, source, value);
1325 if (args) {
1326 fn.apply(this, args);
1327 }
1328 } else {
1329 this._warn(this._logf('_complexObserverEffect', 'observer method `' + effect.met hod + '` not defined'));
1330 }
1331 },
1332 _computeEffect: function (source, value, effect) {
1333 var args = Polymer.Bind._marshalArgs(this.__data__, effect, source, value);
1334 if (args) {
1335 var fn = this[effect.method];
1336 if (fn) {
1337 this.__setProperty(effect.property, fn.apply(this, args));
1338 } else {
1339 this._warn(this._logf('_computeEffect', 'compute method `' + effect.method + '` not defined'));
1340 }
1341 }
1342 },
1343 _annotatedComputationEffect: function (source, value, effect) {
1344 var computedHost = this._rootDataHost || this;
1345 var fn = computedHost[effect.method];
1346 if (fn) {
1347 var args = Polymer.Bind._marshalArgs(this.__data__, effect, source, value);
1348 if (args) {
1349 var computedvalue = fn.apply(computedHost, args);
1350 if (effect.negate) {
1351 computedvalue = !computedvalue;
1352 }
1353 this._applyEffectValue(computedvalue, effect);
1354 }
1355 } else {
1356 computedHost._warn(computedHost._logf('_annotatedComputationEffect', 'compute me thod `' + effect.method + '` not defined'));
1357 }
1358 },
1359 _marshalArgs: function (model, effect, path, value) {
1360 var values = [];
1361 var args = effect.args;
1362 for (var i = 0, l = args.length; i < l; i++) {
1363 var arg = args[i];
1364 var name = arg.name;
1365 var v;
1366 if (arg.literal) {
1367 v = arg.value;
1368 } else if (arg.structured) {
1369 v = Polymer.Base.get(name, model);
1370 } else {
1371 v = model[name];
1372 }
1373 if (args.length > 1 && v === undefined) {
1374 return;
1375 }
1376 if (arg.wildcard) {
1377 var baseChanged = name.indexOf(path + '.') === 0;
1378 var matches = effect.trigger.name.indexOf(name) === 0 && !baseChanged;
1379 values[i] = {
1380 path: matches ? path : name,
1381 value: matches ? value : v,
1382 base: v
1383 };
1384 } else {
1385 values[i] = v;
1386 }
1387 }
1388 return values;
1389 }
1390 });
1391 Polymer.Base._addFeature({
1392 _addPropertyEffect: function (property, kind, effect) {
1393 Polymer.Bind.addPropertyEffect(this, property, kind, effect);
1394 },
1395 _prepEffects: function () {
1396 Polymer.Bind.prepareModel(this);
1397 this._addAnnotationEffects(this._notes);
1398 },
1399 _prepBindings: function () {
1400 Polymer.Bind.createBindings(this);
1401 },
1402 _addPropertyEffects: function (properties) {
1403 if (properties) {
1404 for (var p in properties) {
1405 var prop = properties[p];
1406 if (prop.observer) {
1407 this._addObserverEffect(p, prop.observer);
1408 }
1409 if (prop.computed) {
1410 prop.readOnly = true;
1411 this._addComputedEffect(p, prop.computed);
1412 }
1413 if (prop.notify) {
1414 this._addPropertyEffect(p, 'notify');
1415 }
1416 if (prop.reflectToAttribute) {
1417 this._addPropertyEffect(p, 'reflect');
1418 }
1419 if (prop.readOnly) {
1420 Polymer.Bind.ensurePropertyEffects(this, p);
1421 }
1422 }
1423 }
1424 },
1425 _addComputedEffect: function (name, expression) {
1426 var sig = this._parseMethod(expression);
1427 sig.args.forEach(function (arg) {
1428 this._addPropertyEffect(arg.model, 'compute', {
1429 method: sig.method,
1430 args: sig.args,
1431 trigger: arg,
1432 property: name
1433 });
1434 }, this);
1435 },
1436 _addObserverEffect: function (property, observer) {
1437 this._addPropertyEffect(property, 'observer', {
1438 method: observer,
1439 property: property
1440 });
1441 },
1442 _addComplexObserverEffects: function (observers) {
1443 if (observers) {
1444 observers.forEach(function (observer) {
1445 this._addComplexObserverEffect(observer);
1446 }, this);
1447 }
1448 },
1449 _addComplexObserverEffect: function (observer) {
1450 var sig = this._parseMethod(observer);
1451 sig.args.forEach(function (arg) {
1452 this._addPropertyEffect(arg.model, 'complexObserver', {
1453 method: sig.method,
1454 args: sig.args,
1455 trigger: arg
1456 });
1457 }, this);
1458 },
1459 _addAnnotationEffects: function (notes) {
1460 this._nodes = [];
1461 notes.forEach(function (note) {
1462 var index = this._nodes.push(note) - 1;
1463 note.bindings.forEach(function (binding) {
1464 this._addAnnotationEffect(binding, index);
1465 }, this);
1466 }, this);
1467 },
1468 _addAnnotationEffect: function (note, index) {
1469 if (Polymer.Bind._shouldAddListener(note)) {
1470 Polymer.Bind._addAnnotatedListener(this, index, note.name, note.value, note.even t);
1471 }
1472 if (note.signature) {
1473 this._addAnnotatedComputationEffect(note, index);
1474 } else {
1475 note.index = index;
1476 this._addPropertyEffect(note.model, 'annotation', note);
1477 }
1478 },
1479 _addAnnotatedComputationEffect: function (note, index) {
1480 var sig = note.signature;
1481 if (sig.static) {
1482 this.__addAnnotatedComputationEffect('__static__', index, note, sig, null);
1483 } else {
1484 sig.args.forEach(function (arg) {
1485 if (!arg.literal) {
1486 this.__addAnnotatedComputationEffect(arg.model, index, note, sig, arg);
1487 }
1488 }, this);
1489 }
1490 },
1491 __addAnnotatedComputationEffect: function (property, index, note, sig, trigger) {
1492 this._addPropertyEffect(property, 'annotatedComputation', {
1493 index: index,
1494 kind: note.kind,
1495 property: note.name,
1496 negate: note.negate,
1497 method: sig.method,
1498 args: sig.args,
1499 trigger: trigger
1500 });
1501 },
1502 _parseMethod: function (expression) {
1503 var m = expression.match(/(\w*)\((.*)\)/);
1504 if (m) {
1505 var sig = {
1506 method: m[1],
1507 static: true
1508 };
1509 if (m[2].trim()) {
1510 var args = m[2].replace(/\\,/g, '&comma;').split(',');
1511 return this._parseArgs(args, sig);
1512 } else {
1513 sig.args = Polymer.nar;
1514 return sig;
1515 }
1516 }
1517 },
1518 _parseArgs: function (argList, sig) {
1519 sig.args = argList.map(function (rawArg) {
1520 var arg = this._parseArg(rawArg);
1521 if (!arg.literal) {
1522 sig.static = false;
1523 }
1524 return arg;
1525 }, this);
1526 return sig;
1527 },
1528 _parseArg: function (rawArg) {
1529 var arg = rawArg.trim().replace(/&comma;/g, ',').replace(/\\(.)/g, '$1');
1530 var a = {
1531 name: arg,
1532 model: this._modelForPath(arg)
1533 };
1534 var fc = arg[0];
1535 if (fc >= '0' && fc <= '9') {
1536 fc = '#';
1537 }
1538 switch (fc) {
1539 case '\'':
1540 case '"':
1541 a.value = arg.slice(1, -1);
1542 a.literal = true;
1543 break;
1544 case '#':
1545 a.value = Number(arg);
1546 a.literal = true;
1547 break;
1548 }
1549 if (!a.literal) {
1550 a.structured = arg.indexOf('.') > 0;
1551 if (a.structured) {
1552 a.wildcard = arg.slice(-2) == '.*';
1553 if (a.wildcard) {
1554 a.name = arg.slice(0, -2);
1555 }
1556 }
1557 }
1558 return a;
1559 },
1560 _marshalInstanceEffects: function () {
1561 Polymer.Bind.prepareInstance(this);
1562 Polymer.Bind.setupBindListeners(this);
1563 },
1564 _applyEffectValue: function (value, info) {
1565 var node = this._nodes[info.index];
1566 var property = info.property || info.name || 'textContent';
1567 if (info.kind == 'attribute') {
1568 this.serializeValueToAttribute(value, property, node);
1569 } else {
1570 if (property === 'className') {
1571 value = this._scopeElementClass(node, value);
1572 }
1573 if (property === 'textContent' || node.localName == 'input' && property == 'valu e') {
1574 value = value == undefined ? '' : value;
1575 }
1576 return node[property] = value;
1577 }
1578 },
1579 _executeStaticEffects: function () {
1580 if (this._propertyEffects.__static__) {
1581 this._effectEffects('__static__', null, this._propertyEffects.__static__);
1582 }
1583 }
1584 });
1585 Polymer.Base._addFeature({
1586 _setupConfigure: function (initialConfig) {
1587 this._config = initialConfig || {};
1588 this._handlers = [];
1589 },
1590 _marshalAttributes: function () {
1591 this._takeAttributesToModel(this._config);
1592 },
1593 _configValue: function (name, value) {
1594 this._config[name] = value;
1595 },
1596 _beforeClientsReady: function () {
1597 this._configure();
1598 },
1599 _configure: function () {
1600 this._configureAnnotationReferences();
1601 this._aboveConfig = this.mixin({}, this._config);
1602 var config = {};
1603 this.behaviors.forEach(function (b) {
1604 this._configureProperties(b.properties, config);
1605 }, this);
1606 this._configureProperties(this.properties, config);
1607 this._mixinConfigure(config, this._aboveConfig);
1608 this._config = config;
1609 this._distributeConfig(this._config);
1610 },
1611 _configureProperties: function (properties, config) {
1612 for (var i in properties) {
1613 var c = properties[i];
1614 if (c.value !== undefined) {
1615 var value = c.value;
1616 if (typeof value == 'function') {
1617 value = value.call(this, this._config);
1618 }
1619 config[i] = value;
1620 }
1621 }
1622 },
1623 _mixinConfigure: function (a, b) {
1624 for (var prop in b) {
1625 if (!this.getPropertyInfo(prop).readOnly) {
1626 a[prop] = b[prop];
1627 }
1628 }
1629 },
1630 _distributeConfig: function (config) {
1631 var fx$ = this._propertyEffects;
1632 if (fx$) {
1633 for (var p in config) {
1634 var fx = fx$[p];
1635 if (fx) {
1636 for (var i = 0, l = fx.length, x; i < l && (x = fx[i]); i++) {
1637 if (x.kind === 'annotation') {
1638 var node = this._nodes[x.effect.index];
1639 if (node._configValue) {
1640 var value = p === x.effect.value ? config[p] : this.get(x.effect.value, config);
1641 node._configValue(x.effect.name, value);
1642 }
1643 }
1644 }
1645 }
1646 }
1647 }
1648 },
1649 _afterClientsReady: function () {
1650 this._executeStaticEffects();
1651 this._applyConfig(this._config, this._aboveConfig);
1652 this._flushHandlers();
1653 },
1654 _applyConfig: function (config, aboveConfig) {
1655 for (var n in config) {
1656 if (this[n] === undefined) {
1657 this.__setProperty(n, config[n], n in aboveConfig);
1658 }
1659 }
1660 },
1661 _notifyListener: function (fn, e) {
1662 if (!this._clientsReadied) {
1663 this._queueHandler([
1664 fn,
1665 e,
1666 e.target
1667 ]);
1668 } else {
1669 return fn.call(this, e, e.target);
1670 }
1671 },
1672 _queueHandler: function (args) {
1673 this._handlers.push(args);
1674 },
1675 _flushHandlers: function () {
1676 var h$ = this._handlers;
1677 for (var i = 0, l = h$.length, h; i < l && (h = h$[i]); i++) {
1678 h[0].call(this, h[1], h[2]);
1679 }
1680 }
1681 });
1682 (function () {
1683 'use strict';
1684 Polymer.Base._addFeature({
1685 notifyPath: function (path, value, fromAbove) {
1686 var old = this._propertySetter(path, value);
1687 if (old !== value && (old === old || value === value)) {
1688 this._pathEffector(path, value);
1689 if (!fromAbove) {
1690 this._notifyPath(path, value);
1691 }
1692 return true;
1693 }
1694 },
1695 _getPathParts: function (path) {
1696 if (Array.isArray(path)) {
1697 var parts = [];
1698 for (var i = 0; i < path.length; i++) {
1699 var args = path[i].toString().split('.');
1700 for (var j = 0; j < args.length; j++) {
1701 parts.push(args[j]);
1702 }
1703 }
1704 return parts;
1705 } else {
1706 return path.toString().split('.');
1707 }
1708 },
1709 set: function (path, value, root) {
1710 var prop = root || this;
1711 var parts = this._getPathParts(path);
1712 var array;
1713 var last = parts[parts.length - 1];
1714 if (parts.length > 1) {
1715 for (var i = 0; i < parts.length - 1; i++) {
1716 prop = prop[parts[i]];
1717 if (array) {
1718 parts[i] = Polymer.Collection.get(array).getKey(prop);
1719 }
1720 if (!prop) {
1721 return;
1722 }
1723 array = Array.isArray(prop) ? prop : null;
1724 }
1725 if (array) {
1726 var coll = Polymer.Collection.get(array);
1727 var old = prop[last];
1728 var key = coll.getKey(old);
1729 if (key) {
1730 parts[i] = key;
1731 coll.setItem(key, value);
1732 }
1733 }
1734 prop[last] = value;
1735 if (!root) {
1736 this.notifyPath(parts.join('.'), value);
1737 }
1738 } else {
1739 prop[path] = value;
1740 }
1741 },
1742 get: function (path, root) {
1743 var prop = root || this;
1744 var parts = this._getPathParts(path);
1745 var last = parts.pop();
1746 while (parts.length) {
1747 prop = prop[parts.shift()];
1748 if (!prop) {
1749 return;
1750 }
1751 }
1752 return prop[last];
1753 },
1754 _pathEffector: function (path, value) {
1755 var model = this._modelForPath(path);
1756 var fx$ = this._propertyEffects[model];
1757 if (fx$) {
1758 fx$.forEach(function (fx) {
1759 var fxFn = this['_' + fx.kind + 'PathEffect'];
1760 if (fxFn) {
1761 fxFn.call(this, path, value, fx.effect);
1762 }
1763 }, this);
1764 }
1765 if (this._boundPaths) {
1766 this._notifyBoundPaths(path, value);
1767 }
1768 },
1769 _annotationPathEffect: function (path, value, effect) {
1770 if (effect.value === path || effect.value.indexOf(path + '.') === 0) {
1771 Polymer.Bind._annotationEffect.call(this, path, value, effect);
1772 } else if (path.indexOf(effect.value + '.') === 0 && !effect.negate) {
1773 var node = this._nodes[effect.index];
1774 if (node && node.notifyPath) {
1775 var p = this._fixPath(effect.name, effect.value, path);
1776 node.notifyPath(p, value, true);
1777 }
1778 }
1779 },
1780 _complexObserverPathEffect: function (path, value, effect) {
1781 if (this._pathMatchesEffect(path, effect)) {
1782 Polymer.Bind._complexObserverEffect.call(this, path, value, effect);
1783 }
1784 },
1785 _computePathEffect: function (path, value, effect) {
1786 if (this._pathMatchesEffect(path, effect)) {
1787 Polymer.Bind._computeEffect.call(this, path, value, effect);
1788 }
1789 },
1790 _annotatedComputationPathEffect: function (path, value, effect) {
1791 if (this._pathMatchesEffect(path, effect)) {
1792 Polymer.Bind._annotatedComputationEffect.call(this, path, value, effect);
1793 }
1794 },
1795 _pathMatchesEffect: function (path, effect) {
1796 var effectArg = effect.trigger.name;
1797 return effectArg == path || effectArg.indexOf(path + '.') === 0 || effect.trigge r.wildcard && path.indexOf(effectArg) === 0;
1798 },
1799 linkPaths: function (to, from) {
1800 this._boundPaths = this._boundPaths || {};
1801 if (from) {
1802 this._boundPaths[to] = from;
1803 } else {
1804 this.unbindPath(to);
1805 }
1806 },
1807 unlinkPaths: function (path) {
1808 if (this._boundPaths) {
1809 delete this._boundPaths[path];
1810 }
1811 },
1812 _notifyBoundPaths: function (path, value) {
1813 var from, to;
1814 for (var a in this._boundPaths) {
1815 var b = this._boundPaths[a];
1816 if (path.indexOf(a + '.') == 0) {
1817 from = a;
1818 to = b;
1819 break;
1820 }
1821 if (path.indexOf(b + '.') == 0) {
1822 from = b;
1823 to = a;
1824 break;
1825 }
1826 }
1827 if (from && to) {
1828 var p = this._fixPath(to, from, path);
1829 this.notifyPath(p, value);
1830 }
1831 },
1832 _fixPath: function (property, root, path) {
1833 return property + path.slice(root.length);
1834 },
1835 _notifyPath: function (path, value) {
1836 var rootName = this._modelForPath(path);
1837 var dashCaseName = Polymer.CaseMap.camelToDashCase(rootName);
1838 var eventName = dashCaseName + this._EVENT_CHANGED;
1839 this.fire(eventName, {
1840 path: path,
1841 value: value
1842 }, { bubbles: false });
1843 },
1844 _modelForPath: function (path) {
1845 var dot = path.indexOf('.');
1846 return dot < 0 ? path : path.slice(0, dot);
1847 },
1848 _EVENT_CHANGED: '-changed',
1849 _notifySplice: function (array, path, index, added, removed) {
1850 var splices = [{
1851 index: index,
1852 addedCount: added,
1853 removed: removed,
1854 object: array,
1855 type: 'splice'
1856 }];
1857 var change = {
1858 keySplices: Polymer.Collection.applySplices(array, splices),
1859 indexSplices: splices
1860 };
1861 this.set(path + '.splices', change);
1862 if (added != removed.length) {
1863 this.notifyPath(path + '.length', array.length);
1864 }
1865 change.keySplices = null;
1866 change.indexSplices = null;
1867 },
1868 push: function (path) {
1869 var array = this.get(path);
1870 var args = Array.prototype.slice.call(arguments, 1);
1871 var len = array.length;
1872 var ret = array.push.apply(array, args);
1873 this._notifySplice(array, path, len, args.length, []);
1874 return ret;
1875 },
1876 pop: function (path) {
1877 var array = this.get(path);
1878 var args = Array.prototype.slice.call(arguments, 1);
1879 var rem = array.slice(-1);
1880 var ret = array.pop.apply(array, args);
1881 this._notifySplice(array, path, array.length, 0, rem);
1882 return ret;
1883 },
1884 splice: function (path, start, deleteCount) {
1885 var array = this.get(path);
1886 var args = Array.prototype.slice.call(arguments, 1);
1887 var ret = array.splice.apply(array, args);
1888 this._notifySplice(array, path, start, args.length - 2, ret);
1889 return ret;
1890 },
1891 shift: function (path) {
1892 var array = this.get(path);
1893 var args = Array.prototype.slice.call(arguments, 1);
1894 var ret = array.shift.apply(array, args);
1895 this._notifySplice(array, path, 0, 0, [ret]);
1896 return ret;
1897 },
1898 unshift: function (path) {
1899 var array = this.get(path);
1900 var args = Array.prototype.slice.call(arguments, 1);
1901 var ret = array.unshift.apply(array, args);
1902 this._notifySplice(array, path, 0, args.length, []);
1903 return ret;
1904 }
1905 });
1906 }());
1907 Polymer.Base._addFeature({
1908 resolveUrl: function (url) {
1909 var module = Polymer.DomModule.import(this.is);
1910 var root = '';
1911 if (module) {
1912 var assetPath = module.getAttribute('assetpath') || '';
1913 root = Polymer.ResolveUrl.resolveUrl(assetPath, module.ownerDocument.baseURI);
1914 }
1915 return Polymer.ResolveUrl.resolveUrl(url, root);
1916 }
1917 });
1918 Polymer.CssParse = function () {
1919 var api = {
1920 parse: function (text) {
1921 text = this._clean(text);
1922 return this._parseCss(this._lex(text), text);
1923 },
1924 _clean: function (cssText) {
1925 return cssText.replace(rx.comments, '').replace(rx.port, '');
1926 },
1927 _lex: function (text) {
1928 var root = {
1929 start: 0,
1930 end: text.length
1931 };
1932 var n = root;
1933 for (var i = 0, s = 0, l = text.length; i < l; i++) {
1934 switch (text[i]) {
1935 case this.OPEN_BRACE:
1936 if (!n.rules) {
1937 n.rules = [];
1938 }
1939 var p = n;
1940 var previous = p.rules[p.rules.length - 1];
1941 n = {
1942 start: i + 1,
1943 parent: p,
1944 previous: previous
1945 };
1946 p.rules.push(n);
1947 break;
1948 case this.CLOSE_BRACE:
1949 n.end = i + 1;
1950 n = n.parent || root;
1951 break;
1952 }
1953 }
1954 return root;
1955 },
1956 _parseCss: function (node, text) {
1957 var t = text.substring(node.start, node.end - 1);
1958 node.parsedCssText = node.cssText = t.trim();
1959 if (node.parent) {
1960 var ss = node.previous ? node.previous.end : node.parent.start;
1961 t = text.substring(ss, node.start - 1);
1962 t = t.substring(t.lastIndexOf(';') + 1);
1963 var s = node.parsedSelector = node.selector = t.trim();
1964 node.atRule = s.indexOf(AT_START) === 0;
1965 if (node.atRule) {
1966 if (s.indexOf(MEDIA_START) === 0) {
1967 node.type = this.types.MEDIA_RULE;
1968 } else if (s.match(rx.keyframesRule)) {
1969 node.type = this.types.KEYFRAMES_RULE;
1970 }
1971 } else {
1972 if (s.indexOf(VAR_START) === 0) {
1973 node.type = this.types.MIXIN_RULE;
1974 } else {
1975 node.type = this.types.STYLE_RULE;
1976 }
1977 }
1978 }
1979 var r$ = node.rules;
1980 if (r$) {
1981 for (var i = 0, l = r$.length, r; i < l && (r = r$[i]); i++) {
1982 this._parseCss(r, text);
1983 }
1984 }
1985 return node;
1986 },
1987 stringify: function (node, preserveProperties, text) {
1988 text = text || '';
1989 var cssText = '';
1990 if (node.cssText || node.rules) {
1991 var r$ = node.rules;
1992 if (r$ && (preserveProperties || !hasMixinRules(r$))) {
1993 for (var i = 0, l = r$.length, r; i < l && (r = r$[i]); i++) {
1994 cssText = this.stringify(r, preserveProperties, cssText);
1995 }
1996 } else {
1997 cssText = preserveProperties ? node.cssText : removeCustomProps(node.cssText);
1998 cssText = cssText.trim();
1999 if (cssText) {
2000 cssText = ' ' + cssText + '\n';
2001 }
2002 }
2003 }
2004 if (cssText) {
2005 if (node.selector) {
2006 text += node.selector + ' ' + this.OPEN_BRACE + '\n';
2007 }
2008 text += cssText;
2009 if (node.selector) {
2010 text += this.CLOSE_BRACE + '\n\n';
2011 }
2012 }
2013 return text;
2014 },
2015 types: {
2016 STYLE_RULE: 1,
2017 KEYFRAMES_RULE: 7,
2018 MEDIA_RULE: 4,
2019 MIXIN_RULE: 1000
2020 },
2021 OPEN_BRACE: '{',
2022 CLOSE_BRACE: '}'
2023 };
2024 function hasMixinRules(rules) {
2025 return rules[0].selector.indexOf(VAR_START) >= 0;
2026 }
2027 function removeCustomProps(cssText) {
2028 return cssText.replace(rx.customProp, '').replace(rx.mixinProp, '').replace(rx.m ixinApply, '').replace(rx.varApply, '');
2029 }
2030 var VAR_START = '--';
2031 var MEDIA_START = '@media';
2032 var AT_START = '@';
2033 var rx = {
2034 comments: /\/\*[^*]*\*+([^\/*][^*]*\*+)*\//gim,
2035 port: /@import[^;]*;/gim,
2036 customProp: /(?:^|[\s;])--[^;{]*?:[^{};]*?(?:[;\n]|$)/gim,
2037 mixinProp: /(?:^|[\s;])--[^;{]*?:[^{;]*?{[^}]*?}(?:[;\n]|$)?/gim,
2038 mixinApply: /@apply[\s]*\([^)]*?\)[\s]*(?:[;\n]|$)?/gim,
2039 varApply: /[^;:]*?:[^;]*var[^;]*(?:[;\n]|$)?/gim,
2040 keyframesRule: /^@[^\s]*keyframes/
2041 };
2042 return api;
2043 }();
2044 Polymer.StyleUtil = function () {
2045 return {
2046 MODULE_STYLES_SELECTOR: 'style, link[rel=import][type~=css]',
2047 toCssText: function (rules, callback, preserveProperties) {
2048 if (typeof rules === 'string') {
2049 rules = this.parser.parse(rules);
2050 }
2051 if (callback) {
2052 this.forEachStyleRule(rules, callback);
2053 }
2054 return this.parser.stringify(rules, preserveProperties);
2055 },
2056 forRulesInStyles: function (styles, callback) {
2057 if (styles) {
2058 for (var i = 0, l = styles.length, s; i < l && (s = styles[i]); i++) {
2059 this.forEachStyleRule(this.rulesForStyle(s), callback);
2060 }
2061 }
2062 },
2063 rulesForStyle: function (style) {
2064 if (!style.__cssRules && style.textContent) {
2065 style.__cssRules = this.parser.parse(style.textContent);
2066 }
2067 return style.__cssRules;
2068 },
2069 clearStyleRules: function (style) {
2070 style.__cssRules = null;
2071 },
2072 forEachStyleRule: function (node, callback) {
2073 var s = node.selector;
2074 var skipRules = false;
2075 if (node.type === this.ruleTypes.STYLE_RULE) {
2076 callback(node);
2077 } else if (node.type === this.ruleTypes.KEYFRAMES_RULE || node.type === this.rul eTypes.MIXIN_RULE) {
2078 skipRules = true;
2079 }
2080 var r$ = node.rules;
2081 if (r$ && !skipRules) {
2082 for (var i = 0, l = r$.length, r; i < l && (r = r$[i]); i++) {
2083 this.forEachStyleRule(r, callback);
2084 }
2085 }
2086 },
2087 applyCss: function (cssText, moniker, target, afterNode) {
2088 var style = document.createElement('style');
2089 if (moniker) {
2090 style.setAttribute('scope', moniker);
2091 }
2092 style.textContent = cssText;
2093 target = target || document.head;
2094 if (!afterNode) {
2095 var n$ = target.querySelectorAll('style[scope]');
2096 afterNode = n$[n$.length - 1];
2097 }
2098 target.insertBefore(style, afterNode && afterNode.nextSibling || target.firstChi ld);
2099 return style;
2100 },
2101 cssFromModule: function (moduleId) {
2102 var m = Polymer.DomModule.import(moduleId);
2103 if (m && !m._cssText) {
2104 var cssText = '';
2105 var e$ = Array.prototype.slice.call(m.querySelectorAll(this.MODULE_STYLES_SELECT OR));
2106 for (var i = 0, e; i < e$.length; i++) {
2107 e = e$[i];
2108 if (e.localName === 'style') {
2109 e = e.__appliedElement || e;
2110 e.parentNode.removeChild(e);
2111 } else {
2112 e = e.import && e.import.body;
2113 }
2114 if (e) {
2115 cssText += Polymer.ResolveUrl.resolveCss(e.textContent, e.ownerDocument);
2116 }
2117 }
2118 m._cssText = cssText;
2119 }
2120 return m && m._cssText || '';
2121 },
2122 parser: Polymer.CssParse,
2123 ruleTypes: Polymer.CssParse.types
2124 };
2125 }();
2126 Polymer.StyleTransformer = function () {
2127 var nativeShadow = Polymer.Settings.useNativeShadow;
2128 var styleUtil = Polymer.StyleUtil;
2129 var api = {
2130 dom: function (node, scope, useAttr, shouldRemoveScope) {
2131 this._transformDom(node, scope || '', useAttr, shouldRemoveScope);
2132 },
2133 _transformDom: function (node, selector, useAttr, shouldRemoveScope) {
2134 if (node.setAttribute) {
2135 this.element(node, selector, useAttr, shouldRemoveScope);
2136 }
2137 var c$ = Polymer.dom(node).childNodes;
2138 for (var i = 0; i < c$.length; i++) {
2139 this._transformDom(c$[i], selector, useAttr, shouldRemoveScope);
2140 }
2141 },
2142 element: function (element, scope, useAttr, shouldRemoveScope) {
2143 if (useAttr) {
2144 if (shouldRemoveScope) {
2145 element.removeAttribute(SCOPE_NAME);
2146 } else {
2147 element.setAttribute(SCOPE_NAME, scope);
2148 }
2149 } else {
2150 if (scope) {
2151 if (element.classList) {
2152 if (shouldRemoveScope) {
2153 element.classList.remove(SCOPE_NAME);
2154 element.classList.remove(scope);
2155 } else {
2156 element.classList.add(SCOPE_NAME);
2157 element.classList.add(scope);
2158 }
2159 } else if (element.getAttribute) {
2160 var c = element.getAttribute(CLASS);
2161 if (shouldRemoveScope) {
2162 if (c) {
2163 element.setAttribute(CLASS, c.replace(SCOPE_NAME, '').replace(scope, ''));
2164 }
2165 } else {
2166 element.setAttribute(CLASS, c + (c ? ' ' : '') + SCOPE_NAME + ' ' + scope);
2167 }
2168 }
2169 }
2170 }
2171 },
2172 elementStyles: function (element, callback) {
2173 var styles = element._styles;
2174 var cssText = '';
2175 for (var i = 0, l = styles.length, s, text; i < l && (s = styles[i]); i++) {
2176 var rules = styleUtil.rulesForStyle(s);
2177 cssText += nativeShadow ? styleUtil.toCssText(rules, callback) : this.css(rules, element.is, element.extends, callback, element._scopeCssViaAttr) + '\n\n';
2178 }
2179 return cssText.trim();
2180 },
2181 css: function (rules, scope, ext, callback, useAttr) {
2182 var hostScope = this._calcHostScope(scope, ext);
2183 scope = this._calcElementScope(scope, useAttr);
2184 var self = this;
2185 return styleUtil.toCssText(rules, function (rule) {
2186 if (!rule.isScoped) {
2187 self.rule(rule, scope, hostScope);
2188 rule.isScoped = true;
2189 }
2190 if (callback) {
2191 callback(rule, scope, hostScope);
2192 }
2193 });
2194 },
2195 _calcElementScope: function (scope, useAttr) {
2196 if (scope) {
2197 return useAttr ? CSS_ATTR_PREFIX + scope + CSS_ATTR_SUFFIX : CSS_CLASS_PREFIX + scope;
2198 } else {
2199 return '';
2200 }
2201 },
2202 _calcHostScope: function (scope, ext) {
2203 return ext ? '[is=' + scope + ']' : scope;
2204 },
2205 rule: function (rule, scope, hostScope) {
2206 this._transformRule(rule, this._transformComplexSelector, scope, hostScope);
2207 },
2208 _transformRule: function (rule, transformer, scope, hostScope) {
2209 var p$ = rule.selector.split(COMPLEX_SELECTOR_SEP);
2210 for (var i = 0, l = p$.length, p; i < l && (p = p$[i]); i++) {
2211 p$[i] = transformer.call(this, p, scope, hostScope);
2212 }
2213 rule.selector = p$.join(COMPLEX_SELECTOR_SEP);
2214 },
2215 _transformComplexSelector: function (selector, scope, hostScope) {
2216 var stop = false;
2217 var hostContext = false;
2218 var self = this;
2219 selector = selector.replace(SIMPLE_SELECTOR_SEP, function (m, c, s) {
2220 if (!stop) {
2221 var info = self._transformCompoundSelector(s, c, scope, hostScope);
2222 stop = stop || info.stop;
2223 hostContext = hostContext || info.hostContext;
2224 c = info.combinator;
2225 s = info.value;
2226 } else {
2227 s = s.replace(SCOPE_JUMP, ' ');
2228 }
2229 return c + s;
2230 });
2231 if (hostContext) {
2232 selector = selector.replace(HOST_CONTEXT_PAREN, function (m, pre, paren, post) {
2233 return pre + paren + ' ' + hostScope + post + COMPLEX_SELECTOR_SEP + ' ' + pre + hostScope + paren + post;
2234 });
2235 }
2236 return selector;
2237 },
2238 _transformCompoundSelector: function (selector, combinator, scope, hostScope) {
2239 var jumpIndex = selector.search(SCOPE_JUMP);
2240 var hostContext = false;
2241 if (selector.indexOf(HOST_CONTEXT) >= 0) {
2242 hostContext = true;
2243 } else if (selector.indexOf(HOST) >= 0) {
2244 selector = selector.replace(HOST_PAREN, function (m, host, paren) {
2245 return hostScope + paren;
2246 });
2247 selector = selector.replace(HOST, hostScope);
2248 } else if (jumpIndex !== 0) {
2249 selector = scope ? this._transformSimpleSelector(selector, scope) : selector;
2250 }
2251 if (selector.indexOf(CONTENT) >= 0) {
2252 combinator = '';
2253 }
2254 var stop;
2255 if (jumpIndex >= 0) {
2256 selector = selector.replace(SCOPE_JUMP, ' ');
2257 stop = true;
2258 }
2259 return {
2260 value: selector,
2261 combinator: combinator,
2262 stop: stop,
2263 hostContext: hostContext
2264 };
2265 },
2266 _transformSimpleSelector: function (selector, scope) {
2267 var p$ = selector.split(PSEUDO_PREFIX);
2268 p$[0] += scope;
2269 return p$.join(PSEUDO_PREFIX);
2270 },
2271 documentRule: function (rule) {
2272 rule.selector = rule.parsedSelector;
2273 this.normalizeRootSelector(rule);
2274 if (!nativeShadow) {
2275 this._transformRule(rule, this._transformDocumentSelector);
2276 }
2277 },
2278 normalizeRootSelector: function (rule) {
2279 if (rule.selector === ROOT) {
2280 rule.selector = 'body';
2281 }
2282 },
2283 _transformDocumentSelector: function (selector) {
2284 return selector.match(SCOPE_JUMP) ? this._transformComplexSelector(selector, SCO PE_DOC_SELECTOR) : this._transformSimpleSelector(selector.trim(), SCOPE_DOC_SELE CTOR);
2285 },
2286 SCOPE_NAME: 'style-scope'
2287 };
2288 var SCOPE_NAME = api.SCOPE_NAME;
2289 var SCOPE_DOC_SELECTOR = ':not([' + SCOPE_NAME + '])' + ':not(.' + SCOPE_NAME + ')';
2290 var COMPLEX_SELECTOR_SEP = ',';
2291 var SIMPLE_SELECTOR_SEP = /(^|[\s>+~]+)([^\s>+~]+)/g;
2292 var HOST = ':host';
2293 var ROOT = ':root';
2294 var HOST_PAREN = /(\:host)(?:\(((?:\([^)(]*\)|[^)(]*)+?)\))/g;
2295 var HOST_CONTEXT = ':host-context';
2296 var HOST_CONTEXT_PAREN = /(.*)(?:\:host-context)(?:\(((?:\([^)(]*\)|[^)(]*)+?)\) )(.*)/;
2297 var CONTENT = '::content';
2298 var SCOPE_JUMP = /\:\:content|\:\:shadow|\/deep\//;
2299 var CSS_CLASS_PREFIX = '.';
2300 var CSS_ATTR_PREFIX = '[' + SCOPE_NAME + '~=';
2301 var CSS_ATTR_SUFFIX = ']';
2302 var PSEUDO_PREFIX = ':';
2303 var CLASS = 'class';
2304 return api;
2305 }();
2306 Polymer.StyleExtends = function () {
2307 var styleUtil = Polymer.StyleUtil;
2308 return {
2309 hasExtends: function (cssText) {
2310 return Boolean(cssText.match(this.rx.EXTEND));
2311 },
2312 transform: function (style) {
2313 var rules = styleUtil.rulesForStyle(style);
2314 var self = this;
2315 styleUtil.forEachStyleRule(rules, function (rule) {
2316 var map = self._mapRule(rule);
2317 if (rule.parent) {
2318 var m;
2319 while (m = self.rx.EXTEND.exec(rule.cssText)) {
2320 var extend = m[1];
2321 var extendor = self._findExtendor(extend, rule);
2322 if (extendor) {
2323 self._extendRule(rule, extendor);
2324 }
2325 }
2326 }
2327 rule.cssText = rule.cssText.replace(self.rx.EXTEND, '');
2328 });
2329 return styleUtil.toCssText(rules, function (rule) {
2330 if (rule.selector.match(self.rx.STRIP)) {
2331 rule.cssText = '';
2332 }
2333 }, true);
2334 },
2335 _mapRule: function (rule) {
2336 if (rule.parent) {
2337 var map = rule.parent.map || (rule.parent.map = {});
2338 var parts = rule.selector.split(',');
2339 for (var i = 0, p; i < parts.length; i++) {
2340 p = parts[i];
2341 map[p.trim()] = rule;
2342 }
2343 return map;
2344 }
2345 },
2346 _findExtendor: function (extend, rule) {
2347 return rule.parent && rule.parent.map && rule.parent.map[extend] || this._findEx tendor(extend, rule.parent);
2348 },
2349 _extendRule: function (target, source) {
2350 if (target.parent !== source.parent) {
2351 this._cloneAndAddRuleToParent(source, target.parent);
2352 }
2353 target.extends = target.extends || (target.extends = []);
2354 target.extends.push(source);
2355 source.selector = source.selector.replace(this.rx.STRIP, '');
2356 source.selector = (source.selector && source.selector + ',\n') + target.selector ;
2357 if (source.extends) {
2358 source.extends.forEach(function (e) {
2359 this._extendRule(target, e);
2360 }, this);
2361 }
2362 },
2363 _cloneAndAddRuleToParent: function (rule, parent) {
2364 rule = Object.create(rule);
2365 rule.parent = parent;
2366 if (rule.extends) {
2367 rule.extends = rule.extends.slice();
2368 }
2369 parent.rules.push(rule);
2370 },
2371 rx: {
2372 EXTEND: /@extends\(([^)]*)\)\s*?;/gim,
2373 STRIP: /%[^,]*$/
2374 }
2375 };
2376 }();
2377 (function () {
2378 var prepElement = Polymer.Base._prepElement;
2379 var nativeShadow = Polymer.Settings.useNativeShadow;
2380 var styleUtil = Polymer.StyleUtil;
2381 var styleTransformer = Polymer.StyleTransformer;
2382 var styleExtends = Polymer.StyleExtends;
2383 Polymer.Base._addFeature({
2384 _prepElement: function (element) {
2385 if (this._encapsulateStyle) {
2386 styleTransformer.element(element, this.is, this._scopeCssViaAttr);
2387 }
2388 prepElement.call(this, element);
2389 },
2390 _prepStyles: function () {
2391 if (this._encapsulateStyle === undefined) {
2392 this._encapsulateStyle = !nativeShadow && Boolean(this._template);
2393 }
2394 this._styles = this._collectStyles();
2395 var cssText = styleTransformer.elementStyles(this);
2396 if (cssText && this._template) {
2397 var style = styleUtil.applyCss(cssText, this.is, nativeShadow ? this._template.c ontent : null);
2398 if (!nativeShadow) {
2399 this._scopeStyle = style;
2400 }
2401 }
2402 },
2403 _collectStyles: function () {
2404 var styles = [];
2405 var cssText = '', m$ = this.styleModules;
2406 if (m$) {
2407 for (var i = 0, l = m$.length, m; i < l && (m = m$[i]); i++) {
2408 cssText += styleUtil.cssFromModule(m);
2409 }
2410 }
2411 cssText += styleUtil.cssFromModule(this.is);
2412 if (cssText) {
2413 var style = document.createElement('style');
2414 style.textContent = cssText;
2415 if (styleExtends.hasExtends(style.textContent)) {
2416 cssText = styleExtends.transform(style);
2417 }
2418 styles.push(style);
2419 }
2420 return styles;
2421 },
2422 _elementAdd: function (node) {
2423 if (this._encapsulateStyle) {
2424 if (node.__styleScoped) {
2425 node.__styleScoped = false;
2426 } else {
2427 styleTransformer.dom(node, this.is, this._scopeCssViaAttr);
2428 }
2429 }
2430 },
2431 _elementRemove: function (node) {
2432 if (this._encapsulateStyle) {
2433 styleTransformer.dom(node, this.is, this._scopeCssViaAttr, true);
2434 }
2435 },
2436 scopeSubtree: function (container, shouldObserve) {
2437 if (nativeShadow) {
2438 return;
2439 }
2440 var self = this;
2441 var scopify = function (node) {
2442 if (node.nodeType === Node.ELEMENT_NODE) {
2443 node.className = self._scopeElementClass(node, node.className);
2444 var n$ = node.querySelectorAll('*');
2445 Array.prototype.forEach.call(n$, function (n) {
2446 n.className = self._scopeElementClass(n, n.className);
2447 });
2448 }
2449 };
2450 scopify(container);
2451 if (shouldObserve) {
2452 var mo = new MutationObserver(function (mxns) {
2453 mxns.forEach(function (m) {
2454 if (m.addedNodes) {
2455 for (var i = 0; i < m.addedNodes.length; i++) {
2456 scopify(m.addedNodes[i]);
2457 }
2458 }
2459 });
2460 });
2461 mo.observe(container, {
2462 childList: true,
2463 subtree: true
2464 });
2465 return mo;
2466 }
2467 }
2468 });
2469 }());
2470 Polymer.StyleProperties = function () {
2471 'use strict';
2472 var nativeShadow = Polymer.Settings.useNativeShadow;
2473 var matchesSelector = Polymer.DomApi.matchesSelector;
2474 var styleUtil = Polymer.StyleUtil;
2475 var styleTransformer = Polymer.StyleTransformer;
2476 return {
2477 decorateStyles: function (styles) {
2478 var self = this, props = {};
2479 styleUtil.forRulesInStyles(styles, function (rule) {
2480 self.decorateRule(rule);
2481 self.collectPropertiesInCssText(rule.propertyInfo.cssText, props);
2482 });
2483 var names = [];
2484 for (var i in props) {
2485 names.push(i);
2486 }
2487 return names;
2488 },
2489 decorateRule: function (rule) {
2490 if (rule.propertyInfo) {
2491 return rule.propertyInfo;
2492 }
2493 var info = {}, properties = {};
2494 var hasProperties = this.collectProperties(rule, properties);
2495 if (hasProperties) {
2496 info.properties = properties;
2497 rule.rules = null;
2498 }
2499 info.cssText = this.collectCssText(rule);
2500 rule.propertyInfo = info;
2501 return info;
2502 },
2503 collectProperties: function (rule, properties) {
2504 var info = rule.propertyInfo;
2505 if (info) {
2506 if (info.properties) {
2507 Polymer.Base.mixin(properties, info.properties);
2508 return true;
2509 }
2510 } else {
2511 var m, rx = this.rx.VAR_ASSIGN;
2512 var cssText = rule.parsedCssText;
2513 var any;
2514 while (m = rx.exec(cssText)) {
2515 properties[m[1]] = (m[2] || m[3]).trim();
2516 any = true;
2517 }
2518 return any;
2519 }
2520 },
2521 collectCssText: function (rule) {
2522 var customCssText = '';
2523 var cssText = rule.parsedCssText;
2524 cssText = cssText.replace(this.rx.BRACKETED, '').replace(this.rx.VAR_ASSIGN, '') ;
2525 var parts = cssText.split(';');
2526 for (var i = 0, p; i < parts.length; i++) {
2527 p = parts[i];
2528 if (p.match(this.rx.MIXIN_MATCH) || p.match(this.rx.VAR_MATCH)) {
2529 customCssText += p + ';\n';
2530 }
2531 }
2532 return customCssText;
2533 },
2534 collectPropertiesInCssText: function (cssText, props) {
2535 var m;
2536 while (m = this.rx.VAR_CAPTURE.exec(cssText)) {
2537 props[m[1]] = true;
2538 var def = m[2];
2539 if (def && def.match(this.rx.IS_VAR)) {
2540 props[def] = true;
2541 }
2542 }
2543 },
2544 reify: function (props) {
2545 var names = Object.getOwnPropertyNames(props);
2546 for (var i = 0, n; i < names.length; i++) {
2547 n = names[i];
2548 props[n] = this.valueForProperty(props[n], props);
2549 }
2550 },
2551 valueForProperty: function (property, props) {
2552 if (property) {
2553 if (property.indexOf(';') >= 0) {
2554 property = this.valueForProperties(property, props);
2555 } else {
2556 var self = this;
2557 var fn = function (all, prefix, value, fallback) {
2558 var propertyValue = self.valueForProperty(props[value], props) || (props[fallbac k] ? self.valueForProperty(props[fallback], props) : fallback);
2559 return prefix + (propertyValue || '');
2560 };
2561 property = property.replace(this.rx.VAR_MATCH, fn);
2562 }
2563 }
2564 return property && property.trim() || '';
2565 },
2566 valueForProperties: function (property, props) {
2567 var parts = property.split(';');
2568 for (var i = 0, p, m; i < parts.length && (p = parts[i]); i++) {
2569 m = p.match(this.rx.MIXIN_MATCH);
2570 if (m) {
2571 p = this.valueForProperty(props[m[1]], props);
2572 } else {
2573 var pp = p.split(':');
2574 if (pp[1]) {
2575 pp[1] = pp[1].trim();
2576 pp[1] = this.valueForProperty(pp[1], props) || pp[1];
2577 }
2578 p = pp.join(':');
2579 }
2580 parts[i] = p && p.lastIndexOf(';') === p.length - 1 ? p.slice(0, -1) : p || '';
2581 }
2582 return parts.join(';');
2583 },
2584 applyProperties: function (rule, props) {
2585 var output = '';
2586 if (!rule.propertyInfo) {
2587 this.decorateRule(rule);
2588 }
2589 if (rule.propertyInfo.cssText) {
2590 output = this.valueForProperties(rule.propertyInfo.cssText, props);
2591 }
2592 rule.cssText = output;
2593 },
2594 propertyDataFromStyles: function (styles, element) {
2595 var props = {}, self = this;
2596 var o = [], i = 0;
2597 styleUtil.forRulesInStyles(styles, function (rule) {
2598 if (!rule.propertyInfo) {
2599 self.decorateRule(rule);
2600 }
2601 if (element && rule.propertyInfo.properties && matchesSelector.call(element, rul e.selector)) {
2602 self.collectProperties(rule, props);
2603 addToBitMask(i, o);
2604 }
2605 i++;
2606 });
2607 return {
2608 properties: props,
2609 key: o
2610 };
2611 },
2612 scopePropertiesFromStyles: function (styles) {
2613 if (!styles._scopeStyleProperties) {
2614 styles._scopeStyleProperties = this.selectedPropertiesFromStyles(styles, this.SC OPE_SELECTORS);
2615 }
2616 return styles._scopeStyleProperties;
2617 },
2618 hostPropertiesFromStyles: function (styles) {
2619 if (!styles._hostStyleProperties) {
2620 styles._hostStyleProperties = this.selectedPropertiesFromStyles(styles, this.HOS T_SELECTORS);
2621 }
2622 return styles._hostStyleProperties;
2623 },
2624 selectedPropertiesFromStyles: function (styles, selectors) {
2625 var props = {}, self = this;
2626 styleUtil.forRulesInStyles(styles, function (rule) {
2627 if (!rule.propertyInfo) {
2628 self.decorateRule(rule);
2629 }
2630 for (var i = 0; i < selectors.length; i++) {
2631 if (rule.parsedSelector === selectors[i]) {
2632 self.collectProperties(rule, props);
2633 return;
2634 }
2635 }
2636 });
2637 return props;
2638 },
2639 transformStyles: function (element, properties, scopeSelector) {
2640 var self = this;
2641 var hostSelector = styleTransformer._calcHostScope(element.is, element.extends);
2642 var rxHostSelector = element.extends ? '\\' + hostSelector.slice(0, -1) + '\\]' : hostSelector;
2643 var hostRx = new RegExp(this.rx.HOST_PREFIX + rxHostSelector + this.rx.HOST_SUFF IX);
2644 return styleTransformer.elementStyles(element, function (rule) {
2645 self.applyProperties(rule, properties);
2646 if (rule.cssText && !nativeShadow) {
2647 self._scopeSelector(rule, hostRx, hostSelector, element._scopeCssViaAttr, scopeS elector);
2648 }
2649 });
2650 },
2651 _scopeSelector: function (rule, hostRx, hostSelector, viaAttr, scopeId) {
2652 rule.transformedSelector = rule.transformedSelector || rule.selector;
2653 var selector = rule.transformedSelector;
2654 var scope = viaAttr ? '[' + styleTransformer.SCOPE_NAME + '~=' + scopeId + ']' : '.' + scopeId;
2655 var parts = selector.split(',');
2656 for (var i = 0, l = parts.length, p; i < l && (p = parts[i]); i++) {
2657 parts[i] = p.match(hostRx) ? p.replace(hostSelector, hostSelector + scope) : sco pe + ' ' + p;
2658 }
2659 rule.selector = parts.join(',');
2660 },
2661 applyElementScopeSelector: function (element, selector, old, viaAttr) {
2662 var c = viaAttr ? element.getAttribute(styleTransformer.SCOPE_NAME) : element.cl assName;
2663 var v = old ? c.replace(old, selector) : (c ? c + ' ' : '') + this.XSCOPE_NAME + ' ' + selector;
2664 if (c !== v) {
2665 if (viaAttr) {
2666 element.setAttribute(styleTransformer.SCOPE_NAME, v);
2667 } else {
2668 element.className = v;
2669 }
2670 }
2671 },
2672 applyElementStyle: function (element, properties, selector, style) {
2673 var cssText = style ? style.textContent || '' : this.transformStyles(element, pr operties, selector);
2674 var s = element._customStyle;
2675 if (s && !nativeShadow && s !== style) {
2676 s._useCount--;
2677 if (s._useCount <= 0 && s.parentNode) {
2678 s.parentNode.removeChild(s);
2679 }
2680 }
2681 if (nativeShadow || (!style || !style.parentNode)) {
2682 if (nativeShadow && element._customStyle) {
2683 element._customStyle.textContent = cssText;
2684 style = element._customStyle;
2685 } else if (cssText) {
2686 style = styleUtil.applyCss(cssText, selector, nativeShadow ? element.root : null , element._scopeStyle);
2687 }
2688 }
2689 if (style) {
2690 style._useCount = style._useCount || 0;
2691 if (element._customStyle != style) {
2692 style._useCount++;
2693 }
2694 element._customStyle = style;
2695 }
2696 return style;
2697 },
2698 mixinCustomStyle: function (props, customStyle) {
2699 var v;
2700 for (var i in customStyle) {
2701 v = customStyle[i];
2702 if (v || v === 0) {
2703 props[i] = v;
2704 }
2705 }
2706 },
2707 rx: {
2708 VAR_ASSIGN: /(?:^|[;\n]\s*)(--[\w-]*?):\s*(?:([^;{]*)|{([^}]*)})(?:(?=[;\n])|$)/ gi,
2709 MIXIN_MATCH: /(?:^|\W+)@apply[\s]*\(([^)]*)\)/i,
2710 VAR_MATCH: /(^|\W+)var\([\s]*([^,)]*)[\s]*,?[\s]*((?:[^,)]*)|(?:[^;]*\([^;)]*\)) )[\s]*?\)/gi,
2711 VAR_CAPTURE: /\([\s]*(--[^,\s)]*)(?:,[\s]*(--[^,\s)]*))?(?:\)|,)/gi,
2712 IS_VAR: /^--/,
2713 BRACKETED: /\{[^}]*\}/g,
2714 HOST_PREFIX: '(?:^|[^.#[:])',
2715 HOST_SUFFIX: '($|[.:[\\s>+~])'
2716 },
2717 HOST_SELECTORS: [':host'],
2718 SCOPE_SELECTORS: [':root'],
2719 XSCOPE_NAME: 'x-scope'
2720 };
2721 function addToBitMask(n, bits) {
2722 var o = parseInt(n / 32);
2723 var v = 1 << n % 32;
2724 bits[o] = (bits[o] || 0) | v;
2725 }
2726 }();
2727 (function () {
2728 Polymer.StyleCache = function () {
2729 this.cache = {};
2730 };
2731 Polymer.StyleCache.prototype = {
2732 MAX: 100,
2733 store: function (is, data, keyValues, keyStyles) {
2734 data.keyValues = keyValues;
2735 data.styles = keyStyles;
2736 var s$ = this.cache[is] = this.cache[is] || [];
2737 s$.push(data);
2738 if (s$.length > this.MAX) {
2739 s$.shift();
2740 }
2741 },
2742 retrieve: function (is, keyValues, keyStyles) {
2743 var cache = this.cache[is];
2744 if (cache) {
2745 for (var i = cache.length - 1, data; i >= 0; i--) {
2746 data = cache[i];
2747 if (keyStyles === data.styles && this._objectsEqual(keyValues, data.keyValues)) {
2748 return data;
2749 }
2750 }
2751 }
2752 },
2753 clear: function () {
2754 this.cache = {};
2755 },
2756 _objectsEqual: function (target, source) {
2757 var t, s;
2758 for (var i in target) {
2759 t = target[i], s = source[i];
2760 if (!(typeof t === 'object' && t ? this._objectsStrictlyEqual(t, s) : t === s)) {
2761 return false;
2762 }
2763 }
2764 if (Array.isArray(target)) {
2765 return target.length === source.length;
2766 }
2767 return true;
2768 },
2769 _objectsStrictlyEqual: function (target, source) {
2770 return this._objectsEqual(target, source) && this._objectsEqual(source, target);
2771 }
2772 };
2773 }());
2774 Polymer.StyleDefaults = function () {
2775 var styleProperties = Polymer.StyleProperties;
2776 var styleUtil = Polymer.StyleUtil;
2777 var StyleCache = Polymer.StyleCache;
2778 var api = {
2779 _styles: [],
2780 _properties: null,
2781 customStyle: {},
2782 _styleCache: new StyleCache(),
2783 addStyle: function (style) {
2784 this._styles.push(style);
2785 this._properties = null;
2786 },
2787 get _styleProperties() {
2788 if (!this._properties) {
2789 styleProperties.decorateStyles(this._styles);
2790 this._styles._scopeStyleProperties = null;
2791 this._properties = styleProperties.scopePropertiesFromStyles(this._styles);
2792 styleProperties.mixinCustomStyle(this._properties, this.customStyle);
2793 styleProperties.reify(this._properties);
2794 }
2795 return this._properties;
2796 },
2797 _needsStyleProperties: function () {
2798 },
2799 _computeStyleProperties: function () {
2800 return this._styleProperties;
2801 },
2802 updateStyles: function (properties) {
2803 this._properties = null;
2804 if (properties) {
2805 Polymer.Base.mixin(this.customStyle, properties);
2806 }
2807 this._styleCache.clear();
2808 for (var i = 0, s; i < this._styles.length; i++) {
2809 s = this._styles[i];
2810 s = s.__importElement || s;
2811 s._apply();
2812 }
2813 }
2814 };
2815 return api;
2816 }();
2817 (function () {
2818 'use strict';
2819 var serializeValueToAttribute = Polymer.Base.serializeValueToAttribute;
2820 var propertyUtils = Polymer.StyleProperties;
2821 var styleTransformer = Polymer.StyleTransformer;
2822 var styleUtil = Polymer.StyleUtil;
2823 var styleDefaults = Polymer.StyleDefaults;
2824 var nativeShadow = Polymer.Settings.useNativeShadow;
2825 Polymer.Base._addFeature({
2826 _prepStyleProperties: function () {
2827 this._ownStylePropertyNames = this._styles ? propertyUtils.decorateStyles(this._ styles) : [];
2828 },
2829 _setupStyleProperties: function () {
2830 this.customStyle = {};
2831 },
2832 _needsStyleProperties: function () {
2833 return Boolean(this._ownStylePropertyNames && this._ownStylePropertyNames.length );
2834 },
2835 _beforeAttached: function () {
2836 if (!this._scopeSelector && this._needsStyleProperties()) {
2837 this._updateStyleProperties();
2838 }
2839 },
2840 _findStyleHost: function () {
2841 var e = this, root;
2842 while (root = Polymer.dom(e).getOwnerRoot()) {
2843 if (Polymer.isInstance(root.host)) {
2844 return root.host;
2845 }
2846 e = root.host;
2847 }
2848 return styleDefaults;
2849 },
2850 _updateStyleProperties: function () {
2851 var info, scope = this._findStyleHost();
2852 if (!scope._styleCache) {
2853 scope._styleCache = new Polymer.StyleCache();
2854 }
2855 var scopeData = propertyUtils.propertyDataFromStyles(scope._styles, this);
2856 scopeData.key.customStyle = this.customStyle;
2857 info = scope._styleCache.retrieve(this.is, scopeData.key, this._styles);
2858 var scopeCached = Boolean(info);
2859 if (scopeCached) {
2860 this._styleProperties = info._styleProperties;
2861 } else {
2862 this._computeStyleProperties(scopeData.properties);
2863 }
2864 this._computeOwnStyleProperties();
2865 if (!scopeCached) {
2866 info = styleCache.retrieve(this.is, this._ownStyleProperties, this._styles);
2867 }
2868 var globalCached = Boolean(info) && !scopeCached;
2869 var style = this._applyStyleProperties(info);
2870 if (!scopeCached) {
2871 style = style && nativeShadow ? style.cloneNode(true) : style;
2872 info = {
2873 style: style,
2874 _scopeSelector: this._scopeSelector,
2875 _styleProperties: this._styleProperties
2876 };
2877 scopeData.key.customStyle = {};
2878 this.mixin(scopeData.key.customStyle, this.customStyle);
2879 scope._styleCache.store(this.is, info, scopeData.key, this._styles);
2880 if (!globalCached) {
2881 styleCache.store(this.is, Object.create(info), this._ownStyleProperties, this._s tyles);
2882 }
2883 }
2884 },
2885 _computeStyleProperties: function (scopeProps) {
2886 var scope = this._findStyleHost();
2887 if (!scope._styleProperties) {
2888 scope._computeStyleProperties();
2889 }
2890 var props = Object.create(scope._styleProperties);
2891 this.mixin(props, propertyUtils.hostPropertiesFromStyles(this._styles));
2892 scopeProps = scopeProps || propertyUtils.propertyDataFromStyles(scope._styles, t his).properties;
2893 this.mixin(props, scopeProps);
2894 this.mixin(props, propertyUtils.scopePropertiesFromStyles(this._styles));
2895 propertyUtils.mixinCustomStyle(props, this.customStyle);
2896 propertyUtils.reify(props);
2897 this._styleProperties = props;
2898 },
2899 _computeOwnStyleProperties: function () {
2900 var props = {};
2901 for (var i = 0, n; i < this._ownStylePropertyNames.length; i++) {
2902 n = this._ownStylePropertyNames[i];
2903 props[n] = this._styleProperties[n];
2904 }
2905 this._ownStyleProperties = props;
2906 },
2907 _scopeCount: 0,
2908 _applyStyleProperties: function (info) {
2909 var oldScopeSelector = this._scopeSelector;
2910 this._scopeSelector = info ? info._scopeSelector : this.is + '-' + this.__proto_ _._scopeCount++;
2911 var style = propertyUtils.applyElementStyle(this, this._styleProperties, this._s copeSelector, info && info.style);
2912 if (!nativeShadow) {
2913 propertyUtils.applyElementScopeSelector(this, this._scopeSelector, oldScopeSelec tor, this._scopeCssViaAttr);
2914 }
2915 return style;
2916 },
2917 serializeValueToAttribute: function (value, attribute, node) {
2918 node = node || this;
2919 if (attribute === 'class' && !nativeShadow) {
2920 var host = node === this ? this.domHost || this.dataHost : this;
2921 if (host) {
2922 value = host._scopeElementClass(node, value);
2923 }
2924 }
2925 node = Polymer.dom(node);
2926 serializeValueToAttribute.call(this, value, attribute, node);
2927 },
2928 _scopeElementClass: function (element, selector) {
2929 if (!nativeShadow && !this._scopeCssViaAttr) {
2930 selector += (selector ? ' ' : '') + SCOPE_NAME + ' ' + this.is + (element._scope Selector ? ' ' + XSCOPE_NAME + ' ' + element._scopeSelector : '');
2931 }
2932 return selector;
2933 },
2934 updateStyles: function (properties) {
2935 if (this.isAttached) {
2936 if (properties) {
2937 this.mixin(this.customStyle, properties);
2938 }
2939 if (this._needsStyleProperties()) {
2940 this._updateStyleProperties();
2941 } else {
2942 this._styleProperties = null;
2943 }
2944 if (this._styleCache) {
2945 this._styleCache.clear();
2946 }
2947 this._updateRootStyles();
2948 }
2949 },
2950 _updateRootStyles: function (root) {
2951 root = root || this.root;
2952 var c$ = Polymer.dom(root)._query(function (e) {
2953 return e.shadyRoot || e.shadowRoot;
2954 });
2955 for (var i = 0, l = c$.length, c; i < l && (c = c$[i]); i++) {
2956 if (c.updateStyles) {
2957 c.updateStyles();
2958 }
2959 }
2960 }
2961 });
2962 Polymer.updateStyles = function (properties) {
2963 styleDefaults.updateStyles(properties);
2964 Polymer.Base._updateRootStyles(document);
2965 };
2966 var styleCache = new Polymer.StyleCache();
2967 Polymer.customStyleCache = styleCache;
2968 var SCOPE_NAME = styleTransformer.SCOPE_NAME;
2969 var XSCOPE_NAME = propertyUtils.XSCOPE_NAME;
2970 }());
2971 Polymer.Base._addFeature({
2972 _registerFeatures: function () {
2973 this._prepIs();
2974 this._prepAttributes();
2975 this._prepConstructor();
2976 this._prepTemplate();
2977 this._prepStyles();
2978 this._prepStyleProperties();
2979 this._prepAnnotations();
2980 this._prepEffects();
2981 this._prepBehaviors();
2982 this._prepBindings();
2983 this._prepShady();
2984 },
2985 _prepBehavior: function (b) {
2986 this._addPropertyEffects(b.properties);
2987 this._addComplexObserverEffects(b.observers);
2988 this._addHostAttributes(b.hostAttributes);
2989 },
2990 _initFeatures: function () {
2991 this._poolContent();
2992 this._setupConfigure();
2993 this._setupStyleProperties();
2994 this._pushHost();
2995 this._stampTemplate();
2996 this._popHost();
2997 this._marshalAnnotationReferences();
2998 this._marshalHostAttributes();
2999 this._setupDebouncers();
3000 this._marshalInstanceEffects();
3001 this._marshalBehaviors();
3002 this._marshalAttributes();
3003 this._tryReady();
3004 },
3005 _marshalBehavior: function (b) {
3006 this._listenListeners(b.listeners);
3007 }
3008 });
3009 (function () {
3010 var nativeShadow = Polymer.Settings.useNativeShadow;
3011 var propertyUtils = Polymer.StyleProperties;
3012 var styleUtil = Polymer.StyleUtil;
3013 var styleDefaults = Polymer.StyleDefaults;
3014 var styleTransformer = Polymer.StyleTransformer;
3015 Polymer({
3016 is: 'custom-style',
3017 extends: 'style',
3018 created: function () {
3019 this._tryApply();
3020 },
3021 attached: function () {
3022 this._tryApply();
3023 },
3024 _tryApply: function () {
3025 if (!this._appliesToDocument) {
3026 if (this.parentNode && this.parentNode.localName !== 'dom-module') {
3027 this._appliesToDocument = true;
3028 var e = this.__appliedElement || this;
3029 styleDefaults.addStyle(e);
3030 if (e.textContent) {
3031 this._apply();
3032 } else {
3033 var observer = new MutationObserver(function () {
3034 observer.disconnect();
3035 this._apply();
3036 }.bind(this));
3037 observer.observe(e, { childList: true });
3038 }
3039 }
3040 }
3041 },
3042 _apply: function () {
3043 var e = this.__appliedElement || this;
3044 this._computeStyleProperties();
3045 var props = this._styleProperties;
3046 var self = this;
3047 e.textContent = styleUtil.toCssText(styleUtil.rulesForStyle(e), function (rule) {
3048 var css = rule.cssText = rule.parsedCssText;
3049 if (rule.propertyInfo && rule.propertyInfo.cssText) {
3050 css = css.replace(propertyUtils.rx.VAR_ASSIGN, '');
3051 rule.cssText = propertyUtils.valueForProperties(css, props);
3052 }
3053 styleTransformer.documentRule(rule);
3054 });
3055 }
3056 });
3057 }());
3058 Polymer.Templatizer = {
3059 properties: { __hideTemplateChildren__: { observer: '_showHideChildren' } },
3060 _templatizerStatic: {
3061 count: 0,
3062 callbacks: {},
3063 debouncer: null
3064 },
3065 _instanceProps: Polymer.nob,
3066 created: function () {
3067 this._templatizerId = this._templatizerStatic.count++;
3068 },
3069 templatize: function (template) {
3070 if (!template._content) {
3071 template._content = template.content;
3072 }
3073 if (template._content._ctor) {
3074 this.ctor = template._content._ctor;
3075 this._prepParentProperties(this.ctor.prototype, template);
3076 return;
3077 }
3078 var archetype = Object.create(Polymer.Base);
3079 this._customPrepAnnotations(archetype, template);
3080 archetype._prepEffects();
3081 this._customPrepEffects(archetype);
3082 archetype._prepBehaviors();
3083 archetype._prepBindings();
3084 this._prepParentProperties(archetype, template);
3085 archetype._notifyPath = this._notifyPathImpl;
3086 archetype._scopeElementClass = this._scopeElementClassImpl;
3087 archetype.listen = this._listenImpl;
3088 archetype._showHideChildren = this._showHideChildrenImpl;
3089 var _constructor = this._constructorImpl;
3090 var ctor = function TemplateInstance(model, host) {
3091 _constructor.call(this, model, host);
3092 };
3093 ctor.prototype = archetype;
3094 archetype.constructor = ctor;
3095 template._content._ctor = ctor;
3096 this.ctor = ctor;
3097 },
3098 _getRootDataHost: function () {
3099 return this.dataHost && this.dataHost._rootDataHost || this.dataHost;
3100 },
3101 _showHideChildrenImpl: function (hide) {
3102 var c = this._children;
3103 for (var i = 0; i < c.length; i++) {
3104 var n = c[i];
3105 if (n.style) {
3106 n.style.display = hide ? 'none' : '';
3107 n.__hideTemplateChildren__ = hide;
3108 }
3109 }
3110 },
3111 _debounceTemplate: function (fn) {
3112 this._templatizerStatic.callbacks[this._templatizerId] = fn.bind(this);
3113 this._templatizerStatic.debouncer = Polymer.Debounce(this._templatizerStatic.deb ouncer, this._flushTemplates.bind(this, true));
3114 },
3115 _flushTemplates: function (debouncerExpired) {
3116 var db = this._templatizerStatic.debouncer;
3117 while (debouncerExpired || db && db.finish) {
3118 db.stop();
3119 var cbs = this._templatizerStatic.callbacks;
3120 this._templatizerStatic.callbacks = {};
3121 for (var id in cbs) {
3122 cbs[id]();
3123 }
3124 debouncerExpired = false;
3125 }
3126 },
3127 _customPrepEffects: function (archetype) {
3128 var parentProps = archetype._parentProps;
3129 for (var prop in parentProps) {
3130 archetype._addPropertyEffect(prop, 'function', this._createHostPropEffector(prop ));
3131 }
3132 for (var prop in this._instanceProps) {
3133 archetype._addPropertyEffect(prop, 'function', this._createInstancePropEffector( prop));
3134 }
3135 },
3136 _customPrepAnnotations: function (archetype, template) {
3137 archetype._template = template;
3138 var c = template._content;
3139 if (!c._notes) {
3140 var rootDataHost = archetype._rootDataHost;
3141 if (rootDataHost) {
3142 Polymer.Annotations.prepElement = rootDataHost._prepElement.bind(rootDataHost);
3143 }
3144 c._notes = Polymer.Annotations.parseAnnotations(template);
3145 Polymer.Annotations.prepElement = null;
3146 this._processAnnotations(c._notes);
3147 }
3148 archetype._notes = c._notes;
3149 archetype._parentProps = c._parentProps;
3150 },
3151 _prepParentProperties: function (archetype, template) {
3152 var parentProps = this._parentProps = archetype._parentProps;
3153 if (this._forwardParentProp && parentProps) {
3154 var proto = archetype._parentPropProto;
3155 var prop;
3156 if (!proto) {
3157 for (prop in this._instanceProps) {
3158 delete parentProps[prop];
3159 }
3160 proto = archetype._parentPropProto = Object.create(null);
3161 if (template != this) {
3162 Polymer.Bind.prepareModel(proto);
3163 }
3164 for (prop in parentProps) {
3165 var parentProp = '_parent_' + prop;
3166 var effects = [
3167 {
3168 kind: 'function',
3169 effect: this._createForwardPropEffector(prop)
3170 },
3171 { kind: 'notify' }
3172 ];
3173 Polymer.Bind._createAccessors(proto, parentProp, effects);
3174 }
3175 }
3176 if (template != this) {
3177 Polymer.Bind.prepareInstance(template);
3178 template._forwardParentProp = this._forwardParentProp.bind(this);
3179 }
3180 this._extendTemplate(template, proto);
3181 }
3182 },
3183 _createForwardPropEffector: function (prop) {
3184 return function (source, value) {
3185 this._forwardParentProp(prop, value);
3186 };
3187 },
3188 _createHostPropEffector: function (prop) {
3189 return function (source, value) {
3190 this.dataHost['_parent_' + prop] = value;
3191 };
3192 },
3193 _createInstancePropEffector: function (prop) {
3194 return function (source, value, old, fromAbove) {
3195 if (!fromAbove) {
3196 this.dataHost._forwardInstanceProp(this, prop, value);
3197 }
3198 };
3199 },
3200 _extendTemplate: function (template, proto) {
3201 Object.getOwnPropertyNames(proto).forEach(function (n) {
3202 var val = template[n];
3203 var pd = Object.getOwnPropertyDescriptor(proto, n);
3204 Object.defineProperty(template, n, pd);
3205 if (val !== undefined) {
3206 template._propertySetter(n, val);
3207 }
3208 });
3209 },
3210 _showHideChildren: function (hidden) {
3211 },
3212 _forwardInstancePath: function (inst, path, value) {
3213 },
3214 _forwardInstanceProp: function (inst, prop, value) {
3215 },
3216 _notifyPathImpl: function (path, value) {
3217 var dataHost = this.dataHost;
3218 var dot = path.indexOf('.');
3219 var root = dot < 0 ? path : path.slice(0, dot);
3220 dataHost._forwardInstancePath.call(dataHost, this, path, value);
3221 if (root in dataHost._parentProps) {
3222 dataHost.notifyPath('_parent_' + path, value);
3223 }
3224 },
3225 _pathEffector: function (path, value, fromAbove) {
3226 if (this._forwardParentPath) {
3227 if (path.indexOf('_parent_') === 0) {
3228 this._forwardParentPath(path.substring(8), value);
3229 }
3230 }
3231 Polymer.Base._pathEffector.apply(this, arguments);
3232 },
3233 _constructorImpl: function (model, host) {
3234 this._rootDataHost = host._getRootDataHost();
3235 this._setupConfigure(model);
3236 this._pushHost(host);
3237 this.root = this.instanceTemplate(this._template);
3238 this.root.__noContent = !this._notes._hasContent;
3239 this.root.__styleScoped = true;
3240 this._popHost();
3241 this._marshalAnnotatedNodes();
3242 this._marshalInstanceEffects();
3243 this._marshalAnnotatedListeners();
3244 var children = [];
3245 for (var n = this.root.firstChild; n; n = n.nextSibling) {
3246 children.push(n);
3247 n._templateInstance = this;
3248 }
3249 this._children = children;
3250 if (host.__hideTemplateChildren__) {
3251 this._showHideChildren(true);
3252 }
3253 this._tryReady();
3254 },
3255 _listenImpl: function (node, eventName, methodName) {
3256 var model = this;
3257 var host = this._rootDataHost;
3258 var handler = host._createEventHandler(node, eventName, methodName);
3259 var decorated = function (e) {
3260 e.model = model;
3261 handler(e);
3262 };
3263 host._listen(node, eventName, decorated);
3264 },
3265 _scopeElementClassImpl: function (node, value) {
3266 var host = this._rootDataHost;
3267 if (host) {
3268 return host._scopeElementClass(node, value);
3269 }
3270 },
3271 stamp: function (model) {
3272 model = model || {};
3273 if (this._parentProps) {
3274 for (var prop in this._parentProps) {
3275 model[prop] = this['_parent_' + prop];
3276 }
3277 }
3278 return new this.ctor(model, this);
3279 },
3280 modelForElement: function (el) {
3281 var model;
3282 while (el) {
3283 if (model = el._templateInstance) {
3284 if (model.dataHost != this) {
3285 el = model.dataHost;
3286 } else {
3287 return model;
3288 }
3289 } else {
3290 el = el.parentNode;
3291 }
3292 }
3293 }
3294 };
3295 Polymer({
3296 is: 'dom-template',
3297 extends: 'template',
3298 behaviors: [Polymer.Templatizer],
3299 ready: function () {
3300 this.templatize(this);
3301 }
3302 });
3303 Polymer._collections = new WeakMap();
3304 Polymer.Collection = function (userArray) {
3305 Polymer._collections.set(userArray, this);
3306 this.userArray = userArray;
3307 this.store = userArray.slice();
3308 this.initMap();
3309 };
3310 Polymer.Collection.prototype = {
3311 constructor: Polymer.Collection,
3312 initMap: function () {
3313 var omap = this.omap = new WeakMap();
3314 var pmap = this.pmap = {};
3315 var s = this.store;
3316 for (var i = 0; i < s.length; i++) {
3317 var item = s[i];
3318 if (item && typeof item == 'object') {
3319 omap.set(item, i);
3320 } else {
3321 pmap[item] = i;
3322 }
3323 }
3324 },
3325 add: function (item) {
3326 var key = this.store.push(item) - 1;
3327 if (item && typeof item == 'object') {
3328 this.omap.set(item, key);
3329 } else {
3330 this.pmap[item] = key;
3331 }
3332 return key;
3333 },
3334 removeKey: function (key) {
3335 this._removeFromMap(this.store[key]);
3336 delete this.store[key];
3337 },
3338 _removeFromMap: function (item) {
3339 if (item && typeof item == 'object') {
3340 this.omap.delete(item);
3341 } else {
3342 delete this.pmap[item];
3343 }
3344 },
3345 remove: function (item) {
3346 var key = this.getKey(item);
3347 this.removeKey(key);
3348 return key;
3349 },
3350 getKey: function (item) {
3351 if (item && typeof item == 'object') {
3352 return this.omap.get(item);
3353 } else {
3354 return this.pmap[item];
3355 }
3356 },
3357 getKeys: function () {
3358 return Object.keys(this.store);
3359 },
3360 setItem: function (key, item) {
3361 var old = this.store[key];
3362 if (old) {
3363 this._removeFromMap(old);
3364 }
3365 if (item && typeof item == 'object') {
3366 this.omap.set(item, key);
3367 } else {
3368 this.pmap[item] = key;
3369 }
3370 this.store[key] = item;
3371 },
3372 getItem: function (key) {
3373 return this.store[key];
3374 },
3375 getItems: function () {
3376 var items = [], store = this.store;
3377 for (var key in store) {
3378 items.push(store[key]);
3379 }
3380 return items;
3381 },
3382 _applySplices: function (splices) {
3383 var keySplices = [];
3384 for (var i = 0; i < splices.length; i++) {
3385 var j, o, key, s = splices[i];
3386 var removed = [];
3387 for (j = 0; j < s.removed.length; j++) {
3388 o = s.removed[j];
3389 key = this.remove(o);
3390 removed.push(key);
3391 }
3392 var added = [];
3393 for (j = 0; j < s.addedCount; j++) {
3394 o = this.userArray[s.index + j];
3395 key = this.add(o);
3396 added.push(key);
3397 }
3398 keySplices.push({
3399 index: s.index,
3400 removed: removed,
3401 removedItems: s.removed,
3402 added: added
3403 });
3404 }
3405 return keySplices;
3406 }
3407 };
3408 Polymer.Collection.get = function (userArray) {
3409 return Polymer._collections.get(userArray) || new Polymer.Collection(userArray);
3410 };
3411 Polymer.Collection.applySplices = function (userArray, splices) {
3412 var coll = Polymer._collections.get(userArray);
3413 return coll ? coll._applySplices(splices) : null;
3414 };
3415 Polymer({
3416 is: 'dom-repeat',
3417 extends: 'template',
3418 properties: {
3419 items: { type: Array },
3420 as: {
3421 type: String,
3422 value: 'item'
3423 },
3424 indexAs: {
3425 type: String,
3426 value: 'index'
3427 },
3428 sort: {
3429 type: Function,
3430 observer: '_sortChanged'
3431 },
3432 filter: {
3433 type: Function,
3434 observer: '_filterChanged'
3435 },
3436 observe: {
3437 type: String,
3438 observer: '_observeChanged'
3439 },
3440 delay: Number
3441 },
3442 behaviors: [Polymer.Templatizer],
3443 observers: ['_itemsChanged(items.*)'],
3444 created: function () {
3445 this._instances = [];
3446 },
3447 detached: function () {
3448 for (var i = 0; i < this._instances.length; i++) {
3449 this._detachRow(i);
3450 }
3451 },
3452 attached: function () {
3453 var parentNode = Polymer.dom(this).parentNode;
3454 for (var i = 0; i < this._instances.length; i++) {
3455 Polymer.dom(parentNode).insertBefore(this._instances[i].root, this);
3456 }
3457 },
3458 ready: function () {
3459 this._instanceProps = { __key__: true };
3460 this._instanceProps[this.as] = true;
3461 this._instanceProps[this.indexAs] = true;
3462 if (!this.ctor) {
3463 this.templatize(this);
3464 }
3465 },
3466 _sortChanged: function () {
3467 var dataHost = this._getRootDataHost();
3468 var sort = this.sort;
3469 this._sortFn = sort && (typeof sort == 'function' ? sort : function () {
3470 return dataHost[sort].apply(dataHost, arguments);
3471 });
3472 this._needFullRefresh = true;
3473 if (this.items) {
3474 this._debounceTemplate(this._render);
3475 }
3476 },
3477 _filterChanged: function () {
3478 var dataHost = this._getRootDataHost();
3479 var filter = this.filter;
3480 this._filterFn = filter && (typeof filter == 'function' ? filter : function () {
3481 return dataHost[filter].apply(dataHost, arguments);
3482 });
3483 this._needFullRefresh = true;
3484 if (this.items) {
3485 this._debounceTemplate(this._render);
3486 }
3487 },
3488 _observeChanged: function () {
3489 this._observePaths = this.observe && this.observe.replace('.*', '.').split(' ');
3490 },
3491 _itemsChanged: function (change) {
3492 if (change.path == 'items') {
3493 if (Array.isArray(this.items)) {
3494 this.collection = Polymer.Collection.get(this.items);
3495 } else if (!this.items) {
3496 this.collection = null;
3497 } else {
3498 this._error(this._logf('dom-repeat', 'expected array for `items`,' + ' found', t his.items));
3499 }
3500 this._splices = [];
3501 this._needFullRefresh = true;
3502 this._debounceTemplate(this._render);
3503 } else if (change.path == 'items.splices') {
3504 this._splices = this._splices.concat(change.value.keySplices);
3505 this._debounceTemplate(this._render);
3506 } else {
3507 var subpath = change.path.slice(6);
3508 this._forwardItemPath(subpath, change.value);
3509 this._checkObservedPaths(subpath);
3510 }
3511 },
3512 _checkObservedPaths: function (path) {
3513 if (this._observePaths) {
3514 path = path.substring(path.indexOf('.') + 1);
3515 var paths = this._observePaths;
3516 for (var i = 0; i < paths.length; i++) {
3517 if (path.indexOf(paths[i]) === 0) {
3518 this._needFullRefresh = true;
3519 if (this.delay) {
3520 this.debounce('render', this._render, this.delay);
3521 } else {
3522 this._debounceTemplate(this._render);
3523 }
3524 return;
3525 }
3526 }
3527 }
3528 },
3529 render: function () {
3530 this._needFullRefresh = true;
3531 this._debounceTemplate(this._render);
3532 this._flushTemplates();
3533 },
3534 _render: function () {
3535 var c = this.collection;
3536 if (this._needFullRefresh) {
3537 this._applyFullRefresh();
3538 this._needFullRefresh = false;
3539 } else {
3540 if (this._sortFn) {
3541 this._applySplicesUserSort(this._splices);
3542 } else {
3543 if (this._filterFn) {
3544 this._applyFullRefresh();
3545 } else {
3546 this._applySplicesArrayOrder(this._splices);
3547 }
3548 }
3549 }
3550 this._splices = [];
3551 var keyToIdx = this._keyToInstIdx = {};
3552 for (var i = 0; i < this._instances.length; i++) {
3553 var inst = this._instances[i];
3554 keyToIdx[inst.__key__] = i;
3555 inst.__setProperty(this.indexAs, i, true);
3556 }
3557 this.fire('dom-change');
3558 },
3559 _applyFullRefresh: function () {
3560 var c = this.collection;
3561 var keys;
3562 if (this._sortFn) {
3563 keys = c ? c.getKeys() : [];
3564 } else {
3565 keys = [];
3566 var items = this.items;
3567 if (items) {
3568 for (var i = 0; i < items.length; i++) {
3569 keys.push(c.getKey(items[i]));
3570 }
3571 }
3572 }
3573 if (this._filterFn) {
3574 keys = keys.filter(function (a) {
3575 return this._filterFn(c.getItem(a));
3576 }, this);
3577 }
3578 if (this._sortFn) {
3579 keys.sort(function (a, b) {
3580 return this._sortFn(c.getItem(a), c.getItem(b));
3581 }.bind(this));
3582 }
3583 for (var i = 0; i < keys.length; i++) {
3584 var key = keys[i];
3585 var inst = this._instances[i];
3586 if (inst) {
3587 inst.__setProperty('__key__', key, true);
3588 inst.__setProperty(this.as, c.getItem(key), true);
3589 } else {
3590 this._instances.push(this._insertRow(i, key));
3591 }
3592 }
3593 for (; i < this._instances.length; i++) {
3594 this._detachRow(i);
3595 }
3596 this._instances.splice(keys.length, this._instances.length - keys.length);
3597 },
3598 _keySort: function (a, b) {
3599 return this.collection.getKey(a) - this.collection.getKey(b);
3600 },
3601 _applySplicesUserSort: function (splices) {
3602 var c = this.collection;
3603 var instances = this._instances;
3604 var keyMap = {};
3605 var pool = [];
3606 var sortFn = this._sortFn || this._keySort.bind(this);
3607 splices.forEach(function (s) {
3608 for (var i = 0; i < s.removed.length; i++) {
3609 var key = s.removed[i];
3610 keyMap[key] = keyMap[key] ? null : -1;
3611 }
3612 for (var i = 0; i < s.added.length; i++) {
3613 var key = s.added[i];
3614 keyMap[key] = keyMap[key] ? null : 1;
3615 }
3616 }, this);
3617 var removedIdxs = [];
3618 var addedKeys = [];
3619 for (var key in keyMap) {
3620 if (keyMap[key] === -1) {
3621 removedIdxs.push(this._keyToInstIdx[key]);
3622 }
3623 if (keyMap[key] === 1) {
3624 addedKeys.push(key);
3625 }
3626 }
3627 if (removedIdxs.length) {
3628 removedIdxs.sort();
3629 for (var i = removedIdxs.length - 1; i >= 0; i--) {
3630 var idx = removedIdxs[i];
3631 if (idx !== undefined) {
3632 pool.push(this._detachRow(idx));
3633 instances.splice(idx, 1);
3634 }
3635 }
3636 }
3637 if (addedKeys.length) {
3638 if (this._filterFn) {
3639 addedKeys = addedKeys.filter(function (a) {
3640 return this._filterFn(c.getItem(a));
3641 }, this);
3642 }
3643 addedKeys.sort(function (a, b) {
3644 return this._sortFn(c.getItem(a), c.getItem(b));
3645 }.bind(this));
3646 var start = 0;
3647 for (var i = 0; i < addedKeys.length; i++) {
3648 start = this._insertRowUserSort(start, addedKeys[i], pool);
3649 }
3650 }
3651 },
3652 _insertRowUserSort: function (start, key, pool) {
3653 var c = this.collection;
3654 var item = c.getItem(key);
3655 var end = this._instances.length - 1;
3656 var idx = -1;
3657 var sortFn = this._sortFn || this._keySort.bind(this);
3658 while (start <= end) {
3659 var mid = start + end >> 1;
3660 var midKey = this._instances[mid].__key__;
3661 var cmp = sortFn(c.getItem(midKey), item);
3662 if (cmp < 0) {
3663 start = mid + 1;
3664 } else if (cmp > 0) {
3665 end = mid - 1;
3666 } else {
3667 idx = mid;
3668 break;
3669 }
3670 }
3671 if (idx < 0) {
3672 idx = end + 1;
3673 }
3674 this._instances.splice(idx, 0, this._insertRow(idx, key, pool));
3675 return idx;
3676 },
3677 _applySplicesArrayOrder: function (splices) {
3678 var pool = [];
3679 var c = this.collection;
3680 splices.forEach(function (s) {
3681 for (var i = 0; i < s.removed.length; i++) {
3682 var inst = this._detachRow(s.index + i);
3683 if (!inst.isPlaceholder) {
3684 pool.push(inst);
3685 }
3686 }
3687 this._instances.splice(s.index, s.removed.length);
3688 for (var i = 0; i < s.added.length; i++) {
3689 var inst = {
3690 isPlaceholder: true,
3691 key: s.added[i]
3692 };
3693 this._instances.splice(s.index + i, 0, inst);
3694 }
3695 }, this);
3696 for (var i = this._instances.length - 1; i >= 0; i--) {
3697 var inst = this._instances[i];
3698 if (inst.isPlaceholder) {
3699 this._instances[i] = this._insertRow(i, inst.key, pool, true);
3700 }
3701 }
3702 },
3703 _detachRow: function (idx) {
3704 var inst = this._instances[idx];
3705 if (!inst.isPlaceholder) {
3706 var parentNode = Polymer.dom(this).parentNode;
3707 for (var i = 0; i < inst._children.length; i++) {
3708 var el = inst._children[i];
3709 Polymer.dom(inst.root).appendChild(el);
3710 }
3711 }
3712 return inst;
3713 },
3714 _insertRow: function (idx, key, pool, replace) {
3715 var inst;
3716 if (inst = pool && pool.pop()) {
3717 inst.__setProperty(this.as, this.collection.getItem(key), true);
3718 inst.__setProperty('__key__', key, true);
3719 } else {
3720 inst = this._generateRow(idx, key);
3721 }
3722 var beforeRow = this._instances[replace ? idx + 1 : idx];
3723 var beforeNode = beforeRow ? beforeRow._children[0] : this;
3724 var parentNode = Polymer.dom(this).parentNode;
3725 Polymer.dom(parentNode).insertBefore(inst.root, beforeNode);
3726 return inst;
3727 },
3728 _generateRow: function (idx, key) {
3729 var model = { __key__: key };
3730 model[this.as] = this.collection.getItem(key);
3731 model[this.indexAs] = idx;
3732 var inst = this.stamp(model);
3733 return inst;
3734 },
3735 _showHideChildren: function (hidden) {
3736 for (var i = 0; i < this._instances.length; i++) {
3737 this._instances[i]._showHideChildren(hidden);
3738 }
3739 },
3740 _forwardInstanceProp: function (inst, prop, value) {
3741 if (prop == this.as) {
3742 var idx;
3743 if (this._sortFn || this._filterFn) {
3744 idx = this.items.indexOf(this.collection.getItem(inst.__key__));
3745 } else {
3746 idx = inst[this.indexAs];
3747 }
3748 this.set('items.' + idx, value);
3749 }
3750 },
3751 _forwardInstancePath: function (inst, path, value) {
3752 if (path.indexOf(this.as + '.') === 0) {
3753 this.notifyPath('items.' + inst.__key__ + '.' + path.slice(this.as.length + 1), value);
3754 }
3755 },
3756 _forwardParentProp: function (prop, value) {
3757 this._instances.forEach(function (inst) {
3758 inst.__setProperty(prop, value, true);
3759 }, this);
3760 },
3761 _forwardParentPath: function (path, value) {
3762 this._instances.forEach(function (inst) {
3763 inst.notifyPath(path, value, true);
3764 }, this);
3765 },
3766 _forwardItemPath: function (path, value) {
3767 if (this._keyToInstIdx) {
3768 var dot = path.indexOf('.');
3769 var key = path.substring(0, dot < 0 ? path.length : dot);
3770 var idx = this._keyToInstIdx[key];
3771 var inst = this._instances[idx];
3772 if (inst) {
3773 if (dot >= 0) {
3774 path = this.as + '.' + path.substring(dot + 1);
3775 inst.notifyPath(path, value, true);
3776 } else {
3777 inst.__setProperty(this.as, value, true);
3778 }
3779 }
3780 }
3781 },
3782 itemForElement: function (el) {
3783 var instance = this.modelForElement(el);
3784 return instance && instance[this.as];
3785 },
3786 keyForElement: function (el) {
3787 var instance = this.modelForElement(el);
3788 return instance && instance.__key__;
3789 },
3790 indexForElement: function (el) {
3791 var instance = this.modelForElement(el);
3792 return instance && instance[this.indexAs];
3793 }
3794 });
3795 Polymer({
3796 is: 'array-selector',
3797 properties: {
3798 items: {
3799 type: Array,
3800 observer: '_itemsChanged'
3801 },
3802 selected: {
3803 type: Object,
3804 notify: true
3805 },
3806 toggle: Boolean,
3807 multi: Boolean
3808 },
3809 _itemsChanged: function () {
3810 if (Array.isArray(this.selected)) {
3811 for (var i = 0; i < this.selected.length; i++) {
3812 this.unlinkPaths('selected.' + i);
3813 }
3814 } else {
3815 this.unlinkPaths('selected');
3816 }
3817 if (this.multi) {
3818 this.selected = [];
3819 } else {
3820 this.selected = null;
3821 }
3822 },
3823 deselect: function (item) {
3824 if (this.multi) {
3825 var scol = Polymer.Collection.get(this.selected);
3826 var sidx = this.selected.indexOf(item);
3827 if (sidx >= 0) {
3828 var skey = scol.getKey(item);
3829 this.splice('selected', sidx, 1);
3830 this.unlinkPaths('selected.' + skey);
3831 return true;
3832 }
3833 } else {
3834 this.selected = null;
3835 this.unlinkPaths('selected');
3836 }
3837 },
3838 select: function (item) {
3839 var icol = Polymer.Collection.get(this.items);
3840 var key = icol.getKey(item);
3841 if (this.multi) {
3842 var scol = Polymer.Collection.get(this.selected);
3843 var skey = scol.getKey(item);
3844 if (skey >= 0) {
3845 if (this.toggle) {
3846 this.deselect(item);
3847 }
3848 } else {
3849 this.push('selected', item);
3850 this.async(function () {
3851 skey = scol.getKey(item);
3852 this.linkPaths('selected.' + skey, 'items.' + key);
3853 });
3854 }
3855 } else {
3856 if (this.toggle && item == this.selected) {
3857 this.deselect();
3858 } else {
3859 this.linkPaths('selected', 'items.' + key);
3860 this.selected = item;
3861 }
3862 }
3863 }
3864 });
3865 Polymer({
3866 is: 'dom-if',
3867 extends: 'template',
3868 properties: {
3869 'if': {
3870 type: Boolean,
3871 value: false,
3872 observer: '_queueRender'
3873 },
3874 restamp: {
3875 type: Boolean,
3876 value: false,
3877 observer: '_queueRender'
3878 }
3879 },
3880 behaviors: [Polymer.Templatizer],
3881 _queueRender: function () {
3882 this._debounceTemplate(this._render);
3883 },
3884 detached: function () {
3885 this._teardownInstance();
3886 },
3887 attached: function () {
3888 if (this.if && this.ctor) {
3889 this.async(this._ensureInstance);
3890 }
3891 },
3892 render: function () {
3893 this._flushTemplates();
3894 },
3895 _render: function () {
3896 if (this.if) {
3897 if (!this.ctor) {
3898 this._wrapTextNodes(this._content || this.content);
3899 this.templatize(this);
3900 }
3901 this._ensureInstance();
3902 this._showHideChildren();
3903 } else if (this.restamp) {
3904 this._teardownInstance();
3905 }
3906 if (!this.restamp && this._instance) {
3907 this._showHideChildren();
3908 }
3909 if (this.if != this._lastIf) {
3910 this.fire('dom-change');
3911 this._lastIf = this.if;
3912 }
3913 },
3914 _ensureInstance: function () {
3915 if (!this._instance) {
3916 this._instance = this.stamp();
3917 var root = this._instance.root;
3918 var parent = Polymer.dom(Polymer.dom(this).parentNode);
3919 parent.insertBefore(root, this);
3920 }
3921 },
3922 _teardownInstance: function () {
3923 if (this._instance) {
3924 var c = this._instance._children;
3925 if (c) {
3926 var parent = Polymer.dom(Polymer.dom(c[0]).parentNode);
3927 c.forEach(function (n) {
3928 parent.removeChild(n);
3929 });
3930 }
3931 this._instance = null;
3932 }
3933 },
3934 _wrapTextNodes: function (root) {
3935 for (var n = root.firstChild; n; n = n.nextSibling) {
3936 if (n.nodeType === Node.TEXT_NODE && n.textContent.trim()) {
3937 var s = document.createElement('span');
3938 root.insertBefore(s, n);
3939 s.appendChild(n);
3940 n = s;
3941 }
3942 }
3943 },
3944 _showHideChildren: function () {
3945 var hidden = this.__hideTemplateChildren__ || !this.if;
3946 if (this._instance) {
3947 this._instance._showHideChildren(hidden);
3948 }
3949 },
3950 _forwardParentProp: function (prop, value) {
3951 if (this._instance) {
3952 this._instance[prop] = value;
3953 }
3954 },
3955 _forwardParentPath: function (path, value) {
3956 if (this._instance) {
3957 this._instance.notifyPath(path, value, true);
3958 }
3959 }
3960 });
3961 Polymer.ImportStatus = {
3962 _ready: false,
3963 _callbacks: [],
3964 whenLoaded: function (cb) {
3965 if (this._ready) {
3966 cb();
3967 } else {
3968 this._callbacks.push(cb);
3969 }
3970 },
3971 _importsLoaded: function () {
3972 this._ready = true;
3973 this._callbacks.forEach(function (cb) {
3974 cb();
3975 });
3976 this._callbacks = [];
3977 }
3978 };
3979 window.addEventListener('load', function () {
3980 Polymer.ImportStatus._importsLoaded();
3981 });
3982 if (window.HTMLImports) {
3983 HTMLImports.whenReady(function () {
3984 Polymer.ImportStatus._importsLoaded();
3985 });
3986 }
3987 Polymer({
3988 is: 'dom-bind',
3989 extends: 'template',
3990 created: function () {
3991 Polymer.ImportStatus.whenLoaded(this._readySelf.bind(this));
3992 },
3993 _registerFeatures: function () {
3994 this._prepConstructor();
3995 },
3996 _insertChildren: function () {
3997 var parentDom = Polymer.dom(Polymer.dom(this).parentNode);
3998 parentDom.insertBefore(this.root, this);
3999 },
4000 _removeChildren: function () {
4001 if (this._children) {
4002 for (var i = 0; i < this._children.length; i++) {
4003 this.root.appendChild(this._children[i]);
4004 }
4005 }
4006 },
4007 _initFeatures: function () {
4008 },
4009 _scopeElementClass: function (element, selector) {
4010 if (this.dataHost) {
4011 return this.dataHost._scopeElementClass(element, selector);
4012 } else {
4013 return selector;
4014 }
4015 },
4016 _prepConfigure: function () {
4017 var config = {};
4018 for (var prop in this._propertyEffects) {
4019 config[prop] = this[prop];
4020 }
4021 this._setupConfigure = this._setupConfigure.bind(this, config);
4022 },
4023 attached: function () {
4024 if (!this._children) {
4025 this._template = this;
4026 this._prepAnnotations();
4027 this._prepEffects();
4028 this._prepBehaviors();
4029 this._prepConfigure();
4030 this._prepBindings();
4031 Polymer.Base._initFeatures.call(this);
4032 this._children = Array.prototype.slice.call(this.root.childNodes);
4033 }
4034 this._insertChildren();
4035 this.fire('dom-change');
4036 },
4037 detached: function () {
4038 this._removeChildren();
4039 }
4040 });</script>
OLDNEW
« no previous file with comments | « third_party/polymer/v1_0/components/polymer/build.log ('k') | third_party/polymer/v1_0/components/polymer/polymer-micro.html » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698