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

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

Issue 469823002: Roll polymer to 0.3.5 (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: style nit Created 6 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 /** 1 /**
2 * @license 2 * @license
3 * Copyright (c) 2014 The Polymer Project Authors. All rights reserved. 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 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 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 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 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 8 * subject to an additional IP rights grant found at http://polymer.github.io/PA TENTS.txt
9 */ 9 */
10 window.PolymerGestures = { 10 window.PolymerGestures = {};
11 hasSDPolyfill: Boolean(window.ShadowDOMPolyfill)
12 };
13 PolymerGestures.wrap = PolymerGestures.hasSDPolyfill ? ShadowDOMPolyfill.wrapIfN eeded : function(a){ return a; };
14 11
15 /* 12 /*
16 * Copyright (c) 2014 The Polymer Project Authors. All rights reserved. 13 * Copyright (c) 2014 The Polymer Project Authors. All rights reserved.
17 * This code may only be used under the BSD style license found at http://polyme r.github.io/LICENSE.txt 14 * This code may only be used under the BSD style license found at http://polyme r.github.io/LICENSE.txt
18 * The complete set of authors may be found at http://polymer.github.io/AUTHORS. txt 15 * The complete set of authors may be found at http://polymer.github.io/AUTHORS. txt
19 * The complete set of contributors may be found at http://polymer.github.io/CON TRIBUTORS.txt 16 * The complete set of contributors may be found at http://polymer.github.io/CON TRIBUTORS.txt
20 * Code distributed by Google as part of the polymer project is also 17 * Code distributed by Google as part of the polymer project is also
21 * subject to an additional IP rights grant found at http://polymer.github.io/PA TENTS.txt 18 * subject to an additional IP rights grant found at http://polymer.github.io/PA TENTS.txt
22 */ 19 */
23 20
24 (function(scope) { 21 (function(scope) {
25 var HAS_FULL_PATH = false; 22 var HAS_FULL_PATH = false;
26 23
27 // test for full event path support 24 // test for full event path support
28 var pathTest = document.createElement('meta'); 25 var pathTest = document.createElement('meta');
29 if (!scope.hasSDPolyfill && pathTest.createShadowRoot) { 26 if (pathTest.createShadowRoot) {
30 var sr = pathTest.createShadowRoot(); 27 var sr = pathTest.createShadowRoot();
31 var s = document.createElement('span'); 28 var s = document.createElement('span');
32 sr.appendChild(s); 29 sr.appendChild(s);
33 pathTest.addEventListener('testpath', function(ev) { 30 pathTest.addEventListener('testpath', function(ev) {
34 if (ev.path) { 31 if (ev.path) {
35 // if the span is in the event path, then path[0] is the real source for all events 32 // if the span is in the event path, then path[0] is the real source for all events
36 HAS_FULL_PATH = ev.path[0] === s; 33 HAS_FULL_PATH = ev.path[0] === s;
37 } 34 }
38 ev.stopPropagation(); 35 ev.stopPropagation();
39 }); 36 });
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after
115 } 112 }
116 var x = inEvent.clientX, y = inEvent.clientY; 113 var x = inEvent.clientX, y = inEvent.clientY;
117 // if the listener is in the shadow root, it is much faster to start there 114 // if the listener is in the shadow root, it is much faster to start there
118 var s = this.owner(inEvent.target); 115 var s = this.owner(inEvent.target);
119 // if x, y is not in this root, fall back to document search 116 // if x, y is not in this root, fall back to document search
120 if (!s.elementFromPoint(x, y)) { 117 if (!s.elementFromPoint(x, y)) {
121 s = document; 118 s = document;
122 } 119 }
123 return this.searchRoot(s, x, y); 120 return this.searchRoot(s, x, y);
124 }, 121 },
125 findScrollAxis: function(inEvent) { 122 findTouchAction: function(inEvent) {
126 var n; 123 var n;
127 if (HAS_FULL_PATH && inEvent.path) { 124 if (HAS_FULL_PATH && inEvent.path) {
128 var path = inEvent.path; 125 var path = inEvent.path;
129 for (var i = 0; i < path.length; i++) { 126 for (var i = 0; i < path.length; i++) {
130 n = path[i]; 127 n = path[i];
131 if (n._scrollType) { 128 if (n.nodeType === Node.ELEMENT_NODE && n.hasAttribute('touch-action') ) {
132 return n._scrollType; 129 return n.getAttribute('touch-action');
133 } 130 }
134 } 131 }
135 } else { 132 } else {
136 n = scope.wrap(inEvent.currentTarget); 133 n = inEvent.target;
137 while(n) { 134 while(n) {
138 if (n._scrollType) { 135 if (n.hasAttribute('touch-action')) {
139 return n._scrollType; 136 return n.getAttribute('touch-action');
140 } 137 }
141 n = n.parentNode || n.host; 138 n = n.parentNode || n.host;
142 } 139 }
143 } 140 }
141 // auto is default
142 return "auto";
144 }, 143 },
145 LCA: function(a, b) { 144 LCA: function(a, b) {
146 if (a === b) { 145 if (a === b) {
147 return a; 146 return a;
148 } 147 }
149 if (a && !b) { 148 if (a && !b) {
150 return a; 149 return a;
151 } 150 }
152 if (b && !a) { 151 if (b && !a) {
153 return b; 152 return b;
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after
246 * Copyright (c) 2014 The Polymer Project Authors. All rights reserved. 245 * Copyright (c) 2014 The Polymer Project Authors. All rights reserved.
247 * This code may only be used under the BSD style license found at http://polyme r.github.io/LICENSE.txt 246 * This code may only be used under the BSD style license found at http://polyme r.github.io/LICENSE.txt
248 * The complete set of authors may be found at http://polymer.github.io/AUTHORS. txt 247 * The complete set of authors may be found at http://polymer.github.io/AUTHORS. txt
249 * The complete set of contributors may be found at http://polymer.github.io/CON TRIBUTORS.txt 248 * The complete set of contributors may be found at http://polymer.github.io/CON TRIBUTORS.txt
250 * Code distributed by Google as part of the polymer project is also 249 * Code distributed by Google as part of the polymer project is also
251 * subject to an additional IP rights grant found at http://polymer.github.io/PA TENTS.txt 250 * subject to an additional IP rights grant found at http://polymer.github.io/PA TENTS.txt
252 */ 251 */
253 252
254 (function() { 253 (function() {
255 function shadowSelector(v) { 254 function shadowSelector(v) {
256 return 'body /deep/ ' + selector(v); 255 return 'html /deep/ ' + selector(v);
257 } 256 }
258 function selector(v) { 257 function selector(v) {
259 return '[touch-action="' + v + '"]'; 258 return '[touch-action="' + v + '"]';
260 } 259 }
261 function rule(v) { 260 function rule(v) {
262 return '{ -ms-touch-action: ' + v + '; touch-action: ' + v + ';}'; 261 return '{ -ms-touch-action: ' + v + '; touch-action: ' + v + ';}';
263 } 262 }
264 var attrib2css = [ 263 var attrib2css = [
265 'none', 264 'none',
266 'auto', 265 'auto',
267 'pan-x', 266 'pan-x',
268 'pan-y', 267 'pan-y',
269 { 268 {
270 rule: 'pan-x pan-y', 269 rule: 'pan-x pan-y',
271 selectors: [ 270 selectors: [
272 'pan-x pan-y', 271 'pan-x pan-y',
273 'pan-y pan-x' 272 'pan-y pan-x'
274 ] 273 ]
275 }, 274 },
276 'manipulation' 275 'manipulation'
277 ]; 276 ];
278 var styles = ''; 277 var styles = '';
279 // only install stylesheet if the browser has touch action support 278 // only install stylesheet if the browser has touch action support
280 var head = document.head;
281 var hasTouchAction = typeof document.head.style.touchAction === 'string'; 279 var hasTouchAction = typeof document.head.style.touchAction === 'string';
282 // only add shadow selectors if shadowdom is supported 280 // only add shadow selectors if shadowdom is supported
283 var hasShadowRoot = !window.ShadowDOMPolyfill && document.head.createShadowRoo t; 281 var hasShadowRoot = !window.ShadowDOMPolyfill && document.head.createShadowRoo t;
284 282
285 if (hasTouchAction) { 283 if (hasTouchAction) {
286 attrib2css.forEach(function(r) { 284 attrib2css.forEach(function(r) {
287 if (String(r) === r) { 285 if (String(r) === r) {
288 styles += selector(r) + rule(r) + '\n'; 286 styles += selector(r) + rule(r) + '\n';
289 if (hasShadowRoot) { 287 if (hasShadowRoot) {
290 styles += shadowSelector(r) + rule(r) + '\n'; 288 styles += shadowSelector(r) + rule(r) + '\n';
(...skipping 295 matching lines...) Expand 10 before | Expand all | Expand 10 after
586 0, 584 0,
587 0, 585 0,
588 function(){}, 586 function(){},
589 false 587 false
590 ]; 588 ];
591 589
592 var HAS_SVG_INSTANCE = (typeof SVGElementInstance !== 'undefined'); 590 var HAS_SVG_INSTANCE = (typeof SVGElementInstance !== 'undefined');
593 591
594 var eventFactory = scope.eventFactory; 592 var eventFactory = scope.eventFactory;
595 593
596 var hasSDPolyfill = scope.hasSDPolyfill;
597 var wrap = scope.wrap;
598
599 /** 594 /**
600 * This module is for normalizing events. Mouse and Touch events will be 595 * This module is for normalizing events. Mouse and Touch events will be
601 * collected here, and fire PointerEvents that have the same semantics, no 596 * collected here, and fire PointerEvents that have the same semantics, no
602 * matter the source. 597 * matter the source.
603 * Events fired: 598 * Events fired:
604 * - pointerdown: a pointing is added 599 * - pointerdown: a pointing is added
605 * - pointerup: a pointer is removed 600 * - pointerup: a pointer is removed
606 * - pointermove: a pointer is moved 601 * - pointermove: a pointer is moved
607 * - pointerover: a pointer crosses into an element 602 * - pointerover: a pointer crosses into an element
608 * - pointerout: a pointer leaves an element 603 * - pointerout: a pointer leaves an element
609 * - pointercancel: a pointer will no longer generate events 604 * - pointercancel: a pointer will no longer generate events
610 */ 605 */
611 var dispatcher = { 606 var dispatcher = {
612 pointermap: new scope.PointerMap(), 607 pointermap: new scope.PointerMap(),
613 eventMap: Object.create(null), 608 eventMap: Object.create(null),
614 // Scope objects for native events. 609 // Scope objects for native events.
615 // This exists for ease of testing. 610 // This exists for ease of testing.
616 eventSources: Object.create(null), 611 eventSources: Object.create(null),
617 eventSourceList: [], 612 eventSourceList: [],
618 gestures: [], 613 gestures: [],
614 // map gesture event -> {listeners: int, index: gestures[int]}
615 dependencyMap: {
616 // make sure down and up are in the map to trigger "register"
617 down: {listeners: 0, index: -1},
618 up: {listeners: 0, index: -1}
619 },
619 gestureQueue: [], 620 gestureQueue: [],
620 /** 621 /**
621 * Add a new event source that will generate pointer events. 622 * Add a new event source that will generate pointer events.
622 * 623 *
623 * `inSource` must contain an array of event names named `events`, and 624 * `inSource` must contain an array of event names named `events`, and
624 * functions with the names specified in the `events` array. 625 * functions with the names specified in the `events` array.
625 * @param {string} name A name for the event source 626 * @param {string} name A name for the event source
626 * @param {Object} source A new source of platform events. 627 * @param {Object} source A new source of platform events.
627 */ 628 */
628 registerSource: function(name, source) { 629 registerSource: function(name, source) {
629 var s = source; 630 var s = source;
630 var newEvents = s.events; 631 var newEvents = s.events;
631 if (newEvents) { 632 if (newEvents) {
632 newEvents.forEach(function(e) { 633 newEvents.forEach(function(e) {
633 if (s[e]) { 634 if (s[e]) {
634 this.eventMap[e] = s[e].bind(s); 635 this.eventMap[e] = s[e].bind(s);
635 } 636 }
636 }, this); 637 }, this);
637 this.eventSources[name] = s; 638 this.eventSources[name] = s;
638 this.eventSourceList.push(s); 639 this.eventSourceList.push(s);
639 } 640 }
640 }, 641 },
641 registerGesture: function(name, source) { 642 registerGesture: function(name, source) {
643 var obj = Object.create(null);
644 obj.listeners = 0;
645 obj.index = this.gestures.length;
646 for (var i = 0, g; i < source.exposes.length; i++) {
647 g = source.exposes[i].toLowerCase();
648 this.dependencyMap[g] = obj;
649 }
642 this.gestures.push(source); 650 this.gestures.push(source);
643 }, 651 },
644 register: function(element) { 652 register: function(element, initial) {
645 var l = this.eventSourceList.length; 653 var l = this.eventSourceList.length;
646 for (var i = 0, es; (i < l) && (es = this.eventSourceList[i]); i++) { 654 for (var i = 0, es; (i < l) && (es = this.eventSourceList[i]); i++) {
647 // call eventsource register 655 // call eventsource register
648 es.register.call(es, element); 656 es.register.call(es, element, initial);
649 } 657 }
650 }, 658 },
651 unregister: function(element) { 659 unregister: function(element) {
652 var l = this.eventSourceList.length; 660 var l = this.eventSourceList.length;
653 for (var i = 0, es; (i < l) && (es = this.eventSourceList[i]); i++) { 661 for (var i = 0, es; (i < l) && (es = this.eventSourceList[i]); i++) {
654 // call eventsource register 662 // call eventsource register
655 es.unregister.call(es, element); 663 es.unregister.call(es, element);
656 } 664 }
657 }, 665 },
658 // EVENTS 666 // EVENTS
(...skipping 10 matching lines...) Expand all
669 }, 677 },
670 cancel: function(inEvent) { 678 cancel: function(inEvent) {
671 inEvent.tapPrevented = true; 679 inEvent.tapPrevented = true;
672 this.fireEvent('up', inEvent); 680 this.fireEvent('up', inEvent);
673 }, 681 },
674 // LISTENER LOGIC 682 // LISTENER LOGIC
675 eventHandler: function(inEvent) { 683 eventHandler: function(inEvent) {
676 // This is used to prevent multiple dispatch of events from 684 // This is used to prevent multiple dispatch of events from
677 // platform events. This can happen when two elements in different scopes 685 // platform events. This can happen when two elements in different scopes
678 // are set up to create pointer events, which is relevant to Shadow DOM. 686 // are set up to create pointer events, which is relevant to Shadow DOM.
687
688 // TODO(dfreedm): make this check more granular, allow for minimal event g eneration
689 // e.g inEvent._handledByPG['tap'] and inEvent._handledByPG['track'], etc
679 if (inEvent._handledByPG) { 690 if (inEvent._handledByPG) {
680 return; 691 return;
681 } 692 }
682 var type = inEvent.type; 693 var type = inEvent.type;
683 var fn = this.eventMap && this.eventMap[type]; 694 var fn = this.eventMap && this.eventMap[type];
684 if (fn) { 695 if (fn) {
685 fn(inEvent); 696 fn(inEvent);
686 } 697 }
687 inEvent._handledByPG = true; 698 inEvent._handledByPG = true;
688 }, 699 },
689 // set up event listeners 700 // set up event listeners
690 listen: function(target, events) { 701 listen: function(target, events) {
691 for (var i = 0, l = events.length, e; (i < l) && (e = events[i]); i++) { 702 for (var i = 0, l = events.length, e; (i < l) && (e = events[i]); i++) {
692 this.addEvent(target, e); 703 this.addEvent(target, e);
693 } 704 }
694 }, 705 },
695 // remove event listeners 706 // remove event listeners
696 unlisten: function(target, events) { 707 unlisten: function(target, events) {
697 for (var i = 0, l = events.length, e; (i < l) && (e = events[i]); i++) { 708 for (var i = 0, l = events.length, e; (i < l) && (e = events[i]); i++) {
698 this.removeEvent(target, e); 709 this.removeEvent(target, e);
699 } 710 }
700 }, 711 },
701 addEvent: function(target, eventName) { 712 addEvent: function(target, eventName) {
702 // NOTE: Work around for #4, use native event listener in SD Polyfill 713 target.addEventListener(eventName, this.boundHandler);
703 if (hasSDPolyfill) {
704 target.addEventListener_(eventName, this.boundHandler);
705 } else {
706 target.addEventListener(eventName, this.boundHandler);
707 }
708 }, 714 },
709 removeEvent: function(target, eventName) { 715 removeEvent: function(target, eventName) {
710 // NOTE: Work around for #4, use native event listener in SD Polyfill 716 target.removeEventListener(eventName, this.boundHandler);
711 if (hasSDPolyfill) {
712 target.removeEventListener_(eventName, this.boundHandler);
713 } else {
714 target.removeEventListener(eventName, this.boundHandler);
715 }
716 }, 717 },
717 // EVENT CREATION AND TRACKING 718 // EVENT CREATION AND TRACKING
718 /** 719 /**
719 * Creates a new Event of type `inType`, based on the information in 720 * Creates a new Event of type `inType`, based on the information in
720 * `inEvent`. 721 * `inEvent`.
721 * 722 *
722 * @param {string} inType A string representing the type of event to create 723 * @param {string} inType A string representing the type of event to create
723 * @param {Event} inEvent A platform event with a target 724 * @param {Event} inEvent A platform event with a target
724 * @return {Event} A PointerEvent of type `inType` 725 * @return {Event} A PointerEvent of type `inType`
725 */ 726 */
(...skipping 21 matching lines...) Expand all
747 for (var i = 0; i < CLONE_PROPS.length; i++) { 748 for (var i = 0; i < CLONE_PROPS.length; i++) {
748 p = CLONE_PROPS[i]; 749 p = CLONE_PROPS[i];
749 eventCopy[p] = inEvent[p] || CLONE_DEFAULTS[i]; 750 eventCopy[p] = inEvent[p] || CLONE_DEFAULTS[i];
750 // Work around SVGInstanceElement shadow tree 751 // Work around SVGInstanceElement shadow tree
751 // Return the <use> element that is represented by the instance for Safa ri, Chrome, IE. 752 // Return the <use> element that is represented by the instance for Safa ri, Chrome, IE.
752 // This is the behavior implemented by Firefox. 753 // This is the behavior implemented by Firefox.
753 if (p === 'target' || p === 'relatedTarget') { 754 if (p === 'target' || p === 'relatedTarget') {
754 if (HAS_SVG_INSTANCE && eventCopy[p] instanceof SVGElementInstance) { 755 if (HAS_SVG_INSTANCE && eventCopy[p] instanceof SVGElementInstance) {
755 eventCopy[p] = eventCopy[p].correspondingUseElement; 756 eventCopy[p] = eventCopy[p].correspondingUseElement;
756 } 757 }
757 eventCopy[p] = wrap(eventCopy[p]);
758 } 758 }
759 } 759 }
760 // keep the semantics of preventDefault 760 // keep the semantics of preventDefault
761 eventCopy.preventDefault = inEvent.preventDefault; 761 eventCopy.preventDefault = function() {
762 inEvent.preventDefault();
763 };
762 return eventCopy; 764 return eventCopy;
763 }, 765 },
764 /** 766 /**
765 * Dispatches the event to its target. 767 * Dispatches the event to its target.
766 * 768 *
767 * @param {Event} inEvent The event to be dispatched. 769 * @param {Event} inEvent The event to be dispatched.
768 * @return {Boolean} True if an event handler returns true, false otherwise. 770 * @return {Boolean} True if an event handler returns true, false otherwise.
769 */ 771 */
770 dispatchEvent: function(inEvent) { 772 dispatchEvent: function(inEvent) {
771 var t = inEvent._target; 773 var t = inEvent._target;
772 if (t) { 774 if (t) {
773 t.dispatchEvent(inEvent); 775 t.dispatchEvent(inEvent);
774 // clone the event for the gesture system to process 776 // clone the event for the gesture system to process
775 // clone after dispatch to pick up gesture prevention code 777 // clone after dispatch to pick up gesture prevention code
776 var clone = this.cloneEvent(inEvent); 778 var clone = this.cloneEvent(inEvent);
777 clone.target = t; 779 clone.target = t;
778 this.fillGestureQueue(clone); 780 this.fillGestureQueue(clone);
779 } 781 }
780 }, 782 },
781 gestureTrigger: function() { 783 gestureTrigger: function() {
782 // process the gesture queue 784 // process the gesture queue
783 for (var i = 0, e; i < this.gestureQueue.length; i++) { 785 for (var i = 0, e; i < this.gestureQueue.length; i++) {
784 e = this.gestureQueue[i]; 786 e = this.gestureQueue[i];
785 for (var j = 0, g, fn; j < this.gestures.length; j++) { 787 for (var j = 0, g, fn; j < this.gestures.length; j++) {
786 g = this.gestures[j]; 788 g = this.gestures[j];
787 fn = g[e.type]; 789 fn = g[e.type];
788 if (fn) { 790 if (g.enabled && fn) {
789 fn.call(g, e); 791 fn.call(g, e);
790 } 792 }
791 } 793 }
792 } 794 }
793 this.gestureQueue.length = 0; 795 this.gestureQueue.length = 0;
794 }, 796 },
795 fillGestureQueue: function(ev) { 797 fillGestureQueue: function(ev) {
796 // only trigger the gesture queue once 798 // only trigger the gesture queue once
797 if (!this.gestureQueue.length) { 799 if (!this.gestureQueue.length) {
798 requestAnimationFrame(this.boundGestureTrigger); 800 requestAnimationFrame(this.boundGestureTrigger);
799 } 801 }
800 this.gestureQueue.push(ev); 802 this.gestureQueue.push(ev);
801 } 803 }
802 }; 804 };
803 dispatcher.boundHandler = dispatcher.eventHandler.bind(dispatcher); 805 dispatcher.boundHandler = dispatcher.eventHandler.bind(dispatcher);
804 dispatcher.boundGestureTrigger = dispatcher.gestureTrigger.bind(dispatcher); 806 dispatcher.boundGestureTrigger = dispatcher.gestureTrigger.bind(dispatcher);
805 scope.dispatcher = dispatcher; 807 scope.dispatcher = dispatcher;
806 scope.register = function(root) { 808
807 dispatcher.register(root); 809 /**
810 * Listen for `gesture` on `node` with the `handler` function
811 *
812 * If `handler` is the first listener for `gesture`, the underlying gesture re cognizer is then enabled.
813 *
814 * @param {Element} node
815 * @param {string} gesture
816 * @return Boolean `gesture` is a valid gesture
817 */
818 scope.activateGesture = function(node, gesture) {
819 var g = gesture.toLowerCase();
820 var dep = dispatcher.dependencyMap[g];
821 if (dep) {
822 var recognizer = dispatcher.gestures[dep.index];
823 if (dep.listeners === 0) {
824 if (recognizer) {
825 recognizer.enabled = true;
826 }
827 }
828 dep.listeners++;
829 if (!node._pgListeners) {
830 dispatcher.register(node);
831 node._pgListeners = 0;
832 }
833 // TODO(dfreedm): re-evaluate bookkeeping to avoid using attributes
834 if (recognizer) {
835 var touchAction = recognizer.defaultActions && recognizer.defaultActions [g];
836 var actionNode;
837 switch(node.nodeType) {
838 case Node.ELEMENT_NODE:
839 actionNode = node;
840 break;
841 case Node.DOCUMENT_FRAGMENT_NODE:
842 actionNode = node.host;
843 break;
844 default:
845 actionNode = null;
846 break;
847 }
848 if (touchAction && actionNode && !actionNode.hasAttribute('touch-action' )) {
849 actionNode.setAttribute('touch-action', touchAction);
850 }
851 }
852 node._pgListeners++;
853 }
854 return Boolean(dep);
808 }; 855 };
809 scope.unregister = dispatcher.unregister.bind(dispatcher); 856
810 scope.wrap = wrap; 857 /**
858 *
859 * Listen for `gesture` from `node` with `handler` function.
860 *
861 * @param {Element} node
862 * @param {string} gesture
863 * @param {Function} handler
864 * @param {Boolean} capture
865 */
866 scope.addEventListener = function(node, gesture, handler, capture) {
867 if (handler) {
868 scope.activateGesture(node, gesture);
869 node.addEventListener(gesture, handler, capture);
870 }
871 };
872
873 /**
874 * Tears down the gesture configuration for `node`
875 *
876 * If `handler` is the last listener for `gesture`, the underlying gesture rec ognizer is disabled.
877 *
878 * @param {Element} node
879 * @param {string} gesture
880 * @return Boolean `gesture` is a valid gesture
881 */
882 scope.deactivateGesture = function(node, gesture) {
883 var g = gesture.toLowerCase();
884 var dep = dispatcher.dependencyMap[g];
885 if (dep) {
886 if (dep.listeners > 0) {
887 dep.listeners--;
888 }
889 if (dep.listeners === 0) {
890 var recognizer = dispatcher.gestures[dep.index];
891 if (recognizer) {
892 recognizer.enabled = false;
893 }
894 }
895 if (node._pgListeners > 0) {
896 node._pgListeners--;
897 }
898 if (node._pgListeners === 0) {
899 dispatcher.unregister(node);
900 }
901 }
902 return Boolean(dep);
903 };
904
905 /**
906 * Stop listening for `gesture` from `node` with `handler` function.
907 *
908 * @param {Element} node
909 * @param {string} gesture
910 * @param {Function} handler
911 * @param {Boolean} capture
912 */
913 scope.removeEventListener = function(node, gesture, handler, capture) {
914 if (handler) {
915 scope.deactivateGesture(node, gesture);
916 node.removeEventListener(gesture, handler, capture);
917 }
918 };
811 })(window.PolymerGestures); 919 })(window.PolymerGestures);
812 920
813 /* 921 /*
814 * Copyright (c) 2014 The Polymer Project Authors. All rights reserved.
815 * This code may only be used under the BSD style license found at http://polyme r.github.io/LICENSE.txt
816 * The complete set of authors may be found at http://polymer.github.io/AUTHORS. txt
817 * The complete set of contributors may be found at http://polymer.github.io/CON TRIBUTORS.txt
818 * Code distributed by Google as part of the polymer project is also
819 * subject to an additional IP rights grant found at http://polymer.github.io/PA TENTS.txt
820 */
821
822 /**
823 * This module uses Mutation Observers to dynamically adjust which nodes will
824 * generate Pointer Events.
825 *
826 * All nodes that wish to generate Pointer Events must have the attribute
827 * `touch-action` set to `none`.
828 */
829 (function(scope) {
830 var forEach = Array.prototype.forEach.call.bind(Array.prototype.forEach);
831 var map = Array.prototype.map.call.bind(Array.prototype.map);
832 var toArray = Array.prototype.slice.call.bind(Array.prototype.slice);
833 var filter = Array.prototype.filter.call.bind(Array.prototype.filter);
834 var MO = window.MutationObserver || window.WebKitMutationObserver;
835 var SELECTOR = '[touch-action]';
836 var OBSERVER_INIT = {
837 subtree: true,
838 childList: true,
839 attributes: true,
840 attributeOldValue: true,
841 attributeFilter: ['touch-action']
842 };
843
844 function Installer(add, remove, changed, binder) {
845 this.addCallback = add.bind(binder);
846 this.removeCallback = remove.bind(binder);
847 this.changedCallback = changed.bind(binder);
848 if (MO) {
849 this.observer = new MO(this.mutationWatcher.bind(this));
850 }
851 }
852
853 Installer.prototype = {
854 watchSubtree: function(target) {
855 // Only watch scopes that can target find, as these are top-level.
856 // Otherwise we can see duplicate additions and removals that add noise.
857 //
858 // TODO(dfreedman): For some instances with ShadowDOMPolyfill, we can see
859 // a removal without an insertion when a node is redistributed among
860 // shadows. Since it all ends up correct in the document, watching only
861 // the document will yield the correct mutations to watch.
862 if (scope.targetFinding.canTarget(target)) {
863 this.observer.observe(target, OBSERVER_INIT);
864 }
865 },
866 enableOnSubtree: function(target) {
867 this.watchSubtree(target);
868 if (target === document && document.readyState !== 'complete') {
869 this.installOnLoad();
870 } else {
871 this.installNewSubtree(target);
872 }
873 },
874 installNewSubtree: function(target) {
875 forEach(this.findElements(target), this.addElement, this);
876 },
877 findElements: function(target) {
878 if (target.querySelectorAll) {
879 return target.querySelectorAll(SELECTOR);
880 }
881 return [];
882 },
883 removeElement: function(el) {
884 this.removeCallback(el);
885 },
886 addElement: function(el) {
887 this.addCallback(el);
888 },
889 elementChanged: function(el, oldValue) {
890 this.changedCallback(el, oldValue);
891 },
892 concatLists: function(accum, list) {
893 return accum.concat(toArray(list));
894 },
895 // register all touch-action = none nodes on document load
896 installOnLoad: function() {
897 document.addEventListener('readystatechange', function() {
898 if (document.readyState === 'complete') {
899 this.installNewSubtree(document);
900 }
901 }.bind(this));
902 },
903 isElement: function(n) {
904 return n.nodeType === Node.ELEMENT_NODE;
905 },
906 flattenMutationTree: function(inNodes) {
907 // find children with touch-action
908 var tree = map(inNodes, this.findElements, this);
909 // make sure the added nodes are accounted for
910 tree.push(filter(inNodes, this.isElement));
911 // flatten the list
912 return tree.reduce(this.concatLists, []);
913 },
914 mutationWatcher: function(mutations) {
915 mutations.forEach(this.mutationHandler, this);
916 },
917 mutationHandler: function(m) {
918 if (m.type === 'childList') {
919 var added = this.flattenMutationTree(m.addedNodes);
920 added.forEach(this.addElement, this);
921 var removed = this.flattenMutationTree(m.removedNodes);
922 removed.forEach(this.removeElement, this);
923 } else if (m.type === 'attributes') {
924 this.elementChanged(m.target, m.oldValue);
925 }
926 }
927 };
928
929 if (!MO) {
930 Installer.prototype.watchSubtree = function(){
931 console.warn('PolymerGestures: MutationObservers not found, touch-action w ill not be dynamically detected');
932 };
933 }
934
935 scope.Installer = Installer;
936 })(window.PolymerGestures);
937
938 /*
939 * Copyright (c) 2014 The Polymer Project Authors. All rights reserved. 922 * Copyright (c) 2014 The Polymer Project Authors. All rights reserved.
940 * This code may only be used under the BSD style license found at http://polyme r.github.io/LICENSE.txt 923 * This code may only be used under the BSD style license found at http://polyme r.github.io/LICENSE.txt
941 * The complete set of authors may be found at http://polymer.github.io/AUTHORS. txt 924 * The complete set of authors may be found at http://polymer.github.io/AUTHORS. txt
942 * The complete set of contributors may be found at http://polymer.github.io/CON TRIBUTORS.txt 925 * The complete set of contributors may be found at http://polymer.github.io/CON TRIBUTORS.txt
943 * Code distributed by Google as part of the polymer project is also 926 * Code distributed by Google as part of the polymer project is also
944 * subject to an additional IP rights grant found at http://polymer.github.io/PA TENTS.txt 927 * subject to an additional IP rights grant found at http://polymer.github.io/PA TENTS.txt
945 */ 928 */
946 929
947 (function (scope) { 930 (function (scope) {
948 var dispatcher = scope.dispatcher; 931 var dispatcher = scope.dispatcher;
(...skipping 10 matching lines...) Expand all
959 942
960 // handler block for native mouse events 943 // handler block for native mouse events
961 var mouseEvents = { 944 var mouseEvents = {
962 POINTER_ID: 1, 945 POINTER_ID: 1,
963 POINTER_TYPE: 'mouse', 946 POINTER_TYPE: 'mouse',
964 events: [ 947 events: [
965 'mousedown', 948 'mousedown',
966 'mousemove', 949 'mousemove',
967 'mouseup' 950 'mouseup'
968 ], 951 ],
952 exposes: [
953 'down',
954 'up',
955 'move'
956 ],
969 register: function(target) { 957 register: function(target) {
970 if (target !== document) {
971 return;
972 }
973 dispatcher.listen(target, this.events); 958 dispatcher.listen(target, this.events);
974 }, 959 },
975 unregister: function(target) { 960 unregister: function(target) {
976 dispatcher.unlisten(target, this.events); 961 dispatcher.unlisten(target, this.events);
977 }, 962 },
978 lastTouches: [], 963 lastTouches: [],
979 // collide with the global mouse listener 964 // collide with the global mouse listener
980 isEventSimulatedFromTouch: function(inEvent) { 965 isEventSimulatedFromTouch: function(inEvent) {
981 var lts = this.lastTouches; 966 var lts = this.lastTouches;
982 var x = inEvent.clientX, y = inEvent.clientY; 967 var x = inEvent.clientX, y = inEvent.clientY;
(...skipping 18 matching lines...) Expand all
1001 }, 986 },
1002 mousedown: function(inEvent) { 987 mousedown: function(inEvent) {
1003 if (!this.isEventSimulatedFromTouch(inEvent)) { 988 if (!this.isEventSimulatedFromTouch(inEvent)) {
1004 var p = pointermap.has(this.POINTER_ID); 989 var p = pointermap.has(this.POINTER_ID);
1005 // TODO(dfreedman) workaround for some elements not sending mouseup 990 // TODO(dfreedman) workaround for some elements not sending mouseup
1006 // http://crbug/149091 991 // http://crbug/149091
1007 if (p) { 992 if (p) {
1008 this.mouseup(inEvent); 993 this.mouseup(inEvent);
1009 } 994 }
1010 var e = this.prepareEvent(inEvent); 995 var e = this.prepareEvent(inEvent);
1011 e.target = scope.wrap(scope.findTarget(inEvent)); 996 e.target = scope.findTarget(inEvent);
1012 pointermap.set(this.POINTER_ID, e.target); 997 pointermap.set(this.POINTER_ID, e.target);
1013 dispatcher.down(e); 998 dispatcher.down(e);
1014 } 999 }
1015 }, 1000 },
1016 mousemove: function(inEvent) { 1001 mousemove: function(inEvent) {
1017 if (!this.isEventSimulatedFromTouch(inEvent)) { 1002 if (!this.isEventSimulatedFromTouch(inEvent)) {
1018 var e = this.prepareEvent(inEvent); 1003 var target = pointermap.get(this.POINTER_ID);
1019 e.target = pointermap.get(this.POINTER_ID); 1004 if (target) {
1020 dispatcher.move(e); 1005 var e = this.prepareEvent(inEvent);
1006 e.target = target;
1007 // handle case where we missed a mouseup
1008 if (e.buttons === 0) {
1009 dispatcher.cancel(e);
1010 this.cleanupMouse();
1011 } else {
1012 dispatcher.move(e);
1013 }
1014 }
1021 } 1015 }
1022 }, 1016 },
1023 mouseup: function(inEvent) { 1017 mouseup: function(inEvent) {
1024 if (!this.isEventSimulatedFromTouch(inEvent)) { 1018 if (!this.isEventSimulatedFromTouch(inEvent)) {
1025 var e = this.prepareEvent(inEvent); 1019 var e = this.prepareEvent(inEvent);
1026 e.relatedTarget = scope.wrap(scope.findTarget(inEvent)); 1020 e.relatedTarget = scope.findTarget(inEvent);
1027 e.target = pointermap.get(this.POINTER_ID); 1021 e.target = pointermap.get(this.POINTER_ID);
1028 dispatcher.up(e); 1022 dispatcher.up(e);
1029 this.cleanupMouse(); 1023 this.cleanupMouse();
1030 } 1024 }
1031 }, 1025 },
1032 cleanupMouse: function() { 1026 cleanupMouse: function() {
1033 pointermap['delete'](this.POINTER_ID); 1027 pointermap['delete'](this.POINTER_ID);
1034 } 1028 }
1035 }; 1029 };
1036 1030
(...skipping 12 matching lines...) Expand all
1049 (function(scope) { 1043 (function(scope) {
1050 var dispatcher = scope.dispatcher; 1044 var dispatcher = scope.dispatcher;
1051 var allShadows = scope.targetFinding.allShadows.bind(scope.targetFinding); 1045 var allShadows = scope.targetFinding.allShadows.bind(scope.targetFinding);
1052 var pointermap = dispatcher.pointermap; 1046 var pointermap = dispatcher.pointermap;
1053 var touchMap = Array.prototype.map.call.bind(Array.prototype.map); 1047 var touchMap = Array.prototype.map.call.bind(Array.prototype.map);
1054 // This should be long enough to ignore compat mouse events made by touch 1048 // This should be long enough to ignore compat mouse events made by touch
1055 var DEDUP_TIMEOUT = 2500; 1049 var DEDUP_TIMEOUT = 2500;
1056 var CLICK_COUNT_TIMEOUT = 200; 1050 var CLICK_COUNT_TIMEOUT = 200;
1057 var HYSTERESIS = 20; 1051 var HYSTERESIS = 20;
1058 var ATTRIB = 'touch-action'; 1052 var ATTRIB = 'touch-action';
1059 var INSTALLER; 1053 // TODO(dfreedm): disable until http://crbug.com/399765 is resolved
1060 // maybe one day... 1054 // var HAS_TOUCH_ACTION = ATTRIB in document.head.style;
1061 // var CAN_USE_GLOBAL = ATTRIB in document.head.style; 1055 var HAS_TOUCH_ACTION = false;
1062 var CAN_USE_GLOBAL = false;
1063 1056
1064 // handler block for native touch events 1057 // handler block for native touch events
1065 var touchEvents = { 1058 var touchEvents = {
1066 events: [ 1059 events: [
1067 'touchstart', 1060 'touchstart',
1068 'touchmove', 1061 'touchmove',
1069 'touchend', 1062 'touchend',
1070 'touchcancel' 1063 'touchcancel'
1071 ], 1064 ],
1072 register: function(target) { 1065 exposes: [
1073 if (CAN_USE_GLOBAL) { 1066 'down',
1074 dispatcher.listen(target, this.events); 1067 'up',
1075 } else { 1068 'move'
1076 INSTALLER.enableOnSubtree(target); 1069 ],
1070 register: function(target, initial) {
1071 if (initial) {
1072 return;
1077 } 1073 }
1074 dispatcher.listen(target, this.events);
1078 }, 1075 },
1079 unregister: function(target) { 1076 unregister: function(target) {
1080 if (CAN_USE_GLOBAL) { 1077 dispatcher.unlisten(target, this.events);
1081 dispatcher.unlisten(target, this.events);
1082 } else {
1083 // TODO(dfreedman): is it worth it to disconnect the MO?
1084 }
1085 },
1086 elementAdded: function(el) {
1087 var a = el.getAttribute(ATTRIB);
1088 var st = this.touchActionToScrollType(a);
1089 if (st) {
1090 el._scrollType = st;
1091 dispatcher.listen(el, this.events);
1092 // set touch-action on shadows as well
1093 allShadows(el).forEach(function(s) {
1094 s._scrollType = st;
1095 dispatcher.listen(s, this.events);
1096 }, this);
1097 }
1098 },
1099 elementRemoved: function(el) {
1100 el._scrollType = undefined;
1101 dispatcher.unlisten(el, this.events);
1102 // remove touch-action from shadow
1103 allShadows(el).forEach(function(s) {
1104 s._scrollType = undefined;
1105 dispatcher.unlisten(s, this.events);
1106 }, this);
1107 },
1108 elementChanged: function(el, oldValue) {
1109 var a = el.getAttribute(ATTRIB);
1110 var st = this.touchActionToScrollType(a);
1111 var oldSt = this.touchActionToScrollType(oldValue);
1112 // simply update scrollType if listeners are already established
1113 if (st && oldSt) {
1114 el._scrollType = st;
1115 allShadows(el).forEach(function(s) {
1116 s._scrollType = st;
1117 }, this);
1118 } else if (oldSt) {
1119 this.elementRemoved(el);
1120 } else if (st) {
1121 this.elementAdded(el);
1122 }
1123 }, 1078 },
1124 scrollTypes: { 1079 scrollTypes: {
1125 EMITTER: 'none', 1080 EMITTER: 'none',
1126 XSCROLLER: 'pan-x', 1081 XSCROLLER: 'pan-x',
1127 YSCROLLER: 'pan-y', 1082 YSCROLLER: 'pan-y',
1128 SCROLLER: /^(?:pan-x pan-y)|(?:pan-y pan-x)|auto|manipulation$/
1129 }, 1083 },
1130 touchActionToScrollType: function(touchAction) { 1084 touchActionToScrollType: function(touchAction) {
1131 var t = touchAction; 1085 var t = touchAction;
1132 var st = this.scrollTypes; 1086 var st = this.scrollTypes;
1133 if (t === 'none') { 1087 if (t === st.EMITTER) {
1134 return 'none'; 1088 return 'none';
1135 } else if (t === st.XSCROLLER) { 1089 } else if (t === st.XSCROLLER) {
1136 return 'X'; 1090 return 'X';
1137 } else if (t === st.YSCROLLER) { 1091 } else if (t === st.YSCROLLER) {
1138 return 'Y'; 1092 return 'Y';
1139 } else if (st.SCROLLER.exec(t)) { 1093 } else {
1140 return 'XY'; 1094 return 'XY';
1141 } 1095 }
1142 }, 1096 },
1143 POINTER_TYPE: 'touch', 1097 POINTER_TYPE: 'touch',
1144 firstTouch: null, 1098 firstTouch: null,
1145 isPrimaryTouch: function(inTouch) { 1099 isPrimaryTouch: function(inTouch) {
1146 return this.firstTouch === inTouch.identifier; 1100 return this.firstTouch === inTouch.identifier;
1147 }, 1101 },
1148 setPrimaryTouch: function(inTouch) { 1102 setPrimaryTouch: function(inTouch) {
1149 // set primary touch if there no pointers, or the only pointer is the mous e 1103 // set primary touch if there no pointers, or the only pointer is the mous e
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
1182 } 1136 }
1183 return ret; 1137 return ret;
1184 }, 1138 },
1185 findTarget: function(touch, id) { 1139 findTarget: function(touch, id) {
1186 if (this.currentTouchEvent.type === 'touchstart') { 1140 if (this.currentTouchEvent.type === 'touchstart') {
1187 if (this.isPrimaryTouch(touch)) { 1141 if (this.isPrimaryTouch(touch)) {
1188 var fastPath = { 1142 var fastPath = {
1189 clientX: touch.clientX, 1143 clientX: touch.clientX,
1190 clientY: touch.clientY, 1144 clientY: touch.clientY,
1191 path: this.currentTouchEvent.path, 1145 path: this.currentTouchEvent.path,
1192 target: scope.wrap(this.currentTouchEvent.target) 1146 target: this.currentTouchEvent.target
1193 }; 1147 };
1194 return scope.findTarget(fastPath); 1148 return scope.findTarget(fastPath);
1195 } else { 1149 } else {
1196 return scope.findTarget(touch); 1150 return scope.findTarget(touch);
1197 } 1151 }
1198 } 1152 }
1199 // reuse target we found in touchstart 1153 // reuse target we found in touchstart
1200 return pointermap.get(id); 1154 return pointermap.get(id);
1201 }, 1155 },
1202 touchToPointer: function(inTouch) { 1156 touchToPointer: function(inTouch) {
1203 var cte = this.currentTouchEvent; 1157 var cte = this.currentTouchEvent;
1204 var e = dispatcher.cloneEvent(inTouch); 1158 var e = dispatcher.cloneEvent(inTouch);
1205 // Spec specifies that pointerId 1 is reserved for Mouse. 1159 // Spec specifies that pointerId 1 is reserved for Mouse.
1206 // Touch identifiers can start at 0. 1160 // Touch identifiers can start at 0.
1207 // Add 2 to the touch identifier for compatibility. 1161 // Add 2 to the touch identifier for compatibility.
1208 var id = e.pointerId = inTouch.identifier + 2; 1162 var id = e.pointerId = inTouch.identifier + 2;
1209 e.target = scope.wrap(this.findTarget(inTouch, id)); 1163 e.target = this.findTarget(inTouch, id);
1210 e.bubbles = true; 1164 e.bubbles = true;
1211 e.cancelable = true; 1165 e.cancelable = true;
1212 e.detail = this.clickCount; 1166 e.detail = this.clickCount;
1213 e.buttons = this.typeToButtons(cte.type); 1167 e.buttons = this.typeToButtons(cte.type);
1214 e.width = inTouch.webkitRadiusX || inTouch.radiusX || 0; 1168 e.width = inTouch.webkitRadiusX || inTouch.radiusX || 0;
1215 e.height = inTouch.webkitRadiusY || inTouch.radiusY || 0; 1169 e.height = inTouch.webkitRadiusY || inTouch.radiusY || 0;
1216 e.pressure = inTouch.webkitForce || inTouch.force || 0.5; 1170 e.pressure = inTouch.webkitForce || inTouch.force || 0.5;
1217 e.isPrimary = this.isPrimaryTouch(inTouch); 1171 e.isPrimary = this.isPrimaryTouch(inTouch);
1218 e.pointerType = this.POINTER_TYPE; 1172 e.pointerType = this.POINTER_TYPE;
1219 e._source = 'touch'; 1173 e._source = 'touch';
(...skipping 21 matching lines...) Expand all
1241 if (inEvent.type === 'touchend' || inEvent._cancel) { 1195 if (inEvent.type === 'touchend' || inEvent._cancel) {
1242 this.cleanUpPointer(p); 1196 this.cleanUpPointer(p);
1243 } 1197 }
1244 } 1198 }
1245 }, 1199 },
1246 // For single axis scrollers, determines whether the element should emit 1200 // For single axis scrollers, determines whether the element should emit
1247 // pointer events or behave as a scroller 1201 // pointer events or behave as a scroller
1248 shouldScroll: function(inEvent) { 1202 shouldScroll: function(inEvent) {
1249 if (this.firstXY) { 1203 if (this.firstXY) {
1250 var ret; 1204 var ret;
1251 var scrollAxis = scope.targetFinding.findScrollAxis(inEvent); 1205 var touchAction = scope.targetFinding.findTouchAction(inEvent);
1206 var scrollAxis = this.touchActionToScrollType(touchAction);
1252 if (scrollAxis === 'none') { 1207 if (scrollAxis === 'none') {
1253 // this element is a touch-action: none, should never scroll 1208 // this element is a touch-action: none, should never scroll
1254 ret = false; 1209 ret = false;
1255 } else if (scrollAxis === 'XY') { 1210 } else if (scrollAxis === 'XY') {
1256 // this element should always scroll 1211 // this element should always scroll
1257 ret = true; 1212 ret = true;
1258 } else { 1213 } else {
1259 var t = inEvent.changedTouches[0]; 1214 var t = inEvent.changedTouches[0];
1260 // check the intended scroll axis, and other axis 1215 // check the intended scroll axis, and other axis
1261 var a = scrollAxis; 1216 var a = scrollAxis;
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
1309 this.dedupSynthMouse(inEvent); 1264 this.dedupSynthMouse(inEvent);
1310 if (!this.scrolling) { 1265 if (!this.scrolling) {
1311 this.clickCount++; 1266 this.clickCount++;
1312 this.processTouches(inEvent, this.down); 1267 this.processTouches(inEvent, this.down);
1313 } 1268 }
1314 }, 1269 },
1315 down: function(inPointer) { 1270 down: function(inPointer) {
1316 dispatcher.down(inPointer); 1271 dispatcher.down(inPointer);
1317 }, 1272 },
1318 touchmove: function(inEvent) { 1273 touchmove: function(inEvent) {
1319 if (CAN_USE_GLOBAL) { 1274 if (HAS_TOUCH_ACTION) {
1320 this.processTouches(inEvent, this.move); 1275 // touchevent.cancelable == false is sent when the page is scrolling und er native Touch Action in Chrome 36
1276 // https://groups.google.com/a/chromium.org/d/msg/input-dev/wHnyukcYBcA/ b9kmtwM1jJQJ
1277 if (inEvent.cancelable) {
1278 this.processTouches(inEvent, this.move);
1279 }
1321 } else { 1280 } else {
1322 if (!this.scrolling) { 1281 if (!this.scrolling) {
1323 if (this.scrolling === null && this.shouldScroll(inEvent)) { 1282 if (this.scrolling === null && this.shouldScroll(inEvent)) {
1324 this.scrolling = true; 1283 this.scrolling = true;
1325 } else { 1284 } else {
1326 this.scrolling = false; 1285 this.scrolling = false;
1327 inEvent.preventDefault(); 1286 inEvent.preventDefault();
1328 this.processTouches(inEvent, this.move); 1287 this.processTouches(inEvent, this.move);
1329 } 1288 }
1330 } else if (this.firstXY) { 1289 } else if (this.firstXY) {
(...skipping 10 matching lines...) Expand all
1341 } 1300 }
1342 }, 1301 },
1343 move: function(inPointer) { 1302 move: function(inPointer) {
1344 dispatcher.move(inPointer); 1303 dispatcher.move(inPointer);
1345 }, 1304 },
1346 touchend: function(inEvent) { 1305 touchend: function(inEvent) {
1347 this.dedupSynthMouse(inEvent); 1306 this.dedupSynthMouse(inEvent);
1348 this.processTouches(inEvent, this.up); 1307 this.processTouches(inEvent, this.up);
1349 }, 1308 },
1350 up: function(inPointer) { 1309 up: function(inPointer) {
1351 inPointer.relatedTarget = scope.wrap(scope.findTarget(inPointer)); 1310 inPointer.relatedTarget = scope.findTarget(inPointer);
1352 dispatcher.up(inPointer); 1311 dispatcher.up(inPointer);
1353 }, 1312 },
1354 cancel: function(inPointer) { 1313 cancel: function(inPointer) {
1355 dispatcher.cancel(inPointer); 1314 dispatcher.cancel(inPointer);
1356 }, 1315 },
1357 touchcancel: function(inEvent) { 1316 touchcancel: function(inEvent) {
1358 inEvent._cancel = true; 1317 inEvent._cancel = true;
1359 this.processTouches(inEvent, this.cancel); 1318 this.processTouches(inEvent, this.cancel);
1360 }, 1319 },
1361 cleanUpPointer: function(inPointer) { 1320 cleanUpPointer: function(inPointer) {
(...skipping 13 matching lines...) Expand all
1375 var i = lts.indexOf(lt); 1334 var i = lts.indexOf(lt);
1376 if (i > -1) { 1335 if (i > -1) {
1377 lts.splice(i, 1); 1336 lts.splice(i, 1);
1378 } 1337 }
1379 }).bind(null, lts, lt); 1338 }).bind(null, lts, lt);
1380 setTimeout(fn, DEDUP_TIMEOUT); 1339 setTimeout(fn, DEDUP_TIMEOUT);
1381 } 1340 }
1382 } 1341 }
1383 }; 1342 };
1384 1343
1385 if (!CAN_USE_GLOBAL) {
1386 INSTALLER = new scope.Installer(touchEvents.elementAdded, touchEvents.elemen tRemoved, touchEvents.elementChanged, touchEvents);
1387 }
1388
1389 scope.touchEvents = touchEvents; 1344 scope.touchEvents = touchEvents;
1390 })(window.PolymerGestures); 1345 })(window.PolymerGestures);
1391 1346
1392 /* 1347 /*
1393 * Copyright (c) 2014 The Polymer Project Authors. All rights reserved. 1348 * Copyright (c) 2014 The Polymer Project Authors. All rights reserved.
1394 * This code may only be used under the BSD style license found at http://polyme r.github.io/LICENSE.txt 1349 * This code may only be used under the BSD style license found at http://polyme r.github.io/LICENSE.txt
1395 * The complete set of authors may be found at http://polymer.github.io/AUTHORS. txt 1350 * The complete set of authors may be found at http://polymer.github.io/AUTHORS. txt
1396 * The complete set of contributors may be found at http://polymer.github.io/CON TRIBUTORS.txt 1351 * The complete set of contributors may be found at http://polymer.github.io/CON TRIBUTORS.txt
1397 * Code distributed by Google as part of the polymer project is also 1352 * Code distributed by Google as part of the polymer project is also
1398 * subject to an additional IP rights grant found at http://polymer.github.io/PA TENTS.txt 1353 * subject to an additional IP rights grant found at http://polymer.github.io/PA TENTS.txt
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
1432 e.pointerType = this.POINTER_TYPES[inEvent.pointerType]; 1387 e.pointerType = this.POINTER_TYPES[inEvent.pointerType];
1433 } 1388 }
1434 e._source = 'ms'; 1389 e._source = 'ms';
1435 return e; 1390 return e;
1436 }, 1391 },
1437 cleanup: function(id) { 1392 cleanup: function(id) {
1438 pointermap['delete'](id); 1393 pointermap['delete'](id);
1439 }, 1394 },
1440 MSPointerDown: function(inEvent) { 1395 MSPointerDown: function(inEvent) {
1441 var e = this.prepareEvent(inEvent); 1396 var e = this.prepareEvent(inEvent);
1442 e.target = scope.wrap(scope.findTarget(inEvent)); 1397 e.target = scope.findTarget(inEvent);
1443 pointermap.set(inEvent.pointerId, e.target); 1398 pointermap.set(inEvent.pointerId, e.target);
1444 dispatcher.down(e); 1399 dispatcher.down(e);
1445 }, 1400 },
1446 MSPointerMove: function(inEvent) { 1401 MSPointerMove: function(inEvent) {
1447 var e = this.prepareEvent(inEvent); 1402 var e = this.prepareEvent(inEvent);
1448 e.target = pointermap.get(e.pointerId); 1403 e.target = pointermap.get(e.pointerId);
1449 dispatcher.move(e); 1404 dispatcher.move(e);
1450 }, 1405 },
1451 MSPointerUp: function(inEvent) { 1406 MSPointerUp: function(inEvent) {
1452 var e = this.prepareEvent(inEvent); 1407 var e = this.prepareEvent(inEvent);
1453 e.relatedTarget = scope.wrap(scope.findTarget(inEvent)); 1408 e.relatedTarget = scope.findTarget(inEvent);
1454 e.target = pointermap.get(e.pointerId); 1409 e.target = pointermap.get(e.pointerId);
1455 dispatcher.up(e); 1410 dispatcher.up(e);
1456 this.cleanup(inEvent.pointerId); 1411 this.cleanup(inEvent.pointerId);
1457 }, 1412 },
1458 MSPointerCancel: function(inEvent) { 1413 MSPointerCancel: function(inEvent) {
1459 var e = this.prepareEvent(inEvent); 1414 var e = this.prepareEvent(inEvent);
1460 e.relatedTarget = scope.wrap(scope.findTarget(inEvent)); 1415 e.relatedTarget = scope.findTarget(inEvent);
1461 e.target = pointermap.get(e.pointerId); 1416 e.target = pointermap.get(e.pointerId);
1462 dispatcher.cancel(e); 1417 dispatcher.cancel(e);
1463 this.cleanup(inEvent.pointerId); 1418 this.cleanup(inEvent.pointerId);
1464 } 1419 }
1465 }; 1420 };
1466 1421
1467 scope.msEvents = msEvents; 1422 scope.msEvents = msEvents;
1468 })(window.PolymerGestures); 1423 })(window.PolymerGestures);
1469 1424
1470 /* 1425 /*
(...skipping 27 matching lines...) Expand all
1498 dispatcher.listen(target, this.events); 1453 dispatcher.listen(target, this.events);
1499 }, 1454 },
1500 unregister: function(target) { 1455 unregister: function(target) {
1501 dispatcher.unlisten(target, this.events); 1456 dispatcher.unlisten(target, this.events);
1502 }, 1457 },
1503 cleanup: function(id) { 1458 cleanup: function(id) {
1504 pointermap['delete'](id); 1459 pointermap['delete'](id);
1505 }, 1460 },
1506 pointerdown: function(inEvent) { 1461 pointerdown: function(inEvent) {
1507 var e = this.prepareEvent(inEvent); 1462 var e = this.prepareEvent(inEvent);
1508 e.target = scope.wrap(scope.findTarget(inEvent)); 1463 e.target = scope.findTarget(inEvent);
1509 pointermap.set(e.pointerId, e.target); 1464 pointermap.set(e.pointerId, e.target);
1510 dispatcher.down(e); 1465 dispatcher.down(e);
1511 }, 1466 },
1512 pointermove: function(inEvent) { 1467 pointermove: function(inEvent) {
1513 var e = this.prepareEvent(inEvent); 1468 var e = this.prepareEvent(inEvent);
1514 e.target = pointermap.get(e.pointerId); 1469 e.target = pointermap.get(e.pointerId);
1515 dispatcher.move(e); 1470 dispatcher.move(e);
1516 }, 1471 },
1517 pointerup: function(inEvent) { 1472 pointerup: function(inEvent) {
1518 var e = this.prepareEvent(inEvent); 1473 var e = this.prepareEvent(inEvent);
1519 e.relatedTarget = scope.wrap(scope.findTarget(inEvent)); 1474 e.relatedTarget = scope.findTarget(inEvent);
1520 e.target = pointermap.get(e.pointerId); 1475 e.target = pointermap.get(e.pointerId);
1521 dispatcher.up(e); 1476 dispatcher.up(e);
1522 this.cleanup(inEvent.pointerId); 1477 this.cleanup(inEvent.pointerId);
1523 }, 1478 },
1524 pointercancel: function(inEvent) { 1479 pointercancel: function(inEvent) {
1525 var e = this.prepareEvent(inEvent); 1480 var e = this.prepareEvent(inEvent);
1526 e.relatedTarget = scope.wrap(scope.findTarget(inEvent)); 1481 e.relatedTarget = scope.findTarget(inEvent);
1527 e.target = pointermap.get(e.pointerId); 1482 e.target = pointermap.get(e.pointerId);
1528 dispatcher.cancel(e); 1483 dispatcher.cancel(e);
1529 this.cleanup(inEvent.pointerId); 1484 this.cleanup(inEvent.pointerId);
1530 } 1485 }
1531 }; 1486 };
1532 1487
1533 scope.pointerEvents = pointerEvents; 1488 scope.pointerEvents = pointerEvents;
1534 })(window.PolymerGestures); 1489 })(window.PolymerGestures);
1535 1490
1536 /* 1491 /*
1537 * Copyright (c) 2014 The Polymer Project Authors. All rights reserved. 1492 * Copyright (c) 2014 The Polymer Project Authors. All rights reserved.
1538 * This code may only be used under the BSD style license found at http://polyme r.github.io/LICENSE.txt 1493 * This code may only be used under the BSD style license found at http://polyme r.github.io/LICENSE.txt
1539 * The complete set of authors may be found at http://polymer.github.io/AUTHORS. txt 1494 * The complete set of authors may be found at http://polymer.github.io/AUTHORS. txt
1540 * The complete set of contributors may be found at http://polymer.github.io/CON TRIBUTORS.txt 1495 * The complete set of contributors may be found at http://polymer.github.io/CON TRIBUTORS.txt
1541 * Code distributed by Google as part of the polymer project is also 1496 * Code distributed by Google as part of the polymer project is also
1542 * subject to an additional IP rights grant found at http://polymer.github.io/PA TENTS.txt 1497 * subject to an additional IP rights grant found at http://polymer.github.io/PA TENTS.txt
1543 */ 1498 */
1544 1499
1545 /** 1500 /**
1546 * This module contains the handlers for native platform events. 1501 * This module contains the handlers for native platform events.
1547 * From here, the dispatcher is called to create unified pointer events. 1502 * From here, the dispatcher is called to create unified pointer events.
1548 * Included are touch events (v1), mouse events, and MSPointerEvents. 1503 * Included are touch events (v1), mouse events, and MSPointerEvents.
1549 */ 1504 */
1550 (function(scope) { 1505 (function(scope) {
1551 var dispatcher = scope.dispatcher; 1506 var dispatcher = scope.dispatcher;
1507 var nav = window.navigator;
1552 1508
1553 if (window.PointerEvent) { 1509 if (window.PointerEvent) {
1554 dispatcher.registerSource('pointer', scope.pointerEvents); 1510 dispatcher.registerSource('pointer', scope.pointerEvents);
1555 } else if (window.navigator.msPointerEnabled) { 1511 } else if (nav.msPointerEnabled) {
1556 dispatcher.registerSource('ms', scope.msEvents); 1512 dispatcher.registerSource('ms', scope.msEvents);
1557 } else { 1513 } else {
1558 dispatcher.registerSource('mouse', scope.mouseEvents); 1514 dispatcher.registerSource('mouse', scope.mouseEvents);
1559 if (window.ontouchstart !== undefined) { 1515 if (window.ontouchstart !== undefined) {
1560 dispatcher.registerSource('touch', scope.touchEvents); 1516 dispatcher.registerSource('touch', scope.touchEvents);
1517 /*
1518 * NOTE: an empty touch listener on body will reactivate nodes imported fr om templates with touch listeners
1519 * Removing it will re-break the nodes
1520 *
1521 * Work around for https://bugs.webkit.org/show_bug.cgi?id=135628
1522 */
1523 var isSafari = nav.userAgent.match('Safari') && !nav.userAgent.match('Chro me');
1524 if (isSafari) {
1525 document.body.addEventListener('touchstart', function(){});
1526 }
1561 } 1527 }
1562 } 1528 }
1563 1529 dispatcher.register(document, true);
1564 dispatcher.register(document);
1565 })(window.PolymerGestures); 1530 })(window.PolymerGestures);
1566 1531
1567 /* 1532 /*
1568 * Copyright (c) 2014 The Polymer Project Authors. All rights reserved. 1533 * Copyright (c) 2014 The Polymer Project Authors. All rights reserved.
1569 * This code may only be used under the BSD style license found at http://polyme r.github.io/LICENSE.txt 1534 * This code may only be used under the BSD style license found at http://polyme r.github.io/LICENSE.txt
1570 * The complete set of authors may be found at http://polymer.github.io/AUTHORS. txt 1535 * The complete set of authors may be found at http://polymer.github.io/AUTHORS. txt
1571 * The complete set of contributors may be found at http://polymer.github.io/CON TRIBUTORS.txt 1536 * The complete set of contributors may be found at http://polymer.github.io/CON TRIBUTORS.txt
1572 * Code distributed by Google as part of the polymer project is also 1537 * Code distributed by Google as part of the polymer project is also
1573 * subject to an additional IP rights grant found at http://polymer.github.io/PA TENTS.txt 1538 * subject to an additional IP rights grant found at http://polymer.github.io/PA TENTS.txt
1574 */ 1539 */
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after
1672 (function(scope) { 1637 (function(scope) {
1673 var dispatcher = scope.dispatcher; 1638 var dispatcher = scope.dispatcher;
1674 var eventFactory = scope.eventFactory; 1639 var eventFactory = scope.eventFactory;
1675 var pointermap = new scope.PointerMap(); 1640 var pointermap = new scope.PointerMap();
1676 var track = { 1641 var track = {
1677 events: [ 1642 events: [
1678 'down', 1643 'down',
1679 'move', 1644 'move',
1680 'up', 1645 'up',
1681 ], 1646 ],
1647 exposes: [
1648 'trackstart',
1649 'track',
1650 'trackx',
1651 'tracky',
1652 'trackend'
1653 ],
1654 defaultActions: {
1655 'track': 'none',
1656 'trackx': 'pan-y',
1657 'tracky': 'pan-x'
1658 },
1682 WIGGLE_THRESHOLD: 4, 1659 WIGGLE_THRESHOLD: 4,
1683 clampDir: function(inDelta) { 1660 clampDir: function(inDelta) {
1684 return inDelta > 0 ? 1 : -1; 1661 return inDelta > 0 ? 1 : -1;
1685 }, 1662 },
1686 calcPositionDelta: function(inA, inB) { 1663 calcPositionDelta: function(inA, inB) {
1687 var x = 0, y = 0; 1664 var x = 0, y = 0;
1688 if (inA && inB) { 1665 if (inA && inB) {
1689 x = inB.pageX - inA.pageX; 1666 x = inB.pageX - inA.pageX;
1690 y = inB.pageY - inA.pageY; 1667 y = inB.pageY - inA.pageY;
1691 } 1668 }
1692 return {x: x, y: y}; 1669 return {x: x, y: y};
1693 }, 1670 },
1694 fireTrack: function(inType, inEvent, inTrackingData) { 1671 fireTrack: function(inType, inEvent, inTrackingData) {
1695 var t = inTrackingData; 1672 var t = inTrackingData;
1696 var d = this.calcPositionDelta(t.downEvent, inEvent); 1673 var d = this.calcPositionDelta(t.downEvent, inEvent);
1697 var dd = this.calcPositionDelta(t.lastMoveEvent, inEvent); 1674 var dd = this.calcPositionDelta(t.lastMoveEvent, inEvent);
1698 if (dd.x) { 1675 if (dd.x) {
1699 t.xDirection = this.clampDir(dd.x); 1676 t.xDirection = this.clampDir(dd.x);
1677 } else if (inType === 'trackx') {
1678 return;
1700 } 1679 }
1701 if (dd.y) { 1680 if (dd.y) {
1702 t.yDirection = this.clampDir(dd.y); 1681 t.yDirection = this.clampDir(dd.y);
1682 } else if (inType === 'tracky') {
1683 return;
1703 } 1684 }
1704 var e = eventFactory.makeGestureEvent(inType, { 1685 var gestureProto = {
1705 bubbles: true, 1686 bubbles: true,
1706 cancelable: true, 1687 cancelable: true,
1707 dx: d.x,
1708 dy: d.y,
1709 ddx: dd.x,
1710 ddy: dd.y,
1711 x: inEvent.x,
1712 y: inEvent.y,
1713 clientX: inEvent.clientX,
1714 clientY: inEvent.clientY,
1715 pageX: inEvent.pageX,
1716 pageY: inEvent.pageY,
1717 screenX: inEvent.screenX,
1718 screenY: inEvent.screenY,
1719 xDirection: t.xDirection,
1720 yDirection: t.yDirection,
1721 trackInfo: t.trackInfo, 1688 trackInfo: t.trackInfo,
1722 relatedTarget: inEvent.relatedTarget, 1689 relatedTarget: inEvent.relatedTarget,
1723 pointerType: inEvent.pointerType, 1690 pointerType: inEvent.pointerType,
1724 pointerId: inEvent.pointerId, 1691 pointerId: inEvent.pointerId,
1725 _source: 'track' 1692 _source: 'track'
1726 }); 1693 };
1694 if (inType !== 'tracky') {
1695 gestureProto.x = inEvent.x;
1696 gestureProto.dx = d.x;
1697 gestureProto.ddx = dd.x;
1698 gestureProto.clientX = inEvent.clientX;
1699 gestureProto.pageX = inEvent.pageX;
1700 gestureProto.screenX = inEvent.screenX;
1701 gestureProto.xDirection = t.xDirection;
1702 }
1703 if (inType !== 'trackx') {
1704 gestureProto.dy = d.y;
1705 gestureProto.ddy = dd.y;
1706 gestureProto.y = inEvent.y;
1707 gestureProto.clientY = inEvent.clientY;
1708 gestureProto.pageY = inEvent.pageY;
1709 gestureProto.screenY = inEvent.screenY;
1710 gestureProto.yDirection = t.yDirection;
1711 }
1712 var e = eventFactory.makeGestureEvent(inType, gestureProto);
1727 t.downTarget.dispatchEvent(e); 1713 t.downTarget.dispatchEvent(e);
1728 }, 1714 },
1729 down: function(inEvent) { 1715 down: function(inEvent) {
1730 if (inEvent.isPrimary && (inEvent.pointerType === 'mouse' ? inEvent.butto ns === 1 : true)) { 1716 if (inEvent.isPrimary && (inEvent.pointerType === 'mouse' ? inEvent.butto ns === 1 : true)) {
1731 var p = { 1717 var p = {
1732 downEvent: inEvent, 1718 downEvent: inEvent,
1733 downTarget: inEvent.target, 1719 downTarget: inEvent.target,
1734 trackInfo: {}, 1720 trackInfo: {},
1735 lastMoveEvent: null, 1721 lastMoveEvent: null,
1736 xDirection: 0, 1722 xDirection: 0,
1737 yDirection: 0, 1723 yDirection: 0,
1738 tracking: false 1724 tracking: false
1739 }; 1725 };
1740 pointermap.set(inEvent.pointerId, p); 1726 pointermap.set(inEvent.pointerId, p);
1741 } 1727 }
1742 }, 1728 },
1743 move: function(inEvent) { 1729 move: function(inEvent) {
1744 var p = pointermap.get(inEvent.pointerId); 1730 var p = pointermap.get(inEvent.pointerId);
1745 if (p) { 1731 if (p) {
1746 if (!p.tracking) { 1732 if (!p.tracking) {
1747 var d = this.calcPositionDelta(p.downEvent, inEvent); 1733 var d = this.calcPositionDelta(p.downEvent, inEvent);
1748 var move = d.x * d.x + d.y * d.y; 1734 var move = d.x * d.x + d.y * d.y;
1749 // start tracking only if finger moves more than WIGGLE_THRESHOLD 1735 // start tracking only if finger moves more than WIGGLE_THRESHOLD
1750 if (move > this.WIGGLE_THRESHOLD) { 1736 if (move > this.WIGGLE_THRESHOLD) {
1751 p.tracking = true; 1737 p.tracking = true;
1752 this.fireTrack('trackstart', p.downEvent, p); 1738 p.lastMoveEvent = p.downEvent;
1753 this.fireTrack('track', inEvent, p); 1739 this.fireTrack('trackstart', inEvent, p);
1754 } 1740 }
1755 } else { 1741 }
1742 if (p.tracking) {
1756 this.fireTrack('track', inEvent, p); 1743 this.fireTrack('track', inEvent, p);
1744 this.fireTrack('trackx', inEvent, p);
1745 this.fireTrack('tracky', inEvent, p);
1757 } 1746 }
1758 p.lastMoveEvent = inEvent; 1747 p.lastMoveEvent = inEvent;
1759 } 1748 }
1760 }, 1749 },
1761 up: function(inEvent) { 1750 up: function(inEvent) {
1762 var p = pointermap.get(inEvent.pointerId); 1751 var p = pointermap.get(inEvent.pointerId);
1763 if (p) { 1752 if (p) {
1764 if (p.tracking) { 1753 if (p.tracking) {
1765 this.fireTrack('trackend', inEvent, p); 1754 this.fireTrack('trackend', inEvent, p);
1766 } 1755 }
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
1830 var hold = { 1819 var hold = {
1831 // wait at least HOLD_DELAY ms between hold and pulse events 1820 // wait at least HOLD_DELAY ms between hold and pulse events
1832 HOLD_DELAY: 200, 1821 HOLD_DELAY: 200,
1833 // pointer can move WIGGLE_THRESHOLD pixels before not counting as a hold 1822 // pointer can move WIGGLE_THRESHOLD pixels before not counting as a hold
1834 WIGGLE_THRESHOLD: 16, 1823 WIGGLE_THRESHOLD: 16,
1835 events: [ 1824 events: [
1836 'down', 1825 'down',
1837 'move', 1826 'move',
1838 'up', 1827 'up',
1839 ], 1828 ],
1829 exposes: [
1830 'hold',
1831 'holdpulse',
1832 'release'
1833 ],
1840 heldPointer: null, 1834 heldPointer: null,
1841 holdJob: null, 1835 holdJob: null,
1842 pulse: function() { 1836 pulse: function() {
1843 var hold = Date.now() - this.heldPointer.timeStamp; 1837 var hold = Date.now() - this.heldPointer.timeStamp;
1844 var type = this.held ? 'holdpulse' : 'hold'; 1838 var type = this.held ? 'holdpulse' : 'hold';
1845 this.fireHold(type, hold); 1839 this.fireHold(type, hold);
1846 this.held = true; 1840 this.held = true;
1847 }, 1841 },
1848 cancel: function() { 1842 cancel: function() {
1849 clearInterval(this.holdJob); 1843 clearInterval(this.holdJob);
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after
1936 */ 1930 */
1937 (function(scope) { 1931 (function(scope) {
1938 var dispatcher = scope.dispatcher; 1932 var dispatcher = scope.dispatcher;
1939 var eventFactory = scope.eventFactory; 1933 var eventFactory = scope.eventFactory;
1940 var pointermap = new scope.PointerMap(); 1934 var pointermap = new scope.PointerMap();
1941 var tap = { 1935 var tap = {
1942 events: [ 1936 events: [
1943 'down', 1937 'down',
1944 'up' 1938 'up'
1945 ], 1939 ],
1940 exposes: [
1941 'tap'
1942 ],
1946 down: function(inEvent) { 1943 down: function(inEvent) {
1947 if (inEvent.isPrimary && !inEvent.tapPrevented) { 1944 if (inEvent.isPrimary && !inEvent.tapPrevented) {
1948 pointermap.set(inEvent.pointerId, { 1945 pointermap.set(inEvent.pointerId, {
1949 target: inEvent.target, 1946 target: inEvent.target,
1950 buttons: inEvent.buttons, 1947 buttons: inEvent.buttons,
1951 x: inEvent.clientX, 1948 x: inEvent.clientX,
1952 y: inEvent.clientY 1949 y: inEvent.clientY
1953 }); 1950 });
1954 } 1951 }
1955 }, 1952 },
(...skipping 1364 matching lines...) Expand 10 before | Expand all | Expand 10 after
3320 }; 3317 };
3321 }, 3318 },
3322 3319
3323 createBinaryExpression: function(op, left, right) { 3320 createBinaryExpression: function(op, left, right) {
3324 if (!binaryOperators[op]) 3321 if (!binaryOperators[op])
3325 throw Error('Disallowed operator: ' + op); 3322 throw Error('Disallowed operator: ' + op);
3326 3323
3327 left = getFn(left); 3324 left = getFn(left);
3328 right = getFn(right); 3325 right = getFn(right);
3329 3326
3327 switch (op) {
3328 case '||':
3329 this.dynamicDeps = true;
3330 return function(model, observer, filterRegistry) {
3331 return left(model, observer, filterRegistry) ||
3332 right(model, observer, filterRegistry);
3333 };
3334 case '&&':
3335 this.dynamicDeps = true;
3336 return function(model, observer, filterRegistry) {
3337 return left(model, observer, filterRegistry) &&
3338 right(model, observer, filterRegistry);
3339 };
3340 }
3341
3330 return function(model, observer, filterRegistry) { 3342 return function(model, observer, filterRegistry) {
3331 return binaryOperators[op](left(model, observer, filterRegistry), 3343 return binaryOperators[op](left(model, observer, filterRegistry),
3332 right(model, observer, filterRegistry)); 3344 right(model, observer, filterRegistry));
3333 }; 3345 };
3334 }, 3346 },
3335 3347
3336 createConditionalExpression: function(test, consequent, alternate) { 3348 createConditionalExpression: function(test, consequent, alternate) {
3337 test = getFn(test); 3349 test = getFn(test);
3338 consequent = getFn(consequent); 3350 consequent = getFn(consequent);
3339 alternate = getFn(alternate); 3351 alternate = getFn(alternate);
3340 3352
3353 this.dynamicDeps = true;
3354
3341 return function(model, observer, filterRegistry) { 3355 return function(model, observer, filterRegistry) {
3342 return test(model, observer, filterRegistry) ? 3356 return test(model, observer, filterRegistry) ?
3343 consequent(model, observer, filterRegistry) : 3357 consequent(model, observer, filterRegistry) :
3344 alternate(model, observer, filterRegistry); 3358 alternate(model, observer, filterRegistry);
3345 } 3359 }
3346 }, 3360 },
3347 3361
3348 createIdentifier: function(name) { 3362 createIdentifier: function(name) {
3349 var ident = new IdentPath(name); 3363 var ident = new IdentPath(name);
3350 ident.type = 'Identifier'; 3364 ident.type = 'Identifier';
(...skipping 295 matching lines...) Expand 10 before | Expand all | Expand 10 after
3646 })(this); 3660 })(this);
3647 3661
3648 /* 3662 /*
3649 * Copyright (c) 2014 The Polymer Project Authors. All rights reserved. 3663 * Copyright (c) 2014 The Polymer Project Authors. All rights reserved.
3650 * This code may only be used under the BSD style license found at http://polyme r.github.io/LICENSE.txt 3664 * This code may only be used under the BSD style license found at http://polyme r.github.io/LICENSE.txt
3651 * The complete set of authors may be found at http://polymer.github.io/AUTHORS. txt 3665 * The complete set of authors may be found at http://polymer.github.io/AUTHORS. txt
3652 * The complete set of contributors may be found at http://polymer.github.io/CON TRIBUTORS.txt 3666 * The complete set of contributors may be found at http://polymer.github.io/CON TRIBUTORS.txt
3653 * Code distributed by Google as part of the polymer project is also 3667 * Code distributed by Google as part of the polymer project is also
3654 * subject to an additional IP rights grant found at http://polymer.github.io/PA TENTS.txt 3668 * subject to an additional IP rights grant found at http://polymer.github.io/PA TENTS.txt
3655 */ 3669 */
3670 Polymer = {
3671 version: '0.3.5-5d00e4b'
3672 };
3673
3674 /*
3675 * Copyright (c) 2014 The Polymer Project Authors. All rights reserved.
3676 * This code may only be used under the BSD style license found at http://polyme r.github.io/LICENSE.txt
3677 * The complete set of authors may be found at http://polymer.github.io/AUTHORS. txt
3678 * The complete set of contributors may be found at http://polymer.github.io/CON TRIBUTORS.txt
3679 * Code distributed by Google as part of the polymer project is also
3680 * subject to an additional IP rights grant found at http://polymer.github.io/PA TENTS.txt
3681 */
3656 3682
3657 // TODO(sorvell): this ensures Polymer is an object and not a function 3683 // TODO(sorvell): this ensures Polymer is an object and not a function
3658 // Platform is currently defining it as a function to allow for async loading 3684 // Platform is currently defining it as a function to allow for async loading
3659 // of polymer; once we refine the loading process this likely goes away. 3685 // of polymer; once we refine the loading process this likely goes away.
3660 if (typeof window.Polymer === 'function') { 3686 if (typeof window.Polymer === 'function') {
3661 Polymer = {}; 3687 Polymer = {};
3662 } 3688 }
3663 3689
3664 3690
3665 /* 3691 /*
(...skipping 281 matching lines...) Expand 10 before | Expand all | Expand 10 after
3947 * Copyright (c) 2014 The Polymer Project Authors. All rights reserved. 3973 * Copyright (c) 2014 The Polymer Project Authors. All rights reserved.
3948 * This code may only be used under the BSD style license found at http://polyme r.github.io/LICENSE.txt 3974 * This code may only be used under the BSD style license found at http://polyme r.github.io/LICENSE.txt
3949 * The complete set of authors may be found at http://polymer.github.io/AUTHORS. txt 3975 * The complete set of authors may be found at http://polymer.github.io/AUTHORS. txt
3950 * The complete set of contributors may be found at http://polymer.github.io/CON TRIBUTORS.txt 3976 * The complete set of contributors may be found at http://polymer.github.io/CON TRIBUTORS.txt
3951 * Code distributed by Google as part of the polymer project is also 3977 * Code distributed by Google as part of the polymer project is also
3952 * subject to an additional IP rights grant found at http://polymer.github.io/PA TENTS.txt 3978 * subject to an additional IP rights grant found at http://polymer.github.io/PA TENTS.txt
3953 */ 3979 */
3954 3980
3955 (function(scope) { 3981 (function(scope) {
3956 3982
3983 function noopHandler(value) {
3984 return value;
3985 }
3986
3957 var typeHandlers = { 3987 var typeHandlers = {
3958 string: function(value) { 3988 string: noopHandler,
3959 return value; 3989 'undefined': noopHandler,
3960 },
3961 date: function(value) { 3990 date: function(value) {
3962 return new Date(Date.parse(value) || Date.now()); 3991 return new Date(Date.parse(value) || Date.now());
3963 }, 3992 },
3964 boolean: function(value) { 3993 boolean: function(value) {
3965 if (value === '') { 3994 if (value === '') {
3966 return true; 3995 return true;
3967 } 3996 }
3968 return value === 'false' ? false : !!value; 3997 return value === 'false' ? false : !!value;
3969 }, 3998 },
3970 number: function(value) { 3999 number: function(value) {
(...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after
4091 clearTimeout(handle); 4120 clearTimeout(handle);
4092 } 4121 }
4093 }, 4122 },
4094 /** 4123 /**
4095 * Fire an event. 4124 * Fire an event.
4096 * @method fire 4125 * @method fire
4097 * @returns {Object} event 4126 * @returns {Object} event
4098 * @param {string} type An event name. 4127 * @param {string} type An event name.
4099 * @param {any} detail 4128 * @param {any} detail
4100 * @param {Node} onNode Target node. 4129 * @param {Node} onNode Target node.
4130 * @param {Boolean} bubbles Set false to prevent bubbling, defaults to true
4131 * @param {Boolean} cancelable Set false to prevent cancellation, defaults to true
4101 */ 4132 */
4102 fire: function(type, detail, onNode, bubbles, cancelable) { 4133 fire: function(type, detail, onNode, bubbles, cancelable) {
4103 var node = onNode || this; 4134 var node = onNode || this;
4104 var detail = detail || {}; 4135 var detail = detail === null || detail === undefined ? {} : detail;
4105 var event = new CustomEvent(type, { 4136 var event = new CustomEvent(type, {
4106 bubbles: (bubbles !== undefined ? bubbles : true), 4137 bubbles: bubbles !== undefined ? bubbles : true,
4107 cancelable: (cancelable !== undefined ? cancelable : true), 4138 cancelable: cancelable !== undefined ? cancelable : true,
4108 detail: detail 4139 detail: detail
4109 }); 4140 });
4110 node.dispatchEvent(event); 4141 node.dispatchEvent(event);
4111 return event; 4142 return event;
4112 }, 4143 },
4113 /** 4144 /**
4114 * Fire an event asynchronously. 4145 * Fire an event asynchronously.
4115 * @method asyncFire 4146 * @method asyncFire
4116 * @param {string} type An event name. 4147 * @param {string} type An event name.
4117 * @param detail 4148 * @param detail
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after
4194 // event listeners on host 4225 // event listeners on host
4195 addHostListeners: function() { 4226 addHostListeners: function() {
4196 var events = this.eventDelegates; 4227 var events = this.eventDelegates;
4197 log.events && (Object.keys(events).length > 0) && console.log('[%s] addHos tListeners:', this.localName, events); 4228 log.events && (Object.keys(events).length > 0) && console.log('[%s] addHos tListeners:', this.localName, events);
4198 // NOTE: host events look like bindings but really are not; 4229 // NOTE: host events look like bindings but really are not;
4199 // (1) we don't want the attribute to be set and (2) we want to support 4230 // (1) we don't want the attribute to be set and (2) we want to support
4200 // multiple event listeners ('host' and 'instance') and Node.bind 4231 // multiple event listeners ('host' and 'instance') and Node.bind
4201 // by default supports 1 thing being bound. 4232 // by default supports 1 thing being bound.
4202 for (var type in events) { 4233 for (var type in events) {
4203 var methodName = events[type]; 4234 var methodName = events[type];
4204 this.addEventListener(type, this.element.getEventHandler(this, this, 4235 PolymerGestures.addEventListener(this, type, this.element.getEventHandle r(this, this, methodName));
4205 methodName));
4206 } 4236 }
4207 }, 4237 },
4208 // call 'method' or function method on 'obj' with 'args', if the method exis ts 4238 // call 'method' or function method on 'obj' with 'args', if the method exis ts
4209 dispatchMethod: function(obj, method, args) { 4239 dispatchMethod: function(obj, method, args) {
4210 if (obj) { 4240 if (obj) {
4211 log.events && console.group('[%s] dispatch [%s]', obj.localName, method) ; 4241 log.events && console.group('[%s] dispatch [%s]', obj.localName, method) ;
4212 var fn = typeof method === 'function' ? method : obj[method]; 4242 var fn = typeof method === 'function' ? method : obj[method];
4213 if (fn) { 4243 if (fn) {
4214 fn[args ? 'apply' : 'call'](obj, args); 4244 fn[args ? 'apply' : 'call'](obj, args);
4215 } 4245 }
4216 log.events && console.groupEnd(); 4246 log.events && console.groupEnd();
4217 Platform.flush(); 4247 Platform.flush();
4218 } 4248 }
4219 } 4249 }
4220 }; 4250 };
4221 4251
4222 // exports 4252 // exports
4223 4253
4224 scope.api.instance.events = events; 4254 scope.api.instance.events = events;
4225 4255
4256 // alias PolymerGestures event listener logic
4257 scope.addEventListener = PolymerGestures.addEventListener;
4258 scope.removeEventListener = PolymerGestures.removeEventListener;
4259
4226 })(Polymer); 4260 })(Polymer);
4227 4261
4228 /* 4262 /*
4229 * Copyright (c) 2014 The Polymer Project Authors. All rights reserved. 4263 * Copyright (c) 2014 The Polymer Project Authors. All rights reserved.
4230 * This code may only be used under the BSD style license found at http://polyme r.github.io/LICENSE.txt 4264 * This code may only be used under the BSD style license found at http://polyme r.github.io/LICENSE.txt
4231 * The complete set of authors may be found at http://polymer.github.io/AUTHORS. txt 4265 * The complete set of authors may be found at http://polymer.github.io/AUTHORS. txt
4232 * The complete set of contributors may be found at http://polymer.github.io/CON TRIBUTORS.txt 4266 * The complete set of contributors may be found at http://polymer.github.io/CON TRIBUTORS.txt
4233 * Code distributed by Google as part of the polymer project is also 4267 * Code distributed by Google as part of the polymer project is also
4234 * subject to an additional IP rights grant found at http://polymer.github.io/PA TENTS.txt 4268 * subject to an additional IP rights grant found at http://polymer.github.io/PA TENTS.txt
4235 */ 4269 */
(...skipping 496 matching lines...) Expand 10 before | Expand all | Expand 10 after
4732 ready: function() { 4766 ready: function() {
4733 }, 4767 },
4734 createdCallback: function() { 4768 createdCallback: function() {
4735 if (this.templateInstance && this.templateInstance.model) { 4769 if (this.templateInstance && this.templateInstance.model) {
4736 console.warn('Attributes on ' + this.localName + ' were data bound ' + 4770 console.warn('Attributes on ' + this.localName + ' were data bound ' +
4737 'prior to Polymer upgrading the element. This may result in ' + 4771 'prior to Polymer upgrading the element. This may result in ' +
4738 'incorrect binding types.'); 4772 'incorrect binding types.');
4739 } 4773 }
4740 this.created(); 4774 this.created();
4741 this.prepareElement(); 4775 this.prepareElement();
4742 // TODO(sorvell): replace when ShadowDOMPolyfill issue is corrected 4776 if (!this.ownerDocument.isStagingDocument) {
4743 // https://github.com/Polymer/ShadowDOM/issues/420
4744 if (!this.ownerDocument.isStagingDocument || window.ShadowDOMPolyfill) {
4745 this.makeElementReady(); 4777 this.makeElementReady();
4746 } 4778 }
4747 }, 4779 },
4748 // system entry point, do not override 4780 // system entry point, do not override
4749 prepareElement: function() { 4781 prepareElement: function() {
4750 if (this._elementPrepared) { 4782 if (this._elementPrepared) {
4751 console.warn('Element already prepared', this.localName); 4783 console.warn('Element already prepared', this.localName);
4752 return; 4784 return;
4753 } 4785 }
4754 this._elementPrepared = true; 4786 this._elementPrepared = true;
4755 // storage for shadowRoots info 4787 // storage for shadowRoots info
4756 this.shadowRoots = {}; 4788 this.shadowRoots = {};
4757 // install property observers 4789 // install property observers
4758 this.createPropertyObserver(); 4790 this.createPropertyObserver();
4759 // TODO (sorvell): temporarily open observer when created
4760 this.openPropertyObserver(); 4791 this.openPropertyObserver();
4761 // install boilerplate attributes 4792 // install boilerplate attributes
4762 this.copyInstanceAttributes(); 4793 this.copyInstanceAttributes();
4763 // process input attributes 4794 // process input attributes
4764 this.takeAttributes(); 4795 this.takeAttributes();
4765 // add event listeners 4796 // add event listeners
4766 this.addHostListeners(); 4797 this.addHostListeners();
4767 }, 4798 },
4768 makeElementReady: function() { 4799 makeElementReady: function() {
4769 if (this._readied) { 4800 if (this._readied) {
4770 return; 4801 return;
4771 } 4802 }
4772 this._readied = true; 4803 this._readied = true;
4773 this.createComputedProperties(); 4804 this.createComputedProperties();
4774 // TODO(sorvell): We could create an entry point here 4805 // TODO(sorvell): We could create an entry point here
4775 // for the user to compute property values. 4806 // for the user to compute property values.
4776 // process declarative resources 4807 // process declarative resources
4777 this.parseDeclarations(this.__proto__); 4808 this.parseDeclarations(this.__proto__);
4778 // TODO(sorvell): CE polyfill uses unresolved attribute to simulate 4809 // TODO(sorvell): CE polyfill uses unresolved attribute to simulate
4779 // :unresolved; remove this attribute to be compatible with native 4810 // :unresolved; remove this attribute to be compatible with native
4780 // CE. 4811 // CE.
4781 this.removeAttribute('unresolved'); 4812 this.removeAttribute('unresolved');
4782 // user entry point 4813 // user entry point
4783 this.ready(); 4814 this.ready();
4784 // TODO (sorvell): temporarily open observer when created
4785 // turn on property observation and take any initial changes
4786 //this.openPropertyObserver();
4787 }, 4815 },
4788 attachedCallback: function() { 4816 attachedCallback: function() {
4789 this.cancelUnbindAll(); 4817 this.cancelUnbindAll();
4790 // invoke user action 4818 // invoke user action
4791 if (this.attached) { 4819 if (this.attached) {
4792 this.attached(); 4820 this.attached();
4793 } 4821 }
4794 // TODO(sorvell): bc 4822 // TODO(sorvell): bc
4795 if (this.enteredView) { 4823 if (this.enteredView) {
4796 this.enteredView(); 4824 this.enteredView();
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after
4893 } 4921 }
4894 // perform post-construction initialization tasks on ahem, light root 4922 // perform post-construction initialization tasks on ahem, light root
4895 this.shadowRootReady(this); 4923 this.shadowRootReady(this);
4896 // return the created shadow root 4924 // return the created shadow root
4897 return dom; 4925 return dom;
4898 } 4926 }
4899 }, 4927 },
4900 shadowRootReady: function(root) { 4928 shadowRootReady: function(root) {
4901 // locate nodes with id and store references to them in this.$ hash 4929 // locate nodes with id and store references to them in this.$ hash
4902 this.marshalNodeReferences(root); 4930 this.marshalNodeReferences(root);
4903 // set up polymer gestures
4904 PolymerGestures.register(root);
4905 }, 4931 },
4906 // locate nodes with id and store references to them in this.$ hash 4932 // locate nodes with id and store references to them in this.$ hash
4907 marshalNodeReferences: function(root) { 4933 marshalNodeReferences: function(root) {
4908 // establish $ instance variable 4934 // establish $ instance variable
4909 var $ = this.$ = this.$ || {}; 4935 var $ = this.$ = this.$ || {};
4910 // populate $ from nodes with ID from the LOCAL tree 4936 // populate $ from nodes with ID from the LOCAL tree
4911 if (root) { 4937 if (root) {
4912 var n$ = root.querySelectorAll("[id]"); 4938 var n$ = root.querySelectorAll("[id]");
4913 for (var i=0, l=n$.length, n; (i<l) && (n=n$[i]); i++) { 4939 for (var i=0, l=n$.length, n; (i<l) && (n=n$[i]); i++) {
4914 $[n.id] = n; 4940 $[n.id] = n;
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
4959 * The complete set of contributors may be found at http://polymer.github.io/CON TRIBUTORS.txt 4985 * The complete set of contributors may be found at http://polymer.github.io/CON TRIBUTORS.txt
4960 * Code distributed by Google as part of the polymer project is also 4986 * Code distributed by Google as part of the polymer project is also
4961 * subject to an additional IP rights grant found at http://polymer.github.io/PA TENTS.txt 4987 * subject to an additional IP rights grant found at http://polymer.github.io/PA TENTS.txt
4962 */ 4988 */
4963 4989
4964 (function(scope) { 4990 (function(scope) {
4965 4991
4966 // imports 4992 // imports
4967 4993
4968 var log = window.logFlags || {}; 4994 var log = window.logFlags || {};
4969 4995 var hasShadowDOMPolyfill = window.ShadowDOMPolyfill;
4996
4970 // magic words 4997 // magic words
4971 4998
4972 var STYLE_SCOPE_ATTRIBUTE = 'element'; 4999 var STYLE_SCOPE_ATTRIBUTE = 'element';
4973 var STYLE_CONTROLLER_SCOPE = 'controller'; 5000 var STYLE_CONTROLLER_SCOPE = 'controller';
4974 5001
4975 var styles = { 5002 var styles = {
4976 STYLE_SCOPE_ATTRIBUTE: STYLE_SCOPE_ATTRIBUTE, 5003 STYLE_SCOPE_ATTRIBUTE: STYLE_SCOPE_ATTRIBUTE,
4977 /** 5004 /**
4978 * Installs external stylesheets and <style> elements with the attribute 5005 * Installs external stylesheets and <style> elements with the attribute
4979 * polymer-scope='controller' into the scope of element. This is intended 5006 * polymer-scope='controller' into the scope of element. This is intended
(...skipping 27 matching lines...) Expand all
5007 } 5034 }
5008 this.installScopeCssText(cssText, scope, name); 5035 this.installScopeCssText(cssText, scope, name);
5009 } 5036 }
5010 }, 5037 },
5011 installScopeCssText: function(cssText, scope, name) { 5038 installScopeCssText: function(cssText, scope, name) {
5012 scope = scope || this.findStyleScope(); 5039 scope = scope || this.findStyleScope();
5013 name = name || ''; 5040 name = name || '';
5014 if (!scope) { 5041 if (!scope) {
5015 return; 5042 return;
5016 } 5043 }
5017 if (window.ShadowDOMPolyfill) { 5044 if (hasShadowDOMPolyfill) {
5018 cssText = shimCssText(cssText, scope.host); 5045 cssText = shimCssText(cssText, scope.host);
5019 } 5046 }
5020 var style = this.element.cssTextToScopeStyle(cssText, 5047 var style = this.element.cssTextToScopeStyle(cssText,
5021 STYLE_CONTROLLER_SCOPE); 5048 STYLE_CONTROLLER_SCOPE);
5022 Polymer.applyStyleToScope(style, scope); 5049 Polymer.applyStyleToScope(style, scope);
5023 // cache that this style has been applied 5050 // cache that this style has been applied
5024 this.styleCacheForScope(scope)[this.localName + name] = true; 5051 this.styleCacheForScope(scope)[this.localName + name] = true;
5025 }, 5052 },
5026 findStyleScope: function(node) { 5053 findStyleScope: function(node) {
5027 // find the shadow root that contains this element 5054 // find the shadow root that contains this element
5028 var n = node || this; 5055 var n = node || this;
5029 while (n.parentNode) { 5056 while (n.parentNode) {
5030 n = n.parentNode; 5057 n = n.parentNode;
5031 } 5058 }
5032 return n; 5059 return n;
5033 }, 5060 },
5034 scopeHasNamedStyle: function(scope, name) { 5061 scopeHasNamedStyle: function(scope, name) {
5035 var cache = this.styleCacheForScope(scope); 5062 var cache = this.styleCacheForScope(scope);
5036 return cache[name]; 5063 return cache[name];
5037 }, 5064 },
5038 styleCacheForScope: function(scope) { 5065 styleCacheForScope: function(scope) {
5039 if (window.ShadowDOMPolyfill) { 5066 if (hasShadowDOMPolyfill) {
5040 var scopeName = scope.host ? scope.host.localName : scope.localName; 5067 var scopeName = scope.host ? scope.host.localName : scope.localName;
5041 return polyfillScopeStyleCache[scopeName] || (polyfillScopeStyleCache[sc opeName] = {}); 5068 return polyfillScopeStyleCache[scopeName] || (polyfillScopeStyleCache[sc opeName] = {});
5042 } else { 5069 } else {
5043 return scope._scopeStyles = (scope._scopeStyles || {}); 5070 return scope._scopeStyles = (scope._scopeStyles || {});
5044 } 5071 }
5045 } 5072 }
5046 }; 5073 };
5047 5074
5048 var polyfillScopeStyleCache = {}; 5075 var polyfillScopeStyleCache = {};
5049 5076
(...skipping 164 matching lines...) Expand 10 before | Expand all | Expand 10 after
5214 */ 5241 */
5215 5242
5216 (function(scope) { 5243 (function(scope) {
5217 5244
5218 // imports 5245 // imports
5219 5246
5220 var log = window.logFlags || {}; 5247 var log = window.logFlags || {};
5221 var api = scope.api.instance.styles; 5248 var api = scope.api.instance.styles;
5222 var STYLE_SCOPE_ATTRIBUTE = api.STYLE_SCOPE_ATTRIBUTE; 5249 var STYLE_SCOPE_ATTRIBUTE = api.STYLE_SCOPE_ATTRIBUTE;
5223 5250
5251 var hasShadowDOMPolyfill = window.ShadowDOMPolyfill;
5252
5224 // magic words 5253 // magic words
5225 5254
5226 var STYLE_SELECTOR = 'style'; 5255 var STYLE_SELECTOR = 'style';
5227 var STYLE_LOADABLE_MATCH = '@import'; 5256 var STYLE_LOADABLE_MATCH = '@import';
5228 var SHEET_SELECTOR = 'link[rel=stylesheet]'; 5257 var SHEET_SELECTOR = 'link[rel=stylesheet]';
5229 var STYLE_GLOBAL_SCOPE = 'global'; 5258 var STYLE_GLOBAL_SCOPE = 'global';
5230 var SCOPE_ATTR = 'polymer-scope'; 5259 var SCOPE_ATTR = 'polymer-scope';
5231 5260
5232 var styles = { 5261 var styles = {
5233 // returns true if resources are loading 5262 // returns true if resources are loading
(...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after
5386 function importRuleForSheet(sheet, baseUrl) { 5415 function importRuleForSheet(sheet, baseUrl) {
5387 var href = new URL(sheet.getAttribute('href'), baseUrl).href; 5416 var href = new URL(sheet.getAttribute('href'), baseUrl).href;
5388 return '@import \'' + href + '\';'; 5417 return '@import \'' + href + '\';';
5389 } 5418 }
5390 5419
5391 function applyStyleToScope(style, scope) { 5420 function applyStyleToScope(style, scope) {
5392 if (style) { 5421 if (style) {
5393 if (scope === document) { 5422 if (scope === document) {
5394 scope = document.head; 5423 scope = document.head;
5395 } 5424 }
5396 if (window.ShadowDOMPolyfill) { 5425 if (hasShadowDOMPolyfill) {
5397 scope = document.head; 5426 scope = document.head;
5398 } 5427 }
5399 // TODO(sorvell): necessary for IE 5428 // TODO(sorvell): necessary for IE
5400 // see https://connect.microsoft.com/IE/feedback/details/790212/ 5429 // see https://connect.microsoft.com/IE/feedback/details/790212/
5401 // cloning-a-style-element-and-adding-to-document-produces 5430 // cloning-a-style-element-and-adding-to-document-produces
5402 // -unexpected-result#details 5431 // -unexpected-result#details
5403 // var clone = style.cloneNode(true); 5432 // var clone = style.cloneNode(true);
5404 var clone = createStyleElement(style.textContent); 5433 var clone = createStyleElement(style.textContent);
5405 var attr = style.getAttribute(STYLE_SCOPE_ATTRIBUTE); 5434 var attr = style.getAttribute(STYLE_SCOPE_ATTRIBUTE);
5406 if (attr) { 5435 if (attr) {
(...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after
5527 if (!this.hasEventPrefix(name)) 5556 if (!this.hasEventPrefix(name))
5528 return; 5557 return;
5529 5558
5530 var eventType = this.removeEventPrefix(name); 5559 var eventType = this.removeEventPrefix(name);
5531 eventType = mixedCaseEventTypes[eventType] || eventType; 5560 eventType = mixedCaseEventTypes[eventType] || eventType;
5532 5561
5533 var events = this; 5562 var events = this;
5534 5563
5535 return function(model, node, oneTime) { 5564 return function(model, node, oneTime) {
5536 var handler = events.getEventHandler(undefined, node, pathString); 5565 var handler = events.getEventHandler(undefined, node, pathString);
5537 node.addEventListener(eventType, handler); 5566 PolymerGestures.addEventListener(node, eventType, handler);
5538 5567
5539 if (oneTime) 5568 if (oneTime)
5540 return; 5569 return;
5541 5570
5542 // TODO(rafaelw): This is really pointless work. Aside from the cost 5571 // TODO(rafaelw): This is really pointless work. Aside from the cost
5543 // of these allocations, NodeBind is going to setAttribute back to its 5572 // of these allocations, NodeBind is going to setAttribute back to its
5544 // current value. Fixing this would mean changing the TemplateBinding 5573 // current value. Fixing this would mean changing the TemplateBinding
5545 // binding delegate API. 5574 // binding delegate API.
5546 function bindingValue() { 5575 function bindingValue() {
5547 return '{{ ' + pathString + ' }}'; 5576 return '{{ ' + pathString + ' }}';
5548 } 5577 }
5549 5578
5550 return { 5579 return {
5551 open: bindingValue, 5580 open: bindingValue,
5552 discardChanges: bindingValue, 5581 discardChanges: bindingValue,
5553 close: function() { 5582 close: function() {
5554 node.removeEventListener(eventType, handler); 5583 PolymerGestures.removeEventListener(node, eventType, handler);
5555 } 5584 }
5556 }; 5585 };
5557 }; 5586 };
5558 } 5587 }
5559 }; 5588 };
5560 5589
5561 var prefixLength = EVENT_PREFIX.length; 5590 var prefixLength = EVENT_PREFIX.length;
5562 5591
5563 // exports 5592 // exports
5564 scope.api.declaration.events = events; 5593 scope.api.declaration.events = events;
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after
5635 publishProperties: function(prototype, base) { 5664 publishProperties: function(prototype, base) {
5636 // if we have any properties to publish 5665 // if we have any properties to publish
5637 var publish = prototype.publish; 5666 var publish = prototype.publish;
5638 if (publish) { 5667 if (publish) {
5639 // transcribe `publish` entries onto own prototype 5668 // transcribe `publish` entries onto own prototype
5640 this.requireProperties(publish, prototype, base); 5669 this.requireProperties(publish, prototype, base);
5641 // construct map of lower-cased property names 5670 // construct map of lower-cased property names
5642 prototype._publishLC = this.lowerCaseMap(publish); 5671 prototype._publishLC = this.lowerCaseMap(publish);
5643 } 5672 }
5644 }, 5673 },
5645 // sync prototype to property descriptors;
5646 // desriptor format contains default value and optionally a
5647 // hint for reflecting the property to an attribute.
5648 // e.g. {foo: 5, bar: {value: true, reflect: true}}
5649 // reflect: {foo: true} is also supported
5650 // 5674 //
5651 requireProperties: function(propertyDescriptors, prototype, base) { 5675 // `name: value` entries in the `publish` object may need to generate
5652 // reflected properties 5676 // matching properties on the prototype.
5677 //
5678 // Values that are objects may have a `reflect` property, which
5679 // signals that the value describes property control metadata.
5680 // In metadata objects, the prototype default value (if any)
5681 // is encoded in the `value` property.
5682 //
5683 // publish: {
5684 // foo: 5,
5685 // bar: {value: true, reflect: true},
5686 // zot: {}
5687 // }
5688 //
5689 // `reflect` metadata property controls whether changes to the property
5690 // are reflected back to the attribute (default false).
5691 //
5692 // A value is stored on the prototype unless it's === `undefined`,
5693 // in which case the base chain is checked for a value.
5694 // If the basal value is also undefined, `null` is stored on the prototype.
5695 //
5696 // The reflection data is stored on another prototype object, `reflect`
5697 // which also can be specified directly.
5698 //
5699 // reflect: {
5700 // foo: true
5701 // }
5702 //
5703 requireProperties: function(propertyInfos, prototype, base) {
5704 // per-prototype storage for reflected properties
5653 prototype.reflect = prototype.reflect || {}; 5705 prototype.reflect = prototype.reflect || {};
5654 // ensure a prototype value for each property 5706 // ensure a prototype value for each property
5655 // and update the property's reflect to attribute status 5707 // and update the property's reflect to attribute status
5656 for (var n in propertyDescriptors) { 5708 for (var n in propertyInfos) {
5657 var propertyDescriptor = propertyDescriptors[n]; 5709 var value = propertyInfos[n];
5658 var reflects = this.reflectHintForDescriptor(propertyDescriptor); 5710 // value has metadata if it has a `reflect` property
5659 if (prototype.reflect[n] === undefined && reflects !== undefined) { 5711 if (value && value.reflect !== undefined) {
5660 prototype.reflect[n] = reflects; 5712 prototype.reflect[n] = Boolean(value.reflect);
5713 value = value.value;
5661 } 5714 }
5662 if (prototype[n] === undefined) { 5715 // only set a value if one is specified
5663 prototype[n] = this.valueForDescriptor(propertyDescriptor); 5716 if (value !== undefined) {
5717 prototype[n] = value;
5664 } 5718 }
5665 } 5719 }
5666 }, 5720 },
5667 valueForDescriptor: function(propertyDescriptor) {
5668 var value = typeof propertyDescriptor === 'object' &&
5669 propertyDescriptor ? propertyDescriptor.value : propertyDescriptor;
5670 return value !== undefined ? value : null;
5671 },
5672 // returns the value of the descriptor's 'reflect' property or undefined
5673 reflectHintForDescriptor: function(propertyDescriptor) {
5674 if (typeof propertyDescriptor === 'object' &&
5675 propertyDescriptor && propertyDescriptor.reflect !== undefined) {
5676 return propertyDescriptor.reflect;
5677 }
5678 },
5679 lowerCaseMap: function(properties) { 5721 lowerCaseMap: function(properties) {
5680 var map = {}; 5722 var map = {};
5681 for (var n in properties) { 5723 for (var n in properties) {
5682 map[n.toLowerCase()] = n; 5724 map[n.toLowerCase()] = n;
5683 } 5725 }
5684 return map; 5726 return map;
5685 }, 5727 },
5686 createPropertyAccessor: function(name) { 5728 createPropertyAccessor: function(name) {
5687 var proto = this.prototype; 5729 var proto = this.prototype;
5688 5730
(...skipping 25 matching lines...) Expand all
5714 configurable: true 5756 configurable: true
5715 }); 5757 });
5716 }, 5758 },
5717 createPropertyAccessors: function(prototype) { 5759 createPropertyAccessors: function(prototype) {
5718 var n$ = prototype._publishNames; 5760 var n$ = prototype._publishNames;
5719 if (n$ && n$.length) { 5761 if (n$ && n$.length) {
5720 for (var i=0, l=n$.length, n, fn; (i<l) && (n=n$[i]); i++) { 5762 for (var i=0, l=n$.length, n, fn; (i<l) && (n=n$[i]); i++) {
5721 this.createPropertyAccessor(n); 5763 this.createPropertyAccessor(n);
5722 } 5764 }
5723 } 5765 }
5724
5725 var n$ = prototype._computedNames; 5766 var n$ = prototype._computedNames;
5726 if (n$ && n$.length) { 5767 if (n$ && n$.length) {
5727 for (var i=0, l=n$.length, n, fn; (i<l) && (n=n$[i]); i++) { 5768 for (var i=0, l=n$.length, n, fn; (i<l) && (n=n$[i]); i++) {
5728 this.createPropertyAccessor(n); 5769 this.createPropertyAccessor(n);
5729 } 5770 }
5730 } 5771 }
5731
5732 } 5772 }
5733 }; 5773 };
5734 5774
5735 // exports 5775 // exports
5736 5776
5737 scope.api.declaration.properties = properties; 5777 scope.api.declaration.properties = properties;
5738 5778
5739 })(Polymer); 5779 })(Polymer);
5740 5780
5741 /* 5781 /*
(...skipping 16 matching lines...) Expand all
5758 var attributes = { 5798 var attributes = {
5759 5799
5760 inheritAttributesObjects: function(prototype) { 5800 inheritAttributesObjects: function(prototype) {
5761 // chain our lower-cased publish map to the inherited version 5801 // chain our lower-cased publish map to the inherited version
5762 this.inheritObject(prototype, 'publishLC'); 5802 this.inheritObject(prototype, 'publishLC');
5763 // chain our instance attributes map to the inherited version 5803 // chain our instance attributes map to the inherited version
5764 this.inheritObject(prototype, '_instanceAttributes'); 5804 this.inheritObject(prototype, '_instanceAttributes');
5765 }, 5805 },
5766 5806
5767 publishAttributes: function(prototype, base) { 5807 publishAttributes: function(prototype, base) {
5768 // merge names from 'attributes' attribute 5808 // merge names from 'attributes' attribute into the 'publish' object
5769 var attributes = this.getAttribute(ATTRIBUTES_ATTRIBUTE); 5809 var attributes = this.getAttribute(ATTRIBUTES_ATTRIBUTE);
5770 if (attributes) { 5810 if (attributes) {
5771 // get properties to publish 5811 // create a `publish` object if needed.
5772 var publish = prototype.publish || (prototype.publish = {}); 5812 // the `publish` object is only relevant to this prototype, the
5813 // publishing logic in `declaration/properties.js` is responsible for
5814 // managing property values on the prototype chain.
5815 // TODO(sjmiles): the `publish` object is later chained to it's
5816 // ancestor object, presumably this is only for
5817 // reflection or other non-library uses.
5818 var publish = prototype.publish || (prototype.publish = {});
5773 // names='a b c' or names='a,b,c' 5819 // names='a b c' or names='a,b,c'
5774 var names = attributes.split(ATTRIBUTES_REGEX); 5820 var names = attributes.split(ATTRIBUTES_REGEX);
5775 // record each name for publishing 5821 // record each name for publishing
5776 for (var i=0, l=names.length, n; i<l; i++) { 5822 for (var i=0, l=names.length, n; i<l; i++) {
5777 // remove excess ws 5823 // remove excess ws
5778 n = names[i].trim(); 5824 n = names[i].trim();
5779 // if the user hasn't specified a value, we want to use the 5825 // looks weird, but causes n to exist on `publish` if it does not;
5780 // default, unless a superclass has already chosen one 5826 // a more careful test would need expensive `in` operator
5781 if (n && publish[n] === undefined) { 5827 if (n && publish[n] === undefined) {
5782 // TODO(sjmiles): querying native properties on IE11 (and possibly 5828 publish[n] = undefined;
5783 // on other browsers) throws an exception because there is no actual
5784 // instance.
5785 // In fact, trying to publish native properties is known bad for thi s
5786 // and other reasons, and we need to solve this problem writ large.
5787 try {
5788 var hasValue = (base[n] !== undefined);
5789 } catch(x) {
5790 hasValue = false;
5791 }
5792 // supply an empty 'descriptor' object and let the publishProperties
5793 // code determine a default
5794 if (!hasValue) {
5795 publish[n] = Polymer.nob;
5796 }
5797 } 5829 }
5798 } 5830 }
5799 } 5831 }
5800 }, 5832 },
5801 5833
5802 // record clonable attributes from <element> 5834 // record clonable attributes from <element>
5803 accumulateInstanceAttributes: function() { 5835 accumulateInstanceAttributes: function() {
5804 // inherit instance attributes 5836 // inherit instance attributes
5805 var clonable = this.prototype._instanceAttributes; 5837 var clonable = this.prototype._instanceAttributes;
5806 // merge attributes from element 5838 // merge attributes from element
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after
5893 */ 5925 */
5894 5926
5895 (function(scope) { 5927 (function(scope) {
5896 5928
5897 // imports 5929 // imports
5898 5930
5899 var api = scope.api; 5931 var api = scope.api;
5900 var isBase = scope.isBase; 5932 var isBase = scope.isBase;
5901 var extend = scope.extend; 5933 var extend = scope.extend;
5902 5934
5935 var hasShadowDOMPolyfill = window.ShadowDOMPolyfill;
5936
5903 // prototype api 5937 // prototype api
5904 5938
5905 var prototype = { 5939 var prototype = {
5906 5940
5907 register: function(name, extendeeName) { 5941 register: function(name, extendeeName) {
5908 // build prototype combining extendee, Polymer base, and named api 5942 // build prototype combining extendee, Polymer base, and named api
5909 this.buildPrototype(name, extendeeName); 5943 this.buildPrototype(name, extendeeName);
5910 // register our custom element with the platform 5944 // register our custom element with the platform
5911 this.registerPrototype(name, extendeeName); 5945 this.registerPrototype(name, extendeeName);
5912 // reference constructor in a global named by 'constructor' attribute 5946 // reference constructor in a global named by 'constructor' attribute
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
5979 // compile list of attributes to copy to instances 6013 // compile list of attributes to copy to instances
5980 this.accumulateInstanceAttributes(); 6014 this.accumulateInstanceAttributes();
5981 // parse on-* delegates declared on `this` element 6015 // parse on-* delegates declared on `this` element
5982 this.parseHostEvents(); 6016 this.parseHostEvents();
5983 // 6017 //
5984 // install a helper method this.resolvePath to aid in 6018 // install a helper method this.resolvePath to aid in
5985 // setting resource urls. e.g. 6019 // setting resource urls. e.g.
5986 // this.$.image.src = this.resolvePath('images/foo.png') 6020 // this.$.image.src = this.resolvePath('images/foo.png')
5987 this.addResolvePathApi(); 6021 this.addResolvePathApi();
5988 // under ShadowDOMPolyfill, transforms to approximate missing CSS features 6022 // under ShadowDOMPolyfill, transforms to approximate missing CSS features
5989 if (window.ShadowDOMPolyfill) { 6023 if (hasShadowDOMPolyfill) {
5990 Platform.ShadowCSS.shimStyling(this.templateContent(), name, extendee); 6024 Platform.ShadowCSS.shimStyling(this.templateContent(), name, extendee);
5991 } 6025 }
5992 // allow custom element access to the declarative context 6026 // allow custom element access to the declarative context
5993 if (this.prototype.registerCallback) { 6027 if (this.prototype.registerCallback) {
5994 this.prototype.registerCallback(this); 6028 this.prototype.registerCallback(this);
5995 } 6029 }
5996 }, 6030 },
5997 6031
5998 // if a named constructor is requested in element, map a reference 6032 // if a named constructor is requested in element, map a reference
5999 // to the constructor to the given symbol 6033 // to the constructor to the given symbol
(...skipping 249 matching lines...) Expand 10 before | Expand all | Expand 10 after
6249 6283
6250 addToFlushQueue: function(element) { 6284 addToFlushQueue: function(element) {
6251 flushQueue.push(element); 6285 flushQueue.push(element);
6252 }, 6286 },
6253 6287
6254 flush: function() { 6288 flush: function() {
6255 // prevent re-entrance 6289 // prevent re-entrance
6256 if (this.flushing) { 6290 if (this.flushing) {
6257 return; 6291 return;
6258 } 6292 }
6259 if (flushQueue.length) {
6260 console.warn('flushing %s elements', flushQueue.length);
6261 }
6262 this.flushing = true; 6293 this.flushing = true;
6263 var element; 6294 var element;
6264 while (flushQueue.length) { 6295 while (flushQueue.length) {
6265 element = flushQueue.shift(); 6296 element = flushQueue.shift();
6266 element.__queue.go.call(element); 6297 element.__queue.go.call(element);
6267 element.__queue = null; 6298 element.__queue = null;
6268 } 6299 }
6269 this.flushing = false; 6300 this.flushing = false;
6270 }, 6301 },
6271 6302
(...skipping 331 matching lines...) Expand 10 before | Expand all | Expand 10 after
6603 prepareBinding.call(syntax, pathString, name, node); 6634 prepareBinding.call(syntax, pathString, name, node);
6604 }; 6635 };
6605 return syntax; 6636 return syntax;
6606 } 6637 }
6607 6638
6608 }); 6639 });
6609 6640
6610 })(); 6641 })();
6611 6642
6612 //# sourceMappingURL=polymer.concat.js.map 6643 //# sourceMappingURL=polymer.concat.js.map
OLDNEW
« no previous file with comments | « pkg/polymer/lib/src/js/polymer/polymer.js ('k') | 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