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

Side by Side Diff: dart/pkg/polymer/lib/src/js/polymer/polymer.concat.js

Issue 336013003: Version 1.5.0-dev.4.14 (Closed) Base URL: http://dart.googlecode.com/svn/trunk/
Patch Set: Created 6 years, 6 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 | Annotate | Revision Log
OLDNEW
1 /**
2 * @license
3 * Copyright (c) 2014 The Polymer Project Authors. All rights reserved.
4 * This code may only be used under the BSD style license found at http://polyme r.github.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/CON TRIBUTORS.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/PA TENTS.txt
9 */
10 window.PolymerGestures = {};
11
1 /* 12 /*
2 * Copyright 2013 The Polymer Authors. All rights reserved. 13 * Copyright (c) 2014 The Polymer Project Authors. All rights reserved.
3 * Use of this source code is governed by a BSD-style 14 * This code may only be used under the BSD style license found at http://polyme r.github.io/LICENSE.txt
4 * license that can be found in the LICENSE file. 15 * The complete set of authors may be found at http://polymer.github.io/AUTHORS. txt
5 */ 16 * The complete set of contributors may be found at http://polymer.github.io/CON TRIBUTORS.txt
6 Polymer = {}; 17 * Code distributed by Google as part of the polymer project is also
18 * subject to an additional IP rights grant found at http://polymer.github.io/PA TENTS.txt
19 */
20
21 (function(scope) {
22 var target = {
23 shadow: function(inEl) {
24 if (inEl) {
25 return inEl.shadowRoot || inEl.webkitShadowRoot;
26 }
27 },
28 canTarget: function(shadow) {
29 return shadow && Boolean(shadow.elementFromPoint);
30 },
31 targetingShadow: function(inEl) {
32 var s = this.shadow(inEl);
33 if (this.canTarget(s)) {
34 return s;
35 }
36 },
37 olderShadow: function(shadow) {
38 var os = shadow.olderShadowRoot;
39 if (!os) {
40 var se = shadow.querySelector('shadow');
41 if (se) {
42 os = se.olderShadowRoot;
43 }
44 }
45 return os;
46 },
47 allShadows: function(element) {
48 var shadows = [], s = this.shadow(element);
49 while(s) {
50 shadows.push(s);
51 s = this.olderShadow(s);
52 }
53 return shadows;
54 },
55 searchRoot: function(inRoot, x, y) {
56 if (inRoot) {
57 var t = inRoot.elementFromPoint(x, y);
58 var st, sr, os;
59 // is element a shadow host?
60 sr = this.targetingShadow(t);
61 while (sr) {
62 // find the the element inside the shadow root
63 st = sr.elementFromPoint(x, y);
64 if (!st) {
65 // check for older shadows
66 sr = this.olderShadow(sr);
67 } else {
68 // shadowed element may contain a shadow root
69 var ssr = this.targetingShadow(st);
70 return this.searchRoot(ssr, x, y) || st;
71 }
72 }
73 // light dom element is the target
74 return t;
75 }
76 },
77 owner: function(element) {
78 if (!element) {
79 return document;
80 }
81 var s = element;
82 // walk up until you hit the shadow root or document
83 while (s.parentNode) {
84 s = s.parentNode;
85 }
86 // the owner element is expected to be a Document or ShadowRoot
87 if (s.nodeType != Node.DOCUMENT_NODE && s.nodeType != Node.DOCUMENT_FRAGME NT_NODE) {
88 s = document;
89 }
90 return s;
91 },
92 findTarget: function(inEvent) {
93 var x = inEvent.clientX, y = inEvent.clientY;
94 // if the listener is in the shadow root, it is much faster to start there
95 var s = this.owner(inEvent.target);
96 // if x, y is not in this root, fall back to document search
97 if (!s.elementFromPoint(x, y)) {
98 s = document;
99 }
100 return this.searchRoot(s, x, y);
101 },
102 LCA: function(a, b) {
103 if (a === b) {
104 return a;
105 }
106 if (a && !b) {
107 return a;
108 }
109 if (b && !a) {
110 return b;
111 }
112 if (!b && !a) {
113 return document;
114 }
115 // fast case, a is a direct descendant of b or vice versa
116 if (a.contains && a.contains(b)) {
117 return a;
118 }
119 if (b.contains && b.contains(a)) {
120 return b;
121 }
122 var adepth = this.depth(a);
123 var bdepth = this.depth(b);
124 var d = adepth - bdepth;
125 if (d > 0) {
126 a = this.walk(a, d);
127 } else {
128 b = this.walk(b, -d);
129 }
130 while(a && b && a !== b) {
131 a = this.walk(a, 1);
132 b = this.walk(b, 1);
133 }
134 return a;
135 },
136 walk: function(n, u) {
137 for (var i = 0; n && (i < u); i++) {
138 n = n.parentNode || n.host;
139 }
140 return n;
141 },
142 depth: function(n) {
143 var d = 0;
144 while(n) {
145 d++;
146 n = n.parentNode || n.host;
147 }
148 return d;
149 },
150 deepContains: function(a, b) {
151 var common = this.LCA(a, b);
152 // if a is the common ancestor, it must "deeply" contain b
153 return common === a;
154 },
155 insideNode: function(node, x, y) {
156 var rect = node.getBoundingClientRect();
157 return (rect.left <= x) && (x <= rect.right) && (rect.top <= y) && (y <= r ect.bottom);
158 }
159 };
160 scope.targetFinding = target;
161 /**
162 * Given an event, finds the "deepest" node that could have been the original target before ShadowDOM retargetting
163 *
164 * @param {Event} Event An event object with clientX and clientY properties
165 * @return {Element} The probable event origninator
166 */
167 scope.findTarget = target.findTarget.bind(target);
168 /**
169 * Determines if the "container" node deeply contains the "containee" node, in cluding situations where the "containee" is contained by one or more ShadowDOM
170 * roots.
171 *
172 * @param {Node} container
173 * @param {Node} containee
174 * @return {Boolean}
175 */
176 scope.deepContains = target.deepContains.bind(target);
177
178 /**
179 * Determines if the x/y position is inside the given node.
180 *
181 * Example:
182 *
183 * function upHandler(event) {
184 * var innode = PolymerGestures.insideNode(event.target, event.clientX, event.clientY);
185 * if (innode) {
186 * // wait for tap?
187 * } else {
188 * // tap will never happen
189 * }
190 * }
191 *
192 * @param {Node} node
193 * @param {Number} x Screen X position
194 * @param {Number} y screen Y position
195 * @return {Boolean}
196 */
197 scope.insideNode = target.insideNode;
198
199 })(window.PolymerGestures);
7 200
8 /* 201 /*
9 * Copyright 2013 The Polymer Authors. All rights reserved. 202 *
10 * Use of this source code is governed by a BSD-style 203 * Copyright (c) 2014 The Polymer Project Authors. All rights reserved.
11 * license that can be found in the LICENSE file. 204 * This code may only be used under the BSD style license found at http://polyme r.github.io/LICENSE.txt
205 * The complete set of authors may be found at http://polymer.github.io/AUTHORS. txt
206 * The complete set of contributors may be found at http://polymer.github.io/CON TRIBUTORS.txt
207 * Code distributed by Google as part of the polymer project is also
208 * subject to an additional IP rights grant found at http://polymer.github.io/PA TENTS.txt
209 */
210
211 (function() {
212 function shadowSelector(v) {
213 return 'body /deep/ ' + selector(v);
214 }
215 function selector(v) {
216 return '[touch-action="' + v + '"]';
217 }
218 function rule(v) {
219 return '{ -ms-touch-action: ' + v + '; touch-action: ' + v + ';}';
220 }
221 var attrib2css = [
222 'none',
223 'auto',
224 'pan-x',
225 'pan-y',
226 {
227 rule: 'pan-x pan-y',
228 selectors: [
229 'pan-x pan-y',
230 'pan-y pan-x'
231 ]
232 }
233 ];
234 var styles = '';
235 // only install stylesheet if the browser has touch action support
236 var head = document.head;
237 var hasTouchAction = typeof document.head.style.touchAction === 'string';
238 // only add shadow selectors if shadowdom is supported
239 var hasShadowRoot = !window.ShadowDOMPolyfill && document.head.createShadowRoo t;
240
241 if (hasTouchAction) {
242 attrib2css.forEach(function(r) {
243 if (String(r) === r) {
244 styles += selector(r) + rule(r) + '\n';
245 if (hasShadowRoot) {
246 styles += shadowSelector(r) + rule(r) + '\n';
247 }
248 } else {
249 styles += r.selectors.map(selector) + rule(r.rule) + '\n';
250 if (hasShadowRoot) {
251 styles += r.selectors.map(shadowSelector) + rule(r.rule) + '\n';
252 }
253 }
254 });
255
256 var el = document.createElement('style');
257 el.textContent = styles;
258 document.head.appendChild(el);
259 }
260 })();
261
262 /*
263 * Copyright (c) 2014 The Polymer Project Authors. All rights reserved.
264 * This code may only be used under the BSD style license found at http://polyme r.github.io/LICENSE.txt
265 * The complete set of authors may be found at http://polymer.github.io/AUTHORS. txt
266 * The complete set of contributors may be found at http://polymer.github.io/CON TRIBUTORS.txt
267 * Code distributed by Google as part of the polymer project is also
268 * subject to an additional IP rights grant found at http://polymer.github.io/PA TENTS.txt
269 */
270
271 /**
272 * This is the constructor for new PointerEvents.
273 *
274 * New Pointer Events must be given a type, and an optional dictionary of
275 * initialization properties.
276 *
277 * Due to certain platform requirements, events returned from the constructor
278 * identify as MouseEvents.
279 *
280 * @constructor
281 * @param {String} inType The type of the event to create.
282 * @param {Object} [inDict] An optional dictionary of initial event properties.
283 * @return {Event} A new PointerEvent of type `inType` and initialized with prop erties from `inDict`.
284 */
285 (function(scope) {
286
287 var MOUSE_PROPS = [
288 'bubbles',
289 'cancelable',
290 'view',
291 'detail',
292 'screenX',
293 'screenY',
294 'clientX',
295 'clientY',
296 'ctrlKey',
297 'altKey',
298 'shiftKey',
299 'metaKey',
300 'button',
301 'relatedTarget',
302 'pageX',
303 'pageY'
304 ];
305
306 var MOUSE_DEFAULTS = [
307 false,
308 false,
309 null,
310 null,
311 0,
312 0,
313 0,
314 0,
315 false,
316 false,
317 false,
318 false,
319 0,
320 null,
321 0,
322 0
323 ];
324
325 var NOP_FACTORY = function(){ return function(){}; };
326
327 var eventFactory = {
328 // TODO(dfreedm): this is overridden by tap recognizer, needs review
329 preventTap: NOP_FACTORY,
330 makeBaseEvent: function(inType, inDict) {
331 var e = document.createEvent('Event');
332 e.initEvent(inType, inDict.bubbles || false, inDict.cancelable || false);
333 e.preventTap = eventFactory.preventTap(e);
334 return e;
335 },
336 makeGestureEvent: function(inType, inDict) {
337 inDict = inDict || Object.create(null);
338
339 var e = this.makeBaseEvent(inType, inDict);
340 for (var i = 0, keys = Object.keys(inDict), k; i < keys.length; i++) {
341 k = keys[i];
342 e[k] = inDict[k];
343 }
344 return e;
345 },
346 makePointerEvent: function(inType, inDict) {
347 inDict = inDict || Object.create(null);
348
349 var e = this.makeBaseEvent(inType, inDict);
350 // define inherited MouseEvent properties
351 for(var i = 0, p; i < MOUSE_PROPS.length; i++) {
352 p = MOUSE_PROPS[i];
353 e[p] = inDict[p] || MOUSE_DEFAULTS[i];
354 }
355 e.buttons = inDict.buttons || 0;
356
357 // Spec requires that pointers without pressure specified use 0.5 for down
358 // state and 0 for up state.
359 var pressure = 0;
360 if (inDict.pressure) {
361 pressure = inDict.pressure;
362 } else {
363 pressure = e.buttons ? 0.5 : 0;
364 }
365
366 // add x/y properties aliased to clientX/Y
367 e.x = e.clientX;
368 e.y = e.clientY;
369
370 // define the properties of the PointerEvent interface
371 e.pointerId = inDict.pointerId || 0;
372 e.width = inDict.width || 0;
373 e.height = inDict.height || 0;
374 e.pressure = pressure;
375 e.tiltX = inDict.tiltX || 0;
376 e.tiltY = inDict.tiltY || 0;
377 e.pointerType = inDict.pointerType || '';
378 e.hwTimestamp = inDict.hwTimestamp || 0;
379 e.isPrimary = inDict.isPrimary || false;
380 return e;
381 }
382 };
383
384 scope.eventFactory = eventFactory;
385 })(window.PolymerGestures);
386
387 /*
388 * Copyright (c) 2014 The Polymer Project Authors. All rights reserved.
389 * This code may only be used under the BSD style license found at http://polyme r.github.io/LICENSE.txt
390 * The complete set of authors may be found at http://polymer.github.io/AUTHORS. txt
391 * The complete set of contributors may be found at http://polymer.github.io/CON TRIBUTORS.txt
392 * Code distributed by Google as part of the polymer project is also
393 * subject to an additional IP rights grant found at http://polymer.github.io/PA TENTS.txt
394 */
395
396 /**
397 * This module implements an map of pointer states
398 */
399 (function(scope) {
400 var USE_MAP = window.Map && window.Map.prototype.forEach;
401 var POINTERS_FN = function(){ return this.size; };
402 function PointerMap() {
403 if (USE_MAP) {
404 var m = new Map();
405 m.pointers = POINTERS_FN;
406 return m;
407 } else {
408 this.keys = [];
409 this.values = [];
410 }
411 }
412
413 PointerMap.prototype = {
414 set: function(inId, inEvent) {
415 var i = this.keys.indexOf(inId);
416 if (i > -1) {
417 this.values[i] = inEvent;
418 } else {
419 this.keys.push(inId);
420 this.values.push(inEvent);
421 }
422 },
423 has: function(inId) {
424 return this.keys.indexOf(inId) > -1;
425 },
426 'delete': function(inId) {
427 var i = this.keys.indexOf(inId);
428 if (i > -1) {
429 this.keys.splice(i, 1);
430 this.values.splice(i, 1);
431 }
432 },
433 get: function(inId) {
434 var i = this.keys.indexOf(inId);
435 return this.values[i];
436 },
437 clear: function() {
438 this.keys.length = 0;
439 this.values.length = 0;
440 },
441 // return value, key, map
442 forEach: function(callback, thisArg) {
443 this.values.forEach(function(v, i) {
444 callback.call(thisArg, v, this.keys[i], this);
445 }, this);
446 },
447 pointers: function() {
448 return this.keys.length;
449 }
450 };
451
452 scope.PointerMap = PointerMap;
453 })(window.PolymerGestures);
454
455 /*
456 * Copyright (c) 2014 The Polymer Project Authors. All rights reserved.
457 * This code may only be used under the BSD style license found at http://polyme r.github.io/LICENSE.txt
458 * The complete set of authors may be found at http://polymer.github.io/AUTHORS. txt
459 * The complete set of contributors may be found at http://polymer.github.io/CON TRIBUTORS.txt
460 * Code distributed by Google as part of the polymer project is also
461 * subject to an additional IP rights grant found at http://polymer.github.io/PA TENTS.txt
462 */
463
464 (function(scope) {
465 var CLONE_PROPS = [
466 // MouseEvent
467 'bubbles',
468 'cancelable',
469 'view',
470 'detail',
471 'screenX',
472 'screenY',
473 'clientX',
474 'clientY',
475 'ctrlKey',
476 'altKey',
477 'shiftKey',
478 'metaKey',
479 'button',
480 'relatedTarget',
481 // DOM Level 3
482 'buttons',
483 // PointerEvent
484 'pointerId',
485 'width',
486 'height',
487 'pressure',
488 'tiltX',
489 'tiltY',
490 'pointerType',
491 'hwTimestamp',
492 'isPrimary',
493 // event instance
494 'type',
495 'target',
496 'currentTarget',
497 'which',
498 'pageX',
499 'pageY',
500 'timeStamp',
501 // gesture addons
502 'preventTap',
503 'tapPrevented'
504 ];
505
506 var CLONE_DEFAULTS = [
507 // MouseEvent
508 false,
509 false,
510 null,
511 null,
512 0,
513 0,
514 0,
515 0,
516 false,
517 false,
518 false,
519 false,
520 0,
521 null,
522 // DOM Level 3
523 0,
524 // PointerEvent
525 0,
526 0,
527 0,
528 0,
529 0,
530 0,
531 '',
532 0,
533 false,
534 // event instance
535 '',
536 null,
537 null,
538 0,
539 0,
540 0,
541 0,
542 function(){},
543 false
544 ];
545
546 var HAS_SVG_INSTANCE = (typeof SVGElementInstance !== 'undefined');
547
548 var wrap = window.ShadowDOMPolyfill && ShadowDOMPolyfill.wrapIfNeeded || funct ion(e){ return e; };
549
550 var eventFactory = scope.eventFactory;
551 /**
552 * This module is for normalizing events. Mouse and Touch events will be
553 * collected here, and fire PointerEvents that have the same semantics, no
554 * matter the source.
555 * Events fired:
556 * - pointerdown: a pointing is added
557 * - pointerup: a pointer is removed
558 * - pointermove: a pointer is moved
559 * - pointerover: a pointer crosses into an element
560 * - pointerout: a pointer leaves an element
561 * - pointercancel: a pointer will no longer generate events
562 */
563 var dispatcher = {
564 pointermap: new scope.PointerMap(),
565 eventMap: Object.create(null),
566 // Scope objects for native events.
567 // This exists for ease of testing.
568 eventSources: Object.create(null),
569 eventSourceList: [],
570 gestures: [],
571 gestureQueue: [],
572 /**
573 * Add a new event source that will generate pointer events.
574 *
575 * `inSource` must contain an array of event names named `events`, and
576 * functions with the names specified in the `events` array.
577 * @param {string} name A name for the event source
578 * @param {Object} source A new source of platform events.
579 */
580 registerSource: function(name, source) {
581 var s = source;
582 var newEvents = s.events;
583 if (newEvents) {
584 newEvents.forEach(function(e) {
585 if (s[e]) {
586 this.eventMap[e] = s[e].bind(s);
587 }
588 }, this);
589 this.eventSources[name] = s;
590 this.eventSourceList.push(s);
591 }
592 },
593 registerGesture: function(name, source) {
594 this.gestures.push(source);
595 },
596 register: function(element) {
597 // NOTE: Work around for #4, don't add listeners to individual Polymer elm enets in SD Polyfill
598 if (window.ShadowDOMPolyfill && element !== document) {
599 return;
600 }
601 var l = this.eventSourceList.length;
602 for (var i = 0, es; (i < l) && (es = this.eventSourceList[i]); i++) {
603 // call eventsource register
604 es.register.call(es, element);
605 }
606 },
607 unregister: function(element) {
608 var l = this.eventSourceList.length;
609 for (var i = 0, es; (i < l) && (es = this.eventSourceList[i]); i++) {
610 // call eventsource register
611 es.unregister.call(es, element);
612 }
613 },
614 // EVENTS
615 down: function(inEvent) {
616 this.fireEvent('down', inEvent);
617 },
618 move: function(inEvent) {
619 // pipe move events into gesture queue directly
620 inEvent.type = 'move';
621 this.fillGestureQueue(inEvent);
622 },
623 up: function(inEvent) {
624 this.fireEvent('up', inEvent);
625 },
626 cancel: function(inEvent) {
627 inEvent.tapPrevented = true;
628 this.fireEvent('up', inEvent);
629 },
630 // LISTENER LOGIC
631 eventHandler: function(inEvent) {
632 // This is used to prevent multiple dispatch of events from
633 // platform events. This can happen when two elements in different scopes
634 // are set up to create pointer events, which is relevant to Shadow DOM.
635 if (inEvent._handledByPG) {
636 return;
637 }
638 var type = inEvent.type;
639 var fn = this.eventMap && this.eventMap[type];
640 if (fn) {
641 fn(inEvent);
642 }
643 inEvent._handledByPG = true;
644 },
645 // set up event listeners
646 listen: function(target, events) {
647 events.forEach(function(e) {
648 this.addEvent(target, e);
649 }, this);
650 },
651 // remove event listeners
652 unlisten: function(target, events) {
653 events.forEach(function(e) {
654 this.removeEvent(target, e);
655 }, this);
656 },
657 addEvent: function(target, eventName) {
658 // NOTE: Work around for #4, use native event listener in SD Polyfill
659 if (window.ShadowDOMPolyfill) {
660 target.addEventListener_(eventName, this.boundHandler);
661 } else {
662 target.addEventListener(eventName, this.boundHandler);
663 }
664 },
665 removeEvent: function(target, eventName) {
666 // NOTE: Work around for #4, use native event listener in SD Polyfill
667 if (window.ShadowDOMPolyfill) {
668 target.removeEventListener_(eventName, this.boundHandler);
669 } else {
670 target.removeEventListener(eventName, this.boundHandler);
671 }
672 },
673 // EVENT CREATION AND TRACKING
674 /**
675 * Creates a new Event of type `inType`, based on the information in
676 * `inEvent`.
677 *
678 * @param {string} inType A string representing the type of event to create
679 * @param {Event} inEvent A platform event with a target
680 * @return {Event} A PointerEvent of type `inType`
681 */
682 makeEvent: function(inType, inEvent) {
683 var e = eventFactory.makePointerEvent(inType, inEvent);
684 e.preventDefault = inEvent.preventDefault;
685 e.tapPrevented = inEvent.tapPrevented;
686 e._target = e._target || inEvent.target;
687 return e;
688 },
689 // make and dispatch an event in one call
690 fireEvent: function(inType, inEvent) {
691 var e = this.makeEvent(inType, inEvent);
692 return this.dispatchEvent(e);
693 },
694 /**
695 * Returns a snapshot of inEvent, with writable properties.
696 *
697 * @param {Event} inEvent An event that contains properties to copy.
698 * @return {Object} An object containing shallow copies of `inEvent`'s
699 * properties.
700 */
701 cloneEvent: function(inEvent) {
702 var eventCopy = Object.create(null), p;
703 for (var i = 0; i < CLONE_PROPS.length; i++) {
704 p = CLONE_PROPS[i];
705 eventCopy[p] = inEvent[p] || CLONE_DEFAULTS[i];
706 // Work around SVGInstanceElement shadow tree
707 // Return the <use> element that is represented by the instance for Safa ri, Chrome, IE.
708 // This is the behavior implemented by Firefox.
709 if (p === 'target' || p === 'relatedTarget') {
710 if (HAS_SVG_INSTANCE && eventCopy[p] instanceof SVGElementInstance) {
711 eventCopy[p] = eventCopy[p].correspondingUseElement;
712 }
713 eventCopy[p] = wrap(eventCopy[p]);
714 }
715 }
716 // keep the semantics of preventDefault
717 eventCopy.preventDefault = inEvent.preventDefault;
718 return eventCopy;
719 },
720 /**
721 * Dispatches the event to its target.
722 *
723 * @param {Event} inEvent The event to be dispatched.
724 * @return {Boolean} True if an event handler returns true, false otherwise.
725 */
726 dispatchEvent: function(inEvent) {
727 var t = inEvent._target;
728 if (t) {
729 t.dispatchEvent(inEvent);
730 // clone the event for the gesture system to process
731 // clone after dispatch to pick up gesture prevention code
732 var clone = this.cloneEvent(inEvent);
733 clone.target = t;
734 this.fillGestureQueue(clone);
735 }
736 },
737 gestureTrigger: function() {
738 // process the gesture queue
739 for (var i = 0, e; i < this.gestureQueue.length; i++) {
740 e = this.gestureQueue[i];
741 for (var j = 0, g; j < this.gestures.length; j++) {
742 g = this.gestures[j];
743 if (g.events.indexOf(e.type) >= 0) {
744 g[e.type].call(g, e);
745 }
746 }
747 }
748 this.gestureQueue.length = 0;
749 },
750 fillGestureQueue: function(ev) {
751 // only trigger the gesture queue once
752 if (!this.gestureQueue.length) {
753 requestAnimationFrame(this.boundGestureTrigger);
754 }
755 this.gestureQueue.push(ev);
756 }
757 };
758 dispatcher.boundHandler = dispatcher.eventHandler.bind(dispatcher);
759 dispatcher.boundGestureTrigger = dispatcher.gestureTrigger.bind(dispatcher);
760 scope.dispatcher = dispatcher;
761 scope.register = dispatcher.register.bind(dispatcher);
762 scope.unregister = dispatcher.unregister.bind(dispatcher);
763 })(window.PolymerGestures);
764
765 /*
766 * Copyright (c) 2014 The Polymer Project Authors. All rights reserved.
767 * This code may only be used under the BSD style license found at http://polyme r.github.io/LICENSE.txt
768 * The complete set of authors may be found at http://polymer.github.io/AUTHORS. txt
769 * The complete set of contributors may be found at http://polymer.github.io/CON TRIBUTORS.txt
770 * Code distributed by Google as part of the polymer project is also
771 * subject to an additional IP rights grant found at http://polymer.github.io/PA TENTS.txt
772 */
773
774 /**
775 * This module uses Mutation Observers to dynamically adjust which nodes will
776 * generate Pointer Events.
777 *
778 * All nodes that wish to generate Pointer Events must have the attribute
779 * `touch-action` set to `none`.
780 */
781 (function(scope) {
782 var forEach = Array.prototype.forEach.call.bind(Array.prototype.forEach);
783 var map = Array.prototype.map.call.bind(Array.prototype.map);
784 var toArray = Array.prototype.slice.call.bind(Array.prototype.slice);
785 var filter = Array.prototype.filter.call.bind(Array.prototype.filter);
786 var MO = window.MutationObserver || window.WebKitMutationObserver;
787 var SELECTOR = '[touch-action]';
788 var OBSERVER_INIT = {
789 subtree: true,
790 childList: true,
791 attributes: true,
792 attributeOldValue: true,
793 attributeFilter: ['touch-action']
794 };
795
796 function Installer(add, remove, changed, binder) {
797 this.addCallback = add.bind(binder);
798 this.removeCallback = remove.bind(binder);
799 this.changedCallback = changed.bind(binder);
800 if (MO) {
801 this.observer = new MO(this.mutationWatcher.bind(this));
802 }
803 }
804
805 Installer.prototype = {
806 watchSubtree: function(target) {
807 // Only watch scopes that can target find, as these are top-level.
808 // Otherwise we can see duplicate additions and removals that add noise.
809 //
810 // TODO(dfreedman): For some instances with ShadowDOMPolyfill, we can see
811 // a removal without an insertion when a node is redistributed among
812 // shadows. Since it all ends up correct in the document, watching only
813 // the document will yield the correct mutations to watch.
814 if (scope.targetFinding.canTarget(target)) {
815 this.observer.observe(target, OBSERVER_INIT);
816 }
817 },
818 enableOnSubtree: function(target) {
819 this.watchSubtree(target);
820 if (target === document && document.readyState !== 'complete') {
821 this.installOnLoad();
822 } else {
823 this.installNewSubtree(target);
824 }
825 },
826 installNewSubtree: function(target) {
827 forEach(this.findElements(target), this.addElement, this);
828 },
829 findElements: function(target) {
830 if (target.querySelectorAll) {
831 return target.querySelectorAll(SELECTOR);
832 }
833 return [];
834 },
835 removeElement: function(el) {
836 this.removeCallback(el);
837 },
838 addElement: function(el) {
839 this.addCallback(el);
840 },
841 elementChanged: function(el, oldValue) {
842 this.changedCallback(el, oldValue);
843 },
844 concatLists: function(accum, list) {
845 return accum.concat(toArray(list));
846 },
847 // register all touch-action = none nodes on document load
848 installOnLoad: function() {
849 document.addEventListener('readystatechange', function() {
850 if (document.readyState === 'complete') {
851 this.installNewSubtree(document);
852 }
853 }.bind(this));
854 },
855 isElement: function(n) {
856 return n.nodeType === Node.ELEMENT_NODE;
857 },
858 flattenMutationTree: function(inNodes) {
859 // find children with touch-action
860 var tree = map(inNodes, this.findElements, this);
861 // make sure the added nodes are accounted for
862 tree.push(filter(inNodes, this.isElement));
863 // flatten the list
864 return tree.reduce(this.concatLists, []);
865 },
866 mutationWatcher: function(mutations) {
867 mutations.forEach(this.mutationHandler, this);
868 },
869 mutationHandler: function(m) {
870 if (m.type === 'childList') {
871 var added = this.flattenMutationTree(m.addedNodes);
872 added.forEach(this.addElement, this);
873 var removed = this.flattenMutationTree(m.removedNodes);
874 removed.forEach(this.removeElement, this);
875 } else if (m.type === 'attributes') {
876 this.elementChanged(m.target, m.oldValue);
877 }
878 }
879 };
880
881 if (!MO) {
882 Installer.prototype.watchSubtree = function(){
883 console.warn('PolymerGestures: MutationObservers not found, touch-action w ill not be dynamically detected');
884 };
885 }
886
887 scope.Installer = Installer;
888 })(window.PolymerGestures);
889
890 /*
891 * Copyright (c) 2014 The Polymer Project Authors. All rights reserved.
892 * This code may only be used under the BSD style license found at http://polyme r.github.io/LICENSE.txt
893 * The complete set of authors may be found at http://polymer.github.io/AUTHORS. txt
894 * The complete set of contributors may be found at http://polymer.github.io/CON TRIBUTORS.txt
895 * Code distributed by Google as part of the polymer project is also
896 * subject to an additional IP rights grant found at http://polymer.github.io/PA TENTS.txt
897 */
898
899 (function (scope) {
900 var dispatcher = scope.dispatcher;
901 var pointermap = dispatcher.pointermap;
902 // radius around touchend that swallows mouse events
903 var DEDUP_DIST = 25;
904
905 var WHICH_TO_BUTTONS = [0, 1, 4, 2];
906
907 var HAS_BUTTONS = false;
908 try {
909 HAS_BUTTONS = new MouseEvent('test', {buttons: 1}).buttons === 1;
910 } catch (e) {}
911
912 // handler block for native mouse events
913 var mouseEvents = {
914 POINTER_ID: 1,
915 POINTER_TYPE: 'mouse',
916 events: [
917 'mousedown',
918 'mousemove',
919 'mouseup',
920 ],
921 register: function(target) {
922 dispatcher.listen(target, this.events);
923 },
924 unregister: function(target) {
925 dispatcher.unlisten(target, this.events);
926 },
927 lastTouches: [],
928 // collide with the global mouse listener
929 isEventSimulatedFromTouch: function(inEvent) {
930 var lts = this.lastTouches;
931 var x = inEvent.clientX, y = inEvent.clientY;
932 for (var i = 0, l = lts.length, t; i < l && (t = lts[i]); i++) {
933 // simulated mouse events will be swallowed near a primary touchend
934 var dx = Math.abs(x - t.x), dy = Math.abs(y - t.y);
935 if (dx <= DEDUP_DIST && dy <= DEDUP_DIST) {
936 return true;
937 }
938 }
939 },
940 prepareEvent: function(inEvent) {
941 var e = dispatcher.cloneEvent(inEvent);
942 e.pointerId = this.POINTER_ID;
943 e.isPrimary = true;
944 e.pointerType = this.POINTER_TYPE;
945 if (!HAS_BUTTONS) {
946 e.buttons = WHICH_TO_BUTTONS[e.which] || 0;
947 }
948 return e;
949 },
950 mousedown: function(inEvent) {
951 if (!this.isEventSimulatedFromTouch(inEvent)) {
952 var p = pointermap.has(this.POINTER_ID);
953 // TODO(dfreedman) workaround for some elements not sending mouseup
954 // http://crbug/149091
955 if (p) {
956 this.mouseup(inEvent);
957 }
958 var e = this.prepareEvent(inEvent);
959 pointermap.set(this.POINTER_ID, e.target);
960 dispatcher.down(e);
961 }
962 },
963 mousemove: function(inEvent) {
964 if (!this.isEventSimulatedFromTouch(inEvent)) {
965 var e = this.prepareEvent(inEvent);
966 e.target = pointermap.get(this.POINTER_ID);
967 dispatcher.move(e);
968 }
969 },
970 mouseup: function(inEvent) {
971 if (!this.isEventSimulatedFromTouch(inEvent)) {
972 var e = this.prepareEvent(inEvent);
973 e.relatedTarget = e.target;
974 e.target = pointermap.get(this.POINTER_ID);
975 dispatcher.up(e);
976 this.cleanupMouse();
977 }
978 },
979 cleanupMouse: function() {
980 pointermap['delete'](this.POINTER_ID);
981 }
982 };
983
984 scope.mouseEvents = mouseEvents;
985 })(window.PolymerGestures);
986
987 /*
988 * Copyright (c) 2014 The Polymer Project Authors. All rights reserved.
989 * This code may only be used under the BSD style license found at http://polyme r.github.io/LICENSE.txt
990 * The complete set of authors may be found at http://polymer.github.io/AUTHORS. txt
991 * The complete set of contributors may be found at http://polymer.github.io/CON TRIBUTORS.txt
992 * Code distributed by Google as part of the polymer project is also
993 * subject to an additional IP rights grant found at http://polymer.github.io/PA TENTS.txt
994 */
995
996 (function(scope) {
997 var dispatcher = scope.dispatcher;
998 var allShadows = scope.targetFinding.allShadows.bind(scope.targetFinding);
999 var pointermap = dispatcher.pointermap;
1000 var touchMap = Array.prototype.map.call.bind(Array.prototype.map);
1001 // This should be long enough to ignore compat mouse events made by touch
1002 var DEDUP_TIMEOUT = 2500;
1003 var CLICK_COUNT_TIMEOUT = 200;
1004 var ATTRIB = 'touch-action';
1005 var INSTALLER;
1006 var HAS_TOUCH_ACTION = typeof document.head.style.touchAction === 'string';
1007
1008 // handler block for native touch events
1009 var touchEvents = {
1010 events: [
1011 'touchstart',
1012 'touchmove',
1013 'touchend',
1014 'touchcancel'
1015 ],
1016 register: function(target) {
1017 if (HAS_TOUCH_ACTION) {
1018 dispatcher.listen(target, this.events);
1019 } else {
1020 INSTALLER.enableOnSubtree(target);
1021 }
1022 },
1023 unregister: function(target) {
1024 if (HAS_TOUCH_ACTION) {
1025 dispatcher.unlisten(target, this.events);
1026 } else {
1027 // TODO(dfreedman): is it worth it to disconnect the MO?
1028 }
1029 },
1030 elementAdded: function(el) {
1031 var a = el.getAttribute(ATTRIB);
1032 var st = this.touchActionToScrollType(a);
1033 if (st) {
1034 el._scrollType = st;
1035 dispatcher.listen(el, this.events);
1036 // set touch-action on shadows as well
1037 allShadows(el).forEach(function(s) {
1038 s._scrollType = st;
1039 dispatcher.listen(s, this.events);
1040 }, this);
1041 }
1042 },
1043 elementRemoved: function(el) {
1044 el._scrollType = undefined;
1045 dispatcher.unlisten(el, this.events);
1046 // remove touch-action from shadow
1047 allShadows(el).forEach(function(s) {
1048 s._scrollType = undefined;
1049 dispatcher.unlisten(s, this.events);
1050 }, this);
1051 },
1052 elementChanged: function(el, oldValue) {
1053 var a = el.getAttribute(ATTRIB);
1054 var st = this.touchActionToScrollType(a);
1055 var oldSt = this.touchActionToScrollType(oldValue);
1056 // simply update scrollType if listeners are already established
1057 if (st && oldSt) {
1058 el._scrollType = st;
1059 allShadows(el).forEach(function(s) {
1060 s._scrollType = st;
1061 }, this);
1062 } else if (oldSt) {
1063 this.elementRemoved(el);
1064 } else if (st) {
1065 this.elementAdded(el);
1066 }
1067 },
1068 scrollTypes: {
1069 EMITTER: 'none',
1070 XSCROLLER: 'pan-x',
1071 YSCROLLER: 'pan-y',
1072 SCROLLER: /^(?:pan-x pan-y)|(?:pan-y pan-x)|auto$/
1073 },
1074 touchActionToScrollType: function(touchAction) {
1075 var t = touchAction;
1076 var st = this.scrollTypes;
1077 if (t === 'none') {
1078 return 'none';
1079 } else if (t === st.XSCROLLER) {
1080 return 'X';
1081 } else if (t === st.YSCROLLER) {
1082 return 'Y';
1083 } else if (st.SCROLLER.exec(t)) {
1084 return 'XY';
1085 }
1086 },
1087 POINTER_TYPE: 'touch',
1088 firstTouch: null,
1089 isPrimaryTouch: function(inTouch) {
1090 return this.firstTouch === inTouch.identifier;
1091 },
1092 setPrimaryTouch: function(inTouch) {
1093 // set primary touch if there no pointers, or the only pointer is the mous e
1094 if (pointermap.pointers() === 0 || (pointermap.pointers() === 1 && pointer map.has(1))) {
1095 this.firstTouch = inTouch.identifier;
1096 this.firstXY = {X: inTouch.clientX, Y: inTouch.clientY};
1097 this.scrolling = false;
1098 this.cancelResetClickCount();
1099 }
1100 },
1101 removePrimaryPointer: function(inPointer) {
1102 if (inPointer.isPrimary) {
1103 this.firstTouch = null;
1104 this.firstXY = null;
1105 this.resetClickCount();
1106 }
1107 },
1108 clickCount: 0,
1109 resetId: null,
1110 resetClickCount: function() {
1111 var fn = function() {
1112 this.clickCount = 0;
1113 this.resetId = null;
1114 }.bind(this);
1115 this.resetId = setTimeout(fn, CLICK_COUNT_TIMEOUT);
1116 },
1117 cancelResetClickCount: function() {
1118 if (this.resetId) {
1119 clearTimeout(this.resetId);
1120 }
1121 },
1122 typeToButtons: function(type) {
1123 var ret = 0;
1124 if (type === 'touchstart' || type === 'touchmove') {
1125 ret = 1;
1126 }
1127 return ret;
1128 },
1129 findTarget: function(touch, id) {
1130 if (this.currentTouchEvent.type === 'touchstart') {
1131 return scope.findTarget(touch);
1132 }
1133 // reuse target we found in touchstart
1134 return pointermap.get(id);
1135 },
1136 touchToPointer: function(inTouch) {
1137 var cte = this.currentTouchEvent;
1138 var e = dispatcher.cloneEvent(inTouch);
1139 // Spec specifies that pointerId 1 is reserved for Mouse.
1140 // Touch identifiers can start at 0.
1141 // Add 2 to the touch identifier for compatibility.
1142 var id = e.pointerId = inTouch.identifier + 2;
1143 e.target = this.findTarget(inTouch, id);
1144 e.bubbles = true;
1145 e.cancelable = true;
1146 e.detail = this.clickCount;
1147 e.buttons = this.typeToButtons(cte.type);
1148 e.width = inTouch.webkitRadiusX || inTouch.radiusX || 0;
1149 e.height = inTouch.webkitRadiusY || inTouch.radiusY || 0;
1150 e.pressure = inTouch.webkitForce || inTouch.force || 0.5;
1151 e.isPrimary = this.isPrimaryTouch(inTouch);
1152 e.pointerType = this.POINTER_TYPE;
1153 // forward touch preventDefaults
1154 var self = this;
1155 e.preventDefault = function() {
1156 self.scrolling = false;
1157 self.firstXY = null;
1158 cte.preventDefault();
1159 };
1160 return e;
1161 },
1162 processTouches: function(inEvent, inFunction) {
1163 var tl = inEvent.changedTouches;
1164 this.currentTouchEvent = inEvent;
1165 for (var i = 0, t; i < tl.length; i++) {
1166 t = tl[i];
1167 inFunction.call(this, this.touchToPointer(t));
1168 }
1169 },
1170 // For single axis scrollers, determines whether the element should emit
1171 // pointer events or behave as a scroller
1172 shouldScroll: function(inEvent) {
1173 if (this.firstXY) {
1174 var ret;
1175 var scrollAxis = inEvent.currentTarget._scrollType;
1176 if (scrollAxis === 'none') {
1177 // this element is a touch-action: none, should never scroll
1178 ret = false;
1179 } else if (scrollAxis === 'XY') {
1180 // this element should always scroll
1181 ret = true;
1182 } else {
1183 var t = inEvent.changedTouches[0];
1184 // check the intended scroll axis, and other axis
1185 var a = scrollAxis;
1186 var oa = scrollAxis === 'Y' ? 'X' : 'Y';
1187 var da = Math.abs(t['client' + a] - this.firstXY[a]);
1188 var doa = Math.abs(t['client' + oa] - this.firstXY[oa]);
1189 // if delta in the scroll axis > delta other axis, scroll instead of
1190 // making events
1191 ret = da >= doa;
1192 }
1193 this.firstXY = null;
1194 return ret;
1195 }
1196 },
1197 findTouch: function(inTL, inId) {
1198 for (var i = 0, l = inTL.length, t; i < l && (t = inTL[i]); i++) {
1199 if (t.identifier === inId) {
1200 return true;
1201 }
1202 }
1203 },
1204 // In some instances, a touchstart can happen without a touchend. This
1205 // leaves the pointermap in a broken state.
1206 // Therefore, on every touchstart, we remove the touches that did not fire a
1207 // touchend event.
1208 // To keep state globally consistent, we fire a
1209 // pointercancel for this "abandoned" touch
1210 vacuumTouches: function(inEvent) {
1211 var tl = inEvent.touches;
1212 // pointermap.pointers() should be < tl.length here, as the touchstart has not
1213 // been processed yet.
1214 if (pointermap.pointers() >= tl.length) {
1215 var d = [];
1216 pointermap.forEach(function(value, key) {
1217 // Never remove pointerId == 1, which is mouse.
1218 // Touch identifiers are 2 smaller than their pointerId, which is the
1219 // index in pointermap.
1220 if (key !== 1 && !this.findTouch(tl, key - 2)) {
1221 var p = value.out;
1222 d.push(p);
1223 }
1224 }, this);
1225 d.forEach(this.cancelOut, this);
1226 }
1227 },
1228 touchstart: function(inEvent) {
1229 this.vacuumTouches(inEvent);
1230 this.setPrimaryTouch(inEvent.changedTouches[0]);
1231 this.dedupSynthMouse(inEvent);
1232 if (!this.scrolling) {
1233 this.clickCount++;
1234 this.processTouches(inEvent, this.down);
1235 }
1236 },
1237 down: function(inPointer) {
1238 var p = pointermap.set(inPointer.pointerId, inPointer.target);
1239 dispatcher.down(inPointer);
1240 },
1241 touchmove: function(inEvent) {
1242 if (HAS_TOUCH_ACTION) {
1243 this.processTouches(inEvent, this.move);
1244 } else {
1245 if (!this.scrolling) {
1246 if (this.shouldScroll(inEvent)) {
1247 this.scrolling = true;
1248 this.touchcancel(inEvent);
1249 } else {
1250 inEvent.preventDefault();
1251 this.processTouches(inEvent, this.move);
1252 }
1253 }
1254 }
1255 },
1256 move: function(inPointer) {
1257 var pointer = pointermap.get(inPointer.pointerId);
1258 // a finger drifted off the screen, ignore it
1259 if (!pointer) {
1260 return;
1261 }
1262 dispatcher.move(inPointer);
1263 },
1264 touchend: function(inEvent) {
1265 this.dedupSynthMouse(inEvent);
1266 this.processTouches(inEvent, this.up);
1267 },
1268 up: function(inPointer) {
1269 if (!this.scrolling) {
1270 inPointer.relatedTarget = scope.findTarget(inPointer);
1271 dispatcher.up(inPointer);
1272 }
1273 this.cleanUpPointer(inPointer);
1274 },
1275 cancel: function(inPointer) {
1276 inPointer.relatedTarget = scope.findTarget(inPointer);
1277 dispatcher.cancel(inPointer);
1278 this.cleanUpPointer(inPointer);
1279 },
1280 touchcancel: function(inEvent) {
1281 this.processTouches(inEvent, this.cancel);
1282 },
1283 cleanUpPointer: function(inPointer) {
1284 pointermap['delete'](inPointer.pointerId);
1285 this.removePrimaryPointer(inPointer);
1286 },
1287 // prevent synth mouse events from creating pointer events
1288 dedupSynthMouse: function(inEvent) {
1289 var lts = scope.mouseEvents.lastTouches;
1290 var t = inEvent.changedTouches[0];
1291 // only the primary finger will synth mouse events
1292 if (this.isPrimaryTouch(t)) {
1293 // remember x/y of last touch
1294 var lt = {x: t.clientX, y: t.clientY};
1295 lts.push(lt);
1296 var fn = (function(lts, lt){
1297 var i = lts.indexOf(lt);
1298 if (i > -1) {
1299 lts.splice(i, 1);
1300 }
1301 }).bind(null, lts, lt);
1302 setTimeout(fn, DEDUP_TIMEOUT);
1303 }
1304 }
1305 };
1306
1307 if (!HAS_TOUCH_ACTION) {
1308 INSTALLER = new scope.Installer(touchEvents.elementAdded, touchEvents.elemen tRemoved, touchEvents.elementChanged, touchEvents);
1309 }
1310
1311 scope.touchEvents = touchEvents;
1312 })(window.PolymerGestures);
1313
1314 /*
1315 * Copyright (c) 2014 The Polymer Project Authors. All rights reserved.
1316 * This code may only be used under the BSD style license found at http://polyme r.github.io/LICENSE.txt
1317 * The complete set of authors may be found at http://polymer.github.io/AUTHORS. txt
1318 * The complete set of contributors may be found at http://polymer.github.io/CON TRIBUTORS.txt
1319 * Code distributed by Google as part of the polymer project is also
1320 * subject to an additional IP rights grant found at http://polymer.github.io/PA TENTS.txt
1321 */
1322
1323 (function(scope) {
1324 var dispatcher = scope.dispatcher;
1325 var pointermap = dispatcher.pointermap;
1326 var HAS_BITMAP_TYPE = window.MSPointerEvent && typeof window.MSPointerEvent.MS POINTER_TYPE_MOUSE === 'number';
1327 var msEvents = {
1328 events: [
1329 'MSPointerDown',
1330 'MSPointerMove',
1331 'MSPointerUp',
1332 'MSPointerCancel',
1333 ],
1334 register: function(target) {
1335 dispatcher.listen(target, this.events);
1336 },
1337 unregister: function(target) {
1338 dispatcher.unlisten(target, this.events);
1339 },
1340 POINTER_TYPES: [
1341 '',
1342 'unavailable',
1343 'touch',
1344 'pen',
1345 'mouse'
1346 ],
1347 prepareEvent: function(inEvent) {
1348 var e = inEvent;
1349 if (HAS_BITMAP_TYPE) {
1350 e = dispatcher.cloneEvent(inEvent);
1351 e.pointerType = this.POINTER_TYPES[inEvent.pointerType];
1352 }
1353 return e;
1354 },
1355 cleanup: function(id) {
1356 pointermap['delete'](id);
1357 },
1358 MSPointerDown: function(inEvent) {
1359 var e = this.prepareEvent(inEvent);
1360 pointermap.set(inEvent.pointerId, e.target);
1361 dispatcher.down(e);
1362 },
1363 MSPointerMove: function(inEvent) {
1364 var e = this.prepareEvent(inEvent);
1365 e.target = pointermap.get(e.pointerId);
1366 dispatcher.move(e);
1367 },
1368 MSPointerUp: function(inEvent) {
1369 var e = this.prepareEvent(inEvent);
1370 e.relatedTarget = e.target;
1371 e.target = pointermap.get(e.pointerId);
1372 dispatcher.up(e);
1373 this.cleanup(inEvent.pointerId);
1374 },
1375 MSPointerCancel: function(inEvent) {
1376 var e = this.prepareEvent(inEvent);
1377 e.relatedTarget = e.target;
1378 e.target = pointermap.get(e.pointerId);
1379 dispatcher.cancel(e);
1380 this.cleanup(inEvent.pointerId);
1381 }
1382 };
1383
1384 scope.msEvents = msEvents;
1385 })(window.PolymerGestures);
1386
1387 /*
1388 * Copyright (c) 2014 The Polymer Project Authors. All rights reserved.
1389 * This code may only be used under the BSD style license found at http://polyme r.github.io/LICENSE.txt
1390 * The complete set of authors may be found at http://polymer.github.io/AUTHORS. txt
1391 * The complete set of contributors may be found at http://polymer.github.io/CON TRIBUTORS.txt
1392 * Code distributed by Google as part of the polymer project is also
1393 * subject to an additional IP rights grant found at http://polymer.github.io/PA TENTS.txt
1394 */
1395
1396 (function(scope) {
1397 var dispatcher = scope.dispatcher;
1398 var pointermap = dispatcher.pointermap;
1399 var pointerEvents = {
1400 events: [
1401 'pointerdown',
1402 'pointermove',
1403 'pointerup',
1404 'pointercancel'
1405 ],
1406 prepareEvent: function(inEvent) {
1407 return dispatcher.cloneEvent(inEvent);
1408 },
1409 register: function(target) {
1410 dispatcher.listen(target, this.events);
1411 },
1412 unregister: function(target) {
1413 dispatcher.unlisten(target, this.events);
1414 },
1415 cleanup: function(id) {
1416 pointermap['delete'](id);
1417 },
1418 pointerdown: function(inEvent) {
1419 var e = this.prepareEvent(inEvent);
1420 pointermap.set(e.pointerId, e.target);
1421 dispatcher.down(e);
1422 },
1423 pointermove: function(inEvent) {
1424 var e = this.prepareEvent(inEvent);
1425 e.target = pointermap.get(e.pointerId);
1426 dispatcher.move(e);
1427 },
1428 pointerup: function(inEvent) {
1429 var e = this.prepareEvent(inEvent);
1430 e.relatedTarget = e.target;
1431 e.target = pointermap.get(e.pointerId);
1432 dispatcher.up(e);
1433 this.cleanup(inEvent.pointerId);
1434 },
1435 pointercancel: function(inEvent) {
1436 var e = this.prepareEvent(inEvent);
1437 e.relatedTarget = e.target;
1438 e.target = pointermap.get(e.pointerId);
1439 dispatcher.cancel(e);
1440 this.cleanup(inEvent.pointerId);
1441 }
1442 };
1443
1444 scope.pointerEvents = pointerEvents;
1445 })(window.PolymerGestures);
1446
1447 /*
1448 * Copyright (c) 2014 The Polymer Project Authors. All rights reserved.
1449 * This code may only be used under the BSD style license found at http://polyme r.github.io/LICENSE.txt
1450 * The complete set of authors may be found at http://polymer.github.io/AUTHORS. txt
1451 * The complete set of contributors may be found at http://polymer.github.io/CON TRIBUTORS.txt
1452 * Code distributed by Google as part of the polymer project is also
1453 * subject to an additional IP rights grant found at http://polymer.github.io/PA TENTS.txt
1454 */
1455
1456 /**
1457 * This module contains the handlers for native platform events.
1458 * From here, the dispatcher is called to create unified pointer events.
1459 * Included are touch events (v1), mouse events, and MSPointerEvents.
1460 */
1461 (function(scope) {
1462 var dispatcher = scope.dispatcher;
1463
1464 if (window.PointerEvent) {
1465 dispatcher.registerSource('pointer', scope.pointerEvents);
1466 } else if (window.navigator.msPointerEnabled) {
1467 dispatcher.registerSource('ms', scope.msEvents);
1468 } else {
1469 dispatcher.registerSource('mouse', scope.mouseEvents);
1470 if (window.ontouchstart !== undefined) {
1471 dispatcher.registerSource('touch', scope.touchEvents);
1472 }
1473 }
1474
1475 dispatcher.register(document);
1476 })(window.PolymerGestures);
1477
1478 /*
1479 * Copyright (c) 2014 The Polymer Project Authors. All rights reserved.
1480 * This code may only be used under the BSD style license found at http://polyme r.github.io/LICENSE.txt
1481 * The complete set of authors may be found at http://polymer.github.io/AUTHORS. txt
1482 * The complete set of contributors may be found at http://polymer.github.io/CON TRIBUTORS.txt
1483 * Code distributed by Google as part of the polymer project is also
1484 * subject to an additional IP rights grant found at http://polymer.github.io/PA TENTS.txt
1485 */
1486
1487 /**
1488 * This event denotes the beginning of a series of tracking events.
1489 *
1490 * @module PointerGestures
1491 * @submodule Events
1492 * @class trackstart
1493 */
1494 /**
1495 * Pixels moved in the x direction since trackstart.
1496 * @type Number
1497 * @property dx
1498 */
1499 /**
1500 * Pixes moved in the y direction since trackstart.
1501 * @type Number
1502 * @property dy
1503 */
1504 /**
1505 * Pixels moved in the x direction since the last track.
1506 * @type Number
1507 * @property ddx
1508 */
1509 /**
1510 * Pixles moved in the y direction since the last track.
1511 * @type Number
1512 * @property ddy
1513 */
1514 /**
1515 * The clientX position of the track gesture.
1516 * @type Number
1517 * @property clientX
1518 */
1519 /**
1520 * The clientY position of the track gesture.
1521 * @type Number
1522 * @property clientY
1523 */
1524 /**
1525 * The pageX position of the track gesture.
1526 * @type Number
1527 * @property pageX
1528 */
1529 /**
1530 * The pageY position of the track gesture.
1531 * @type Number
1532 * @property pageY
1533 */
1534 /**
1535 * The screenX position of the track gesture.
1536 * @type Number
1537 * @property screenX
1538 */
1539 /**
1540 * The screenY position of the track gesture.
1541 * @type Number
1542 * @property screenY
1543 */
1544 /**
1545 * The last x axis direction of the pointer.
1546 * @type Number
1547 * @property xDirection
1548 */
1549 /**
1550 * The last y axis direction of the pointer.
1551 * @type Number
1552 * @property yDirection
1553 */
1554 /**
1555 * A shared object between all tracking events.
1556 * @type Object
1557 * @property trackInfo
1558 */
1559 /**
1560 * The element currently under the pointer.
1561 * @type Element
1562 * @property relatedTarget
1563 */
1564 /**
1565 * The type of pointer that make the track gesture.
1566 * @type String
1567 * @property pointerType
1568 */
1569 /**
1570 *
1571 * This event fires for all pointer movement being tracked.
1572 *
1573 * @class track
1574 * @extends trackstart
1575 */
1576 /**
1577 * This event fires when the pointer is no longer being tracked.
1578 *
1579 * @class trackend
1580 * @extends trackstart
1581 */
1582
1583 (function(scope) {
1584 var dispatcher = scope.dispatcher;
1585 var eventFactory = scope.eventFactory;
1586 var pointermap = new scope.PointerMap();
1587 var track = {
1588 events: [
1589 'down',
1590 'move',
1591 'up',
1592 ],
1593 WIGGLE_THRESHOLD: 4,
1594 clampDir: function(inDelta) {
1595 return inDelta > 0 ? 1 : -1;
1596 },
1597 calcPositionDelta: function(inA, inB) {
1598 var x = 0, y = 0;
1599 if (inA && inB) {
1600 x = inB.pageX - inA.pageX;
1601 y = inB.pageY - inA.pageY;
1602 }
1603 return {x: x, y: y};
1604 },
1605 fireTrack: function(inType, inEvent, inTrackingData) {
1606 var t = inTrackingData;
1607 var d = this.calcPositionDelta(t.downEvent, inEvent);
1608 var dd = this.calcPositionDelta(t.lastMoveEvent, inEvent);
1609 if (dd.x) {
1610 t.xDirection = this.clampDir(dd.x);
1611 }
1612 if (dd.y) {
1613 t.yDirection = this.clampDir(dd.y);
1614 }
1615 var e = eventFactory.makeGestureEvent(inType, {
1616 bubbles: true,
1617 cancelable: true,
1618 dx: d.x,
1619 dy: d.y,
1620 ddx: dd.x,
1621 ddy: dd.y,
1622 x: inEvent.x,
1623 y: inEvent.y,
1624 clientX: inEvent.clientX,
1625 clientY: inEvent.clientY,
1626 pageX: inEvent.pageX,
1627 pageY: inEvent.pageY,
1628 screenX: inEvent.screenX,
1629 screenY: inEvent.screenY,
1630 xDirection: t.xDirection,
1631 yDirection: t.yDirection,
1632 trackInfo: t.trackInfo,
1633 relatedTarget: inEvent.relatedTarget,
1634 pointerType: inEvent.pointerType,
1635 pointerId: inEvent.pointerId
1636 });
1637 t.downTarget.dispatchEvent(e);
1638 },
1639 down: function(inEvent) {
1640 if (inEvent.isPrimary && (inEvent.pointerType === 'mouse' ? inEvent.butto ns === 1 : true)) {
1641 var p = {
1642 downEvent: inEvent,
1643 downTarget: inEvent.target,
1644 trackInfo: {},
1645 lastMoveEvent: null,
1646 xDirection: 0,
1647 yDirection: 0,
1648 tracking: false
1649 };
1650 pointermap.set(inEvent.pointerId, p);
1651 }
1652 },
1653 move: function(inEvent) {
1654 var p = pointermap.get(inEvent.pointerId);
1655 if (p) {
1656 if (!p.tracking) {
1657 var d = this.calcPositionDelta(p.downEvent, inEvent);
1658 var move = d.x * d.x + d.y * d.y;
1659 // start tracking only if finger moves more than WIGGLE_THRESHOLD
1660 if (move > this.WIGGLE_THRESHOLD) {
1661 p.tracking = true;
1662 this.fireTrack('trackstart', p.downEvent, p);
1663 this.fireTrack('track', inEvent, p);
1664 }
1665 } else {
1666 this.fireTrack('track', inEvent, p);
1667 }
1668 p.lastMoveEvent = inEvent;
1669 }
1670 },
1671 up: function(inEvent) {
1672 var p = pointermap.get(inEvent.pointerId);
1673 if (p) {
1674 if (p.tracking) {
1675 this.fireTrack('trackend', inEvent, p);
1676 }
1677 pointermap.delete(inEvent.pointerId);
1678 }
1679 }
1680 };
1681 dispatcher.registerGesture('track', track);
1682 })(window.PolymerGestures);
1683
1684 /*
1685 * Copyright (c) 2014 The Polymer Project Authors. All rights reserved.
1686 * This code may only be used under the BSD style license found at http://polyme r.github.io/LICENSE.txt
1687 * The complete set of authors may be found at http://polymer.github.io/AUTHORS. txt
1688 * The complete set of contributors may be found at http://polymer.github.io/CON TRIBUTORS.txt
1689 * Code distributed by Google as part of the polymer project is also
1690 * subject to an additional IP rights grant found at http://polymer.github.io/PA TENTS.txt
1691 */
1692
1693 /**
1694 * This event is fired when a pointer is held down for 200ms.
1695 *
1696 * @module PointerGestures
1697 * @submodule Events
1698 * @class hold
1699 */
1700 /**
1701 * Type of pointer that made the holding event.
1702 * @type String
1703 * @property pointerType
1704 */
1705 /**
1706 * Screen X axis position of the held pointer
1707 * @type Number
1708 * @property clientX
1709 */
1710 /**
1711 * Screen Y axis position of the held pointer
1712 * @type Number
1713 * @property clientY
1714 */
1715 /**
1716 * Type of pointer that made the holding event.
1717 * @type String
1718 * @property pointerType
1719 */
1720 /**
1721 * This event is fired every 200ms while a pointer is held down.
1722 *
1723 * @class holdpulse
1724 * @extends hold
1725 */
1726 /**
1727 * Milliseconds pointer has been held down.
1728 * @type Number
1729 * @property holdTime
1730 */
1731 /**
1732 * This event is fired when a held pointer is released or moved.
1733 *
1734 * @class released
1735 */
1736
1737 (function(scope) {
1738 var dispatcher = scope.dispatcher;
1739 var eventFactory = scope.eventFactory;
1740 var hold = {
1741 // wait at least HOLD_DELAY ms between hold and pulse events
1742 HOLD_DELAY: 200,
1743 // pointer can move WIGGLE_THRESHOLD pixels before not counting as a hold
1744 WIGGLE_THRESHOLD: 16,
1745 events: [
1746 'down',
1747 'move',
1748 'up',
1749 ],
1750 heldPointer: null,
1751 holdJob: null,
1752 pulse: function() {
1753 var hold = Date.now() - this.heldPointer.timeStamp;
1754 var type = this.held ? 'holdpulse' : 'hold';
1755 this.fireHold(type, hold);
1756 this.held = true;
1757 },
1758 cancel: function() {
1759 clearInterval(this.holdJob);
1760 if (this.held) {
1761 this.fireHold('release');
1762 }
1763 this.held = false;
1764 this.heldPointer = null;
1765 this.target = null;
1766 this.holdJob = null;
1767 },
1768 down: function(inEvent) {
1769 if (inEvent.isPrimary && !this.heldPointer) {
1770 this.heldPointer = inEvent;
1771 this.target = inEvent.target;
1772 this.holdJob = setInterval(this.pulse.bind(this), this.HOLD_DELAY);
1773 }
1774 },
1775 up: function(inEvent) {
1776 if (this.heldPointer && this.heldPointer.pointerId === inEvent.pointerId) {
1777 this.cancel();
1778 }
1779 },
1780 move: function(inEvent) {
1781 if (this.heldPointer && this.heldPointer.pointerId === inEvent.pointerId) {
1782 var x = inEvent.clientX - this.heldPointer.clientX;
1783 var y = inEvent.clientY - this.heldPointer.clientY;
1784 if ((x * x + y * y) > this.WIGGLE_THRESHOLD) {
1785 this.cancel();
1786 }
1787 }
1788 },
1789 fireHold: function(inType, inHoldTime) {
1790 var p = {
1791 bubbles: true,
1792 cancelable: true,
1793 pointerType: this.heldPointer.pointerType,
1794 pointerId: this.heldPointer.pointerId,
1795 x: this.heldPointer.clientX,
1796 y: this.heldPointer.clientY
1797 };
1798 if (inHoldTime) {
1799 p.holdTime = inHoldTime;
1800 }
1801 var e = eventFactory.makeGestureEvent(inType, p);
1802 this.target.dispatchEvent(e);
1803 }
1804 };
1805 dispatcher.registerGesture('hold', hold);
1806 })(window.PolymerGestures);
1807
1808 /*
1809 * Copyright (c) 2014 The Polymer Project Authors. All rights reserved.
1810 * This code may only be used under the BSD style license found at http://polyme r.github.io/LICENSE.txt
1811 * The complete set of authors may be found at http://polymer.github.io/AUTHORS. txt
1812 * The complete set of contributors may be found at http://polymer.github.io/CON TRIBUTORS.txt
1813 * Code distributed by Google as part of the polymer project is also
1814 * subject to an additional IP rights grant found at http://polymer.github.io/PA TENTS.txt
1815 */
1816
1817 /**
1818 * This event is fired when a pointer quickly goes down and up, and is used to
1819 * denote activation.
1820 *
1821 * Any gesture event can prevent the tap event from being created by calling
1822 * `event.preventTap`.
1823 *
1824 * Any pointer event can prevent the tap by setting the `tapPrevented` property
1825 * on itself.
1826 *
1827 * @module PointerGestures
1828 * @submodule Events
1829 * @class tap
1830 */
1831 /**
1832 * X axis position of the tap.
1833 * @property x
1834 * @type Number
1835 */
1836 /**
1837 * Y axis position of the tap.
1838 * @property y
1839 * @type Number
1840 */
1841 /**
1842 * Type of the pointer that made the tap.
1843 * @property pointerType
1844 * @type String
1845 */
1846 (function(scope) {
1847 var dispatcher = scope.dispatcher;
1848 var eventFactory = scope.eventFactory;
1849 var pointermap = new scope.PointerMap();
1850 var tap = {
1851 events: [
1852 'down',
1853 'up'
1854 ],
1855 down: function(inEvent) {
1856 if (inEvent.isPrimary && !inEvent.tapPrevented) {
1857 pointermap.set(inEvent.pointerId, {
1858 target: inEvent.target,
1859 buttons: inEvent.buttons,
1860 x: inEvent.clientX,
1861 y: inEvent.clientY
1862 });
1863 }
1864 },
1865 shouldTap: function(e, downState) {
1866 if (e.pointerType === 'mouse') {
1867 // only allow left click to tap for mouse
1868 return downState.buttons === 1;
1869 }
1870 return !e.tapPrevented;
1871 },
1872 up: function(inEvent) {
1873 var start = pointermap.get(inEvent.pointerId);
1874 if (start && this.shouldTap(inEvent, start)) {
1875 // up.relatedTarget is target currently under finger
1876 var t = scope.targetFinding.LCA(start.target, inEvent.relatedTarget);
1877 if (t) {
1878 var e = eventFactory.makeGestureEvent('tap', {
1879 bubbles: true,
1880 cancelable: true,
1881 x: inEvent.clientX,
1882 y: inEvent.clientY,
1883 detail: inEvent.detail,
1884 pointerType: inEvent.pointerType,
1885 pointerId: inEvent.pointerId,
1886 altKey: inEvent.altKey,
1887 ctrlKey: inEvent.ctrlKey,
1888 metaKey: inEvent.metaKey,
1889 shiftKey: inEvent.shiftKey
1890 });
1891 t.dispatchEvent(e);
1892 }
1893 }
1894 pointermap.delete(inEvent.pointerId);
1895 }
1896 };
1897 // patch eventFactory to remove id from tap's pointermap for preventTap calls
1898 eventFactory.preventTap = function(e) {
1899 return function() {
1900 e.tapPrevented = true;
1901 pointermap.delete(e.pointerId);
1902 };
1903 };
1904 dispatcher.registerGesture('tap', tap);
1905 })(window.PolymerGestures);
1906
1907 /*
1908 Copyright (C) 2013 Ariya Hidayat <ariya.hidayat@gmail.com>
1909 Copyright (C) 2013 Thaddee Tyl <thaddee.tyl@gmail.com>
1910 Copyright (C) 2012 Ariya Hidayat <ariya.hidayat@gmail.com>
1911 Copyright (C) 2012 Mathias Bynens <mathias@qiwi.be>
1912 Copyright (C) 2012 Joost-Wim Boekesteijn <joost-wim@boekesteijn.nl>
1913 Copyright (C) 2012 Kris Kowal <kris.kowal@cixar.com>
1914 Copyright (C) 2012 Yusuke Suzuki <utatane.tea@gmail.com>
1915 Copyright (C) 2012 Arpad Borsos <arpad.borsos@googlemail.com>
1916 Copyright (C) 2011 Ariya Hidayat <ariya.hidayat@gmail.com>
1917
1918 Redistribution and use in source and binary forms, with or without
1919 modification, are permitted provided that the following conditions are met:
1920
1921 * Redistributions of source code must retain the above copyright
1922 notice, this list of conditions and the following disclaimer.
1923 * Redistributions in binary form must reproduce the above copyright
1924 notice, this list of conditions and the following disclaimer in the
1925 documentation and/or other materials provided with the distribution.
1926
1927 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
1928 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1929 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1930 ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
1931 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
1932 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
1933 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
1934 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
1935 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
1936 THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
1937 */
1938
1939 (function (global) {
1940 'use strict';
1941
1942 var Token,
1943 TokenName,
1944 Syntax,
1945 Messages,
1946 source,
1947 index,
1948 length,
1949 delegate,
1950 lookahead,
1951 state;
1952
1953 Token = {
1954 BooleanLiteral: 1,
1955 EOF: 2,
1956 Identifier: 3,
1957 Keyword: 4,
1958 NullLiteral: 5,
1959 NumericLiteral: 6,
1960 Punctuator: 7,
1961 StringLiteral: 8
1962 };
1963
1964 TokenName = {};
1965 TokenName[Token.BooleanLiteral] = 'Boolean';
1966 TokenName[Token.EOF] = '<end>';
1967 TokenName[Token.Identifier] = 'Identifier';
1968 TokenName[Token.Keyword] = 'Keyword';
1969 TokenName[Token.NullLiteral] = 'Null';
1970 TokenName[Token.NumericLiteral] = 'Numeric';
1971 TokenName[Token.Punctuator] = 'Punctuator';
1972 TokenName[Token.StringLiteral] = 'String';
1973
1974 Syntax = {
1975 ArrayExpression: 'ArrayExpression',
1976 BinaryExpression: 'BinaryExpression',
1977 CallExpression: 'CallExpression',
1978 ConditionalExpression: 'ConditionalExpression',
1979 EmptyStatement: 'EmptyStatement',
1980 ExpressionStatement: 'ExpressionStatement',
1981 Identifier: 'Identifier',
1982 Literal: 'Literal',
1983 LabeledStatement: 'LabeledStatement',
1984 LogicalExpression: 'LogicalExpression',
1985 MemberExpression: 'MemberExpression',
1986 ObjectExpression: 'ObjectExpression',
1987 Program: 'Program',
1988 Property: 'Property',
1989 ThisExpression: 'ThisExpression',
1990 UnaryExpression: 'UnaryExpression'
1991 };
1992
1993 // Error messages should be identical to V8.
1994 Messages = {
1995 UnexpectedToken: 'Unexpected token %0',
1996 UnknownLabel: 'Undefined label \'%0\'',
1997 Redeclaration: '%0 \'%1\' has already been declared'
1998 };
1999
2000 // Ensure the condition is true, otherwise throw an error.
2001 // This is only to have a better contract semantic, i.e. another safety net
2002 // to catch a logic error. The condition shall be fulfilled in normal case.
2003 // Do NOT use this to enforce a certain condition on any user input.
2004
2005 function assert(condition, message) {
2006 if (!condition) {
2007 throw new Error('ASSERT: ' + message);
2008 }
2009 }
2010
2011 function isDecimalDigit(ch) {
2012 return (ch >= 48 && ch <= 57); // 0..9
2013 }
2014
2015
2016 // 7.2 White Space
2017
2018 function isWhiteSpace(ch) {
2019 return (ch === 32) || // space
2020 (ch === 9) || // tab
2021 (ch === 0xB) ||
2022 (ch === 0xC) ||
2023 (ch === 0xA0) ||
2024 (ch >= 0x1680 && '\u1680\u180E\u2000\u2001\u2002\u2003\u2004\u2005\u 2006\u2007\u2008\u2009\u200A\u202F\u205F\u3000\uFEFF'.indexOf(String.fromCharCod e(ch)) > 0);
2025 }
2026
2027 // 7.3 Line Terminators
2028
2029 function isLineTerminator(ch) {
2030 return (ch === 10) || (ch === 13) || (ch === 0x2028) || (ch === 0x2029);
2031 }
2032
2033 // 7.6 Identifier Names and Identifiers
2034
2035 function isIdentifierStart(ch) {
2036 return (ch === 36) || (ch === 95) || // $ (dollar) and _ (underscore)
2037 (ch >= 65 && ch <= 90) || // A..Z
2038 (ch >= 97 && ch <= 122); // a..z
2039 }
2040
2041 function isIdentifierPart(ch) {
2042 return (ch === 36) || (ch === 95) || // $ (dollar) and _ (underscore)
2043 (ch >= 65 && ch <= 90) || // A..Z
2044 (ch >= 97 && ch <= 122) || // a..z
2045 (ch >= 48 && ch <= 57); // 0..9
2046 }
2047
2048 // 7.6.1.1 Keywords
2049
2050 function isKeyword(id) {
2051 return (id === 'this')
2052 }
2053
2054 // 7.4 Comments
2055
2056 function skipWhitespace() {
2057 while (index < length && isWhiteSpace(source.charCodeAt(index))) {
2058 ++index;
2059 }
2060 }
2061
2062 function getIdentifier() {
2063 var start, ch;
2064
2065 start = index++;
2066 while (index < length) {
2067 ch = source.charCodeAt(index);
2068 if (isIdentifierPart(ch)) {
2069 ++index;
2070 } else {
2071 break;
2072 }
2073 }
2074
2075 return source.slice(start, index);
2076 }
2077
2078 function scanIdentifier() {
2079 var start, id, type;
2080
2081 start = index;
2082
2083 id = getIdentifier();
2084
2085 // There is no keyword or literal with only one character.
2086 // Thus, it must be an identifier.
2087 if (id.length === 1) {
2088 type = Token.Identifier;
2089 } else if (isKeyword(id)) {
2090 type = Token.Keyword;
2091 } else if (id === 'null') {
2092 type = Token.NullLiteral;
2093 } else if (id === 'true' || id === 'false') {
2094 type = Token.BooleanLiteral;
2095 } else {
2096 type = Token.Identifier;
2097 }
2098
2099 return {
2100 type: type,
2101 value: id,
2102 range: [start, index]
2103 };
2104 }
2105
2106
2107 // 7.7 Punctuators
2108
2109 function scanPunctuator() {
2110 var start = index,
2111 code = source.charCodeAt(index),
2112 code2,
2113 ch1 = source[index],
2114 ch2;
2115
2116 switch (code) {
2117
2118 // Check for most common single-character punctuators.
2119 case 46: // . dot
2120 case 40: // ( open bracket
2121 case 41: // ) close bracket
2122 case 59: // ; semicolon
2123 case 44: // , comma
2124 case 123: // { open curly brace
2125 case 125: // } close curly brace
2126 case 91: // [
2127 case 93: // ]
2128 case 58: // :
2129 case 63: // ?
2130 ++index;
2131 return {
2132 type: Token.Punctuator,
2133 value: String.fromCharCode(code),
2134 range: [start, index]
2135 };
2136
2137 default:
2138 code2 = source.charCodeAt(index + 1);
2139
2140 // '=' (char #61) marks an assignment or comparison operator.
2141 if (code2 === 61) {
2142 switch (code) {
2143 case 37: // %
2144 case 38: // &
2145 case 42: // *:
2146 case 43: // +
2147 case 45: // -
2148 case 47: // /
2149 case 60: // <
2150 case 62: // >
2151 case 124: // |
2152 index += 2;
2153 return {
2154 type: Token.Punctuator,
2155 value: String.fromCharCode(code) + String.fromCharCode(c ode2),
2156 range: [start, index]
2157 };
2158
2159 case 33: // !
2160 case 61: // =
2161 index += 2;
2162
2163 // !== and ===
2164 if (source.charCodeAt(index) === 61) {
2165 ++index;
2166 }
2167 return {
2168 type: Token.Punctuator,
2169 value: source.slice(start, index),
2170 range: [start, index]
2171 };
2172 default:
2173 break;
2174 }
2175 }
2176 break;
2177 }
2178
2179 // Peek more characters.
2180
2181 ch2 = source[index + 1];
2182
2183 // Other 2-character punctuators: && ||
2184
2185 if (ch1 === ch2 && ('&|'.indexOf(ch1) >= 0)) {
2186 index += 2;
2187 return {
2188 type: Token.Punctuator,
2189 value: ch1 + ch2,
2190 range: [start, index]
2191 };
2192 }
2193
2194 if ('<>=!+-*%&|^/'.indexOf(ch1) >= 0) {
2195 ++index;
2196 return {
2197 type: Token.Punctuator,
2198 value: ch1,
2199 range: [start, index]
2200 };
2201 }
2202
2203 throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
2204 }
2205
2206 // 7.8.3 Numeric Literals
2207 function scanNumericLiteral() {
2208 var number, start, ch;
2209
2210 ch = source[index];
2211 assert(isDecimalDigit(ch.charCodeAt(0)) || (ch === '.'),
2212 'Numeric literal must start with a decimal digit or a decimal point' );
2213
2214 start = index;
2215 number = '';
2216 if (ch !== '.') {
2217 number = source[index++];
2218 ch = source[index];
2219
2220 // Hex number starts with '0x'.
2221 // Octal number starts with '0'.
2222 if (number === '0') {
2223 // decimal number starts with '0' such as '09' is illegal.
2224 if (ch && isDecimalDigit(ch.charCodeAt(0))) {
2225 throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
2226 }
2227 }
2228
2229 while (isDecimalDigit(source.charCodeAt(index))) {
2230 number += source[index++];
2231 }
2232 ch = source[index];
2233 }
2234
2235 if (ch === '.') {
2236 number += source[index++];
2237 while (isDecimalDigit(source.charCodeAt(index))) {
2238 number += source[index++];
2239 }
2240 ch = source[index];
2241 }
2242
2243 if (ch === 'e' || ch === 'E') {
2244 number += source[index++];
2245
2246 ch = source[index];
2247 if (ch === '+' || ch === '-') {
2248 number += source[index++];
2249 }
2250 if (isDecimalDigit(source.charCodeAt(index))) {
2251 while (isDecimalDigit(source.charCodeAt(index))) {
2252 number += source[index++];
2253 }
2254 } else {
2255 throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
2256 }
2257 }
2258
2259 if (isIdentifierStart(source.charCodeAt(index))) {
2260 throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
2261 }
2262
2263 return {
2264 type: Token.NumericLiteral,
2265 value: parseFloat(number),
2266 range: [start, index]
2267 };
2268 }
2269
2270 // 7.8.4 String Literals
2271
2272 function scanStringLiteral() {
2273 var str = '', quote, start, ch, octal = false;
2274
2275 quote = source[index];
2276 assert((quote === '\'' || quote === '"'),
2277 'String literal must starts with a quote');
2278
2279 start = index;
2280 ++index;
2281
2282 while (index < length) {
2283 ch = source[index++];
2284
2285 if (ch === quote) {
2286 quote = '';
2287 break;
2288 } else if (ch === '\\') {
2289 ch = source[index++];
2290 if (!ch || !isLineTerminator(ch.charCodeAt(0))) {
2291 switch (ch) {
2292 case 'n':
2293 str += '\n';
2294 break;
2295 case 'r':
2296 str += '\r';
2297 break;
2298 case 't':
2299 str += '\t';
2300 break;
2301 case 'b':
2302 str += '\b';
2303 break;
2304 case 'f':
2305 str += '\f';
2306 break;
2307 case 'v':
2308 str += '\x0B';
2309 break;
2310
2311 default:
2312 str += ch;
2313 break;
2314 }
2315 } else {
2316 if (ch === '\r' && source[index] === '\n') {
2317 ++index;
2318 }
2319 }
2320 } else if (isLineTerminator(ch.charCodeAt(0))) {
2321 break;
2322 } else {
2323 str += ch;
2324 }
2325 }
2326
2327 if (quote !== '') {
2328 throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
2329 }
2330
2331 return {
2332 type: Token.StringLiteral,
2333 value: str,
2334 octal: octal,
2335 range: [start, index]
2336 };
2337 }
2338
2339 function isIdentifierName(token) {
2340 return token.type === Token.Identifier ||
2341 token.type === Token.Keyword ||
2342 token.type === Token.BooleanLiteral ||
2343 token.type === Token.NullLiteral;
2344 }
2345
2346 function advance() {
2347 var ch;
2348
2349 skipWhitespace();
2350
2351 if (index >= length) {
2352 return {
2353 type: Token.EOF,
2354 range: [index, index]
2355 };
2356 }
2357
2358 ch = source.charCodeAt(index);
2359
2360 // Very common: ( and ) and ;
2361 if (ch === 40 || ch === 41 || ch === 58) {
2362 return scanPunctuator();
2363 }
2364
2365 // String literal starts with single quote (#39) or double quote (#34).
2366 if (ch === 39 || ch === 34) {
2367 return scanStringLiteral();
2368 }
2369
2370 if (isIdentifierStart(ch)) {
2371 return scanIdentifier();
2372 }
2373
2374 // Dot (.) char #46 can also start a floating-point number, hence the ne ed
2375 // to check the next character.
2376 if (ch === 46) {
2377 if (isDecimalDigit(source.charCodeAt(index + 1))) {
2378 return scanNumericLiteral();
2379 }
2380 return scanPunctuator();
2381 }
2382
2383 if (isDecimalDigit(ch)) {
2384 return scanNumericLiteral();
2385 }
2386
2387 return scanPunctuator();
2388 }
2389
2390 function lex() {
2391 var token;
2392
2393 token = lookahead;
2394 index = token.range[1];
2395
2396 lookahead = advance();
2397
2398 index = token.range[1];
2399
2400 return token;
2401 }
2402
2403 function peek() {
2404 var pos;
2405
2406 pos = index;
2407 lookahead = advance();
2408 index = pos;
2409 }
2410
2411 // Throw an exception
2412
2413 function throwError(token, messageFormat) {
2414 var error,
2415 args = Array.prototype.slice.call(arguments, 2),
2416 msg = messageFormat.replace(
2417 /%(\d)/g,
2418 function (whole, index) {
2419 assert(index < args.length, 'Message reference must be in ra nge');
2420 return args[index];
2421 }
2422 );
2423
2424 error = new Error(msg);
2425 error.index = index;
2426 error.description = msg;
2427 throw error;
2428 }
2429
2430 // Throw an exception because of the token.
2431
2432 function throwUnexpected(token) {
2433 throwError(token, Messages.UnexpectedToken, token.value);
2434 }
2435
2436 // Expect the next token to match the specified punctuator.
2437 // If not, an exception will be thrown.
2438
2439 function expect(value) {
2440 var token = lex();
2441 if (token.type !== Token.Punctuator || token.value !== value) {
2442 throwUnexpected(token);
2443 }
2444 }
2445
2446 // Return true if the next token matches the specified punctuator.
2447
2448 function match(value) {
2449 return lookahead.type === Token.Punctuator && lookahead.value === value;
2450 }
2451
2452 // Return true if the next token matches the specified keyword
2453
2454 function matchKeyword(keyword) {
2455 return lookahead.type === Token.Keyword && lookahead.value === keyword;
2456 }
2457
2458 function consumeSemicolon() {
2459 // Catch the very common case first: immediately a semicolon (char #59).
2460 if (source.charCodeAt(index) === 59) {
2461 lex();
2462 return;
2463 }
2464
2465 skipWhitespace();
2466
2467 if (match(';')) {
2468 lex();
2469 return;
2470 }
2471
2472 if (lookahead.type !== Token.EOF && !match('}')) {
2473 throwUnexpected(lookahead);
2474 }
2475 }
2476
2477 // 11.1.4 Array Initialiser
2478
2479 function parseArrayInitialiser() {
2480 var elements = [];
2481
2482 expect('[');
2483
2484 while (!match(']')) {
2485 if (match(',')) {
2486 lex();
2487 elements.push(null);
2488 } else {
2489 elements.push(parseExpression());
2490
2491 if (!match(']')) {
2492 expect(',');
2493 }
2494 }
2495 }
2496
2497 expect(']');
2498
2499 return delegate.createArrayExpression(elements);
2500 }
2501
2502 // 11.1.5 Object Initialiser
2503
2504 function parseObjectPropertyKey() {
2505 var token;
2506
2507 skipWhitespace();
2508 token = lex();
2509
2510 // Note: This function is called only from parseObjectProperty(), where
2511 // EOF and Punctuator tokens are already filtered out.
2512 if (token.type === Token.StringLiteral || token.type === Token.NumericLi teral) {
2513 return delegate.createLiteral(token);
2514 }
2515
2516 return delegate.createIdentifier(token.value);
2517 }
2518
2519 function parseObjectProperty() {
2520 var token, key;
2521
2522 token = lookahead;
2523 skipWhitespace();
2524
2525 if (token.type === Token.EOF || token.type === Token.Punctuator) {
2526 throwUnexpected(token);
2527 }
2528
2529 key = parseObjectPropertyKey();
2530 expect(':');
2531 return delegate.createProperty('init', key, parseExpression());
2532 }
2533
2534 function parseObjectInitialiser() {
2535 var properties = [];
2536
2537 expect('{');
2538
2539 while (!match('}')) {
2540 properties.push(parseObjectProperty());
2541
2542 if (!match('}')) {
2543 expect(',');
2544 }
2545 }
2546
2547 expect('}');
2548
2549 return delegate.createObjectExpression(properties);
2550 }
2551
2552 // 11.1.6 The Grouping Operator
2553
2554 function parseGroupExpression() {
2555 var expr;
2556
2557 expect('(');
2558
2559 expr = parseExpression();
2560
2561 expect(')');
2562
2563 return expr;
2564 }
2565
2566
2567 // 11.1 Primary Expressions
2568
2569 function parsePrimaryExpression() {
2570 var type, token, expr;
2571
2572 if (match('(')) {
2573 return parseGroupExpression();
2574 }
2575
2576 type = lookahead.type;
2577
2578 if (type === Token.Identifier) {
2579 expr = delegate.createIdentifier(lex().value);
2580 } else if (type === Token.StringLiteral || type === Token.NumericLiteral ) {
2581 expr = delegate.createLiteral(lex());
2582 } else if (type === Token.Keyword) {
2583 if (matchKeyword('this')) {
2584 lex();
2585 expr = delegate.createThisExpression();
2586 }
2587 } else if (type === Token.BooleanLiteral) {
2588 token = lex();
2589 token.value = (token.value === 'true');
2590 expr = delegate.createLiteral(token);
2591 } else if (type === Token.NullLiteral) {
2592 token = lex();
2593 token.value = null;
2594 expr = delegate.createLiteral(token);
2595 } else if (match('[')) {
2596 expr = parseArrayInitialiser();
2597 } else if (match('{')) {
2598 expr = parseObjectInitialiser();
2599 }
2600
2601 if (expr) {
2602 return expr;
2603 }
2604
2605 throwUnexpected(lex());
2606 }
2607
2608 // 11.2 Left-Hand-Side Expressions
2609
2610 function parseArguments() {
2611 var args = [];
2612
2613 expect('(');
2614
2615 if (!match(')')) {
2616 while (index < length) {
2617 args.push(parseExpression());
2618 if (match(')')) {
2619 break;
2620 }
2621 expect(',');
2622 }
2623 }
2624
2625 expect(')');
2626
2627 return args;
2628 }
2629
2630 function parseNonComputedProperty() {
2631 var token;
2632
2633 token = lex();
2634
2635 if (!isIdentifierName(token)) {
2636 throwUnexpected(token);
2637 }
2638
2639 return delegate.createIdentifier(token.value);
2640 }
2641
2642 function parseNonComputedMember() {
2643 expect('.');
2644
2645 return parseNonComputedProperty();
2646 }
2647
2648 function parseComputedMember() {
2649 var expr;
2650
2651 expect('[');
2652
2653 expr = parseExpression();
2654
2655 expect(']');
2656
2657 return expr;
2658 }
2659
2660 function parseLeftHandSideExpression() {
2661 var expr, property;
2662
2663 expr = parsePrimaryExpression();
2664
2665 while (match('.') || match('[')) {
2666 if (match('[')) {
2667 property = parseComputedMember();
2668 expr = delegate.createMemberExpression('[', expr, property);
2669 } else {
2670 property = parseNonComputedMember();
2671 expr = delegate.createMemberExpression('.', expr, property);
2672 }
2673 }
2674
2675 return expr;
2676 }
2677
2678 // 11.3 Postfix Expressions
2679
2680 var parsePostfixExpression = parseLeftHandSideExpression;
2681
2682 // 11.4 Unary Operators
2683
2684 function parseUnaryExpression() {
2685 var token, expr;
2686
2687 if (lookahead.type !== Token.Punctuator && lookahead.type !== Token.Keyw ord) {
2688 expr = parsePostfixExpression();
2689 } else if (match('+') || match('-') || match('!')) {
2690 token = lex();
2691 expr = parseUnaryExpression();
2692 expr = delegate.createUnaryExpression(token.value, expr);
2693 } else if (matchKeyword('delete') || matchKeyword('void') || matchKeywor d('typeof')) {
2694 throwError({}, Messages.UnexpectedToken);
2695 } else {
2696 expr = parsePostfixExpression();
2697 }
2698
2699 return expr;
2700 }
2701
2702 function binaryPrecedence(token) {
2703 var prec = 0;
2704
2705 if (token.type !== Token.Punctuator && token.type !== Token.Keyword) {
2706 return 0;
2707 }
2708
2709 switch (token.value) {
2710 case '||':
2711 prec = 1;
2712 break;
2713
2714 case '&&':
2715 prec = 2;
2716 break;
2717
2718 case '==':
2719 case '!=':
2720 case '===':
2721 case '!==':
2722 prec = 6;
2723 break;
2724
2725 case '<':
2726 case '>':
2727 case '<=':
2728 case '>=':
2729 case 'instanceof':
2730 prec = 7;
2731 break;
2732
2733 case 'in':
2734 prec = 7;
2735 break;
2736
2737 case '+':
2738 case '-':
2739 prec = 9;
2740 break;
2741
2742 case '*':
2743 case '/':
2744 case '%':
2745 prec = 11;
2746 break;
2747
2748 default:
2749 break;
2750 }
2751
2752 return prec;
2753 }
2754
2755 // 11.5 Multiplicative Operators
2756 // 11.6 Additive Operators
2757 // 11.7 Bitwise Shift Operators
2758 // 11.8 Relational Operators
2759 // 11.9 Equality Operators
2760 // 11.10 Binary Bitwise Operators
2761 // 11.11 Binary Logical Operators
2762
2763 function parseBinaryExpression() {
2764 var expr, token, prec, stack, right, operator, left, i;
2765
2766 left = parseUnaryExpression();
2767
2768 token = lookahead;
2769 prec = binaryPrecedence(token);
2770 if (prec === 0) {
2771 return left;
2772 }
2773 token.prec = prec;
2774 lex();
2775
2776 right = parseUnaryExpression();
2777
2778 stack = [left, token, right];
2779
2780 while ((prec = binaryPrecedence(lookahead)) > 0) {
2781
2782 // Reduce: make a binary expression from the three topmost entries.
2783 while ((stack.length > 2) && (prec <= stack[stack.length - 2].prec)) {
2784 right = stack.pop();
2785 operator = stack.pop().value;
2786 left = stack.pop();
2787 expr = delegate.createBinaryExpression(operator, left, right);
2788 stack.push(expr);
2789 }
2790
2791 // Shift.
2792 token = lex();
2793 token.prec = prec;
2794 stack.push(token);
2795 expr = parseUnaryExpression();
2796 stack.push(expr);
2797 }
2798
2799 // Final reduce to clean-up the stack.
2800 i = stack.length - 1;
2801 expr = stack[i];
2802 while (i > 1) {
2803 expr = delegate.createBinaryExpression(stack[i - 1].value, stack[i - 2], expr);
2804 i -= 2;
2805 }
2806
2807 return expr;
2808 }
2809
2810
2811 // 11.12 Conditional Operator
2812
2813 function parseConditionalExpression() {
2814 var expr, consequent, alternate;
2815
2816 expr = parseBinaryExpression();
2817
2818 if (match('?')) {
2819 lex();
2820 consequent = parseConditionalExpression();
2821 expect(':');
2822 alternate = parseConditionalExpression();
2823
2824 expr = delegate.createConditionalExpression(expr, consequent, altern ate);
2825 }
2826
2827 return expr;
2828 }
2829
2830 // Simplification since we do not support AssignmentExpression.
2831 var parseExpression = parseConditionalExpression;
2832
2833 // Polymer Syntax extensions
2834
2835 // Filter ::
2836 // Identifier
2837 // Identifier "(" ")"
2838 // Identifier "(" FilterArguments ")"
2839
2840 function parseFilter() {
2841 var identifier, args;
2842
2843 identifier = lex();
2844
2845 if (identifier.type !== Token.Identifier) {
2846 throwUnexpected(identifier);
2847 }
2848
2849 args = match('(') ? parseArguments() : [];
2850
2851 return delegate.createFilter(identifier.value, args);
2852 }
2853
2854 // Filters ::
2855 // "|" Filter
2856 // Filters "|" Filter
2857
2858 function parseFilters() {
2859 while (match('|')) {
2860 lex();
2861 parseFilter();
2862 }
2863 }
2864
2865 // TopLevel ::
2866 // LabelledExpressions
2867 // AsExpression
2868 // InExpression
2869 // FilterExpression
2870
2871 // AsExpression ::
2872 // FilterExpression as Identifier
2873
2874 // InExpression ::
2875 // Identifier, Identifier in FilterExpression
2876 // Identifier in FilterExpression
2877
2878 // FilterExpression ::
2879 // Expression
2880 // Expression Filters
2881
2882 function parseTopLevel() {
2883 skipWhitespace();
2884 peek();
2885
2886 var expr = parseExpression();
2887 if (expr) {
2888 if (lookahead.value === ',' || lookahead.value == 'in' &&
2889 expr.type === Syntax.Identifier) {
2890 parseInExpression(expr);
2891 } else {
2892 parseFilters();
2893 if (lookahead.value === 'as') {
2894 parseAsExpression(expr);
2895 } else {
2896 delegate.createTopLevel(expr);
2897 }
2898 }
2899 }
2900
2901 if (lookahead.type !== Token.EOF) {
2902 throwUnexpected(lookahead);
2903 }
2904 }
2905
2906 function parseAsExpression(expr) {
2907 lex(); // as
2908 var identifier = lex().value;
2909 delegate.createAsExpression(expr, identifier);
2910 }
2911
2912 function parseInExpression(identifier) {
2913 var indexName;
2914 if (lookahead.value === ',') {
2915 lex();
2916 if (lookahead.type !== Token.Identifier)
2917 throwUnexpected(lookahead);
2918 indexName = lex().value;
2919 }
2920
2921 lex(); // in
2922 var expr = parseExpression();
2923 parseFilters();
2924 delegate.createInExpression(identifier.name, indexName, expr);
2925 }
2926
2927 function parse(code, inDelegate) {
2928 delegate = inDelegate;
2929 source = code;
2930 index = 0;
2931 length = source.length;
2932 lookahead = null;
2933 state = {
2934 labelSet: {}
2935 };
2936
2937 return parseTopLevel();
2938 }
2939
2940 global.esprima = {
2941 parse: parse
2942 };
2943 })(this);
2944
2945 // Copyright (c) 2014 The Polymer Project Authors. All rights reserved.
2946 // This code may only be used under the BSD style license found at http://polyme r.github.io/LICENSE.txt
2947 // The complete set of authors may be found at http://polymer.github.io/AUTHORS. txt
2948 // The complete set of contributors may be found at http://polymer.github.io/CON TRIBUTORS.txt
2949 // Code distributed by Google as part of the polymer project is also
2950 // subject to an additional IP rights grant found at http://polymer.github.io/PA TENTS.txt
2951
2952 (function (global) {
2953 'use strict';
2954
2955 function prepareBinding(expressionText, name, node, filterRegistry) {
2956 var expression;
2957 try {
2958 expression = getExpression(expressionText);
2959 if (expression.scopeIdent &&
2960 (node.nodeType !== Node.ELEMENT_NODE ||
2961 node.tagName !== 'TEMPLATE' ||
2962 (name !== 'bind' && name !== 'repeat'))) {
2963 throw Error('as and in can only be used within <template bind/repeat>');
2964 }
2965 } catch (ex) {
2966 console.error('Invalid expression syntax: ' + expressionText, ex);
2967 return;
2968 }
2969
2970 return function(model, node, oneTime) {
2971 var binding = expression.getBinding(model, filterRegistry, oneTime);
2972 if (expression.scopeIdent && binding) {
2973 node.polymerExpressionScopeIdent_ = expression.scopeIdent;
2974 if (expression.indexIdent)
2975 node.polymerExpressionIndexIdent_ = expression.indexIdent;
2976 }
2977
2978 return binding;
2979 }
2980 }
2981
2982 // TODO(rafaelw): Implement simple LRU.
2983 var expressionParseCache = Object.create(null);
2984
2985 function getExpression(expressionText) {
2986 var expression = expressionParseCache[expressionText];
2987 if (!expression) {
2988 var delegate = new ASTDelegate();
2989 esprima.parse(expressionText, delegate);
2990 expression = new Expression(delegate);
2991 expressionParseCache[expressionText] = expression;
2992 }
2993 return expression;
2994 }
2995
2996 function Literal(value) {
2997 this.value = value;
2998 this.valueFn_ = undefined;
2999 }
3000
3001 Literal.prototype = {
3002 valueFn: function() {
3003 if (!this.valueFn_) {
3004 var value = this.value;
3005 this.valueFn_ = function() {
3006 return value;
3007 }
3008 }
3009
3010 return this.valueFn_;
3011 }
3012 }
3013
3014 function IdentPath(name) {
3015 this.name = name;
3016 this.path = Path.get(name);
3017 }
3018
3019 IdentPath.prototype = {
3020 valueFn: function() {
3021 if (!this.valueFn_) {
3022 var name = this.name;
3023 var path = this.path;
3024 this.valueFn_ = function(model, observer) {
3025 if (observer)
3026 observer.addPath(model, path);
3027
3028 return path.getValueFrom(model);
3029 }
3030 }
3031
3032 return this.valueFn_;
3033 },
3034
3035 setValue: function(model, newValue) {
3036 if (this.path.length == 1);
3037 model = findScope(model, this.path[0]);
3038
3039 return this.path.setValueFrom(model, newValue);
3040 }
3041 };
3042
3043 function MemberExpression(object, property, accessor) {
3044 this.dynamicDeps = typeof object == 'function' ||
3045 object.dynamicDeps ||
3046 (accessor == '[' && !(property instanceof Literal));
3047
3048 // convert literal computed property access where literal value is a value
3049 // path to ident dot-access.
3050 if (accessor == '[' &&
3051 property instanceof Literal &&
3052 Path.get(property.value).valid) {
3053 accessor = '.';
3054 property = new IdentPath(property.value);
3055 }
3056
3057 this.simplePath =
3058 !this.dynamicDeps &&
3059 property instanceof IdentPath &&
3060 (object instanceof MemberExpression || object instanceof IdentPath);
3061
3062 this.object = this.simplePath ? object : getFn(object);
3063 this.property = accessor == '.' ? property : getFn(property);
3064 }
3065
3066 MemberExpression.prototype = {
3067 get fullPath() {
3068 if (!this.fullPath_) {
3069 var last = this.object instanceof IdentPath ?
3070 this.object.name : this.object.fullPath;
3071 this.fullPath_ = Path.get(last + '.' + this.property.name);
3072 }
3073
3074 return this.fullPath_;
3075 },
3076
3077 valueFn: function() {
3078 if (!this.valueFn_) {
3079 var object = this.object;
3080
3081 if (this.simplePath) {
3082 var path = this.fullPath;
3083
3084 this.valueFn_ = function(model, observer) {
3085 if (observer)
3086 observer.addPath(model, path);
3087
3088 return path.getValueFrom(model);
3089 };
3090 } else if (this.property instanceof IdentPath) {
3091 var path = Path.get(this.property.name);
3092
3093 this.valueFn_ = function(model, observer) {
3094 var context = object(model, observer);
3095
3096 if (observer)
3097 observer.addPath(context, path);
3098
3099 return path.getValueFrom(context);
3100 }
3101 } else {
3102 // Computed property.
3103 var property = this.property;
3104
3105 this.valueFn_ = function(model, observer) {
3106 var context = object(model, observer);
3107 var propName = property(model, observer);
3108 if (observer)
3109 observer.addPath(context, propName);
3110
3111 return context ? context[propName] : undefined;
3112 };
3113 }
3114 }
3115 return this.valueFn_;
3116 },
3117
3118 setValue: function(model, newValue) {
3119 if (this.simplePath) {
3120 this.fullPath.setValueFrom(model, newValue);
3121 return newValue;
3122 }
3123
3124 var object = this.object(model);
3125 var propName = this.property instanceof IdentPath ? this.property.name :
3126 this.property(model);
3127 return object[propName] = newValue;
3128 }
3129 };
3130
3131 function Filter(name, args) {
3132 this.name = name;
3133 this.args = [];
3134 for (var i = 0; i < args.length; i++) {
3135 this.args[i] = getFn(args[i]);
3136 }
3137 }
3138
3139 Filter.prototype = {
3140 transform: function(value, toModelDirection, filterRegistry, model,
3141 observer) {
3142 var fn = filterRegistry[this.name];
3143 var context = model;
3144 if (fn) {
3145 context = undefined;
3146 } else {
3147 fn = context[this.name];
3148 if (!fn) {
3149 console.error('Cannot find filter: ' + this.name);
3150 return;
3151 }
3152 }
3153
3154 // If toModelDirection is falsey, then the "normal" (dom-bound) direction
3155 // is used. Otherwise, it looks for a 'toModel' property function on the
3156 // object.
3157 if (toModelDirection) {
3158 fn = fn.toModel;
3159 } else if (typeof fn.toDOM == 'function') {
3160 fn = fn.toDOM;
3161 }
3162
3163 if (typeof fn != 'function') {
3164 console.error('No ' + (toModelDirection ? 'toModel' : 'toDOM') +
3165 ' found on' + this.name);
3166 return;
3167 }
3168
3169 var args = [value];
3170 for (var i = 0; i < this.args.length; i++) {
3171 args[i + 1] = getFn(this.args[i])(model, observer);
3172 }
3173
3174 return fn.apply(context, args);
3175 }
3176 };
3177
3178 function notImplemented() { throw Error('Not Implemented'); }
3179
3180 var unaryOperators = {
3181 '+': function(v) { return +v; },
3182 '-': function(v) { return -v; },
3183 '!': function(v) { return !v; }
3184 };
3185
3186 var binaryOperators = {
3187 '+': function(l, r) { return l+r; },
3188 '-': function(l, r) { return l-r; },
3189 '*': function(l, r) { return l*r; },
3190 '/': function(l, r) { return l/r; },
3191 '%': function(l, r) { return l%r; },
3192 '<': function(l, r) { return l<r; },
3193 '>': function(l, r) { return l>r; },
3194 '<=': function(l, r) { return l<=r; },
3195 '>=': function(l, r) { return l>=r; },
3196 '==': function(l, r) { return l==r; },
3197 '!=': function(l, r) { return l!=r; },
3198 '===': function(l, r) { return l===r; },
3199 '!==': function(l, r) { return l!==r; },
3200 '&&': function(l, r) { return l&&r; },
3201 '||': function(l, r) { return l||r; },
3202 };
3203
3204 function getFn(arg) {
3205 return typeof arg == 'function' ? arg : arg.valueFn();
3206 }
3207
3208 function ASTDelegate() {
3209 this.expression = null;
3210 this.filters = [];
3211 this.deps = {};
3212 this.currentPath = undefined;
3213 this.scopeIdent = undefined;
3214 this.indexIdent = undefined;
3215 this.dynamicDeps = false;
3216 }
3217
3218 ASTDelegate.prototype = {
3219 createUnaryExpression: function(op, argument) {
3220 if (!unaryOperators[op])
3221 throw Error('Disallowed operator: ' + op);
3222
3223 argument = getFn(argument);
3224
3225 return function(model, observer) {
3226 return unaryOperators[op](argument(model, observer));
3227 };
3228 },
3229
3230 createBinaryExpression: function(op, left, right) {
3231 if (!binaryOperators[op])
3232 throw Error('Disallowed operator: ' + op);
3233
3234 left = getFn(left);
3235 right = getFn(right);
3236
3237 return function(model, observer) {
3238 return binaryOperators[op](left(model, observer),
3239 right(model, observer));
3240 };
3241 },
3242
3243 createConditionalExpression: function(test, consequent, alternate) {
3244 test = getFn(test);
3245 consequent = getFn(consequent);
3246 alternate = getFn(alternate);
3247
3248 return function(model, observer) {
3249 return test(model, observer) ?
3250 consequent(model, observer) : alternate(model, observer);
3251 }
3252 },
3253
3254 createIdentifier: function(name) {
3255 var ident = new IdentPath(name);
3256 ident.type = 'Identifier';
3257 return ident;
3258 },
3259
3260 createMemberExpression: function(accessor, object, property) {
3261 var ex = new MemberExpression(object, property, accessor);
3262 if (ex.dynamicDeps)
3263 this.dynamicDeps = true;
3264 return ex;
3265 },
3266
3267 createLiteral: function(token) {
3268 return new Literal(token.value);
3269 },
3270
3271 createArrayExpression: function(elements) {
3272 for (var i = 0; i < elements.length; i++)
3273 elements[i] = getFn(elements[i]);
3274
3275 return function(model, observer) {
3276 var arr = []
3277 for (var i = 0; i < elements.length; i++)
3278 arr.push(elements[i](model, observer));
3279 return arr;
3280 }
3281 },
3282
3283 createProperty: function(kind, key, value) {
3284 return {
3285 key: key instanceof IdentPath ? key.name : key.value,
3286 value: value
3287 };
3288 },
3289
3290 createObjectExpression: function(properties) {
3291 for (var i = 0; i < properties.length; i++)
3292 properties[i].value = getFn(properties[i].value);
3293
3294 return function(model, observer) {
3295 var obj = {};
3296 for (var i = 0; i < properties.length; i++)
3297 obj[properties[i].key] = properties[i].value(model, observer);
3298 return obj;
3299 }
3300 },
3301
3302 createFilter: function(name, args) {
3303 this.filters.push(new Filter(name, args));
3304 },
3305
3306 createAsExpression: function(expression, scopeIdent) {
3307 this.expression = expression;
3308 this.scopeIdent = scopeIdent;
3309 },
3310
3311 createInExpression: function(scopeIdent, indexIdent, expression) {
3312 this.expression = expression;
3313 this.scopeIdent = scopeIdent;
3314 this.indexIdent = indexIdent;
3315 },
3316
3317 createTopLevel: function(expression) {
3318 this.expression = expression;
3319 },
3320
3321 createThisExpression: notImplemented
3322 }
3323
3324 function ConstantObservable(value) {
3325 this.value_ = value;
3326 }
3327
3328 ConstantObservable.prototype = {
3329 open: function() { return this.value_; },
3330 discardChanges: function() { return this.value_; },
3331 deliver: function() {},
3332 close: function() {},
3333 }
3334
3335 function Expression(delegate) {
3336 this.scopeIdent = delegate.scopeIdent;
3337 this.indexIdent = delegate.indexIdent;
3338
3339 if (!delegate.expression)
3340 throw Error('No expression found.');
3341
3342 this.expression = delegate.expression;
3343 getFn(this.expression); // forces enumeration of path dependencies
3344
3345 this.filters = delegate.filters;
3346 this.dynamicDeps = delegate.dynamicDeps;
3347 }
3348
3349 Expression.prototype = {
3350 getBinding: function(model, filterRegistry, oneTime) {
3351 if (oneTime)
3352 return this.getValue(model, undefined, filterRegistry);
3353
3354 var observer = new CompoundObserver();
3355 // captures deps.
3356 var firstValue = this.getValue(model, observer, filterRegistry);
3357 var firstTime = true;
3358 var self = this;
3359
3360 function valueFn() {
3361 // deps cannot have changed on first value retrieval.
3362 if (firstTime) {
3363 firstTime = false;
3364 return firstValue;
3365 }
3366
3367 if (self.dynamicDeps)
3368 observer.startReset();
3369
3370 var value = self.getValue(model,
3371 self.dynamicDeps ? observer : undefined,
3372 filterRegistry);
3373 if (self.dynamicDeps)
3374 observer.finishReset();
3375
3376 return value;
3377 }
3378
3379 function setValueFn(newValue) {
3380 self.setValue(model, newValue, filterRegistry);
3381 return newValue;
3382 }
3383
3384 return new ObserverTransform(observer, valueFn, setValueFn, true);
3385 },
3386
3387 getValue: function(model, observer, filterRegistry) {
3388 var value = getFn(this.expression)(model, observer);
3389 for (var i = 0; i < this.filters.length; i++) {
3390 value = this.filters[i].transform(value, false, filterRegistry, model,
3391 observer);
3392 }
3393
3394 return value;
3395 },
3396
3397 setValue: function(model, newValue, filterRegistry) {
3398 var count = this.filters ? this.filters.length : 0;
3399 while (count-- > 0) {
3400 newValue = this.filters[count].transform(newValue, true, filterRegistry,
3401 model);
3402 }
3403
3404 if (this.expression.setValue)
3405 return this.expression.setValue(model, newValue);
3406 }
3407 }
3408
3409 /**
3410 * Converts a style property name to a css property name. For example:
3411 * "WebkitUserSelect" to "-webkit-user-select"
3412 */
3413 function convertStylePropertyName(name) {
3414 return String(name).replace(/[A-Z]/g, function(c) {
3415 return '-' + c.toLowerCase();
3416 });
3417 }
3418
3419 var parentScopeName = '@' + Math.random().toString(36).slice(2);
3420
3421 // Single ident paths must bind directly to the appropriate scope object.
3422 // I.e. Pushed values in two-bindings need to be assigned to the actual model
3423 // object.
3424 function findScope(model, prop) {
3425 while (model[parentScopeName] &&
3426 !Object.prototype.hasOwnProperty.call(model, prop)) {
3427 model = model[parentScopeName];
3428 }
3429
3430 return model;
3431 }
3432
3433 function isLiteralExpression(pathString) {
3434 switch (pathString) {
3435 case '':
3436 return false;
3437
3438 case 'false':
3439 case 'null':
3440 case 'true':
3441 return true;
3442 }
3443
3444 if (!isNaN(Number(pathString)))
3445 return true;
3446
3447 return false;
3448 };
3449
3450 function PolymerExpressions() {}
3451
3452 PolymerExpressions.prototype = {
3453 // "built-in" filters
3454 styleObject: function(value) {
3455 var parts = [];
3456 for (var key in value) {
3457 parts.push(convertStylePropertyName(key) + ': ' + value[key]);
3458 }
3459 return parts.join('; ');
3460 },
3461
3462 tokenList: function(value) {
3463 var tokens = [];
3464 for (var key in value) {
3465 if (value[key])
3466 tokens.push(key);
3467 }
3468 return tokens.join(' ');
3469 },
3470
3471 // binding delegate API
3472 prepareInstancePositionChanged: function(template) {
3473 var indexIdent = template.polymerExpressionIndexIdent_;
3474 if (!indexIdent)
3475 return;
3476
3477 return function(templateInstance, index) {
3478 templateInstance.model[indexIdent] = index;
3479 };
3480 },
3481
3482 prepareBinding: function(pathString, name, node) {
3483 var path = Path.get(pathString);
3484
3485 if (!isLiteralExpression(pathString) && path.valid) {
3486 if (path.length == 1) {
3487 return function(model, node, oneTime) {
3488 if (oneTime)
3489 return path.getValueFrom(model);
3490
3491 var scope = findScope(model, path[0]);
3492 return new PathObserver(scope, path);
3493 };
3494 }
3495 return; // bail out early if pathString is simple path.
3496 }
3497
3498 return prepareBinding(pathString, name, node, this);
3499 },
3500
3501 prepareInstanceModel: function(template) {
3502 var scopeName = template.polymerExpressionScopeIdent_;
3503 if (!scopeName)
3504 return;
3505
3506 var parentScope = template.templateInstance ?
3507 template.templateInstance.model :
3508 template.model;
3509
3510 var indexName = template.polymerExpressionIndexIdent_;
3511
3512 return function(model) {
3513 var scope = Object.create(parentScope);
3514 scope[scopeName] = model;
3515 scope[indexName] = undefined;
3516 scope[parentScopeName] = parentScope;
3517 return scope;
3518 };
3519 }
3520 };
3521
3522 global.PolymerExpressions = PolymerExpressions;
3523 if (global.exposeGetExpression)
3524 global.getExpression_ = getExpression;
3525
3526 })(this);
3527
3528 /*
3529 * Copyright (c) 2014 The Polymer Project Authors. All rights reserved.
3530 * This code may only be used under the BSD style license found at http://polyme r.github.io/LICENSE.txt
3531 * The complete set of authors may be found at http://polymer.github.io/AUTHORS. txt
3532 * The complete set of contributors may be found at http://polymer.github.io/CON TRIBUTORS.txt
3533 * Code distributed by Google as part of the polymer project is also
3534 * subject to an additional IP rights grant found at http://polymer.github.io/PA TENTS.txt
3535 */
3536 Polymer = {
3537 version: '0.3.1-604ba08'
3538 };
3539
3540 /*
3541 * Copyright (c) 2014 The Polymer Project Authors. All rights reserved.
3542 * This code may only be used under the BSD style license found at http://polyme r.github.io/LICENSE.txt
3543 * The complete set of authors may be found at http://polymer.github.io/AUTHORS. txt
3544 * The complete set of contributors may be found at http://polymer.github.io/CON TRIBUTORS.txt
3545 * Code distributed by Google as part of the polymer project is also
3546 * subject to an additional IP rights grant found at http://polymer.github.io/PA TENTS.txt
12 */ 3547 */
13 3548
14 // TODO(sorvell): this ensures Polymer is an object and not a function 3549 // TODO(sorvell): this ensures Polymer is an object and not a function
15 // Platform is currently defining it as a function to allow for async loading 3550 // Platform is currently defining it as a function to allow for async loading
16 // of polymer; once we refine the loading process this likely goes away. 3551 // of polymer; once we refine the loading process this likely goes away.
17 if (typeof window.Polymer === 'function') { 3552 if (typeof window.Polymer === 'function') {
18 Polymer = {}; 3553 Polymer = {};
19 } 3554 }
20 3555
21 3556
22 /* 3557 /*
23 * Copyright 2013 The Polymer Authors. All rights reserved. 3558 * Copyright (c) 2014 The Polymer Project Authors. All rights reserved.
24 * Use of this source code is governed by a BSD-style 3559 * This code may only be used under the BSD style license found at http://polyme r.github.io/LICENSE.txt
25 * license that can be found in the LICENSE file. 3560 * The complete set of authors may be found at http://polymer.github.io/AUTHORS. txt
3561 * The complete set of contributors may be found at http://polymer.github.io/CON TRIBUTORS.txt
3562 * Code distributed by Google as part of the polymer project is also
3563 * subject to an additional IP rights grant found at http://polymer.github.io/PA TENTS.txt
26 */ 3564 */
3565
27 (function(scope) { 3566 (function(scope) {
28 3567
29 // copy own properties from 'api' to 'prototype, with name hinting for 'super' 3568 // copy own properties from 'api' to 'prototype, with name hinting for 'super'
30 function extend(prototype, api) { 3569 function extend(prototype, api) {
31 if (prototype && api) { 3570 if (prototype && api) {
32 // use only own properties of 'api' 3571 // use only own properties of 'api'
33 Object.getOwnPropertyNames(api).forEach(function(n) { 3572 Object.getOwnPropertyNames(api).forEach(function(n) {
34 // acquire property descriptor 3573 // acquire property descriptor
35 var pd = Object.getOwnPropertyDescriptor(api, n); 3574 var pd = Object.getOwnPropertyDescriptor(api, n);
36 if (pd) { 3575 if (pd) {
37 // clone property via descriptor 3576 // clone property via descriptor
38 Object.defineProperty(prototype, n, pd); 3577 Object.defineProperty(prototype, n, pd);
39 // cache name-of-method for 'super' engine 3578 // cache name-of-method for 'super' engine
40 if (typeof pd.value == 'function') { 3579 if (typeof pd.value == 'function') {
41 // hint the 'super' engine 3580 // hint the 'super' engine
42 pd.value.nom = n; 3581 pd.value.nom = n;
43 } 3582 }
44 } 3583 }
45 }); 3584 });
46 } 3585 }
47 return prototype; 3586 return prototype;
48 } 3587 }
49 3588
50 // exports 3589 // exports
51 3590
52 scope.extend = extend; 3591 scope.extend = extend;
53 3592
54 })(Polymer); 3593 })(Polymer);
55 3594
56 /* 3595 /*
57 * Copyright 2013 The Polymer Authors. All rights reserved. 3596 * Copyright (c) 2014 The Polymer Project Authors. All rights reserved.
58 * Use of this source code is governed by a BSD-style 3597 * This code may only be used under the BSD style license found at http://polyme r.github.io/LICENSE.txt
59 * license that can be found in the LICENSE file. 3598 * The complete set of authors may be found at http://polymer.github.io/AUTHORS. txt
3599 * The complete set of contributors may be found at http://polymer.github.io/CON TRIBUTORS.txt
3600 * Code distributed by Google as part of the polymer project is also
3601 * subject to an additional IP rights grant found at http://polymer.github.io/PA TENTS.txt
60 */ 3602 */
61 3603
62 (function(scope) { 3604 (function(scope) {
63 3605
64 // usage 3606 // usage
65 3607
66 // invoke cb.call(this) in 100ms, unless the job is re-registered, 3608 // invoke cb.call(this) in 100ms, unless the job is re-registered,
67 // which resets the timer 3609 // which resets the timer
68 // 3610 //
69 // this.myJob = this.job(this.myJob, cb, 100) 3611 // this.myJob = this.job(this.myJob, cb, 100)
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
114 return job; 3656 return job;
115 } 3657 }
116 3658
117 // exports 3659 // exports
118 3660
119 scope.job = job; 3661 scope.job = job;
120 3662
121 })(Polymer); 3663 })(Polymer);
122 3664
123 /* 3665 /*
124 * Copyright 2013 The Polymer Authors. All rights reserved. 3666 * Copyright (c) 2014 The Polymer Project Authors. All rights reserved.
125 * Use of this source code is governed by a BSD-style 3667 * This code may only be used under the BSD style license found at http://polyme r.github.io/LICENSE.txt
126 * license that can be found in the LICENSE file. 3668 * The complete set of authors may be found at http://polymer.github.io/AUTHORS. txt
3669 * The complete set of contributors may be found at http://polymer.github.io/CON TRIBUTORS.txt
3670 * Code distributed by Google as part of the polymer project is also
3671 * subject to an additional IP rights grant found at http://polymer.github.io/PA TENTS.txt
127 */ 3672 */
3673
128 (function(scope) { 3674 (function(scope) {
129 3675
130 var registry = {}; 3676 var registry = {};
131 3677
132 HTMLElement.register = function(tag, prototype) { 3678 HTMLElement.register = function(tag, prototype) {
133 registry[tag] = prototype; 3679 registry[tag] = prototype;
134 } 3680 }
135 3681
136 // get prototype mapped to node <tag> 3682 // get prototype mapped to node <tag>
137 HTMLElement.getPrototypeForTag = function(tag) { 3683 HTMLElement.getPrototypeForTag = function(tag) {
(...skipping 11 matching lines...) Expand all
149 3695
150 // TODO(sorvell): remove when we're sure imports does not need 3696 // TODO(sorvell): remove when we're sure imports does not need
151 // to load stylesheets 3697 // to load stylesheets
152 /* 3698 /*
153 HTMLImports.importer.preloadSelectors += 3699 HTMLImports.importer.preloadSelectors +=
154 ', polymer-element link[rel=stylesheet]'; 3700 ', polymer-element link[rel=stylesheet]';
155 */ 3701 */
156 })(Polymer); 3702 })(Polymer);
157 3703
158 /* 3704 /*
159 * Copyright 2013 The Polymer Authors. All rights reserved. 3705 * Copyright (c) 2014 The Polymer Project Authors. All rights reserved.
160 * Use of this source code is governed by a BSD-style 3706 * This code may only be used under the BSD style license found at http://polyme r.github.io/LICENSE.txt
161 * license that can be found in the LICENSE file. 3707 * The complete set of authors may be found at http://polymer.github.io/AUTHORS. txt
3708 * The complete set of contributors may be found at http://polymer.github.io/CON TRIBUTORS.txt
3709 * Code distributed by Google as part of the polymer project is also
3710 * subject to an additional IP rights grant found at http://polymer.github.io/PA TENTS.txt
162 */ 3711 */
3712
163 (function(scope) { 3713 (function(scope) {
164 // super 3714 // super
165 3715
166 // `arrayOfArgs` is an optional array of args like one might pass 3716 // `arrayOfArgs` is an optional array of args like one might pass
167 // to `Function.apply` 3717 // to `Function.apply`
168 3718
169 // TODO(sjmiles): 3719 // TODO(sjmiles):
170 // $super must be installed on an instance or prototype chain 3720 // $super must be installed on an instance or prototype chain
171 // as `super`, and invoked via `this`, e.g. 3721 // as `super`, and invoked via `this`, e.g.
172 // `this.super();` 3722 // `this.super();`
(...skipping 16 matching lines...) Expand all
189 var _super = caller._super; 3739 var _super = caller._super;
190 if (!_super) { 3740 if (!_super) {
191 if (!nom) { 3741 if (!nom) {
192 nom = caller.nom = nameInThis.call(this, caller); 3742 nom = caller.nom = nameInThis.call(this, caller);
193 } 3743 }
194 if (!nom) { 3744 if (!nom) {
195 console.warn('called super() on a method not installed declaratively ( has no .nom property)'); 3745 console.warn('called super() on a method not installed declaratively ( has no .nom property)');
196 } 3746 }
197 // super prototype is either cached or we have to find it 3747 // super prototype is either cached or we have to find it
198 // by searching __proto__ (at the 'top') 3748 // by searching __proto__ (at the 'top')
3749 // invariant: because we cache _super on fn below, we never reach
3750 // here from inside a series of calls to super(), so it's ok to
3751 // start searching from the prototype of 'this' (at the 'top')
3752 // we must never memoize a null super for this reason
199 _super = memoizeSuper(caller, nom, getPrototypeOf(this)); 3753 _super = memoizeSuper(caller, nom, getPrototypeOf(this));
200 } 3754 }
201 if (!_super) { 3755 // our super function
202 // if _super is falsey, there is no super implementation 3756 var fn = _super[nom];
203 //console.warn('called $super(' + nom + ') where there is no super imple mentation'); 3757 if (fn) {
204 } else {
205 // our super function
206 var fn = _super[nom];
207 // memoize information so 'fn' can call 'super' 3758 // memoize information so 'fn' can call 'super'
208 if (!fn._super) { 3759 if (!fn._super) {
3760 // must not memoize null, or we lose our invariant above
209 memoizeSuper(fn, nom, _super); 3761 memoizeSuper(fn, nom, _super);
210 } 3762 }
211 // invoke the inherited method 3763 // invoke the inherited method
212 // if 'fn' is not function valued, this will throw 3764 // if 'fn' is not function valued, this will throw
213 return fn.apply(this, arrayOfArgs || []); 3765 return fn.apply(this, arrayOfArgs || []);
214 } 3766 }
215 } 3767 }
216 3768
217 function nextSuper(proto, name, caller) {
218 // look for an inherited prototype that implements name
219 while (proto) {
220 if ((proto[name] !== caller) && proto[name]) {
221 return proto;
222 }
223 proto = getPrototypeOf(proto);
224 }
225 }
226
227 function memoizeSuper(method, name, proto) {
228 // find and cache next prototype containing `name`
229 // we need the prototype so we can do another lookup
230 // from here
231 method._super = nextSuper(proto, name, method);
232 if (method._super) {
233 // _super is a prototype, the actual method is _super[name]
234 // tag super method with it's name for further lookups
235 method._super[name].nom = name;
236 }
237 return method._super;
238 }
239
240 function nameInThis(value) { 3769 function nameInThis(value) {
241 var p = this.__proto__; 3770 var p = this.__proto__;
242 while (p && p !== HTMLElement.prototype) { 3771 while (p && p !== HTMLElement.prototype) {
243 // TODO(sjmiles): getOwnPropertyNames is absurdly expensive 3772 // TODO(sjmiles): getOwnPropertyNames is absurdly expensive
244 var n$ = Object.getOwnPropertyNames(p); 3773 var n$ = Object.getOwnPropertyNames(p);
245 for (var i=0, l=n$.length, n; i<l && (n=n$[i]); i++) { 3774 for (var i=0, l=n$.length, n; i<l && (n=n$[i]); i++) {
246 var d = Object.getOwnPropertyDescriptor(p, n); 3775 var d = Object.getOwnPropertyDescriptor(p, n);
247 if (typeof d.value === 'function' && d.value === value) { 3776 if (typeof d.value === 'function' && d.value === value) {
248 return n; 3777 return n;
249 } 3778 }
250 } 3779 }
251 p = p.__proto__; 3780 p = p.__proto__;
252 } 3781 }
253 } 3782 }
254 3783
3784 function memoizeSuper(method, name, proto) {
3785 // find and cache next prototype containing `name`
3786 // we need the prototype so we can do another lookup
3787 // from here
3788 var s = nextSuper(proto, name, method);
3789 if (s[name]) {
3790 // `s` is a prototype, the actual method is `s[name]`
3791 // tag super method with it's name for quicker lookups
3792 s[name].nom = name;
3793 }
3794 return method._super = s;
3795 }
3796
3797 function nextSuper(proto, name, caller) {
3798 // look for an inherited prototype that implements name
3799 while (proto) {
3800 if ((proto[name] !== caller) && proto[name]) {
3801 return proto;
3802 }
3803 proto = getPrototypeOf(proto);
3804 }
3805 // must not return null, or we lose our invariant above
3806 // in this case, a super() call was invoked where no superclass
3807 // method exists
3808 // TODO(sjmiles): thow an exception?
3809 return Object;
3810 }
3811
255 // NOTE: In some platforms (IE10) the prototype chain is faked via 3812 // NOTE: In some platforms (IE10) the prototype chain is faked via
256 // __proto__. Therefore, always get prototype via __proto__ instead of 3813 // __proto__. Therefore, always get prototype via __proto__ instead of
257 // the more standard Object.getPrototypeOf. 3814 // the more standard Object.getPrototypeOf.
258 function getPrototypeOf(prototype) { 3815 function getPrototypeOf(prototype) {
259 return prototype.__proto__; 3816 return prototype.__proto__;
260 } 3817 }
261 3818
262 // utility function to precompute name tags for functions 3819 // utility function to precompute name tags for functions
263 // in a (unchained) prototype 3820 // in a (unchained) prototype
264 function hintSuper(prototype) { 3821 function hintSuper(prototype) {
265 // tag functions with their prototype name to optimize 3822 // tag functions with their prototype name to optimize
266 // super call invocations 3823 // super call invocations
267 for (var n in prototype) { 3824 for (var n in prototype) {
268 var pd = Object.getOwnPropertyDescriptor(prototype, n); 3825 var pd = Object.getOwnPropertyDescriptor(prototype, n);
269 if (pd && typeof pd.value === 'function') { 3826 if (pd && typeof pd.value === 'function') {
270 pd.value.nom = n; 3827 pd.value.nom = n;
271 } 3828 }
272 } 3829 }
273 } 3830 }
274 3831
275 // exports 3832 // exports
276 3833
277 scope.super = $super; 3834 scope.super = $super;
278 3835
279 })(Polymer); 3836 })(Polymer);
280 3837
281 /* 3838 /*
282 * Copyright 2013 The Polymer Authors. All rights reserved. 3839 * Copyright (c) 2014 The Polymer Project Authors. All rights reserved.
283 * Use of this source code is governed by a BSD-style 3840 * This code may only be used under the BSD style license found at http://polyme r.github.io/LICENSE.txt
284 * license that can be found in the LICENSE file. 3841 * The complete set of authors may be found at http://polymer.github.io/AUTHORS. txt
3842 * The complete set of contributors may be found at http://polymer.github.io/CON TRIBUTORS.txt
3843 * Code distributed by Google as part of the polymer project is also
3844 * subject to an additional IP rights grant found at http://polymer.github.io/PA TENTS.txt
285 */ 3845 */
286 3846
287 (function(scope) { 3847 (function(scope) {
288 3848
289 var typeHandlers = { 3849 var typeHandlers = {
290 string: function(value) { 3850 string: function(value) {
291 return value; 3851 return value;
292 }, 3852 },
293 date: function(value) { 3853 date: function(value) {
294 return new Date(Date.parse(value) || Date.now()); 3854 return new Date(Date.parse(value) || Date.now());
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
341 return typeHandlers[inferredType](value, currentValue); 3901 return typeHandlers[inferredType](value, currentValue);
342 } 3902 }
343 3903
344 // exports 3904 // exports
345 3905
346 scope.deserializeValue = deserializeValue; 3906 scope.deserializeValue = deserializeValue;
347 3907
348 })(Polymer); 3908 })(Polymer);
349 3909
350 /* 3910 /*
351 * Copyright 2013 The Polymer Authors. All rights reserved. 3911 * Copyright (c) 2014 The Polymer Project Authors. All rights reserved.
352 * Use of this source code is governed by a BSD-style 3912 * This code may only be used under the BSD style license found at http://polyme r.github.io/LICENSE.txt
353 * license that can be found in the LICENSE file. 3913 * The complete set of authors may be found at http://polymer.github.io/AUTHORS. txt
3914 * The complete set of contributors may be found at http://polymer.github.io/CON TRIBUTORS.txt
3915 * Code distributed by Google as part of the polymer project is also
3916 * subject to an additional IP rights grant found at http://polymer.github.io/PA TENTS.txt
354 */ 3917 */
355 (function(scope) { 3918 (function(scope) {
356 3919
357 // imports 3920 // imports
358 3921
359 var extend = scope.extend; 3922 var extend = scope.extend;
360 3923
361 // module 3924 // module
362 3925
363 var api = {}; 3926 var api = {};
364 3927
365 api.declaration = {}; 3928 api.declaration = {};
366 api.instance = {}; 3929 api.instance = {};
367 3930
368 api.publish = function(apis, prototype) { 3931 api.publish = function(apis, prototype) {
369 for (var n in apis) { 3932 for (var n in apis) {
370 extend(prototype, apis[n]); 3933 extend(prototype, apis[n]);
371 } 3934 }
372 } 3935 };
373 3936
374 // exports 3937 // exports
375 3938
376 scope.api = api; 3939 scope.api = api;
377 3940
378 })(Polymer); 3941 })(Polymer);
379 3942
380 /* 3943 /*
381 * Copyright 2013 The Polymer Authors. All rights reserved. 3944 * Copyright (c) 2014 The Polymer Project Authors. All rights reserved.
382 * Use of this source code is governed by a BSD-style 3945 * This code may only be used under the BSD style license found at http://polyme r.github.io/LICENSE.txt
383 * license that can be found in the LICENSE file. 3946 * The complete set of authors may be found at http://polymer.github.io/AUTHORS. txt
3947 * The complete set of contributors may be found at http://polymer.github.io/CON TRIBUTORS.txt
3948 * Code distributed by Google as part of the polymer project is also
3949 * subject to an additional IP rights grant found at http://polymer.github.io/PA TENTS.txt
384 */ 3950 */
3951
385 (function(scope) { 3952 (function(scope) {
386 3953
387 var utils = { 3954 var utils = {
388 /** 3955 /**
389 * Invokes a function asynchronously. The context of the callback 3956 * Invokes a function asynchronously. The context of the callback
390 * function is bound to 'this' automatically. 3957 * function is bound to 'this' automatically.
391 * @method async 3958 * @method async
392 * @param {Function|String} method 3959 * @param {Function|String} method
393 * @param {any|Array} args 3960 * @param {any|Array} args
394 * @param {number} timeout 3961 * @param {number} timeout
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after
474 4041
475 // exports 4042 // exports
476 4043
477 scope.api.instance.utils = utils; 4044 scope.api.instance.utils = utils;
478 scope.nop = nop; 4045 scope.nop = nop;
479 scope.nob = nob; 4046 scope.nob = nob;
480 4047
481 })(Polymer); 4048 })(Polymer);
482 4049
483 /* 4050 /*
484 * Copyright 2013 The Polymer Authors. All rights reserved. 4051 * Copyright (c) 2014 The Polymer Project Authors. All rights reserved.
485 * Use of this source code is governed by a BSD-style 4052 * This code may only be used under the BSD style license found at http://polyme r.github.io/LICENSE.txt
486 * license that can be found in the LICENSE file. 4053 * The complete set of authors may be found at http://polymer.github.io/AUTHORS. txt
4054 * The complete set of contributors may be found at http://polymer.github.io/CON TRIBUTORS.txt
4055 * Code distributed by Google as part of the polymer project is also
4056 * subject to an additional IP rights grant found at http://polymer.github.io/PA TENTS.txt
487 */ 4057 */
488 4058
489 (function(scope) { 4059 (function(scope) {
490 4060
491 // imports 4061 // imports
492 4062
493 var log = window.logFlags || {}; 4063 var log = window.logFlags || {};
494 var EVENT_PREFIX = 'on-'; 4064 var EVENT_PREFIX = 'on-';
495 4065
496 // instance events api 4066 // instance events api
497 var events = { 4067 var events = {
498 // read-only 4068 // read-only
499 EVENT_PREFIX: EVENT_PREFIX, 4069 EVENT_PREFIX: EVENT_PREFIX,
500 // event listeners on host 4070 // event listeners on host
501 addHostListeners: function() { 4071 addHostListeners: function() {
502 var events = this.eventDelegates; 4072 var events = this.eventDelegates;
503 log.events && (Object.keys(events).length > 0) && console.log('[%s] addHos tListeners:', this.localName, events); 4073 log.events && (Object.keys(events).length > 0) && console.log('[%s] addHos tListeners:', this.localName, events);
504 // NOTE: host events look like bindings but really are not; 4074 // NOTE: host events look like bindings but really are not;
505 // (1) we don't want the attribute to be set and (2) we want to support 4075 // (1) we don't want the attribute to be set and (2) we want to support
506 // multiple event listeners ('host' and 'instance') and Node.bind 4076 // multiple event listeners ('host' and 'instance') and Node.bind
507 // by default supports 1 thing being bound. 4077 // by default supports 1 thing being bound.
508 // We do, however, leverage the event hookup code in PolymerExpressions 4078 for (var type in events) {
509 // so that we have a common code path for handling declarative events. 4079 var methodName = events[type];
510 var self = this, bindable, eventName; 4080 this.addEventListener(type, this.element.getEventHandler(this, this,
511 for (var n in events) { 4081 methodName));
512 eventName = EVENT_PREFIX + n;
513 bindable = PolymerExpressions.prepareEventBinding(
514 Path.get(events[n]),
515 eventName,
516 {
517 resolveEventHandler: function(model, path, node) {
518 var fn = path.getValueFrom(self);
519 if (fn) {
520 return fn.bind(self);
521 }
522 }
523 }
524 );
525 bindable(this, this, false);
526 } 4082 }
527 }, 4083 },
528 // call 'method' or function method on 'obj' with 'args', if the method exis ts 4084 // call 'method' or function method on 'obj' with 'args', if the method exis ts
529 dispatchMethod: function(obj, method, args) { 4085 dispatchMethod: function(obj, method, args) {
530 if (obj) { 4086 if (obj) {
531 log.events && console.group('[%s] dispatch [%s]', obj.localName, method) ; 4087 log.events && console.group('[%s] dispatch [%s]', obj.localName, method) ;
532 var fn = typeof method === 'function' ? method : obj[method]; 4088 var fn = typeof method === 'function' ? method : obj[method];
533 if (fn) { 4089 if (fn) {
534 fn[args ? 'apply' : 'call'](obj, args); 4090 fn[args ? 'apply' : 'call'](obj, args);
535 } 4091 }
536 log.events && console.groupEnd(); 4092 log.events && console.groupEnd();
537 Platform.flush(); 4093 Platform.flush();
538 } 4094 }
539 } 4095 }
540 }; 4096 };
541 4097
542 // exports 4098 // exports
543 4099
544 scope.api.instance.events = events; 4100 scope.api.instance.events = events;
545 4101
546 })(Polymer); 4102 })(Polymer);
547 4103
548 /* 4104 /*
549 * Copyright 2013 The Polymer Authors. All rights reserved. 4105 * Copyright (c) 2014 The Polymer Project Authors. All rights reserved.
550 * Use of this source code is governed by a BSD-style 4106 * This code may only be used under the BSD style license found at http://polyme r.github.io/LICENSE.txt
551 * license that can be found in the LICENSE file. 4107 * The complete set of authors may be found at http://polymer.github.io/AUTHORS. txt
4108 * The complete set of contributors may be found at http://polymer.github.io/CON TRIBUTORS.txt
4109 * Code distributed by Google as part of the polymer project is also
4110 * subject to an additional IP rights grant found at http://polymer.github.io/PA TENTS.txt
552 */ 4111 */
4112
553 (function(scope) { 4113 (function(scope) {
554 4114
555 // instance api for attributes 4115 // instance api for attributes
556 4116
557 var attributes = { 4117 var attributes = {
558 copyInstanceAttributes: function () { 4118 copyInstanceAttributes: function () {
559 var a$ = this._instanceAttributes; 4119 var a$ = this._instanceAttributes;
560 for (var k in a$) { 4120 for (var k in a$) {
561 if (!this.hasAttribute(k)) { 4121 if (!this.hasAttribute(k)) {
562 this.setAttribute(k, a$[k]); 4122 this.setAttribute(k, a$[k]);
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after
633 } 4193 }
634 }; 4194 };
635 4195
636 // exports 4196 // exports
637 4197
638 scope.api.instance.attributes = attributes; 4198 scope.api.instance.attributes = attributes;
639 4199
640 })(Polymer); 4200 })(Polymer);
641 4201
642 /* 4202 /*
643 * Copyright 2013 The Polymer Authors. All rights reserved. 4203 * Copyright (c) 2014 The Polymer Project Authors. All rights reserved.
644 * Use of this source code is governed by a BSD-style 4204 * This code may only be used under the BSD style license found at http://polyme r.github.io/LICENSE.txt
645 * license that can be found in the LICENSE file. 4205 * The complete set of authors may be found at http://polymer.github.io/AUTHORS. txt
4206 * The complete set of contributors may be found at http://polymer.github.io/CON TRIBUTORS.txt
4207 * Code distributed by Google as part of the polymer project is also
4208 * subject to an additional IP rights grant found at http://polymer.github.io/PA TENTS.txt
646 */ 4209 */
4210
647 (function(scope) { 4211 (function(scope) {
648 4212
649 // imports 4213 // imports
650 4214
651 var log = window.logFlags || {}; 4215 var log = window.logFlags || {};
652 4216
653 // magic words 4217 // magic words
654 4218
655 var OBSERVE_SUFFIX = 'Changed'; 4219 var OBSERVE_SUFFIX = 'Changed';
656 4220
657 // element api 4221 // element api
658 4222
659 var empty = []; 4223 var empty = [];
660 4224
661 var properties = { 4225 var properties = {
662 observeProperties: function() { 4226 createPropertyObserver: function() {
663 var n$ = this._observeNames, pn$ = this._publishNames; 4227 var n$ = this._observeNames;
664 if ((n$ && n$.length) || (pn$ && pn$.length)) { 4228 if (n$ && n$.length) {
665 var self = this; 4229 var o = this._propertyObserver = new CompoundObserver(true);
666 var o = this._propertyObserver = new CompoundObserver();
667 // keep track of property observer so we can shut it down
668 this.registerObservers([o]); 4230 this.registerObservers([o]);
4231 // TODO(sorvell): may not be kosher to access the value here (this[n]);
4232 // previously we looked at the descriptor on the prototype
4233 // this doesn't work for inheritance and not for accessors without
4234 // a value property
669 for (var i=0, l=n$.length, n; (i<l) && (n=n$[i]); i++) { 4235 for (var i=0, l=n$.length, n; (i<l) && (n=n$[i]); i++) {
670 o.addPath(this, n); 4236 o.addPath(this, n);
671 // observer array properties 4237 this.observeArrayValue(n, this[n], null);
672 var pd = Object.getOwnPropertyDescriptor(this.__proto__, n);
673 if (pd && pd.value) {
674 this.observeArrayValue(n, pd.value, null);
675 }
676 } 4238 }
677 for (var i=0, l=pn$.length, n; (i<l) && (n=pn$[i]); i++) { 4239 }
678 if (!this.observe || (this.observe[n] === undefined)) { 4240 },
679 o.addPath(this, n); 4241 openPropertyObserver: function() {
680 } 4242 if (this._propertyObserver) {
681 } 4243 this._propertyObserver.open(this.notifyPropertyChanges, this);
682 o.open(this.notifyPropertyChanges, this);
683 } 4244 }
684 }, 4245 },
685 notifyPropertyChanges: function(newValues, oldValues, paths) { 4246 notifyPropertyChanges: function(newValues, oldValues, paths) {
686 var name, method, called = {}; 4247 var name, method, called = {};
687 for (var i in oldValues) { 4248 for (var i in oldValues) {
688 // note: paths is of form [object, path, object, path] 4249 // note: paths is of form [object, path, object, path]
689 name = paths[2 * i + 1]; 4250 name = paths[2 * i + 1];
690 if (this.publish[name] !== undefined) {
691 this.reflectPropertyToAttribute(name);
692 }
693 method = this.observe[name]; 4251 method = this.observe[name];
694 if (method) { 4252 if (method) {
695 this.observeArrayValue(name, newValues[i], oldValues[i]); 4253 var ov = oldValues[i], nv = newValues[i];
4254 // observes the value if it is an array
4255 this.observeArrayValue(name, nv, ov);
696 if (!called[method]) { 4256 if (!called[method]) {
697 called[method] = true; 4257 // only invoke change method if one of ov or nv is not (undefined | null)
698 // observes the value if it is an array 4258 if ((ov !== undefined && ov !== null) || (nv !== undefined && nv !== null)) {
699 this.invokeMethod(method, [oldValues[i], newValues[i], arguments]); 4259 called[method] = true;
4260 // TODO(sorvell): call method with the set of values it's expectin g;
4261 // e.g. 'foo bar': 'invalidate' expects the new and old values for
4262 // foo and bar. Currently we give only one of these and then
4263 // deliver all the arguments.
4264 this.invokeMethod(method, [ov, nv, arguments]);
4265 }
700 } 4266 }
701 } 4267 }
702 } 4268 }
703 }, 4269 },
4270 deliverChanges: function() {
4271 if (this._propertyObserver) {
4272 this._propertyObserver.deliver();
4273 }
4274 },
4275 propertyChanged_: function(name, value, oldValue) {
4276 if (this.reflect[name]) {
4277 this.reflectPropertyToAttribute(name);
4278 }
4279 },
704 observeArrayValue: function(name, value, old) { 4280 observeArrayValue: function(name, value, old) {
705 // we only care if there are registered side-effects 4281 // we only care if there are registered side-effects
706 var callbackName = this.observe[name]; 4282 var callbackName = this.observe[name];
707 if (callbackName) { 4283 if (callbackName) {
708 // if we are observing the previous value, stop 4284 // if we are observing the previous value, stop
709 if (Array.isArray(old)) { 4285 if (Array.isArray(old)) {
710 log.observe && console.log('[%s] observeArrayValue: unregister observe r [%s]', this.localName, name); 4286 log.observe && console.log('[%s] observeArrayValue: unregister observe r [%s]', this.localName, name);
711 this.closeNamedObserver(name + '__array'); 4287 this.closeNamedObserver(name + '__array');
712 } 4288 }
713 // if the new value is an array, being observing it 4289 // if the new value is an array, being observing it
714 if (Array.isArray(value)) { 4290 if (Array.isArray(value)) {
715 log.observe && console.log('[%s] observeArrayValue: register observer [%s]', this.localName, name, value); 4291 log.observe && console.log('[%s] observeArrayValue: register observer [%s]', this.localName, name, value);
716 var observer = new ArrayObserver(value); 4292 var observer = new ArrayObserver(value);
717 observer.open(function(value, old) { 4293 observer.open(function(value, old) {
718 this.invokeMethod(callbackName, [old]); 4294 this.invokeMethod(callbackName, [old]);
719 }, this); 4295 }, this);
720 this.registerNamedObserver(name + '__array', observer); 4296 this.registerNamedObserver(name + '__array', observer);
721 } 4297 }
722 } 4298 }
723 }, 4299 },
724 bindProperty: function(property, observable) { 4300 bindProperty: function(property, observable, oneTime) {
725 // apply Polymer two-way reference binding 4301 if (oneTime) {
4302 this[property] = observable;
4303 return;
4304 }
726 return bindProperties(this, property, observable); 4305 return bindProperties(this, property, observable);
727 }, 4306 },
728 invokeMethod: function(method, args) { 4307 invokeMethod: function(method, args) {
729 var fn = this[method] || method; 4308 var fn = this[method] || method;
730 if (typeof fn === 'function') { 4309 if (typeof fn === 'function') {
731 fn.apply(this, args); 4310 fn.apply(this, args);
732 } 4311 }
733 }, 4312 },
734 registerObservers: function(observers) { 4313 registerObservers: function(observers) {
4314 this._observers = this._observers || [];
735 this._observers.push(observers); 4315 this._observers.push(observers);
736 }, 4316 },
737 // observer array items are arrays of observers. 4317 // observer array items are arrays of observers.
738 closeObservers: function() { 4318 closeObservers: function() {
4319 if (!this._observers) {
4320 return;
4321 }
739 for (var i=0, l=this._observers.length; i<l; i++) { 4322 for (var i=0, l=this._observers.length; i<l; i++) {
740 this.closeObserverArray(this._observers[i]); 4323 this.closeObserverArray(this._observers[i]);
741 } 4324 }
742 this._observers = []; 4325 this._observers = [];
743 }, 4326 },
744 closeObserverArray: function(observerArray) { 4327 closeObserverArray: function(observerArray) {
745 for (var i=0, l=observerArray.length, o; i<l; i++) { 4328 for (var i=0, l=observerArray.length, o; i<l; i++) {
746 o = observerArray[i]; 4329 o = observerArray[i];
747 if (o && o.close) { 4330 if (o && o.close) {
748 o.close(); 4331 o.close();
749 } 4332 }
750 } 4333 }
751 }, 4334 },
752 // bookkeeping observers for memory management 4335 // bookkeeping observers for memory management
753 registerNamedObserver: function(name, observer) { 4336 registerNamedObserver: function(name, observer) {
754 var o$ = this._namedObservers || (this._namedObservers = {}); 4337 var o$ = this._namedObservers || (this._namedObservers = {});
755 o$[name] = observer; 4338 o$[name] = observer;
756 }, 4339 },
757 closeNamedObserver: function(name) { 4340 closeNamedObserver: function(name) {
758 var o$ = this._namedObservers; 4341 var o$ = this._namedObservers;
759 if (o$ && o$[name]) { 4342 if (o$ && o$[name]) {
760 o$[name].close(); 4343 o$[name].close();
761 o$[name] = null; 4344 o$[name] = null;
762 return true; 4345 return true;
763 } 4346 }
764 }, 4347 },
765 closeNamedObservers: function() { 4348 closeNamedObservers: function() {
766 if (this._namedObservers) { 4349 if (this._namedObservers) {
767 var keys=Object.keys(this._namedObservers); 4350 for (var i in this._namedObservers) {
768 for (var i=0, l=keys.length, k, o; (i < l) && (k=keys[i]); i++) { 4351 this.closeNamedObserver(i);
769 o = this._namedObservers[k];
770 o.close();
771 } 4352 }
772 this._namedObservers = {}; 4353 this._namedObservers = {};
773 } 4354 }
774 } 4355 }
775 }; 4356 };
776 4357
777 // property binding 4358 // property binding
778 // bind a property in A to a path in B by converting A[property] to a 4359 // bind a property in A to a path in B by converting A[property] to a
779 // getter/setter pair that accesses B[...path...] 4360 // getter/setter pair that accesses B[...path...]
780 function bindProperties(inA, inProperty, observable) { 4361 function bindProperties(a, property, observable) {
781 log.bind && console.log(LOG_BIND_PROPS, inB.localName || 'object', inPath, i nA.localName, inProperty); 4362 // apply Polymer two-way reference binding
782 // capture A's value if B's value is null or undefined, 4363 return Observer.bindToInstance(a, property, observable, resolveBindingValue) ;
783 // otherwise use B's value 4364 }
784 // TODO(sorvell): need to review, can do with ObserverTransform 4365
785 var v = observable.discardChanges(); 4366 // capture A's value if B's value is null or undefined,
786 if (v === null || v === undefined) { 4367 // otherwise use B's value
787 observable.setValue(inA[inProperty]); 4368 function resolveBindingValue(oldValue, value) {
4369 if (value === undefined && oldValue === null) {
4370 return value;
788 } 4371 }
789 return Observer.defineComputedProperty(inA, inProperty, observable); 4372 return (value === null || value === undefined) ? oldValue : value;
790 } 4373 }
791 4374
792 // logging 4375 // logging
793 var LOG_OBSERVE = '[%s] watching [%s]'; 4376 var LOG_OBSERVE = '[%s] watching [%s]';
794 var LOG_OBSERVED = '[%s#%s] watch: [%s] now [%s] was [%s]'; 4377 var LOG_OBSERVED = '[%s#%s] watch: [%s] now [%s] was [%s]';
795 var LOG_CHANGED = '[%s#%s] propertyChanged: [%s] now [%s] was [%s]'; 4378 var LOG_CHANGED = '[%s#%s] propertyChanged: [%s] now [%s] was [%s]';
796 var LOG_BIND_PROPS = "[%s]: bindProperties: [%s] to [%s].[%s]";
797 4379
798 // exports 4380 // exports
799 4381
800 scope.api.instance.properties = properties; 4382 scope.api.instance.properties = properties;
801 4383
802 })(Polymer); 4384 })(Polymer);
803 4385
804 /* 4386 /*
805 * Copyright 2013 The Polymer Authors. All rights reserved. 4387 * Copyright (c) 2014 The Polymer Project Authors. All rights reserved.
806 * Use of this source code is governed by a BSD-style 4388 * This code may only be used under the BSD style license found at http://polyme r.github.io/LICENSE.txt
807 * license that can be found in the LICENSE file. 4389 * The complete set of authors may be found at http://polymer.github.io/AUTHORS. txt
4390 * The complete set of contributors may be found at http://polymer.github.io/CON TRIBUTORS.txt
4391 * Code distributed by Google as part of the polymer project is also
4392 * subject to an additional IP rights grant found at http://polymer.github.io/PA TENTS.txt
808 */ 4393 */
4394
809 (function(scope) { 4395 (function(scope) {
810 4396
811 // imports 4397 // imports
812 4398
813 var log = window.logFlags || 0; 4399 var log = window.logFlags || 0;
814 var events = scope.api.instance.events;
815
816 var syntax = new PolymerExpressions();
817 syntax.resolveEventHandler = function(model, path, node) {
818 var ctlr = findEventController(node);
819 if (ctlr) {
820 var fn = path.getValueFrom(ctlr);
821 if (fn) {
822 return fn.bind(ctlr);
823 }
824 }
825 }
826
827 // An event controller is the host element for the shadowRoot in which
828 // the node exists, or the first ancestor with a 'lightDomController'
829 // property.
830 function findEventController(node) {
831 while (node.parentNode) {
832 if (node.lightDomController) {
833 return node;
834 }
835 node = node.parentNode;
836 }
837 return node.host;
838 };
839 4400
840 // element api supporting mdv 4401 // element api supporting mdv
841
842 var mdv = { 4402 var mdv = {
843 syntax: syntax,
844 instanceTemplate: function(template) { 4403 instanceTemplate: function(template) {
845 var dom = template.createInstance(this, this.syntax); 4404 // ensure a default bindingDelegate
4405 var syntax = this.syntax || (!template.bindingDelegate &&
4406 this.element.syntax);
4407 var dom = template.createInstance(this, syntax);
846 this.registerObservers(dom.bindings_); 4408 this.registerObservers(dom.bindings_);
847 return dom; 4409 return dom;
848 }, 4410 },
849 bind: function(name, observable, oneTime) { 4411 bind: function(name, observable, oneTime) {
850 var property = this.propertyForAttribute(name); 4412 var property = this.propertyForAttribute(name);
851 if (!property) { 4413 if (!property) {
852 // TODO(sjmiles): this mixin method must use the special form 4414 // TODO(sjmiles): this mixin method must use the special form
853 // of `super` installed by `mixinMethod` in declaration/prototype.js 4415 // of `super` installed by `mixinMethod` in declaration/prototype.js
854 return this.mixinSuper(arguments); 4416 return this.mixinSuper(arguments);
855 } else { 4417 } else {
856 // use n-way Polymer binding 4418 // use n-way Polymer binding
857 var observer = this.bindProperty(property, observable); 4419 var observer = this.bindProperty(property, observable, oneTime);
858 this.reflectPropertyToAttribute(property);
859 // NOTE: reflecting binding information is typically required only for 4420 // NOTE: reflecting binding information is typically required only for
860 // tooling. It has a performance cost so it's opt-in in Node.bind. 4421 // tooling. It has a performance cost so it's opt-in in Node.bind.
861 if (Platform.enableBindingsReflection) { 4422 if (Platform.enableBindingsReflection && observer) {
862 observer.path = observable.path_; 4423 observer.path = observable.path_;
863 this.bindings_ = this.bindings_ || {}; 4424 this._recordBinding(property, observer);
864 this.bindings_[name] = observer; 4425 }
4426 if (this.reflect[property]) {
4427 this.reflectPropertyToAttribute(property);
865 } 4428 }
866 return observer; 4429 return observer;
867 } 4430 }
868 }, 4431 },
4432 bindFinished: function() {
4433 this.makeElementReady();
4434 },
4435 _recordBinding: function(name, observer) {
4436 this.bindings_ = this.bindings_ || {};
4437 this.bindings_[name] = observer;
4438 },
869 // TODO(sorvell): unbind/unbindAll has been removed, as public api, from 4439 // TODO(sorvell): unbind/unbindAll has been removed, as public api, from
870 // TemplateBinding. We still need to close/dispose of observers but perhaps 4440 // TemplateBinding. We still need to close/dispose of observers but perhaps
871 // we should choose a more explicit name. 4441 // we should choose a more explicit name.
872 asyncUnbindAll: function() { 4442 asyncUnbindAll: function() {
873 if (!this._unbound) { 4443 if (!this._unbound) {
874 log.unbind && console.log('[%s] asyncUnbindAll', this.localName); 4444 log.unbind && console.log('[%s] asyncUnbindAll', this.localName);
875 this._unbindAllJob = this.job(this._unbindAllJob, this.unbindAll, 0); 4445 this._unbindAllJob = this.job(this._unbindAllJob, this.unbindAll, 0);
876 } 4446 }
877 }, 4447 },
878 unbindAll: function() { 4448 unbindAll: function() {
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
914 var mustachePattern = /\{\{([^{}]*)}}/; 4484 var mustachePattern = /\{\{([^{}]*)}}/;
915 4485
916 // exports 4486 // exports
917 4487
918 scope.bindPattern = mustachePattern; 4488 scope.bindPattern = mustachePattern;
919 scope.api.instance.mdv = mdv; 4489 scope.api.instance.mdv = mdv;
920 4490
921 })(Polymer); 4491 })(Polymer);
922 4492
923 /* 4493 /*
924 * Copyright 2013 The Polymer Authors. All rights reserved. 4494 * Copyright (c) 2014 The Polymer Project Authors. All rights reserved.
925 * Use of this source code is governed by a BSD-style 4495 * This code may only be used under the BSD style license found at http://polyme r.github.io/LICENSE.txt
926 * license that can be found in the LICENSE file. 4496 * The complete set of authors may be found at http://polymer.github.io/AUTHORS. txt
4497 * The complete set of contributors may be found at http://polymer.github.io/CON TRIBUTORS.txt
4498 * Code distributed by Google as part of the polymer project is also
4499 * subject to an additional IP rights grant found at http://polymer.github.io/PA TENTS.txt
927 */ 4500 */
4501
928 (function(scope) { 4502 (function(scope) {
929 4503
930 var base = { 4504 var base = {
931 PolymerBase: true, 4505 PolymerBase: true,
932 job: function(job, callback, wait) { 4506 job: function(job, callback, wait) {
933 if (typeof job === 'string') { 4507 if (typeof job === 'string') {
934 var n = '___' + job; 4508 var n = '___' + job;
935 this[n] = Polymer.job.call(this, this[n], callback, wait); 4509 this[n] = Polymer.job.call(this, this[n], callback, wait);
936 } else { 4510 } else {
937 return Polymer.job.call(this, job, callback, wait); 4511 return Polymer.job.call(this, job, callback, wait);
938 } 4512 }
939 }, 4513 },
940 super: Polymer.super, 4514 super: Polymer.super,
941 // user entry point for element has had its createdCallback called 4515 // user entry point for element has had its createdCallback called
942 created: function() { 4516 created: function() {
943 }, 4517 },
944 // user entry point for element has shadowRoot and is ready for 4518 // user entry point for element has shadowRoot and is ready for
945 // api interaction 4519 // api interaction
946 ready: function() { 4520 ready: function() {
947 }, 4521 },
948 createdCallback: function() { 4522 createdCallback: function() {
949 if (this.templateInstance && this.templateInstance.model) { 4523 if (this.templateInstance && this.templateInstance.model) {
950 console.warn('Attributes on ' + this.localName + ' were data bound ' + 4524 console.warn('Attributes on ' + this.localName + ' were data bound ' +
951 'prior to Polymer upgrading the element. This may result in ' + 4525 'prior to Polymer upgrading the element. This may result in ' +
952 'incorrect binding types.'); 4526 'incorrect binding types.');
953 } 4527 }
954 this.created(); 4528 this.created();
955 this.prepareElement(); 4529 this.prepareElement();
4530 // TODO(sorvell): replace when ShadowDOMPolyfill issue is corrected
4531 // https://github.com/Polymer/ShadowDOM/issues/420
4532 if (!this.ownerDocument.isStagingDocument || window.ShadowDOMPolyfill) {
4533 this.makeElementReady();
4534 }
956 }, 4535 },
957 // system entry point, do not override 4536 // system entry point, do not override
958 prepareElement: function() { 4537 prepareElement: function() {
4538 if (this._elementPrepared) {
4539 console.warn('Element already prepared', this.localName);
4540 return;
4541 }
959 this._elementPrepared = true; 4542 this._elementPrepared = true;
960 // install shadowRoots storage 4543 // storage for shadowRoots info
961 this.shadowRoots = {}; 4544 this.shadowRoots = {};
962 // storage for closeable observers.
963 this._observers = [];
964 // install property observers 4545 // install property observers
965 this.observeProperties(); 4546 this.createPropertyObserver();
4547 // TODO (sorvell): temporarily open observer when created
4548 this.openPropertyObserver();
966 // install boilerplate attributes 4549 // install boilerplate attributes
967 this.copyInstanceAttributes(); 4550 this.copyInstanceAttributes();
968 // process input attributes 4551 // process input attributes
969 this.takeAttributes(); 4552 this.takeAttributes();
970 // add event listeners 4553 // add event listeners
971 this.addHostListeners(); 4554 this.addHostListeners();
4555 },
4556 makeElementReady: function() {
4557 if (this._readied) {
4558 return;
4559 }
4560 this._readied = true;
4561 // TODO(sorvell): We could create an entry point here
4562 // for the user to compute property values.
972 // process declarative resources 4563 // process declarative resources
973 this.parseDeclarations(this.__proto__); 4564 this.parseDeclarations(this.__proto__);
974 // TODO(sorvell): CE polyfill uses unresolved attribute to simulate 4565 // TODO(sorvell): CE polyfill uses unresolved attribute to simulate
975 // :unresolved; remove this attribute to be compatible with native 4566 // :unresolved; remove this attribute to be compatible with native
976 // CE. 4567 // CE.
977 this.removeAttribute('unresolved'); 4568 this.removeAttribute('unresolved');
978 // user entry point 4569 // user entry point
979 this.ready(); 4570 this.ready();
4571 // TODO (sorvell): temporarily open observer when created
4572 // turn on property observation and take any initial changes
4573 //this.openPropertyObserver();
980 }, 4574 },
981 attachedCallback: function() { 4575 attachedCallback: function() {
982 this.cancelUnbindAll(); 4576 this.cancelUnbindAll();
983 // invoke user action 4577 // invoke user action
984 if (this.attached) { 4578 if (this.attached) {
985 this.attached(); 4579 this.attached();
986 } 4580 }
987 // TODO(sorvell): bc 4581 // TODO(sorvell): bc
988 if (this.enteredView) { 4582 if (this.enteredView) {
989 this.enteredView(); 4583 this.enteredView();
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after
1061 root.appendChild(dom); 4655 root.appendChild(dom);
1062 // perform post-construction initialization tasks on shadow root 4656 // perform post-construction initialization tasks on shadow root
1063 this.shadowRootReady(root, template); 4657 this.shadowRootReady(root, template);
1064 // return the created shadow root 4658 // return the created shadow root
1065 return root; 4659 return root;
1066 } 4660 }
1067 }, 4661 },
1068 // utility function that stamps a <template> into light-dom 4662 // utility function that stamps a <template> into light-dom
1069 lightFromTemplate: function(template, refNode) { 4663 lightFromTemplate: function(template, refNode) {
1070 if (template) { 4664 if (template) {
1071 // TODO(sorvell): mark this element as a lightDOMController so that 4665 // TODO(sorvell): mark this element as an eventController so that
1072 // event listeners on bound nodes inside it will be called on it. 4666 // event listeners on bound nodes inside it will be called on it.
1073 // Note, the expectation here is that events on all descendants 4667 // Note, the expectation here is that events on all descendants
1074 // should be handled by this element. 4668 // should be handled by this element.
1075 this.lightDomController = true; 4669 this.eventController = this;
1076 // stamp template 4670 // stamp template
1077 // which includes parsing and applying MDV bindings before being 4671 // which includes parsing and applying MDV bindings before being
1078 // inserted (to avoid {{}} in attribute values) 4672 // inserted (to avoid {{}} in attribute values)
1079 // e.g. to prevent <img src="images/{{icon}}"> from generating a 404. 4673 // e.g. to prevent <img src="images/{{icon}}"> from generating a 404.
1080 var dom = this.instanceTemplate(template); 4674 var dom = this.instanceTemplate(template);
1081 // append to shadow dom 4675 // append to shadow dom
1082 if (refNode) { 4676 if (refNode) {
1083 this.insertBefore(dom, refNode); 4677 this.insertBefore(dom, refNode);
1084 } else { 4678 } else {
1085 this.appendChild(dom); 4679 this.appendChild(dom);
1086 } 4680 }
1087 // perform post-construction initialization tasks on ahem, light root 4681 // perform post-construction initialization tasks on ahem, light root
1088 this.shadowRootReady(this); 4682 this.shadowRootReady(this);
1089 // return the created shadow root 4683 // return the created shadow root
1090 return dom; 4684 return dom;
1091 } 4685 }
1092 }, 4686 },
1093 shadowRootReady: function(root) { 4687 shadowRootReady: function(root) {
1094 // locate nodes with id and store references to them in this.$ hash 4688 // locate nodes with id and store references to them in this.$ hash
1095 this.marshalNodeReferences(root); 4689 this.marshalNodeReferences(root);
1096 // set up pointer gestures 4690 // set up polymer gestures
1097 PointerGestures.register(root); 4691 PolymerGestures.register(root);
1098 }, 4692 },
1099 // locate nodes with id and store references to them in this.$ hash 4693 // locate nodes with id and store references to them in this.$ hash
1100 marshalNodeReferences: function(root) { 4694 marshalNodeReferences: function(root) {
1101 // establish $ instance variable 4695 // establish $ instance variable
1102 var $ = this.$ = this.$ || {}; 4696 var $ = this.$ = this.$ || {};
1103 // populate $ from nodes with ID from the LOCAL tree 4697 // populate $ from nodes with ID from the LOCAL tree
1104 if (root) { 4698 if (root) {
1105 var n$ = root.querySelectorAll("[id]"); 4699 var n$ = root.querySelectorAll("[id]");
1106 for (var i=0, l=n$.length, n; (i<l) && (n=n$[i]); i++) { 4700 for (var i=0, l=n$.length, n; (i<l) && (n=n$[i]); i++) {
1107 $[n.id] = n; 4701 $[n.id] = n;
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
1139 4733
1140 // exports 4734 // exports
1141 4735
1142 scope.Base = PolymerBase; 4736 scope.Base = PolymerBase;
1143 scope.isBase = isBase; 4737 scope.isBase = isBase;
1144 scope.api.instance.base = base; 4738 scope.api.instance.base = base;
1145 4739
1146 })(Polymer); 4740 })(Polymer);
1147 4741
1148 /* 4742 /*
1149 * Copyright 2013 The Polymer Authors. All rights reserved. 4743 * Copyright (c) 2014 The Polymer Project Authors. All rights reserved.
1150 * Use of this source code is governed by a BSD-style 4744 * This code may only be used under the BSD style license found at http://polyme r.github.io/LICENSE.txt
1151 * license that can be found in the LICENSE file. 4745 * The complete set of authors may be found at http://polymer.github.io/AUTHORS. txt
4746 * The complete set of contributors may be found at http://polymer.github.io/CON TRIBUTORS.txt
4747 * Code distributed by Google as part of the polymer project is also
4748 * subject to an additional IP rights grant found at http://polymer.github.io/PA TENTS.txt
1152 */ 4749 */
4750
1153 (function(scope) { 4751 (function(scope) {
1154 4752
1155 // imports 4753 // imports
1156 4754
1157 var log = window.logFlags || {}; 4755 var log = window.logFlags || {};
1158 4756
1159 // magic words 4757 // magic words
1160 4758
1161 var STYLE_SCOPE_ATTRIBUTE = 'element'; 4759 var STYLE_SCOPE_ATTRIBUTE = 'element';
1162 var STYLE_CONTROLLER_SCOPE = 'controller'; 4760 var STYLE_CONTROLLER_SCOPE = 'controller';
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after
1242 return Platform.ShadowCSS.shimCssText(cssText, selector); 4840 return Platform.ShadowCSS.shimCssText(cssText, selector);
1243 } 4841 }
1244 4842
1245 // exports 4843 // exports
1246 4844
1247 scope.api.instance.styles = styles; 4845 scope.api.instance.styles = styles;
1248 4846
1249 })(Polymer); 4847 })(Polymer);
1250 4848
1251 /* 4849 /*
1252 * Copyright 2013 The Polymer Authors. All rights reserved. 4850 * Copyright (c) 2014 The Polymer Project Authors. All rights reserved.
1253 * Use of this source code is governed by a BSD-style 4851 * This code may only be used under the BSD style license found at http://polyme r.github.io/LICENSE.txt
1254 * license that can be found in the LICENSE file. 4852 * The complete set of authors may be found at http://polymer.github.io/AUTHORS. txt
4853 * The complete set of contributors may be found at http://polymer.github.io/CON TRIBUTORS.txt
4854 * Code distributed by Google as part of the polymer project is also
4855 * subject to an additional IP rights grant found at http://polymer.github.io/PA TENTS.txt
1255 */ 4856 */
4857
1256 (function(scope) { 4858 (function(scope) {
1257 4859
1258 // imports 4860 // imports
1259 4861
1260 var extend = scope.extend; 4862 var extend = scope.extend;
1261 var api = scope.api; 4863 var api = scope.api;
1262 4864
1263 // imperative implementation: Polymer() 4865 // imperative implementation: Polymer()
1264 4866
1265 // specify an 'own' prototype for tag `name` 4867 // specify an 'own' prototype for tag `name`
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after
1341 4943
1342 var declarations = Platform.deliverDeclarations(); 4944 var declarations = Platform.deliverDeclarations();
1343 if (declarations) { 4945 if (declarations) {
1344 for (var i=0, l=declarations.length, d; (i<l) && (d=declarations[i]); i++) { 4946 for (var i=0, l=declarations.length, d; (i<l) && (d=declarations[i]); i++) {
1345 element.apply(null, d); 4947 element.apply(null, d);
1346 } 4948 }
1347 } 4949 }
1348 4950
1349 })(Polymer); 4951 })(Polymer);
1350 4952
1351 /* 4953 /*
1352 * Copyright 2013 The Polymer Authors. All rights reserved. 4954 * Copyright (c) 2014 The Polymer Project Authors. All rights reserved.
1353 * Use of this source code is governed by a BSD-style 4955 * This code may only be used under the BSD style license found at http://polyme r.github.io/LICENSE.txt
1354 * license that can be found in the LICENSE file. 4956 * The complete set of authors may be found at http://polymer.github.io/AUTHORS. txt
4957 * The complete set of contributors may be found at http://polymer.github.io/CON TRIBUTORS.txt
4958 * Code distributed by Google as part of the polymer project is also
4959 * subject to an additional IP rights grant found at http://polymer.github.io/PA TENTS.txt
1355 */ 4960 */
1356 4961
1357 (function(scope) { 4962 (function(scope) {
1358 4963
1359 var path = { 4964 var path = {
1360 resolveElementPaths: function(node) { 4965 resolveElementPaths: function(node) {
1361 Platform.urlResolver.resolveDom(node); 4966 Platform.urlResolver.resolveDom(node);
1362 }, 4967 },
1363 addResolvePathApi: function() { 4968 addResolvePathApi: function() {
1364 // let assetpath attribute modify the resolve path 4969 // let assetpath attribute modify the resolve path
1365 var assetPath = this.getAttribute('assetpath') || ''; 4970 var assetPath = this.getAttribute('assetpath') || '';
1366 var root = new URL(assetPath, this.ownerDocument.baseURI); 4971 var root = new URL(assetPath, this.ownerDocument.baseURI);
1367 this.prototype.resolvePath = function(urlPath, base) { 4972 this.prototype.resolvePath = function(urlPath, base) {
1368 var u = new URL(urlPath, base || root); 4973 var u = new URL(urlPath, base || root);
1369 return u.href; 4974 return u.href;
1370 }; 4975 };
1371 } 4976 }
1372 }; 4977 };
1373 4978
1374 // exports 4979 // exports
1375 scope.api.declaration.path = path; 4980 scope.api.declaration.path = path;
1376 4981
1377 })(Polymer); 4982 })(Polymer);
1378 4983
1379 /* 4984 /*
1380 * Copyright 2013 The Polymer Authors. All rights reserved. 4985 * Copyright (c) 2014 The Polymer Project Authors. All rights reserved.
1381 * Use of this source code is governed by a BSD-style 4986 * This code may only be used under the BSD style license found at http://polyme r.github.io/LICENSE.txt
1382 * license that can be found in the LICENSE file. 4987 * The complete set of authors may be found at http://polymer.github.io/AUTHORS. txt
4988 * The complete set of contributors may be found at http://polymer.github.io/CON TRIBUTORS.txt
4989 * Code distributed by Google as part of the polymer project is also
4990 * subject to an additional IP rights grant found at http://polymer.github.io/PA TENTS.txt
1383 */ 4991 */
4992
1384 (function(scope) { 4993 (function(scope) {
1385 4994
1386 // imports 4995 // imports
1387 4996
1388 var log = window.logFlags || {}; 4997 var log = window.logFlags || {};
1389 var api = scope.api.instance.styles; 4998 var api = scope.api.instance.styles;
1390 var STYLE_SCOPE_ATTRIBUTE = api.STYLE_SCOPE_ATTRIBUTE; 4999 var STYLE_SCOPE_ATTRIBUTE = api.STYLE_SCOPE_ATTRIBUTE;
1391 5000
1392 // magic words 5001 // magic words
1393 5002
1394 var STYLE_SELECTOR = 'style'; 5003 var STYLE_SELECTOR = 'style';
1395 var STYLE_LOADABLE_MATCH = '@import'; 5004 var STYLE_LOADABLE_MATCH = '@import';
1396 var SHEET_SELECTOR = 'link[rel=stylesheet]'; 5005 var SHEET_SELECTOR = 'link[rel=stylesheet]';
1397 var STYLE_GLOBAL_SCOPE = 'global'; 5006 var STYLE_GLOBAL_SCOPE = 'global';
1398 var SCOPE_ATTR = 'polymer-scope'; 5007 var SCOPE_ATTR = 'polymer-scope';
1399 5008
1400 var styles = { 5009 var styles = {
1401 // returns true if resources are loading 5010 // returns true if resources are loading
1402 loadStyles: function(callback) { 5011 loadStyles: function(callback) {
1403 var content = this.templateContent(); 5012 var template = this.fetchTemplate();
5013 var content = template && this.templateContent();
1404 if (content) { 5014 if (content) {
1405 this.convertSheetsToStyles(content); 5015 this.convertSheetsToStyles(content);
5016 var styles = this.findLoadableStyles(content);
5017 if (styles.length) {
5018 var templateUrl = template.ownerDocument.baseURI;
5019 return Platform.styleResolver.loadStyles(styles, templateUrl, callback );
5020 }
1406 } 5021 }
1407 var styles = this.findLoadableStyles(content); 5022 if (callback) {
1408 if (styles.length) {
1409 Platform.styleResolver.loadStyles(styles, callback);
1410 } else if (callback) {
1411 callback(); 5023 callback();
1412 } 5024 }
1413 }, 5025 },
1414 convertSheetsToStyles: function(root) { 5026 convertSheetsToStyles: function(root) {
1415 var s$ = root.querySelectorAll(SHEET_SELECTOR); 5027 var s$ = root.querySelectorAll(SHEET_SELECTOR);
1416 for (var i=0, l=s$.length, s, c; (i<l) && (s=s$[i]); i++) { 5028 for (var i=0, l=s$.length, s, c; (i<l) && (s=s$[i]); i++) {
1417 c = createStyleElement(importRuleForSheet(s, this.ownerDocument.baseURI) , 5029 c = createStyleElement(importRuleForSheet(s, this.ownerDocument.baseURI) ,
1418 this.ownerDocument); 5030 this.ownerDocument);
1419 this.copySheetAttributes(c, s); 5031 this.copySheetAttributes(c, s);
1420 s.parentNode.replaceChild(c, s); 5032 s.parentNode.replaceChild(c, s);
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after
1496 }, 5108 },
1497 findNodes: function(selector, matcher) { 5109 findNodes: function(selector, matcher) {
1498 var nodes = this.querySelectorAll(selector).array(); 5110 var nodes = this.querySelectorAll(selector).array();
1499 var content = this.templateContent(); 5111 var content = this.templateContent();
1500 if (content) { 5112 if (content) {
1501 var templateNodes = content.querySelectorAll(selector).array(); 5113 var templateNodes = content.querySelectorAll(selector).array();
1502 nodes = nodes.concat(templateNodes); 5114 nodes = nodes.concat(templateNodes);
1503 } 5115 }
1504 return matcher ? nodes.filter(matcher) : nodes; 5116 return matcher ? nodes.filter(matcher) : nodes;
1505 }, 5117 },
1506 templateContent: function() {
1507 var template = this.querySelector('template');
1508 return template && templateContent(template);
1509 },
1510 /** 5118 /**
1511 * Promotes external stylesheets and <style> elements with the attribute 5119 * Promotes external stylesheets and <style> elements with the attribute
1512 * polymer-scope='global' into global scope. 5120 * polymer-scope='global' into global scope.
1513 * This is particularly useful for defining @keyframe rules which 5121 * This is particularly useful for defining @keyframe rules which
1514 * currently do not function in scoped or shadow style elements. 5122 * currently do not function in scoped or shadow style elements.
1515 * (See wkb.ug/72462) 5123 * (See wkb.ug/72462)
1516 * @param elementElement The <element> element to style. 5124 * @param elementElement The <element> element to style.
1517 */ 5125 */
1518 // TODO(sorvell): remove when wkb.ug/72462 is addressed. 5126 // TODO(sorvell): remove when wkb.ug/72462 is addressed.
1519 installGlobalStyles: function() { 5127 installGlobalStyles: function() {
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after
1611 || p.mozMatchesSelector; 5219 || p.mozMatchesSelector;
1612 5220
1613 // exports 5221 // exports
1614 5222
1615 scope.api.declaration.styles = styles; 5223 scope.api.declaration.styles = styles;
1616 scope.applyStyleToScope = applyStyleToScope; 5224 scope.applyStyleToScope = applyStyleToScope;
1617 5225
1618 })(Polymer); 5226 })(Polymer);
1619 5227
1620 /* 5228 /*
1621 * Copyright 2013 The Polymer Authors. All rights reserved. 5229 * Copyright (c) 2014 The Polymer Project Authors. All rights reserved.
1622 * Use of this source code is governed by a BSD-style 5230 * This code may only be used under the BSD style license found at http://polyme r.github.io/LICENSE.txt
1623 * license that can be found in the LICENSE file. 5231 * The complete set of authors may be found at http://polymer.github.io/AUTHORS. txt
5232 * The complete set of contributors may be found at http://polymer.github.io/CON TRIBUTORS.txt
5233 * Code distributed by Google as part of the polymer project is also
5234 * subject to an additional IP rights grant found at http://polymer.github.io/PA TENTS.txt
1624 */ 5235 */
1625 5236
1626 (function(scope) { 5237 (function(scope) {
1627 5238
1628 // imports 5239 // imports
1629 5240
1630 var log = window.logFlags || {}; 5241 var log = window.logFlags || {};
1631 var api = scope.api.instance.events; 5242 var api = scope.api.instance.events;
1632 var EVENT_PREFIX = api.EVENT_PREFIX; 5243 var EVENT_PREFIX = api.EVENT_PREFIX;
1633 // polymer-element declarative api: events feature 5244 // polymer-element declarative api: events feature
1634 5245
1635 var events = { 5246 var mixedCaseEventTypes = {};
5247 [
5248 'webkitAnimationStart',
5249 'webkitAnimationEnd',
5250 'webkitTransitionEnd',
5251 'DOMFocusOut',
5252 'DOMFocusIn',
5253 'DOMMouseScroll'
5254 ].forEach(function(e) {
5255 mixedCaseEventTypes[e.toLowerCase()] = e;
5256 });
5257
5258 var events = {
1636 parseHostEvents: function() { 5259 parseHostEvents: function() {
1637 // our delegates map 5260 // our delegates map
1638 var delegates = this.prototype.eventDelegates; 5261 var delegates = this.prototype.eventDelegates;
1639 // extract data from attributes into delegates 5262 // extract data from attributes into delegates
1640 this.addAttributeDelegates(delegates); 5263 this.addAttributeDelegates(delegates);
1641 }, 5264 },
1642 addAttributeDelegates: function(delegates) { 5265 addAttributeDelegates: function(delegates) {
1643 // for each attribute 5266 // for each attribute
1644 for (var i=0, a; a=this.attributes[i]; i++) { 5267 for (var i=0, a; a=this.attributes[i]; i++) {
1645 // does it have magic marker identifying it as an event delegate? 5268 // does it have magic marker identifying it as an event delegate?
1646 if (this.hasEventPrefix(a.name)) { 5269 if (this.hasEventPrefix(a.name)) {
1647 // if so, add the info to delegates 5270 // if so, add the info to delegates
1648 delegates[this.removeEventPrefix(a.name)] = a.value.replace('{{', '') 5271 delegates[this.removeEventPrefix(a.name)] = a.value.replace('{{', '')
1649 .replace('}}', '').trim(); 5272 .replace('}}', '').trim();
1650 } 5273 }
1651 } 5274 }
1652 }, 5275 },
1653 // starts with 'on-' 5276 // starts with 'on-'
1654 hasEventPrefix: function (n) { 5277 hasEventPrefix: function (n) {
1655 return n && (n[0] === 'o') && (n[1] === 'n') && (n[2] === '-'); 5278 return n && (n[0] === 'o') && (n[1] === 'n') && (n[2] === '-');
1656 }, 5279 },
1657 removeEventPrefix: function(n) { 5280 removeEventPrefix: function(n) {
1658 return n.slice(prefixLength); 5281 return n.slice(prefixLength);
5282 },
5283 findController: function(node) {
5284 while (node.parentNode) {
5285 if (node.eventController) {
5286 return node.eventController;
5287 }
5288 node = node.parentNode;
5289 }
5290 return node.host;
5291 },
5292 getEventHandler: function(controller, target, method) {
5293 var events = this;
5294 return function(e) {
5295 if (!controller || !controller.PolymerBase) {
5296 controller = events.findController(target);
5297 }
5298
5299 var args = [e, e.detail, e.currentTarget];
5300 controller.dispatchMethod(controller, method, args);
5301 };
5302 },
5303 prepareEventBinding: function(pathString, name, node) {
5304 if (!this.hasEventPrefix(name))
5305 return;
5306
5307 var eventType = this.removeEventPrefix(name);
5308 eventType = mixedCaseEventTypes[eventType] || eventType;
5309
5310 var events = this;
5311
5312 return function(model, node, oneTime) {
5313 var handler = events.getEventHandler(undefined, node, pathString);
5314 node.addEventListener(eventType, handler);
5315
5316 if (oneTime)
5317 return;
5318
5319 // TODO(rafaelw): This is really pointless work. Aside from the cost
5320 // of these allocations, NodeBind is going to setAttribute back to its
5321 // current value. Fixing this would mean changing the TemplateBinding
5322 // binding delegate API.
5323 function bindingValue() {
5324 return '{{ ' + pathString + ' }}';
5325 }
5326
5327 return {
5328 open: bindingValue,
5329 discardChanges: bindingValue,
5330 close: function() {
5331 node.removeEventListener(eventType, handler);
5332 }
5333 };
5334 };
1659 } 5335 }
1660 }; 5336 };
1661 5337
1662 var prefixLength = EVENT_PREFIX.length; 5338 var prefixLength = EVENT_PREFIX.length;
1663 5339
1664 // exports 5340 // exports
1665 scope.api.declaration.events = events; 5341 scope.api.declaration.events = events;
1666 5342
1667 })(Polymer); 5343 })(Polymer);
5344
1668 /* 5345 /*
1669 * Copyright 2013 The Polymer Authors. All rights reserved. 5346 * Copyright (c) 2014 The Polymer Project Authors. All rights reserved.
1670 * Use of this source code is governed by a BSD-style 5347 * This code may only be used under the BSD style license found at http://polyme r.github.io/LICENSE.txt
1671 * license that can be found in the LICENSE file. 5348 * The complete set of authors may be found at http://polymer.github.io/AUTHORS. txt
5349 * The complete set of contributors may be found at http://polymer.github.io/CON TRIBUTORS.txt
5350 * Code distributed by Google as part of the polymer project is also
5351 * subject to an additional IP rights grant found at http://polymer.github.io/PA TENTS.txt
1672 */ 5352 */
5353
1673 (function(scope) { 5354 (function(scope) {
1674 5355
1675 // element api 5356 // element api
1676 5357
1677 var properties = { 5358 var properties = {
1678 inferObservers: function(prototype) { 5359 inferObservers: function(prototype) {
1679 // called before prototype.observe is chained to inherited object 5360 // called before prototype.observe is chained to inherited object
1680 var observe = prototype.observe, property; 5361 var observe = prototype.observe, property;
1681 for (var n in prototype) { 5362 for (var n in prototype) {
1682 if (n.slice(-7) === 'Changed') { 5363 if (n.slice(-7) === 'Changed') {
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
1724 publishProperties: function(prototype, base) { 5405 publishProperties: function(prototype, base) {
1725 // if we have any properties to publish 5406 // if we have any properties to publish
1726 var publish = prototype.publish; 5407 var publish = prototype.publish;
1727 if (publish) { 5408 if (publish) {
1728 // transcribe `publish` entries onto own prototype 5409 // transcribe `publish` entries onto own prototype
1729 this.requireProperties(publish, prototype, base); 5410 this.requireProperties(publish, prototype, base);
1730 // construct map of lower-cased property names 5411 // construct map of lower-cased property names
1731 prototype._publishLC = this.lowerCaseMap(publish); 5412 prototype._publishLC = this.lowerCaseMap(publish);
1732 } 5413 }
1733 }, 5414 },
1734 requireProperties: function(properties, prototype, base) { 5415 // sync prototype to property descriptors;
5416 // desriptor format contains default value and optionally a
5417 // hint for reflecting the property to an attribute.
5418 // e.g. {foo: 5, bar: {value: true, reflect: true}}
5419 // reflect: {foo: true} is also supported
5420 //
5421 requireProperties: function(propertyDescriptors, prototype, base) {
5422 // reflected properties
5423 prototype.reflect = prototype.reflect || {};
1735 // ensure a prototype value for each property 5424 // ensure a prototype value for each property
1736 for (var n in properties) { 5425 // and update the property's reflect to attribute status
1737 if (prototype[n] === undefined && base[n] === undefined) { 5426 for (var n in propertyDescriptors) {
1738 prototype[n] = properties[n]; 5427 var propertyDescriptor = propertyDescriptors[n];
5428 var reflects = this.reflectHintForDescriptor(propertyDescriptor);
5429 if (prototype.reflect[n] === undefined && reflects !== undefined) {
5430 prototype.reflect[n] = reflects;
1739 } 5431 }
5432 if (prototype[n] === undefined) {
5433 prototype[n] = this.valueForDescriptor(propertyDescriptor);
5434 }
5435 }
5436 },
5437 valueForDescriptor: function(propertyDescriptor) {
5438 var value = typeof propertyDescriptor === 'object' &&
5439 propertyDescriptor ? propertyDescriptor.value : propertyDescriptor;
5440 return value !== undefined ? value : null;
5441 },
5442 // returns the value of the descriptor's 'reflect' property or undefined
5443 reflectHintForDescriptor: function(propertyDescriptor) {
5444 if (typeof propertyDescriptor === 'object' &&
5445 propertyDescriptor && propertyDescriptor.reflect !== undefined) {
5446 return propertyDescriptor.reflect;
1740 } 5447 }
1741 }, 5448 },
1742 lowerCaseMap: function(properties) { 5449 lowerCaseMap: function(properties) {
1743 var map = {}; 5450 var map = {};
1744 for (var n in properties) { 5451 for (var n in properties) {
1745 map[n.toLowerCase()] = n; 5452 map[n.toLowerCase()] = n;
1746 } 5453 }
1747 return map; 5454 return map;
5455 },
5456 createPropertyAccessors: function(prototype) {
5457 var n$ = prototype._publishNames;
5458 if (n$ && n$.length) {
5459 for (var i=0, l=n$.length, n, fn; (i<l) && (n=n$[i]); i++) {
5460 Observer.createBindablePrototypeAccessor(prototype, n);
5461 }
5462 }
1748 } 5463 }
1749 }; 5464 };
1750 5465
1751 // exports 5466 // exports
1752 5467
1753 scope.api.declaration.properties = properties; 5468 scope.api.declaration.properties = properties;
1754 5469
1755 })(Polymer); 5470 })(Polymer);
1756 5471
1757 /* 5472 /*
1758 * Copyright 2013 The Polymer Authors. All rights reserved. 5473 * Copyright (c) 2014 The Polymer Project Authors. All rights reserved.
1759 * Use of this source code is governed by a BSD-style 5474 * This code may only be used under the BSD style license found at http://polyme r.github.io/LICENSE.txt
1760 * license that can be found in the LICENSE file. 5475 * The complete set of authors may be found at http://polymer.github.io/AUTHORS. txt
5476 * The complete set of contributors may be found at http://polymer.github.io/CON TRIBUTORS.txt
5477 * Code distributed by Google as part of the polymer project is also
5478 * subject to an additional IP rights grant found at http://polymer.github.io/PA TENTS.txt
1761 */ 5479 */
1762 (function(scope) { 5480 (function(scope) {
1763 5481
1764 // magic words 5482 // magic words
1765 5483
1766 var ATTRIBUTES_ATTRIBUTE = 'attributes'; 5484 var ATTRIBUTES_ATTRIBUTE = 'attributes';
1767 var ATTRIBUTES_REGEX = /\s|,/; 5485 var ATTRIBUTES_REGEX = /\s|,/;
1768 5486
1769 // attributes api 5487 // attributes api
1770 5488
1771 var attributes = { 5489 var attributes = {
5490
1772 inheritAttributesObjects: function(prototype) { 5491 inheritAttributesObjects: function(prototype) {
1773 // chain our lower-cased publish map to the inherited version 5492 // chain our lower-cased publish map to the inherited version
1774 this.inheritObject(prototype, 'publishLC'); 5493 this.inheritObject(prototype, 'publishLC');
1775 // chain our instance attributes map to the inherited version 5494 // chain our instance attributes map to the inherited version
1776 this.inheritObject(prototype, '_instanceAttributes'); 5495 this.inheritObject(prototype, '_instanceAttributes');
1777 }, 5496 },
5497
1778 publishAttributes: function(prototype, base) { 5498 publishAttributes: function(prototype, base) {
1779 // merge names from 'attributes' attribute 5499 // merge names from 'attributes' attribute
1780 var attributes = this.getAttribute(ATTRIBUTES_ATTRIBUTE); 5500 var attributes = this.getAttribute(ATTRIBUTES_ATTRIBUTE);
1781 if (attributes) { 5501 if (attributes) {
1782 // get properties to publish 5502 // get properties to publish
1783 var publish = prototype.publish || (prototype.publish = {}); 5503 var publish = prototype.publish || (prototype.publish = {});
1784 // names='a b c' or names='a,b,c' 5504 // names='a b c' or names='a,b,c'
1785 var names = attributes.split(ATTRIBUTES_REGEX); 5505 var names = attributes.split(ATTRIBUTES_REGEX);
1786 // record each name for publishing 5506 // record each name for publishing
1787 for (var i=0, l=names.length, n; i<l; i++) { 5507 for (var i=0, l=names.length, n; i<l; i++) {
1788 // remove excess ws 5508 // remove excess ws
1789 n = names[i].trim(); 5509 n = names[i].trim();
1790 // do not override explicit entries 5510 // do not override explicit entries
1791 if (n && publish[n] === undefined && base[n] === undefined) { 5511 if (n && publish[n] === undefined && base[n] === undefined) {
1792 publish[n] = null; 5512 // supply an empty 'descriptor' object and let the publishProperties
5513 // code determine a default
5514 publish[n] = Polymer.nob;
1793 } 5515 }
1794 } 5516 }
1795 } 5517 }
1796 }, 5518 },
5519
1797 // record clonable attributes from <element> 5520 // record clonable attributes from <element>
1798 accumulateInstanceAttributes: function() { 5521 accumulateInstanceAttributes: function() {
1799 // inherit instance attributes 5522 // inherit instance attributes
1800 var clonable = this.prototype._instanceAttributes; 5523 var clonable = this.prototype._instanceAttributes;
1801 // merge attributes from element 5524 // merge attributes from element
1802 var a$ = this.attributes; 5525 var a$ = this.attributes;
1803 for (var i=0, l=a$.length, a; (i<l) && (a=a$[i]); i++) { 5526 for (var i=0, l=a$.length, a; (i<l) && (a=a$[i]); i++) {
1804 if (this.isInstanceAttribute(a.name)) { 5527 if (this.isInstanceAttribute(a.name)) {
1805 clonable[a.name] = a.value; 5528 clonable[a.name] = a.value;
1806 } 5529 }
1807 } 5530 }
1808 }, 5531 },
5532
1809 isInstanceAttribute: function(name) { 5533 isInstanceAttribute: function(name) {
1810 return !this.blackList[name] && name.slice(0,3) !== 'on-'; 5534 return !this.blackList[name] && name.slice(0,3) !== 'on-';
1811 }, 5535 },
5536
1812 // do not clone these attributes onto instances 5537 // do not clone these attributes onto instances
1813 blackList: { 5538 blackList: {
1814 name: 1, 5539 name: 1,
1815 'extends': 1, 5540 'extends': 1,
1816 constructor: 1, 5541 constructor: 1,
1817 noscript: 1, 5542 noscript: 1,
1818 assetpath: 1, 5543 assetpath: 1,
1819 'cache-csstext': 1 5544 'cache-csstext': 1
1820 } 5545 }
5546
1821 }; 5547 };
1822 5548
1823 // add ATTRIBUTES_ATTRIBUTE to the blacklist 5549 // add ATTRIBUTES_ATTRIBUTE to the blacklist
1824 attributes.blackList[ATTRIBUTES_ATTRIBUTE] = 1; 5550 attributes.blackList[ATTRIBUTES_ATTRIBUTE] = 1;
1825 5551
1826 // exports 5552 // exports
1827 5553
1828 scope.api.declaration.attributes = attributes; 5554 scope.api.declaration.attributes = attributes;
1829 5555
1830 })(Polymer); 5556 })(Polymer);
1831 5557
1832 /* 5558 /*
1833 * Copyright 2013 The Polymer Authors. All rights reserved. 5559 * Copyright (c) 2014 The Polymer Project Authors. All rights reserved.
1834 * Use of this source code is governed by a BSD-style 5560 * This code may only be used under the BSD style license found at http://polyme r.github.io/LICENSE.txt
1835 * license that can be found in the LICENSE file. 5561 * The complete set of authors may be found at http://polymer.github.io/AUTHORS. txt
5562 * The complete set of contributors may be found at http://polymer.github.io/CON TRIBUTORS.txt
5563 * Code distributed by Google as part of the polymer project is also
5564 * subject to an additional IP rights grant found at http://polymer.github.io/PA TENTS.txt
1836 */ 5565 */
5566
5567 (function(scope) {
5568
5569 // imports
5570 var events = scope.api.declaration.events;
5571
5572 var syntax = new PolymerExpressions();
5573 var prepareBinding = syntax.prepareBinding;
5574
5575 // Polymer takes a first crack at the binding to see if it's a declarative
5576 // event handler.
5577 syntax.prepareBinding = function(pathString, name, node) {
5578 return events.prepareEventBinding(pathString, name, node) ||
5579 prepareBinding.call(syntax, pathString, name, node);
5580 };
5581
5582 // declaration api supporting mdv
5583 var mdv = {
5584 syntax: syntax,
5585 fetchTemplate: function() {
5586 return this.querySelector('template');
5587 },
5588 templateContent: function() {
5589 var template = this.fetchTemplate();
5590 return template && Platform.templateContent(template);
5591 },
5592 installBindingDelegate: function(template) {
5593 if (template) {
5594 template.bindingDelegate = this.syntax;
5595 }
5596 }
5597 };
5598
5599 // exports
5600 scope.api.declaration.mdv = mdv;
5601
5602 })(Polymer);
5603
5604 /*
5605 * Copyright (c) 2014 The Polymer Project Authors. All rights reserved.
5606 * This code may only be used under the BSD style license found at http://polyme r.github.io/LICENSE.txt
5607 * The complete set of authors may be found at http://polymer.github.io/AUTHORS. txt
5608 * The complete set of contributors may be found at http://polymer.github.io/CON TRIBUTORS.txt
5609 * Code distributed by Google as part of the polymer project is also
5610 * subject to an additional IP rights grant found at http://polymer.github.io/PA TENTS.txt
5611 */
5612
1837 (function(scope) { 5613 (function(scope) {
1838 5614
1839 // imports 5615 // imports
1840 5616
1841 var api = scope.api; 5617 var api = scope.api;
1842 var isBase = scope.isBase; 5618 var isBase = scope.isBase;
1843 var extend = scope.extend; 5619 var extend = scope.extend;
1844 5620
1845 // prototype api 5621 // prototype api
1846 5622
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
1890 // x-platform fixup 5666 // x-platform fixup
1891 ensurePrototypeTraversal(chained); 5667 ensurePrototypeTraversal(chained);
1892 return chained; 5668 return chained;
1893 }, 5669 },
1894 5670
1895 inheritMetaData: function(prototype, base) { 5671 inheritMetaData: function(prototype, base) {
1896 // chain observe object to inherited 5672 // chain observe object to inherited
1897 this.inheritObject('observe', prototype, base); 5673 this.inheritObject('observe', prototype, base);
1898 // chain publish object to inherited 5674 // chain publish object to inherited
1899 this.inheritObject('publish', prototype, base); 5675 this.inheritObject('publish', prototype, base);
5676 // chain reflect object to inherited
5677 this.inheritObject('reflect', prototype, base);
1900 // chain our lower-cased publish map to the inherited version 5678 // chain our lower-cased publish map to the inherited version
1901 this.inheritObject('_publishLC', prototype, base); 5679 this.inheritObject('_publishLC', prototype, base);
1902 // chain our instance attributes map to the inherited version 5680 // chain our instance attributes map to the inherited version
1903 this.inheritObject('_instanceAttributes', prototype, base); 5681 this.inheritObject('_instanceAttributes', prototype, base);
1904 // chain our event delegates map to the inherited version 5682 // chain our event delegates map to the inherited version
1905 this.inheritObject('eventDelegates', prototype, base); 5683 this.inheritObject('eventDelegates', prototype, base);
1906 }, 5684 },
1907 5685
1908 // implement various declarative features 5686 // implement various declarative features
1909 desugarAfterChaining: function(name, extendee) { 5687 desugarAfterChaining: function(name, extendee) {
1910 // build side-chained lists to optimize iterations 5688 // build side-chained lists to optimize iterations
1911 this.optimizePropertyMaps(this.prototype); 5689 this.optimizePropertyMaps(this.prototype);
5690 this.createPropertyAccessors(this.prototype);
5691 // install mdv delegate on template
5692 this.installBindingDelegate(this.fetchTemplate());
1912 // install external stylesheets as if they are inline 5693 // install external stylesheets as if they are inline
1913 this.installSheets(); 5694 this.installSheets();
1914 // adjust any paths in dom from imports 5695 // adjust any paths in dom from imports
1915 this.resolveElementPaths(this); 5696 this.resolveElementPaths(this);
1916 // compile list of attributes to copy to instances 5697 // compile list of attributes to copy to instances
1917 this.accumulateInstanceAttributes(); 5698 this.accumulateInstanceAttributes();
1918 // parse on-* delegates declared on `this` element 5699 // parse on-* delegates declared on `this` element
1919 this.parseHostEvents(); 5700 this.parseHostEvents();
1920 // 5701 //
1921 // install a helper method this.resolvePath to aid in 5702 // install a helper method this.resolvePath to aid in
(...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after
2067 } 5848 }
2068 } 5849 }
2069 5850
2070 // exports 5851 // exports
2071 5852
2072 api.declaration.prototype = prototype; 5853 api.declaration.prototype = prototype;
2073 5854
2074 })(Polymer); 5855 })(Polymer);
2075 5856
2076 /* 5857 /*
2077 * Copyright 2013 The Polymer Authors. All rights reserved. 5858 * Copyright (c) 2014 The Polymer Project Authors. All rights reserved.
2078 * Use of this source code is governed by a BSD-style 5859 * This code may only be used under the BSD style license found at http://polyme r.github.io/LICENSE.txt
2079 * license that can be found in the LICENSE file. 5860 * The complete set of authors may be found at http://polymer.github.io/AUTHORS. txt
5861 * The complete set of contributors may be found at http://polymer.github.io/CON TRIBUTORS.txt
5862 * Code distributed by Google as part of the polymer project is also
5863 * subject to an additional IP rights grant found at http://polymer.github.io/PA TENTS.txt
2080 */ 5864 */
5865
2081 (function(scope) { 5866 (function(scope) {
2082 5867
5868 /*
5869
5870 Elements are added to a registration queue so that they register in
5871 the proper order at the appropriate time. We do this for a few reasons:
5872
5873 * to enable elements to load resources (like stylesheets)
5874 asynchronously. We need to do this until the platform provides an efficient
5875 alternative. One issue is that remote @import stylesheets are
5876 re-fetched whenever stamped into a shadowRoot.
5877
5878 * to ensure elements loaded 'at the same time' (e.g. via some set of
5879 imports) are registered as a batch. This allows elements to be enured from
5880 upgrade ordering as long as they query the dom tree 1 task after
5881 upgrade (aka domReady). This is a performance tradeoff. On the one hand,
5882 elements that could register while imports are loading are prevented from
5883 doing so. On the other, grouping upgrades into a single task means less
5884 incremental work (for example style recalcs), Also, we can ensure the
5885 document is in a known state at the single quantum of time when
5886 elements upgrade.
5887
5888 */
2083 var queue = { 5889 var queue = {
2084 // tell the queue to wait for an element to be ready 5890 // tell the queue to wait for an element to be ready
2085 wait: function(element, check, go) { 5891 wait: function(element, check, go) {
2086 if (this.indexOf(element) === -1) { 5892 var shouldAdd = (this.indexOf(element) === -1 &&
5893 flushQueue.indexOf(element) === -1);
5894 if (shouldAdd) {
2087 this.add(element); 5895 this.add(element);
2088 element.__check = check; 5896 element.__check = check;
2089 element.__go = go; 5897 element.__go = go;
2090 } 5898 }
2091 return (this.indexOf(element) !== 0); 5899 return (this.indexOf(element) !== 0);
2092 }, 5900 },
2093 add: function(element) { 5901 add: function(element) {
2094 //console.log('queueing', element.name); 5902 //console.log('queueing', element.name);
2095 queueForElement(element).push(element); 5903 queueForElement(element).push(element);
2096 }, 5904 },
2097 indexOf: function(element) { 5905 indexOf: function(element) {
2098 var i = queueForElement(element).indexOf(element); 5906 var i = queueForElement(element).indexOf(element);
2099 if (i >= 0 && document.contains(element)) { 5907 if (i >= 0 && document.contains(element)) {
2100 i += (HTMLImports.useNative || HTMLImports.ready) ? 5908 i += (HTMLImports.useNative || HTMLImports.ready) ?
2101 importQueue.length : 1e9; 5909 importQueue.length : 1e9;
2102 } 5910 }
2103 return i; 5911 return i;
2104 }, 5912 },
2105 // tell the queue an element is ready to be registered 5913 // tell the queue an element is ready to be registered
2106 go: function(element) { 5914 go: function(element) {
2107 var readied = this.remove(element); 5915 var readied = this.remove(element);
2108 if (readied) { 5916 if (readied) {
2109 readied.__go.call(readied); 5917 this.addToFlushQueue(readied);
2110 readied.__check = readied.__go = null;
2111 this.check(); 5918 this.check();
2112 } 5919 }
2113 }, 5920 },
2114 remove: function(element) { 5921 remove: function(element) {
2115 var i = this.indexOf(element); 5922 var i = this.indexOf(element);
2116 if (i !== 0) { 5923 if (i !== 0) {
2117 //console.warn('queue order wrong', i); 5924 //console.warn('queue order wrong', i);
2118 return; 5925 return;
2119 } 5926 }
2120 return queueForElement(element).shift(); 5927 return queueForElement(element).shift();
(...skipping 11 matching lines...) Expand all
2132 }, 5939 },
2133 nextElement: function() { 5940 nextElement: function() {
2134 return nextQueued(); 5941 return nextQueued();
2135 }, 5942 },
2136 canReady: function() { 5943 canReady: function() {
2137 return !this.waitToReady && this.isEmpty(); 5944 return !this.waitToReady && this.isEmpty();
2138 }, 5945 },
2139 isEmpty: function() { 5946 isEmpty: function() {
2140 return !importQueue.length && !mainQueue.length; 5947 return !importQueue.length && !mainQueue.length;
2141 }, 5948 },
5949 addToFlushQueue: function(element) {
5950 flushQueue.push(element);
5951 },
5952 flush: function() {
5953 var element;
5954 while (flushQueue.length) {
5955 element = flushQueue.shift();
5956 element.__go.call(element);
5957 element.__check = element.__go = null;
5958 }
5959 },
2142 ready: function() { 5960 ready: function() {
5961 this.flush();
2143 // TODO(sorvell): As an optimization, turn off CE polyfill upgrading 5962 // TODO(sorvell): As an optimization, turn off CE polyfill upgrading
2144 // while registering. This way we avoid having to upgrade each document 5963 // while registering. This way we avoid having to upgrade each document
2145 // piecemeal per registration and can instead register all elements 5964 // piecemeal per registration and can instead register all elements
2146 // and upgrade once in a batch. Without this optimization, upgrade time 5965 // and upgrade once in a batch. Without this optimization, upgrade time
2147 // degrades significantly when SD polyfill is used. This is mainly because 5966 // degrades significantly when SD polyfill is used. This is mainly because
2148 // querying the document tree for elements is slow under the SD polyfill. 5967 // querying the document tree for elements is slow under the SD polyfill.
2149 if (CustomElements.ready === false) { 5968 if (CustomElements.ready === false) {
2150 CustomElements.upgradeDocumentTree(document); 5969 CustomElements.upgradeDocumentTree(document);
2151 CustomElements.ready = true; 5970 CustomElements.ready = true;
2152 } 5971 }
5972 Platform.flush();
5973 requestAnimationFrame(this.flushReadyCallbacks);
5974 },
5975 addReadyCallback: function(callback) {
5976 if (callback) {
5977 readyCallbacks.push(callback);
5978 }
5979 },
5980 flushReadyCallbacks: function() {
2153 if (readyCallbacks) { 5981 if (readyCallbacks) {
2154 var fn; 5982 var fn;
2155 while (readyCallbacks.length) { 5983 while (readyCallbacks.length) {
2156 fn = readyCallbacks.shift(); 5984 fn = readyCallbacks.shift();
2157 fn(); 5985 fn();
2158 } 5986 }
2159 } 5987 }
2160 }, 5988 },
2161 addReadyCallback: function(callback) {
2162 if (callback) {
2163 readyCallbacks.push(callback);
2164 }
2165 },
2166 waitToReady: true 5989 waitToReady: true
2167 }; 5990 };
2168 5991
5992 var flushQueue = [];
5993
2169 var importQueue = []; 5994 var importQueue = [];
2170 var mainQueue = []; 5995 var mainQueue = [];
2171 var readyCallbacks = []; 5996 var readyCallbacks = [];
2172 5997
2173 function queueForElement(element) { 5998 function queueForElement(element) {
2174 return document.contains(element) ? mainQueue : importQueue; 5999 return document.contains(element) ? mainQueue : importQueue;
2175 } 6000 }
2176 6001
2177 function nextQueued() { 6002 function nextQueued() {
2178 return importQueue.length ? importQueue[0] : mainQueue[0]; 6003 return importQueue.length ? importQueue[0] : mainQueue[0];
(...skipping 14 matching lines...) Expand all
2193 queue.check(); 6018 queue.check();
2194 }); 6019 });
2195 } 6020 }
2196 6021
2197 // exports 6022 // exports
2198 scope.queue = queue; 6023 scope.queue = queue;
2199 scope.whenPolymerReady = whenPolymerReady; 6024 scope.whenPolymerReady = whenPolymerReady;
2200 })(Polymer); 6025 })(Polymer);
2201 6026
2202 /* 6027 /*
2203 * Copyright 2013 The Polymer Authors. All rights reserved. 6028 * Copyright (c) 2014 The Polymer Project Authors. All rights reserved.
2204 * Use of this source code is governed by a BSD-style 6029 * This code may only be used under the BSD style license found at http://polyme r.github.io/LICENSE.txt
2205 * license that can be found in the LICENSE file. 6030 * The complete set of authors may be found at http://polymer.github.io/AUTHORS. txt
6031 * The complete set of contributors may be found at http://polymer.github.io/CON TRIBUTORS.txt
6032 * Code distributed by Google as part of the polymer project is also
6033 * subject to an additional IP rights grant found at http://polymer.github.io/PA TENTS.txt
2206 */ 6034 */
6035
2207 (function(scope) { 6036 (function(scope) {
2208 6037
2209 var whenPolymerReady = scope.whenPolymerReady; 6038 var whenPolymerReady = scope.whenPolymerReady;
2210 6039
2211 function importElements(elementOrFragment, callback) { 6040 function importElements(elementOrFragment, callback) {
2212 if (elementOrFragment) { 6041 if (elementOrFragment) {
2213 document.head.appendChild(elementOrFragment); 6042 document.head.appendChild(elementOrFragment);
2214 whenPolymerReady(callback); 6043 whenPolymerReady(callback);
2215 } else if (callback) { 6044 } else if (callback) {
2216 callback(); 6045 callback();
(...skipping 15 matching lines...) Expand all
2232 } 6061 }
2233 } 6062 }
2234 6063
2235 // exports 6064 // exports
2236 scope.import = importUrls; 6065 scope.import = importUrls;
2237 scope.importElements = importElements; 6066 scope.importElements = importElements;
2238 6067
2239 })(Polymer); 6068 })(Polymer);
2240 6069
2241 /* 6070 /*
2242 * Copyright 2013 The Polymer Authors. All rights reserved. 6071 * Copyright (c) 2014 The Polymer Project Authors. All rights reserved.
2243 * Use of this source code is governed by a BSD-style 6072 * This code may only be used under the BSD style license found at http://polyme r.github.io/LICENSE.txt
2244 * license that can be found in the LICENSE file. 6073 * The complete set of authors may be found at http://polymer.github.io/AUTHORS. txt
6074 * The complete set of contributors may be found at http://polymer.github.io/CON TRIBUTORS.txt
6075 * Code distributed by Google as part of the polymer project is also
6076 * subject to an additional IP rights grant found at http://polymer.github.io/PA TENTS.txt
2245 */ 6077 */
6078
2246 (function(scope) { 6079 (function(scope) {
2247 6080
2248 // imports 6081 // imports
2249 6082
2250 var extend = scope.extend; 6083 var extend = scope.extend;
2251 var api = scope.api; 6084 var api = scope.api;
2252 var queue = scope.queue; 6085 var queue = scope.queue;
2253 var whenPolymerReady = scope.whenPolymerReady; 6086 var whenPolymerReady = scope.whenPolymerReady;
2254 var getRegisteredPrototype = scope.getRegisteredPrototype; 6087 var getRegisteredPrototype = scope.getRegisteredPrototype;
2255 var waitingForPrototype = scope.waitingForPrototype; 6088 var waitingForPrototype = scope.waitingForPrototype;
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after
2363 // utility and bookkeeping 6196 // utility and bookkeeping
2364 6197
2365 function isRegistered(name) { 6198 function isRegistered(name) {
2366 return Boolean(HTMLElement.getPrototypeForTag(name)); 6199 return Boolean(HTMLElement.getPrototypeForTag(name));
2367 } 6200 }
2368 6201
2369 function isCustomTag(name) { 6202 function isCustomTag(name) {
2370 return (name && name.indexOf('-') >= 0); 6203 return (name && name.indexOf('-') >= 0);
2371 } 6204 }
2372 6205
2373 // exports
2374
2375 scope.getRegisteredPrototype = getRegisteredPrototype;
2376
2377 // boot tasks 6206 // boot tasks
2378 6207
2379 whenPolymerReady(function() { 6208 whenPolymerReady(function() {
2380 document.body.removeAttribute('unresolved'); 6209 document.body.removeAttribute('unresolved');
2381 document.dispatchEvent( 6210 document.dispatchEvent(
2382 new CustomEvent('polymer-ready', {bubbles: true}) 6211 new CustomEvent('polymer-ready', {bubbles: true})
2383 ); 6212 );
2384 }); 6213 });
2385 6214
2386 // register polymer-element with document 6215 // register polymer-element with document
2387 6216
2388 document.registerElement('polymer-element', {prototype: prototype}); 6217 document.registerElement('polymer-element', {prototype: prototype});
2389 6218
2390 })(Polymer); 6219 })(Polymer);
2391 6220
6221 /*
6222 * Copyright (c) 2014 The Polymer Project Authors. All rights reserved.
6223 * This code may only be used under the BSD style license found at http://polyme r.github.io/LICENSE.txt
6224 * The complete set of authors may be found at http://polymer.github.io/AUTHORS. txt
6225 * The complete set of contributors may be found at http://polymer.github.io/CON TRIBUTORS.txt
6226 * Code distributed by Google as part of the polymer project is also
6227 * subject to an additional IP rights grant found at http://polymer.github.io/PA TENTS.txt
6228 */
6229
6230 /**
6231 * The `auto-binding` element extends the template element. It provides a quick
6232 * and easy way to do data binding without the need to setup a model.
6233 * The `auto-binding` element itself serves as the model and controller for the
6234 * elements it contains. Both data and event handlers can be bound.
6235 *
6236 * The `auto-binding` element acts just like a template that is bound to
6237 * a model. It stamps its content in the dom adjacent to itself. When the
6238 * content is stamped, the `template-bound` event is fired.
6239 *
6240 * Example:
6241 *
6242 * <template is="auto-binding">
6243 * <div>Say something: <input value="{{value}}"></div>
6244 * <div>You said: {{value}}</div>
6245 * <button on-tap="{{buttonTap}}">Tap me!</button>
6246 * </template>
6247 * <script>
6248 * var template = document.querySelector('template');
6249 * template.value = 'something';
6250 * template.buttonTap = function() {
6251 * console.log('tap!');
6252 * };
6253 * </script>
6254 *
6255 * @module Polymer
6256 * @status stable
6257 */
6258
6259 (function() {
6260
6261 var element = document.createElement('polymer-element');
6262 element.setAttribute('name', 'auto-binding');
6263 element.setAttribute('extends', 'template');
6264 element.init();
6265
6266 Polymer('auto-binding', {
6267
6268 createdCallback: function() {
6269 this.syntax = this.bindingDelegate = this.makeSyntax();
6270 // delay stamping until polymer-ready so that auto-binding is not
6271 // required to load last.
6272 Polymer.whenPolymerReady(function() {
6273 this.model = this;
6274 this.setAttribute('bind', '');
6275 // we don't bother with an explicit signal here, we could ust a MO
6276 // if necessary
6277 this.async(function() {
6278 // note: this will marshall *all* the elements in the parentNode
6279 // rather than just stamped ones. We'd need to use createInstance
6280 // to fix this or something else fancier.
6281 this.marshalNodeReferences(this.parentNode);
6282 // template stamping is asynchronous so stamping isn't complete
6283 // by polymer-ready; fire an event so users can use stamped elements
6284 this.fire('template-bound');
6285 });
6286 }.bind(this));
6287 },
6288
6289 makeSyntax: function() {
6290 var events = Object.create(Polymer.api.declaration.events);
6291 var self = this;
6292 events.findController = function() { return self.model; };
6293
6294 var syntax = new PolymerExpressions();
6295 var prepareBinding = syntax.prepareBinding;
6296 syntax.prepareBinding = function(pathString, name, node) {
6297 return events.prepareEventBinding(pathString, name, node) ||
6298 prepareBinding.call(syntax, pathString, name, node);
6299 };
6300 return syntax;
6301 }
6302
6303 });
6304
6305 })();
6306
2392 //# sourceMappingURL=polymer.concat.js.map 6307 //# sourceMappingURL=polymer.concat.js.map
OLDNEW
« no previous file with comments | « dart/pkg/polymer/lib/src/js/polymer/polymer-body.html ('k') | dart/pkg/polymer/lib/src/js/polymer/polymer.concat.js.map » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698