OLD | NEW |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 |
OLD | NEW |