| Index: pkg/polymer/lib/src/js/polymer/polymer.concat.js
|
| diff --git a/pkg/polymer/lib/src/js/polymer/polymer.concat.js b/pkg/polymer/lib/src/js/polymer/polymer.concat.js
|
| index 816116fdded03a7826dc3a1c2b2bff338c4d2e60..65d22b94d5be066be10de506f2182b3ef454c6a4 100644
|
| --- a/pkg/polymer/lib/src/js/polymer/polymer.concat.js
|
| +++ b/pkg/polymer/lib/src/js/polymer/polymer.concat.js
|
| @@ -7,10 +7,7 @@
|
| * Code distributed by Google as part of the polymer project is also
|
| * subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
|
| */
|
| -window.PolymerGestures = {
|
| - hasSDPolyfill: Boolean(window.ShadowDOMPolyfill)
|
| -};
|
| -PolymerGestures.wrap = PolymerGestures.hasSDPolyfill ? ShadowDOMPolyfill.wrapIfNeeded : function(a){ return a; };
|
| +window.PolymerGestures = {};
|
|
|
| /*
|
| * Copyright (c) 2014 The Polymer Project Authors. All rights reserved.
|
| @@ -26,7 +23,7 @@ PolymerGestures.wrap = PolymerGestures.hasSDPolyfill ? ShadowDOMPolyfill.wrapIfN
|
|
|
| // test for full event path support
|
| var pathTest = document.createElement('meta');
|
| - if (!scope.hasSDPolyfill && pathTest.createShadowRoot) {
|
| + if (pathTest.createShadowRoot) {
|
| var sr = pathTest.createShadowRoot();
|
| var s = document.createElement('span');
|
| sr.appendChild(s);
|
| @@ -122,25 +119,27 @@ PolymerGestures.wrap = PolymerGestures.hasSDPolyfill ? ShadowDOMPolyfill.wrapIfN
|
| }
|
| return this.searchRoot(s, x, y);
|
| },
|
| - findScrollAxis: function(inEvent) {
|
| + findTouchAction: function(inEvent) {
|
| var n;
|
| if (HAS_FULL_PATH && inEvent.path) {
|
| var path = inEvent.path;
|
| for (var i = 0; i < path.length; i++) {
|
| n = path[i];
|
| - if (n._scrollType) {
|
| - return n._scrollType;
|
| + if (n.nodeType === Node.ELEMENT_NODE && n.hasAttribute('touch-action')) {
|
| + return n.getAttribute('touch-action');
|
| }
|
| }
|
| } else {
|
| - n = scope.wrap(inEvent.currentTarget);
|
| + n = inEvent.target;
|
| while(n) {
|
| - if (n._scrollType) {
|
| - return n._scrollType;
|
| + if (n.hasAttribute('touch-action')) {
|
| + return n.getAttribute('touch-action');
|
| }
|
| n = n.parentNode || n.host;
|
| }
|
| }
|
| + // auto is default
|
| + return "auto";
|
| },
|
| LCA: function(a, b) {
|
| if (a === b) {
|
| @@ -253,7 +252,7 @@ PolymerGestures.wrap = PolymerGestures.hasSDPolyfill ? ShadowDOMPolyfill.wrapIfN
|
|
|
| (function() {
|
| function shadowSelector(v) {
|
| - return 'body /deep/ ' + selector(v);
|
| + return 'html /deep/ ' + selector(v);
|
| }
|
| function selector(v) {
|
| return '[touch-action="' + v + '"]';
|
| @@ -277,7 +276,6 @@ PolymerGestures.wrap = PolymerGestures.hasSDPolyfill ? ShadowDOMPolyfill.wrapIfN
|
| ];
|
| var styles = '';
|
| // only install stylesheet if the browser has touch action support
|
| - var head = document.head;
|
| var hasTouchAction = typeof document.head.style.touchAction === 'string';
|
| // only add shadow selectors if shadowdom is supported
|
| var hasShadowRoot = !window.ShadowDOMPolyfill && document.head.createShadowRoot;
|
| @@ -593,9 +591,6 @@ PolymerGestures.wrap = PolymerGestures.hasSDPolyfill ? ShadowDOMPolyfill.wrapIfN
|
|
|
| var eventFactory = scope.eventFactory;
|
|
|
| - var hasSDPolyfill = scope.hasSDPolyfill;
|
| - var wrap = scope.wrap;
|
| -
|
| /**
|
| * This module is for normalizing events. Mouse and Touch events will be
|
| * collected here, and fire PointerEvents that have the same semantics, no
|
| @@ -616,6 +611,12 @@ PolymerGestures.wrap = PolymerGestures.hasSDPolyfill ? ShadowDOMPolyfill.wrapIfN
|
| eventSources: Object.create(null),
|
| eventSourceList: [],
|
| gestures: [],
|
| + // map gesture event -> {listeners: int, index: gestures[int]}
|
| + dependencyMap: {
|
| + // make sure down and up are in the map to trigger "register"
|
| + down: {listeners: 0, index: -1},
|
| + up: {listeners: 0, index: -1}
|
| + },
|
| gestureQueue: [],
|
| /**
|
| * Add a new event source that will generate pointer events.
|
| @@ -639,13 +640,20 @@ PolymerGestures.wrap = PolymerGestures.hasSDPolyfill ? ShadowDOMPolyfill.wrapIfN
|
| }
|
| },
|
| registerGesture: function(name, source) {
|
| + var obj = Object.create(null);
|
| + obj.listeners = 0;
|
| + obj.index = this.gestures.length;
|
| + for (var i = 0, g; i < source.exposes.length; i++) {
|
| + g = source.exposes[i].toLowerCase();
|
| + this.dependencyMap[g] = obj;
|
| + }
|
| this.gestures.push(source);
|
| },
|
| - register: function(element) {
|
| + register: function(element, initial) {
|
| var l = this.eventSourceList.length;
|
| for (var i = 0, es; (i < l) && (es = this.eventSourceList[i]); i++) {
|
| // call eventsource register
|
| - es.register.call(es, element);
|
| + es.register.call(es, element, initial);
|
| }
|
| },
|
| unregister: function(element) {
|
| @@ -676,6 +684,9 @@ PolymerGestures.wrap = PolymerGestures.hasSDPolyfill ? ShadowDOMPolyfill.wrapIfN
|
| // This is used to prevent multiple dispatch of events from
|
| // platform events. This can happen when two elements in different scopes
|
| // are set up to create pointer events, which is relevant to Shadow DOM.
|
| +
|
| + // TODO(dfreedm): make this check more granular, allow for minimal event generation
|
| + // e.g inEvent._handledByPG['tap'] and inEvent._handledByPG['track'], etc
|
| if (inEvent._handledByPG) {
|
| return;
|
| }
|
| @@ -699,20 +710,10 @@ PolymerGestures.wrap = PolymerGestures.hasSDPolyfill ? ShadowDOMPolyfill.wrapIfN
|
| }
|
| },
|
| addEvent: function(target, eventName) {
|
| - // NOTE: Work around for #4, use native event listener in SD Polyfill
|
| - if (hasSDPolyfill) {
|
| - target.addEventListener_(eventName, this.boundHandler);
|
| - } else {
|
| - target.addEventListener(eventName, this.boundHandler);
|
| - }
|
| + target.addEventListener(eventName, this.boundHandler);
|
| },
|
| removeEvent: function(target, eventName) {
|
| - // NOTE: Work around for #4, use native event listener in SD Polyfill
|
| - if (hasSDPolyfill) {
|
| - target.removeEventListener_(eventName, this.boundHandler);
|
| - } else {
|
| - target.removeEventListener(eventName, this.boundHandler);
|
| - }
|
| + target.removeEventListener(eventName, this.boundHandler);
|
| },
|
| // EVENT CREATION AND TRACKING
|
| /**
|
| @@ -754,11 +755,12 @@ PolymerGestures.wrap = PolymerGestures.hasSDPolyfill ? ShadowDOMPolyfill.wrapIfN
|
| if (HAS_SVG_INSTANCE && eventCopy[p] instanceof SVGElementInstance) {
|
| eventCopy[p] = eventCopy[p].correspondingUseElement;
|
| }
|
| - eventCopy[p] = wrap(eventCopy[p]);
|
| }
|
| }
|
| // keep the semantics of preventDefault
|
| - eventCopy.preventDefault = inEvent.preventDefault;
|
| + eventCopy.preventDefault = function() {
|
| + inEvent.preventDefault();
|
| + };
|
| return eventCopy;
|
| },
|
| /**
|
| @@ -785,7 +787,7 @@ PolymerGestures.wrap = PolymerGestures.hasSDPolyfill ? ShadowDOMPolyfill.wrapIfN
|
| for (var j = 0, g, fn; j < this.gestures.length; j++) {
|
| g = this.gestures[j];
|
| fn = g[e.type];
|
| - if (fn) {
|
| + if (g.enabled && fn) {
|
| fn.call(g, e);
|
| }
|
| }
|
| @@ -803,136 +805,117 @@ PolymerGestures.wrap = PolymerGestures.hasSDPolyfill ? ShadowDOMPolyfill.wrapIfN
|
| dispatcher.boundHandler = dispatcher.eventHandler.bind(dispatcher);
|
| dispatcher.boundGestureTrigger = dispatcher.gestureTrigger.bind(dispatcher);
|
| scope.dispatcher = dispatcher;
|
| - scope.register = function(root) {
|
| - dispatcher.register(root);
|
| - };
|
| - scope.unregister = dispatcher.unregister.bind(dispatcher);
|
| - scope.wrap = wrap;
|
| -})(window.PolymerGestures);
|
|
|
| -/*
|
| - * Copyright (c) 2014 The Polymer Project Authors. All rights reserved.
|
| - * This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
|
| - * The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
|
| - * The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
|
| - * Code distributed by Google as part of the polymer project is also
|
| - * subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
|
| - */
|
| -
|
| -/**
|
| - * This module uses Mutation Observers to dynamically adjust which nodes will
|
| - * generate Pointer Events.
|
| - *
|
| - * All nodes that wish to generate Pointer Events must have the attribute
|
| - * `touch-action` set to `none`.
|
| - */
|
| -(function(scope) {
|
| - var forEach = Array.prototype.forEach.call.bind(Array.prototype.forEach);
|
| - var map = Array.prototype.map.call.bind(Array.prototype.map);
|
| - var toArray = Array.prototype.slice.call.bind(Array.prototype.slice);
|
| - var filter = Array.prototype.filter.call.bind(Array.prototype.filter);
|
| - var MO = window.MutationObserver || window.WebKitMutationObserver;
|
| - var SELECTOR = '[touch-action]';
|
| - var OBSERVER_INIT = {
|
| - subtree: true,
|
| - childList: true,
|
| - attributes: true,
|
| - attributeOldValue: true,
|
| - attributeFilter: ['touch-action']
|
| + /**
|
| + * Listen for `gesture` on `node` with the `handler` function
|
| + *
|
| + * If `handler` is the first listener for `gesture`, the underlying gesture recognizer is then enabled.
|
| + *
|
| + * @param {Element} node
|
| + * @param {string} gesture
|
| + * @return Boolean `gesture` is a valid gesture
|
| + */
|
| + scope.activateGesture = function(node, gesture) {
|
| + var g = gesture.toLowerCase();
|
| + var dep = dispatcher.dependencyMap[g];
|
| + if (dep) {
|
| + var recognizer = dispatcher.gestures[dep.index];
|
| + if (dep.listeners === 0) {
|
| + if (recognizer) {
|
| + recognizer.enabled = true;
|
| + }
|
| + }
|
| + dep.listeners++;
|
| + if (!node._pgListeners) {
|
| + dispatcher.register(node);
|
| + node._pgListeners = 0;
|
| + }
|
| + // TODO(dfreedm): re-evaluate bookkeeping to avoid using attributes
|
| + if (recognizer) {
|
| + var touchAction = recognizer.defaultActions && recognizer.defaultActions[g];
|
| + var actionNode;
|
| + switch(node.nodeType) {
|
| + case Node.ELEMENT_NODE:
|
| + actionNode = node;
|
| + break;
|
| + case Node.DOCUMENT_FRAGMENT_NODE:
|
| + actionNode = node.host;
|
| + break;
|
| + default:
|
| + actionNode = null;
|
| + break;
|
| + }
|
| + if (touchAction && actionNode && !actionNode.hasAttribute('touch-action')) {
|
| + actionNode.setAttribute('touch-action', touchAction);
|
| + }
|
| + }
|
| + node._pgListeners++;
|
| + }
|
| + return Boolean(dep);
|
| };
|
|
|
| - function Installer(add, remove, changed, binder) {
|
| - this.addCallback = add.bind(binder);
|
| - this.removeCallback = remove.bind(binder);
|
| - this.changedCallback = changed.bind(binder);
|
| - if (MO) {
|
| - this.observer = new MO(this.mutationWatcher.bind(this));
|
| + /**
|
| + *
|
| + * Listen for `gesture` from `node` with `handler` function.
|
| + *
|
| + * @param {Element} node
|
| + * @param {string} gesture
|
| + * @param {Function} handler
|
| + * @param {Boolean} capture
|
| + */
|
| + scope.addEventListener = function(node, gesture, handler, capture) {
|
| + if (handler) {
|
| + scope.activateGesture(node, gesture);
|
| + node.addEventListener(gesture, handler, capture);
|
| }
|
| - }
|
| + };
|
|
|
| - Installer.prototype = {
|
| - watchSubtree: function(target) {
|
| - // Only watch scopes that can target find, as these are top-level.
|
| - // Otherwise we can see duplicate additions and removals that add noise.
|
| - //
|
| - // TODO(dfreedman): For some instances with ShadowDOMPolyfill, we can see
|
| - // a removal without an insertion when a node is redistributed among
|
| - // shadows. Since it all ends up correct in the document, watching only
|
| - // the document will yield the correct mutations to watch.
|
| - if (scope.targetFinding.canTarget(target)) {
|
| - this.observer.observe(target, OBSERVER_INIT);
|
| - }
|
| - },
|
| - enableOnSubtree: function(target) {
|
| - this.watchSubtree(target);
|
| - if (target === document && document.readyState !== 'complete') {
|
| - this.installOnLoad();
|
| - } else {
|
| - this.installNewSubtree(target);
|
| + /**
|
| + * Tears down the gesture configuration for `node`
|
| + *
|
| + * If `handler` is the last listener for `gesture`, the underlying gesture recognizer is disabled.
|
| + *
|
| + * @param {Element} node
|
| + * @param {string} gesture
|
| + * @return Boolean `gesture` is a valid gesture
|
| + */
|
| + scope.deactivateGesture = function(node, gesture) {
|
| + var g = gesture.toLowerCase();
|
| + var dep = dispatcher.dependencyMap[g];
|
| + if (dep) {
|
| + if (dep.listeners > 0) {
|
| + dep.listeners--;
|
| + }
|
| + if (dep.listeners === 0) {
|
| + var recognizer = dispatcher.gestures[dep.index];
|
| + if (recognizer) {
|
| + recognizer.enabled = false;
|
| + }
|
| }
|
| - },
|
| - installNewSubtree: function(target) {
|
| - forEach(this.findElements(target), this.addElement, this);
|
| - },
|
| - findElements: function(target) {
|
| - if (target.querySelectorAll) {
|
| - return target.querySelectorAll(SELECTOR);
|
| + if (node._pgListeners > 0) {
|
| + node._pgListeners--;
|
| }
|
| - return [];
|
| - },
|
| - removeElement: function(el) {
|
| - this.removeCallback(el);
|
| - },
|
| - addElement: function(el) {
|
| - this.addCallback(el);
|
| - },
|
| - elementChanged: function(el, oldValue) {
|
| - this.changedCallback(el, oldValue);
|
| - },
|
| - concatLists: function(accum, list) {
|
| - return accum.concat(toArray(list));
|
| - },
|
| - // register all touch-action = none nodes on document load
|
| - installOnLoad: function() {
|
| - document.addEventListener('readystatechange', function() {
|
| - if (document.readyState === 'complete') {
|
| - this.installNewSubtree(document);
|
| - }
|
| - }.bind(this));
|
| - },
|
| - isElement: function(n) {
|
| - return n.nodeType === Node.ELEMENT_NODE;
|
| - },
|
| - flattenMutationTree: function(inNodes) {
|
| - // find children with touch-action
|
| - var tree = map(inNodes, this.findElements, this);
|
| - // make sure the added nodes are accounted for
|
| - tree.push(filter(inNodes, this.isElement));
|
| - // flatten the list
|
| - return tree.reduce(this.concatLists, []);
|
| - },
|
| - mutationWatcher: function(mutations) {
|
| - mutations.forEach(this.mutationHandler, this);
|
| - },
|
| - mutationHandler: function(m) {
|
| - if (m.type === 'childList') {
|
| - var added = this.flattenMutationTree(m.addedNodes);
|
| - added.forEach(this.addElement, this);
|
| - var removed = this.flattenMutationTree(m.removedNodes);
|
| - removed.forEach(this.removeElement, this);
|
| - } else if (m.type === 'attributes') {
|
| - this.elementChanged(m.target, m.oldValue);
|
| + if (node._pgListeners === 0) {
|
| + dispatcher.unregister(node);
|
| }
|
| }
|
| + return Boolean(dep);
|
| };
|
|
|
| - if (!MO) {
|
| - Installer.prototype.watchSubtree = function(){
|
| - console.warn('PolymerGestures: MutationObservers not found, touch-action will not be dynamically detected');
|
| - };
|
| - }
|
| -
|
| - scope.Installer = Installer;
|
| + /**
|
| + * Stop listening for `gesture` from `node` with `handler` function.
|
| + *
|
| + * @param {Element} node
|
| + * @param {string} gesture
|
| + * @param {Function} handler
|
| + * @param {Boolean} capture
|
| + */
|
| + scope.removeEventListener = function(node, gesture, handler, capture) {
|
| + if (handler) {
|
| + scope.deactivateGesture(node, gesture);
|
| + node.removeEventListener(gesture, handler, capture);
|
| + }
|
| + };
|
| })(window.PolymerGestures);
|
|
|
| /*
|
| @@ -966,10 +949,12 @@ PolymerGestures.wrap = PolymerGestures.hasSDPolyfill ? ShadowDOMPolyfill.wrapIfN
|
| 'mousemove',
|
| 'mouseup'
|
| ],
|
| + exposes: [
|
| + 'down',
|
| + 'up',
|
| + 'move'
|
| + ],
|
| register: function(target) {
|
| - if (target !== document) {
|
| - return;
|
| - }
|
| dispatcher.listen(target, this.events);
|
| },
|
| unregister: function(target) {
|
| @@ -1008,22 +993,31 @@ PolymerGestures.wrap = PolymerGestures.hasSDPolyfill ? ShadowDOMPolyfill.wrapIfN
|
| this.mouseup(inEvent);
|
| }
|
| var e = this.prepareEvent(inEvent);
|
| - e.target = scope.wrap(scope.findTarget(inEvent));
|
| + e.target = scope.findTarget(inEvent);
|
| pointermap.set(this.POINTER_ID, e.target);
|
| dispatcher.down(e);
|
| }
|
| },
|
| mousemove: function(inEvent) {
|
| if (!this.isEventSimulatedFromTouch(inEvent)) {
|
| - var e = this.prepareEvent(inEvent);
|
| - e.target = pointermap.get(this.POINTER_ID);
|
| - dispatcher.move(e);
|
| + var target = pointermap.get(this.POINTER_ID);
|
| + if (target) {
|
| + var e = this.prepareEvent(inEvent);
|
| + e.target = target;
|
| + // handle case where we missed a mouseup
|
| + if (e.buttons === 0) {
|
| + dispatcher.cancel(e);
|
| + this.cleanupMouse();
|
| + } else {
|
| + dispatcher.move(e);
|
| + }
|
| + }
|
| }
|
| },
|
| mouseup: function(inEvent) {
|
| if (!this.isEventSimulatedFromTouch(inEvent)) {
|
| var e = this.prepareEvent(inEvent);
|
| - e.relatedTarget = scope.wrap(scope.findTarget(inEvent));
|
| + e.relatedTarget = scope.findTarget(inEvent);
|
| e.target = pointermap.get(this.POINTER_ID);
|
| dispatcher.up(e);
|
| this.cleanupMouse();
|
| @@ -1056,10 +1050,9 @@ PolymerGestures.wrap = PolymerGestures.hasSDPolyfill ? ShadowDOMPolyfill.wrapIfN
|
| var CLICK_COUNT_TIMEOUT = 200;
|
| var HYSTERESIS = 20;
|
| var ATTRIB = 'touch-action';
|
| - var INSTALLER;
|
| - // maybe one day...
|
| - // var CAN_USE_GLOBAL = ATTRIB in document.head.style;
|
| - var CAN_USE_GLOBAL = false;
|
| + // TODO(dfreedm): disable until http://crbug.com/399765 is resolved
|
| + // var HAS_TOUCH_ACTION = ATTRIB in document.head.style;
|
| + var HAS_TOUCH_ACTION = false;
|
|
|
| // handler block for native touch events
|
| var touchEvents = {
|
| @@ -1069,74 +1062,35 @@ PolymerGestures.wrap = PolymerGestures.hasSDPolyfill ? ShadowDOMPolyfill.wrapIfN
|
| 'touchend',
|
| 'touchcancel'
|
| ],
|
| - register: function(target) {
|
| - if (CAN_USE_GLOBAL) {
|
| - dispatcher.listen(target, this.events);
|
| - } else {
|
| - INSTALLER.enableOnSubtree(target);
|
| + exposes: [
|
| + 'down',
|
| + 'up',
|
| + 'move'
|
| + ],
|
| + register: function(target, initial) {
|
| + if (initial) {
|
| + return;
|
| }
|
| + dispatcher.listen(target, this.events);
|
| },
|
| unregister: function(target) {
|
| - if (CAN_USE_GLOBAL) {
|
| - dispatcher.unlisten(target, this.events);
|
| - } else {
|
| - // TODO(dfreedman): is it worth it to disconnect the MO?
|
| - }
|
| - },
|
| - elementAdded: function(el) {
|
| - var a = el.getAttribute(ATTRIB);
|
| - var st = this.touchActionToScrollType(a);
|
| - if (st) {
|
| - el._scrollType = st;
|
| - dispatcher.listen(el, this.events);
|
| - // set touch-action on shadows as well
|
| - allShadows(el).forEach(function(s) {
|
| - s._scrollType = st;
|
| - dispatcher.listen(s, this.events);
|
| - }, this);
|
| - }
|
| - },
|
| - elementRemoved: function(el) {
|
| - el._scrollType = undefined;
|
| - dispatcher.unlisten(el, this.events);
|
| - // remove touch-action from shadow
|
| - allShadows(el).forEach(function(s) {
|
| - s._scrollType = undefined;
|
| - dispatcher.unlisten(s, this.events);
|
| - }, this);
|
| - },
|
| - elementChanged: function(el, oldValue) {
|
| - var a = el.getAttribute(ATTRIB);
|
| - var st = this.touchActionToScrollType(a);
|
| - var oldSt = this.touchActionToScrollType(oldValue);
|
| - // simply update scrollType if listeners are already established
|
| - if (st && oldSt) {
|
| - el._scrollType = st;
|
| - allShadows(el).forEach(function(s) {
|
| - s._scrollType = st;
|
| - }, this);
|
| - } else if (oldSt) {
|
| - this.elementRemoved(el);
|
| - } else if (st) {
|
| - this.elementAdded(el);
|
| - }
|
| + dispatcher.unlisten(target, this.events);
|
| },
|
| scrollTypes: {
|
| EMITTER: 'none',
|
| XSCROLLER: 'pan-x',
|
| YSCROLLER: 'pan-y',
|
| - SCROLLER: /^(?:pan-x pan-y)|(?:pan-y pan-x)|auto|manipulation$/
|
| },
|
| touchActionToScrollType: function(touchAction) {
|
| var t = touchAction;
|
| var st = this.scrollTypes;
|
| - if (t === 'none') {
|
| + if (t === st.EMITTER) {
|
| return 'none';
|
| } else if (t === st.XSCROLLER) {
|
| return 'X';
|
| } else if (t === st.YSCROLLER) {
|
| return 'Y';
|
| - } else if (st.SCROLLER.exec(t)) {
|
| + } else {
|
| return 'XY';
|
| }
|
| },
|
| @@ -1189,7 +1143,7 @@ PolymerGestures.wrap = PolymerGestures.hasSDPolyfill ? ShadowDOMPolyfill.wrapIfN
|
| clientX: touch.clientX,
|
| clientY: touch.clientY,
|
| path: this.currentTouchEvent.path,
|
| - target: scope.wrap(this.currentTouchEvent.target)
|
| + target: this.currentTouchEvent.target
|
| };
|
| return scope.findTarget(fastPath);
|
| } else {
|
| @@ -1206,7 +1160,7 @@ PolymerGestures.wrap = PolymerGestures.hasSDPolyfill ? ShadowDOMPolyfill.wrapIfN
|
| // Touch identifiers can start at 0.
|
| // Add 2 to the touch identifier for compatibility.
|
| var id = e.pointerId = inTouch.identifier + 2;
|
| - e.target = scope.wrap(this.findTarget(inTouch, id));
|
| + e.target = this.findTarget(inTouch, id);
|
| e.bubbles = true;
|
| e.cancelable = true;
|
| e.detail = this.clickCount;
|
| @@ -1248,7 +1202,8 @@ PolymerGestures.wrap = PolymerGestures.hasSDPolyfill ? ShadowDOMPolyfill.wrapIfN
|
| shouldScroll: function(inEvent) {
|
| if (this.firstXY) {
|
| var ret;
|
| - var scrollAxis = scope.targetFinding.findScrollAxis(inEvent);
|
| + var touchAction = scope.targetFinding.findTouchAction(inEvent);
|
| + var scrollAxis = this.touchActionToScrollType(touchAction);
|
| if (scrollAxis === 'none') {
|
| // this element is a touch-action: none, should never scroll
|
| ret = false;
|
| @@ -1316,8 +1271,12 @@ PolymerGestures.wrap = PolymerGestures.hasSDPolyfill ? ShadowDOMPolyfill.wrapIfN
|
| dispatcher.down(inPointer);
|
| },
|
| touchmove: function(inEvent) {
|
| - if (CAN_USE_GLOBAL) {
|
| - this.processTouches(inEvent, this.move);
|
| + if (HAS_TOUCH_ACTION) {
|
| + // touchevent.cancelable == false is sent when the page is scrolling under native Touch Action in Chrome 36
|
| + // https://groups.google.com/a/chromium.org/d/msg/input-dev/wHnyukcYBcA/b9kmtwM1jJQJ
|
| + if (inEvent.cancelable) {
|
| + this.processTouches(inEvent, this.move);
|
| + }
|
| } else {
|
| if (!this.scrolling) {
|
| if (this.scrolling === null && this.shouldScroll(inEvent)) {
|
| @@ -1348,7 +1307,7 @@ PolymerGestures.wrap = PolymerGestures.hasSDPolyfill ? ShadowDOMPolyfill.wrapIfN
|
| this.processTouches(inEvent, this.up);
|
| },
|
| up: function(inPointer) {
|
| - inPointer.relatedTarget = scope.wrap(scope.findTarget(inPointer));
|
| + inPointer.relatedTarget = scope.findTarget(inPointer);
|
| dispatcher.up(inPointer);
|
| },
|
| cancel: function(inPointer) {
|
| @@ -1382,10 +1341,6 @@ PolymerGestures.wrap = PolymerGestures.hasSDPolyfill ? ShadowDOMPolyfill.wrapIfN
|
| }
|
| };
|
|
|
| - if (!CAN_USE_GLOBAL) {
|
| - INSTALLER = new scope.Installer(touchEvents.elementAdded, touchEvents.elementRemoved, touchEvents.elementChanged, touchEvents);
|
| - }
|
| -
|
| scope.touchEvents = touchEvents;
|
| })(window.PolymerGestures);
|
|
|
| @@ -1439,7 +1394,7 @@ PolymerGestures.wrap = PolymerGestures.hasSDPolyfill ? ShadowDOMPolyfill.wrapIfN
|
| },
|
| MSPointerDown: function(inEvent) {
|
| var e = this.prepareEvent(inEvent);
|
| - e.target = scope.wrap(scope.findTarget(inEvent));
|
| + e.target = scope.findTarget(inEvent);
|
| pointermap.set(inEvent.pointerId, e.target);
|
| dispatcher.down(e);
|
| },
|
| @@ -1450,14 +1405,14 @@ PolymerGestures.wrap = PolymerGestures.hasSDPolyfill ? ShadowDOMPolyfill.wrapIfN
|
| },
|
| MSPointerUp: function(inEvent) {
|
| var e = this.prepareEvent(inEvent);
|
| - e.relatedTarget = scope.wrap(scope.findTarget(inEvent));
|
| + e.relatedTarget = scope.findTarget(inEvent);
|
| e.target = pointermap.get(e.pointerId);
|
| dispatcher.up(e);
|
| this.cleanup(inEvent.pointerId);
|
| },
|
| MSPointerCancel: function(inEvent) {
|
| var e = this.prepareEvent(inEvent);
|
| - e.relatedTarget = scope.wrap(scope.findTarget(inEvent));
|
| + e.relatedTarget = scope.findTarget(inEvent);
|
| e.target = pointermap.get(e.pointerId);
|
| dispatcher.cancel(e);
|
| this.cleanup(inEvent.pointerId);
|
| @@ -1505,7 +1460,7 @@ PolymerGestures.wrap = PolymerGestures.hasSDPolyfill ? ShadowDOMPolyfill.wrapIfN
|
| },
|
| pointerdown: function(inEvent) {
|
| var e = this.prepareEvent(inEvent);
|
| - e.target = scope.wrap(scope.findTarget(inEvent));
|
| + e.target = scope.findTarget(inEvent);
|
| pointermap.set(e.pointerId, e.target);
|
| dispatcher.down(e);
|
| },
|
| @@ -1516,14 +1471,14 @@ PolymerGestures.wrap = PolymerGestures.hasSDPolyfill ? ShadowDOMPolyfill.wrapIfN
|
| },
|
| pointerup: function(inEvent) {
|
| var e = this.prepareEvent(inEvent);
|
| - e.relatedTarget = scope.wrap(scope.findTarget(inEvent));
|
| + e.relatedTarget = scope.findTarget(inEvent);
|
| e.target = pointermap.get(e.pointerId);
|
| dispatcher.up(e);
|
| this.cleanup(inEvent.pointerId);
|
| },
|
| pointercancel: function(inEvent) {
|
| var e = this.prepareEvent(inEvent);
|
| - e.relatedTarget = scope.wrap(scope.findTarget(inEvent));
|
| + e.relatedTarget = scope.findTarget(inEvent);
|
| e.target = pointermap.get(e.pointerId);
|
| dispatcher.cancel(e);
|
| this.cleanup(inEvent.pointerId);
|
| @@ -1549,19 +1504,29 @@ PolymerGestures.wrap = PolymerGestures.hasSDPolyfill ? ShadowDOMPolyfill.wrapIfN
|
| */
|
| (function(scope) {
|
| var dispatcher = scope.dispatcher;
|
| + var nav = window.navigator;
|
|
|
| if (window.PointerEvent) {
|
| dispatcher.registerSource('pointer', scope.pointerEvents);
|
| - } else if (window.navigator.msPointerEnabled) {
|
| + } else if (nav.msPointerEnabled) {
|
| dispatcher.registerSource('ms', scope.msEvents);
|
| } else {
|
| dispatcher.registerSource('mouse', scope.mouseEvents);
|
| if (window.ontouchstart !== undefined) {
|
| dispatcher.registerSource('touch', scope.touchEvents);
|
| + /*
|
| + * NOTE: an empty touch listener on body will reactivate nodes imported from templates with touch listeners
|
| + * Removing it will re-break the nodes
|
| + *
|
| + * Work around for https://bugs.webkit.org/show_bug.cgi?id=135628
|
| + */
|
| + var isSafari = nav.userAgent.match('Safari') && !nav.userAgent.match('Chrome');
|
| + if (isSafari) {
|
| + document.body.addEventListener('touchstart', function(){});
|
| + }
|
| }
|
| }
|
| -
|
| - dispatcher.register(document);
|
| + dispatcher.register(document, true);
|
| })(window.PolymerGestures);
|
|
|
| /*
|
| @@ -1679,6 +1644,18 @@ PolymerGestures.wrap = PolymerGestures.hasSDPolyfill ? ShadowDOMPolyfill.wrapIfN
|
| 'move',
|
| 'up',
|
| ],
|
| + exposes: [
|
| + 'trackstart',
|
| + 'track',
|
| + 'trackx',
|
| + 'tracky',
|
| + 'trackend'
|
| + ],
|
| + defaultActions: {
|
| + 'track': 'none',
|
| + 'trackx': 'pan-y',
|
| + 'tracky': 'pan-x'
|
| + },
|
| WIGGLE_THRESHOLD: 4,
|
| clampDir: function(inDelta) {
|
| return inDelta > 0 ? 1 : -1;
|
| @@ -1697,33 +1674,42 @@ PolymerGestures.wrap = PolymerGestures.hasSDPolyfill ? ShadowDOMPolyfill.wrapIfN
|
| var dd = this.calcPositionDelta(t.lastMoveEvent, inEvent);
|
| if (dd.x) {
|
| t.xDirection = this.clampDir(dd.x);
|
| + } else if (inType === 'trackx') {
|
| + return;
|
| }
|
| if (dd.y) {
|
| t.yDirection = this.clampDir(dd.y);
|
| + } else if (inType === 'tracky') {
|
| + return;
|
| }
|
| - var e = eventFactory.makeGestureEvent(inType, {
|
| + var gestureProto = {
|
| bubbles: true,
|
| cancelable: true,
|
| - dx: d.x,
|
| - dy: d.y,
|
| - ddx: dd.x,
|
| - ddy: dd.y,
|
| - x: inEvent.x,
|
| - y: inEvent.y,
|
| - clientX: inEvent.clientX,
|
| - clientY: inEvent.clientY,
|
| - pageX: inEvent.pageX,
|
| - pageY: inEvent.pageY,
|
| - screenX: inEvent.screenX,
|
| - screenY: inEvent.screenY,
|
| - xDirection: t.xDirection,
|
| - yDirection: t.yDirection,
|
| trackInfo: t.trackInfo,
|
| relatedTarget: inEvent.relatedTarget,
|
| pointerType: inEvent.pointerType,
|
| pointerId: inEvent.pointerId,
|
| _source: 'track'
|
| - });
|
| + };
|
| + if (inType !== 'tracky') {
|
| + gestureProto.x = inEvent.x;
|
| + gestureProto.dx = d.x;
|
| + gestureProto.ddx = dd.x;
|
| + gestureProto.clientX = inEvent.clientX;
|
| + gestureProto.pageX = inEvent.pageX;
|
| + gestureProto.screenX = inEvent.screenX;
|
| + gestureProto.xDirection = t.xDirection;
|
| + }
|
| + if (inType !== 'trackx') {
|
| + gestureProto.dy = d.y;
|
| + gestureProto.ddy = dd.y;
|
| + gestureProto.y = inEvent.y;
|
| + gestureProto.clientY = inEvent.clientY;
|
| + gestureProto.pageY = inEvent.pageY;
|
| + gestureProto.screenY = inEvent.screenY;
|
| + gestureProto.yDirection = t.yDirection;
|
| + }
|
| + var e = eventFactory.makeGestureEvent(inType, gestureProto);
|
| t.downTarget.dispatchEvent(e);
|
| },
|
| down: function(inEvent) {
|
| @@ -1749,11 +1735,14 @@ PolymerGestures.wrap = PolymerGestures.hasSDPolyfill ? ShadowDOMPolyfill.wrapIfN
|
| // start tracking only if finger moves more than WIGGLE_THRESHOLD
|
| if (move > this.WIGGLE_THRESHOLD) {
|
| p.tracking = true;
|
| - this.fireTrack('trackstart', p.downEvent, p);
|
| - this.fireTrack('track', inEvent, p);
|
| + p.lastMoveEvent = p.downEvent;
|
| + this.fireTrack('trackstart', inEvent, p);
|
| }
|
| - } else {
|
| + }
|
| + if (p.tracking) {
|
| this.fireTrack('track', inEvent, p);
|
| + this.fireTrack('trackx', inEvent, p);
|
| + this.fireTrack('tracky', inEvent, p);
|
| }
|
| p.lastMoveEvent = inEvent;
|
| }
|
| @@ -1837,6 +1826,11 @@ PolymerGestures.wrap = PolymerGestures.hasSDPolyfill ? ShadowDOMPolyfill.wrapIfN
|
| 'move',
|
| 'up',
|
| ],
|
| + exposes: [
|
| + 'hold',
|
| + 'holdpulse',
|
| + 'release'
|
| + ],
|
| heldPointer: null,
|
| holdJob: null,
|
| pulse: function() {
|
| @@ -1943,6 +1937,9 @@ PolymerGestures.wrap = PolymerGestures.hasSDPolyfill ? ShadowDOMPolyfill.wrapIfN
|
| 'down',
|
| 'up'
|
| ],
|
| + exposes: [
|
| + 'tap'
|
| + ],
|
| down: function(inEvent) {
|
| if (inEvent.isPrimary && !inEvent.tapPrevented) {
|
| pointermap.set(inEvent.pointerId, {
|
| @@ -3327,6 +3324,21 @@ PolymerGestures.wrap = PolymerGestures.hasSDPolyfill ? ShadowDOMPolyfill.wrapIfN
|
| left = getFn(left);
|
| right = getFn(right);
|
|
|
| + switch (op) {
|
| + case '||':
|
| + this.dynamicDeps = true;
|
| + return function(model, observer, filterRegistry) {
|
| + return left(model, observer, filterRegistry) ||
|
| + right(model, observer, filterRegistry);
|
| + };
|
| + case '&&':
|
| + this.dynamicDeps = true;
|
| + return function(model, observer, filterRegistry) {
|
| + return left(model, observer, filterRegistry) &&
|
| + right(model, observer, filterRegistry);
|
| + };
|
| + }
|
| +
|
| return function(model, observer, filterRegistry) {
|
| return binaryOperators[op](left(model, observer, filterRegistry),
|
| right(model, observer, filterRegistry));
|
| @@ -3338,6 +3350,8 @@ PolymerGestures.wrap = PolymerGestures.hasSDPolyfill ? ShadowDOMPolyfill.wrapIfN
|
| consequent = getFn(consequent);
|
| alternate = getFn(alternate);
|
|
|
| + this.dynamicDeps = true;
|
| +
|
| return function(model, observer, filterRegistry) {
|
| return test(model, observer, filterRegistry) ?
|
| consequent(model, observer, filterRegistry) :
|
| @@ -3653,6 +3667,18 @@ PolymerGestures.wrap = PolymerGestures.hasSDPolyfill ? ShadowDOMPolyfill.wrapIfN
|
| * Code distributed by Google as part of the polymer project is also
|
| * subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
|
| */
|
| +Polymer = {
|
| + version: '0.3.5-5d00e4b'
|
| +};
|
| +
|
| +/*
|
| + * Copyright (c) 2014 The Polymer Project Authors. All rights reserved.
|
| + * This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
|
| + * The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
|
| + * The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
|
| + * Code distributed by Google as part of the polymer project is also
|
| + * subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
|
| + */
|
|
|
| // TODO(sorvell): this ensures Polymer is an object and not a function
|
| // Platform is currently defining it as a function to allow for async loading
|
| @@ -3954,10 +3980,13 @@ if (typeof window.Polymer === 'function') {
|
|
|
| (function(scope) {
|
|
|
| + function noopHandler(value) {
|
| + return value;
|
| + }
|
| +
|
| var typeHandlers = {
|
| - string: function(value) {
|
| - return value;
|
| - },
|
| + string: noopHandler,
|
| + 'undefined': noopHandler,
|
| date: function(value) {
|
| return new Date(Date.parse(value) || Date.now());
|
| },
|
| @@ -4098,13 +4127,15 @@ if (typeof window.Polymer === 'function') {
|
| * @param {string} type An event name.
|
| * @param {any} detail
|
| * @param {Node} onNode Target node.
|
| + * @param {Boolean} bubbles Set false to prevent bubbling, defaults to true
|
| + * @param {Boolean} cancelable Set false to prevent cancellation, defaults to true
|
| */
|
| fire: function(type, detail, onNode, bubbles, cancelable) {
|
| var node = onNode || this;
|
| - var detail = detail || {};
|
| + var detail = detail === null || detail === undefined ? {} : detail;
|
| var event = new CustomEvent(type, {
|
| - bubbles: (bubbles !== undefined ? bubbles : true),
|
| - cancelable: (cancelable !== undefined ? cancelable : true),
|
| + bubbles: bubbles !== undefined ? bubbles : true,
|
| + cancelable: cancelable !== undefined ? cancelable : true,
|
| detail: detail
|
| });
|
| node.dispatchEvent(event);
|
| @@ -4201,8 +4232,7 @@ if (typeof window.Polymer === 'function') {
|
| // by default supports 1 thing being bound.
|
| for (var type in events) {
|
| var methodName = events[type];
|
| - this.addEventListener(type, this.element.getEventHandler(this, this,
|
| - methodName));
|
| + PolymerGestures.addEventListener(this, type, this.element.getEventHandler(this, this, methodName));
|
| }
|
| },
|
| // call 'method' or function method on 'obj' with 'args', if the method exists
|
| @@ -4223,6 +4253,10 @@ if (typeof window.Polymer === 'function') {
|
|
|
| scope.api.instance.events = events;
|
|
|
| + // alias PolymerGestures event listener logic
|
| + scope.addEventListener = PolymerGestures.addEventListener;
|
| + scope.removeEventListener = PolymerGestures.removeEventListener;
|
| +
|
| })(Polymer);
|
|
|
| /*
|
| @@ -4739,9 +4773,7 @@ if (typeof window.Polymer === 'function') {
|
| }
|
| this.created();
|
| this.prepareElement();
|
| - // TODO(sorvell): replace when ShadowDOMPolyfill issue is corrected
|
| - // https://github.com/Polymer/ShadowDOM/issues/420
|
| - if (!this.ownerDocument.isStagingDocument || window.ShadowDOMPolyfill) {
|
| + if (!this.ownerDocument.isStagingDocument) {
|
| this.makeElementReady();
|
| }
|
| },
|
| @@ -4756,7 +4788,6 @@ if (typeof window.Polymer === 'function') {
|
| this.shadowRoots = {};
|
| // install property observers
|
| this.createPropertyObserver();
|
| - // TODO (sorvell): temporarily open observer when created
|
| this.openPropertyObserver();
|
| // install boilerplate attributes
|
| this.copyInstanceAttributes();
|
| @@ -4781,9 +4812,6 @@ if (typeof window.Polymer === 'function') {
|
| this.removeAttribute('unresolved');
|
| // user entry point
|
| this.ready();
|
| - // TODO (sorvell): temporarily open observer when created
|
| - // turn on property observation and take any initial changes
|
| - //this.openPropertyObserver();
|
| },
|
| attachedCallback: function() {
|
| this.cancelUnbindAll();
|
| @@ -4900,8 +4928,6 @@ if (typeof window.Polymer === 'function') {
|
| shadowRootReady: function(root) {
|
| // locate nodes with id and store references to them in this.$ hash
|
| this.marshalNodeReferences(root);
|
| - // set up polymer gestures
|
| - PolymerGestures.register(root);
|
| },
|
| // locate nodes with id and store references to them in this.$ hash
|
| marshalNodeReferences: function(root) {
|
| @@ -4966,7 +4992,8 @@ if (typeof window.Polymer === 'function') {
|
| // imports
|
|
|
| var log = window.logFlags || {};
|
| -
|
| + var hasShadowDOMPolyfill = window.ShadowDOMPolyfill;
|
| +
|
| // magic words
|
|
|
| var STYLE_SCOPE_ATTRIBUTE = 'element';
|
| @@ -5014,7 +5041,7 @@ if (typeof window.Polymer === 'function') {
|
| if (!scope) {
|
| return;
|
| }
|
| - if (window.ShadowDOMPolyfill) {
|
| + if (hasShadowDOMPolyfill) {
|
| cssText = shimCssText(cssText, scope.host);
|
| }
|
| var style = this.element.cssTextToScopeStyle(cssText,
|
| @@ -5036,7 +5063,7 @@ if (typeof window.Polymer === 'function') {
|
| return cache[name];
|
| },
|
| styleCacheForScope: function(scope) {
|
| - if (window.ShadowDOMPolyfill) {
|
| + if (hasShadowDOMPolyfill) {
|
| var scopeName = scope.host ? scope.host.localName : scope.localName;
|
| return polyfillScopeStyleCache[scopeName] || (polyfillScopeStyleCache[scopeName] = {});
|
| } else {
|
| @@ -5221,6 +5248,8 @@ scope.api.declaration.path = path;
|
| var api = scope.api.instance.styles;
|
| var STYLE_SCOPE_ATTRIBUTE = api.STYLE_SCOPE_ATTRIBUTE;
|
|
|
| + var hasShadowDOMPolyfill = window.ShadowDOMPolyfill;
|
| +
|
| // magic words
|
|
|
| var STYLE_SELECTOR = 'style';
|
| @@ -5393,7 +5422,7 @@ scope.api.declaration.path = path;
|
| if (scope === document) {
|
| scope = document.head;
|
| }
|
| - if (window.ShadowDOMPolyfill) {
|
| + if (hasShadowDOMPolyfill) {
|
| scope = document.head;
|
| }
|
| // TODO(sorvell): necessary for IE
|
| @@ -5534,7 +5563,7 @@ scope.api.declaration.path = path;
|
|
|
| return function(model, node, oneTime) {
|
| var handler = events.getEventHandler(undefined, node, pathString);
|
| - node.addEventListener(eventType, handler);
|
| + PolymerGestures.addEventListener(node, eventType, handler);
|
|
|
| if (oneTime)
|
| return;
|
| @@ -5551,7 +5580,7 @@ scope.api.declaration.path = path;
|
| open: bindingValue,
|
| discardChanges: bindingValue,
|
| close: function() {
|
| - node.removeEventListener(eventType, handler);
|
| + PolymerGestures.removeEventListener(node, eventType, handler);
|
| }
|
| };
|
| };
|
| @@ -5642,40 +5671,53 @@ scope.api.declaration.path = path;
|
| prototype._publishLC = this.lowerCaseMap(publish);
|
| }
|
| },
|
| - // sync prototype to property descriptors;
|
| - // desriptor format contains default value and optionally a
|
| - // hint for reflecting the property to an attribute.
|
| - // e.g. {foo: 5, bar: {value: true, reflect: true}}
|
| - // reflect: {foo: true} is also supported
|
| //
|
| - requireProperties: function(propertyDescriptors, prototype, base) {
|
| - // reflected properties
|
| + // `name: value` entries in the `publish` object may need to generate
|
| + // matching properties on the prototype.
|
| + //
|
| + // Values that are objects may have a `reflect` property, which
|
| + // signals that the value describes property control metadata.
|
| + // In metadata objects, the prototype default value (if any)
|
| + // is encoded in the `value` property.
|
| + //
|
| + // publish: {
|
| + // foo: 5,
|
| + // bar: {value: true, reflect: true},
|
| + // zot: {}
|
| + // }
|
| + //
|
| + // `reflect` metadata property controls whether changes to the property
|
| + // are reflected back to the attribute (default false).
|
| + //
|
| + // A value is stored on the prototype unless it's === `undefined`,
|
| + // in which case the base chain is checked for a value.
|
| + // If the basal value is also undefined, `null` is stored on the prototype.
|
| + //
|
| + // The reflection data is stored on another prototype object, `reflect`
|
| + // which also can be specified directly.
|
| + //
|
| + // reflect: {
|
| + // foo: true
|
| + // }
|
| + //
|
| + requireProperties: function(propertyInfos, prototype, base) {
|
| + // per-prototype storage for reflected properties
|
| prototype.reflect = prototype.reflect || {};
|
| // ensure a prototype value for each property
|
| // and update the property's reflect to attribute status
|
| - for (var n in propertyDescriptors) {
|
| - var propertyDescriptor = propertyDescriptors[n];
|
| - var reflects = this.reflectHintForDescriptor(propertyDescriptor);
|
| - if (prototype.reflect[n] === undefined && reflects !== undefined) {
|
| - prototype.reflect[n] = reflects;
|
| + for (var n in propertyInfos) {
|
| + var value = propertyInfos[n];
|
| + // value has metadata if it has a `reflect` property
|
| + if (value && value.reflect !== undefined) {
|
| + prototype.reflect[n] = Boolean(value.reflect);
|
| + value = value.value;
|
| }
|
| - if (prototype[n] === undefined) {
|
| - prototype[n] = this.valueForDescriptor(propertyDescriptor);
|
| + // only set a value if one is specified
|
| + if (value !== undefined) {
|
| + prototype[n] = value;
|
| }
|
| }
|
| },
|
| - valueForDescriptor: function(propertyDescriptor) {
|
| - var value = typeof propertyDescriptor === 'object' &&
|
| - propertyDescriptor ? propertyDescriptor.value : propertyDescriptor;
|
| - return value !== undefined ? value : null;
|
| - },
|
| - // returns the value of the descriptor's 'reflect' property or undefined
|
| - reflectHintForDescriptor: function(propertyDescriptor) {
|
| - if (typeof propertyDescriptor === 'object' &&
|
| - propertyDescriptor && propertyDescriptor.reflect !== undefined) {
|
| - return propertyDescriptor.reflect;
|
| - }
|
| - },
|
| lowerCaseMap: function(properties) {
|
| var map = {};
|
| for (var n in properties) {
|
| @@ -5721,14 +5763,12 @@ scope.api.declaration.path = path;
|
| this.createPropertyAccessor(n);
|
| }
|
| }
|
| -
|
| var n$ = prototype._computedNames;
|
| if (n$ && n$.length) {
|
| for (var i=0, l=n$.length, n, fn; (i<l) && (n=n$[i]); i++) {
|
| this.createPropertyAccessor(n);
|
| }
|
| }
|
| -
|
| }
|
| };
|
|
|
| @@ -5765,35 +5805,27 @@ scope.api.declaration.path = path;
|
| },
|
|
|
| publishAttributes: function(prototype, base) {
|
| - // merge names from 'attributes' attribute
|
| + // merge names from 'attributes' attribute into the 'publish' object
|
| var attributes = this.getAttribute(ATTRIBUTES_ATTRIBUTE);
|
| if (attributes) {
|
| - // get properties to publish
|
| - var publish = prototype.publish || (prototype.publish = {});
|
| + // create a `publish` object if needed.
|
| + // the `publish` object is only relevant to this prototype, the
|
| + // publishing logic in `declaration/properties.js` is responsible for
|
| + // managing property values on the prototype chain.
|
| + // TODO(sjmiles): the `publish` object is later chained to it's
|
| + // ancestor object, presumably this is only for
|
| + // reflection or other non-library uses.
|
| + var publish = prototype.publish || (prototype.publish = {});
|
| // names='a b c' or names='a,b,c'
|
| var names = attributes.split(ATTRIBUTES_REGEX);
|
| // record each name for publishing
|
| for (var i=0, l=names.length, n; i<l; i++) {
|
| // remove excess ws
|
| n = names[i].trim();
|
| - // if the user hasn't specified a value, we want to use the
|
| - // default, unless a superclass has already chosen one
|
| + // looks weird, but causes n to exist on `publish` if it does not;
|
| + // a more careful test would need expensive `in` operator
|
| if (n && publish[n] === undefined) {
|
| - // TODO(sjmiles): querying native properties on IE11 (and possibly
|
| - // on other browsers) throws an exception because there is no actual
|
| - // instance.
|
| - // In fact, trying to publish native properties is known bad for this
|
| - // and other reasons, and we need to solve this problem writ large.
|
| - try {
|
| - var hasValue = (base[n] !== undefined);
|
| - } catch(x) {
|
| - hasValue = false;
|
| - }
|
| - // supply an empty 'descriptor' object and let the publishProperties
|
| - // code determine a default
|
| - if (!hasValue) {
|
| - publish[n] = Polymer.nob;
|
| - }
|
| + publish[n] = undefined;
|
| }
|
| }
|
| }
|
| @@ -5900,6 +5932,8 @@ scope.api.declaration.path = path;
|
| var isBase = scope.isBase;
|
| var extend = scope.extend;
|
|
|
| + var hasShadowDOMPolyfill = window.ShadowDOMPolyfill;
|
| +
|
| // prototype api
|
|
|
| var prototype = {
|
| @@ -5986,7 +6020,7 @@ scope.api.declaration.path = path;
|
| // this.$.image.src = this.resolvePath('images/foo.png')
|
| this.addResolvePathApi();
|
| // under ShadowDOMPolyfill, transforms to approximate missing CSS features
|
| - if (window.ShadowDOMPolyfill) {
|
| + if (hasShadowDOMPolyfill) {
|
| Platform.ShadowCSS.shimStyling(this.templateContent(), name, extendee);
|
| }
|
| // allow custom element access to the declarative context
|
| @@ -6256,9 +6290,6 @@ scope.api.declaration.path = path;
|
| if (this.flushing) {
|
| return;
|
| }
|
| - if (flushQueue.length) {
|
| - console.warn('flushing %s elements', flushQueue.length);
|
| - }
|
| this.flushing = true;
|
| var element;
|
| while (flushQueue.length) {
|
|
|