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

Unified Diff: pkg/polymer/lib/src/js/polymer/polymer.concat.js

Issue 482763002: Revert "Roll polymer to 0.3.5" (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 6 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « pkg/polymer/lib/src/js/polymer/polymer.js ('k') | pkg/polymer/lib/src/js/polymer/polymer.concat.js.map » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 65d22b94d5be066be10de506f2182b3ef454c6a4..816116fdded03a7826dc3a1c2b2bff338c4d2e60 100644
--- a/pkg/polymer/lib/src/js/polymer/polymer.concat.js
+++ b/pkg/polymer/lib/src/js/polymer/polymer.concat.js
@@ -7,7 +7,10 @@
* 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 = {};
+window.PolymerGestures = {
+ hasSDPolyfill: Boolean(window.ShadowDOMPolyfill)
+};
+PolymerGestures.wrap = PolymerGestures.hasSDPolyfill ? ShadowDOMPolyfill.wrapIfNeeded : function(a){ return a; };
/*
* Copyright (c) 2014 The Polymer Project Authors. All rights reserved.
@@ -23,7 +26,7 @@ window.PolymerGestures = {};
// test for full event path support
var pathTest = document.createElement('meta');
- if (pathTest.createShadowRoot) {
+ if (!scope.hasSDPolyfill && pathTest.createShadowRoot) {
var sr = pathTest.createShadowRoot();
var s = document.createElement('span');
sr.appendChild(s);
@@ -119,27 +122,25 @@ window.PolymerGestures = {};
}
return this.searchRoot(s, x, y);
},
- findTouchAction: function(inEvent) {
+ findScrollAxis: 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.nodeType === Node.ELEMENT_NODE && n.hasAttribute('touch-action')) {
- return n.getAttribute('touch-action');
+ if (n._scrollType) {
+ return n._scrollType;
}
}
} else {
- n = inEvent.target;
+ n = scope.wrap(inEvent.currentTarget);
while(n) {
- if (n.hasAttribute('touch-action')) {
- return n.getAttribute('touch-action');
+ if (n._scrollType) {
+ return n._scrollType;
}
n = n.parentNode || n.host;
}
}
- // auto is default
- return "auto";
},
LCA: function(a, b) {
if (a === b) {
@@ -252,7 +253,7 @@ window.PolymerGestures = {};
(function() {
function shadowSelector(v) {
- return 'html /deep/ ' + selector(v);
+ return 'body /deep/ ' + selector(v);
}
function selector(v) {
return '[touch-action="' + v + '"]';
@@ -276,6 +277,7 @@ window.PolymerGestures = {};
];
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;
@@ -591,6 +593,9 @@ window.PolymerGestures = {};
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
@@ -611,12 +616,6 @@ window.PolymerGestures = {};
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.
@@ -640,20 +639,13 @@ window.PolymerGestures = {};
}
},
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, initial) {
+ register: function(element) {
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, initial);
+ es.register.call(es, element);
}
},
unregister: function(element) {
@@ -684,9 +676,6 @@ window.PolymerGestures = {};
// 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;
}
@@ -710,10 +699,20 @@ window.PolymerGestures = {};
}
},
addEvent: function(target, eventName) {
- target.addEventListener(eventName, this.boundHandler);
+ // 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);
+ }
},
removeEvent: function(target, eventName) {
- target.removeEventListener(eventName, this.boundHandler);
+ // 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);
+ }
},
// EVENT CREATION AND TRACKING
/**
@@ -755,12 +754,11 @@ window.PolymerGestures = {};
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 = function() {
- inEvent.preventDefault();
- };
+ eventCopy.preventDefault = inEvent.preventDefault;
return eventCopy;
},
/**
@@ -787,7 +785,7 @@ window.PolymerGestures = {};
for (var j = 0, g, fn; j < this.gestures.length; j++) {
g = this.gestures[j];
fn = g[e.type];
- if (g.enabled && fn) {
+ if (fn) {
fn.call(g, e);
}
}
@@ -805,117 +803,136 @@ window.PolymerGestures = {};
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);
- /**
- * 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);
+/*
+ * 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` 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);
+ 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));
}
- };
+ }
- /**
- * 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;
- }
+ 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);
}
- if (node._pgListeners > 0) {
- node._pgListeners--;
+ },
+ installNewSubtree: function(target) {
+ forEach(this.findElements(target), this.addElement, this);
+ },
+ findElements: function(target) {
+ if (target.querySelectorAll) {
+ return target.querySelectorAll(SELECTOR);
}
- if (node._pgListeners === 0) {
- dispatcher.unregister(node);
+ 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);
}
}
- return Boolean(dep);
};
- /**
- * 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);
- }
- };
+ if (!MO) {
+ Installer.prototype.watchSubtree = function(){
+ console.warn('PolymerGestures: MutationObservers not found, touch-action will not be dynamically detected');
+ };
+ }
+
+ scope.Installer = Installer;
})(window.PolymerGestures);
/*
@@ -949,12 +966,10 @@ window.PolymerGestures = {};
'mousemove',
'mouseup'
],
- exposes: [
- 'down',
- 'up',
- 'move'
- ],
register: function(target) {
+ if (target !== document) {
+ return;
+ }
dispatcher.listen(target, this.events);
},
unregister: function(target) {
@@ -993,31 +1008,22 @@ window.PolymerGestures = {};
this.mouseup(inEvent);
}
var e = this.prepareEvent(inEvent);
- e.target = scope.findTarget(inEvent);
+ e.target = scope.wrap(scope.findTarget(inEvent));
pointermap.set(this.POINTER_ID, e.target);
dispatcher.down(e);
}
},
mousemove: function(inEvent) {
if (!this.isEventSimulatedFromTouch(inEvent)) {
- 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);
- }
- }
+ var e = this.prepareEvent(inEvent);
+ e.target = pointermap.get(this.POINTER_ID);
+ dispatcher.move(e);
}
},
mouseup: function(inEvent) {
if (!this.isEventSimulatedFromTouch(inEvent)) {
var e = this.prepareEvent(inEvent);
- e.relatedTarget = scope.findTarget(inEvent);
+ e.relatedTarget = scope.wrap(scope.findTarget(inEvent));
e.target = pointermap.get(this.POINTER_ID);
dispatcher.up(e);
this.cleanupMouse();
@@ -1050,9 +1056,10 @@ window.PolymerGestures = {};
var CLICK_COUNT_TIMEOUT = 200;
var HYSTERESIS = 20;
var ATTRIB = 'touch-action';
- // TODO(dfreedm): disable until http://crbug.com/399765 is resolved
- // var HAS_TOUCH_ACTION = ATTRIB in document.head.style;
- var HAS_TOUCH_ACTION = false;
+ var INSTALLER;
+ // maybe one day...
+ // var CAN_USE_GLOBAL = ATTRIB in document.head.style;
+ var CAN_USE_GLOBAL = false;
// handler block for native touch events
var touchEvents = {
@@ -1062,35 +1069,74 @@ window.PolymerGestures = {};
'touchend',
'touchcancel'
],
- exposes: [
- 'down',
- 'up',
- 'move'
- ],
- register: function(target, initial) {
- if (initial) {
- return;
+ register: function(target) {
+ if (CAN_USE_GLOBAL) {
+ dispatcher.listen(target, this.events);
+ } else {
+ INSTALLER.enableOnSubtree(target);
}
- dispatcher.listen(target, this.events);
},
unregister: function(target) {
- dispatcher.unlisten(target, this.events);
+ 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);
+ }
},
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 === st.EMITTER) {
+ if (t === 'none') {
return 'none';
} else if (t === st.XSCROLLER) {
return 'X';
} else if (t === st.YSCROLLER) {
return 'Y';
- } else {
+ } else if (st.SCROLLER.exec(t)) {
return 'XY';
}
},
@@ -1143,7 +1189,7 @@ window.PolymerGestures = {};
clientX: touch.clientX,
clientY: touch.clientY,
path: this.currentTouchEvent.path,
- target: this.currentTouchEvent.target
+ target: scope.wrap(this.currentTouchEvent.target)
};
return scope.findTarget(fastPath);
} else {
@@ -1160,7 +1206,7 @@ window.PolymerGestures = {};
// Touch identifiers can start at 0.
// Add 2 to the touch identifier for compatibility.
var id = e.pointerId = inTouch.identifier + 2;
- e.target = this.findTarget(inTouch, id);
+ e.target = scope.wrap(this.findTarget(inTouch, id));
e.bubbles = true;
e.cancelable = true;
e.detail = this.clickCount;
@@ -1202,8 +1248,7 @@ window.PolymerGestures = {};
shouldScroll: function(inEvent) {
if (this.firstXY) {
var ret;
- var touchAction = scope.targetFinding.findTouchAction(inEvent);
- var scrollAxis = this.touchActionToScrollType(touchAction);
+ var scrollAxis = scope.targetFinding.findScrollAxis(inEvent);
if (scrollAxis === 'none') {
// this element is a touch-action: none, should never scroll
ret = false;
@@ -1271,12 +1316,8 @@ window.PolymerGestures = {};
dispatcher.down(inPointer);
},
touchmove: function(inEvent) {
- 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);
- }
+ if (CAN_USE_GLOBAL) {
+ this.processTouches(inEvent, this.move);
} else {
if (!this.scrolling) {
if (this.scrolling === null && this.shouldScroll(inEvent)) {
@@ -1307,7 +1348,7 @@ window.PolymerGestures = {};
this.processTouches(inEvent, this.up);
},
up: function(inPointer) {
- inPointer.relatedTarget = scope.findTarget(inPointer);
+ inPointer.relatedTarget = scope.wrap(scope.findTarget(inPointer));
dispatcher.up(inPointer);
},
cancel: function(inPointer) {
@@ -1341,6 +1382,10 @@ window.PolymerGestures = {};
}
};
+ if (!CAN_USE_GLOBAL) {
+ INSTALLER = new scope.Installer(touchEvents.elementAdded, touchEvents.elementRemoved, touchEvents.elementChanged, touchEvents);
+ }
+
scope.touchEvents = touchEvents;
})(window.PolymerGestures);
@@ -1394,7 +1439,7 @@ window.PolymerGestures = {};
},
MSPointerDown: function(inEvent) {
var e = this.prepareEvent(inEvent);
- e.target = scope.findTarget(inEvent);
+ e.target = scope.wrap(scope.findTarget(inEvent));
pointermap.set(inEvent.pointerId, e.target);
dispatcher.down(e);
},
@@ -1405,14 +1450,14 @@ window.PolymerGestures = {};
},
MSPointerUp: function(inEvent) {
var e = this.prepareEvent(inEvent);
- e.relatedTarget = scope.findTarget(inEvent);
+ e.relatedTarget = scope.wrap(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.findTarget(inEvent);
+ e.relatedTarget = scope.wrap(scope.findTarget(inEvent));
e.target = pointermap.get(e.pointerId);
dispatcher.cancel(e);
this.cleanup(inEvent.pointerId);
@@ -1460,7 +1505,7 @@ window.PolymerGestures = {};
},
pointerdown: function(inEvent) {
var e = this.prepareEvent(inEvent);
- e.target = scope.findTarget(inEvent);
+ e.target = scope.wrap(scope.findTarget(inEvent));
pointermap.set(e.pointerId, e.target);
dispatcher.down(e);
},
@@ -1471,14 +1516,14 @@ window.PolymerGestures = {};
},
pointerup: function(inEvent) {
var e = this.prepareEvent(inEvent);
- e.relatedTarget = scope.findTarget(inEvent);
+ e.relatedTarget = scope.wrap(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.findTarget(inEvent);
+ e.relatedTarget = scope.wrap(scope.findTarget(inEvent));
e.target = pointermap.get(e.pointerId);
dispatcher.cancel(e);
this.cleanup(inEvent.pointerId);
@@ -1504,29 +1549,19 @@ window.PolymerGestures = {};
*/
(function(scope) {
var dispatcher = scope.dispatcher;
- var nav = window.navigator;
if (window.PointerEvent) {
dispatcher.registerSource('pointer', scope.pointerEvents);
- } else if (nav.msPointerEnabled) {
+ } else if (window.navigator.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, true);
+
+ dispatcher.register(document);
})(window.PolymerGestures);
/*
@@ -1644,18 +1679,6 @@ window.PolymerGestures = {};
'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;
@@ -1674,42 +1697,33 @@ window.PolymerGestures = {};
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 gestureProto = {
+ var e = eventFactory.makeGestureEvent(inType, {
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) {
@@ -1735,14 +1749,11 @@ window.PolymerGestures = {};
// start tracking only if finger moves more than WIGGLE_THRESHOLD
if (move > this.WIGGLE_THRESHOLD) {
p.tracking = true;
- p.lastMoveEvent = p.downEvent;
- this.fireTrack('trackstart', inEvent, p);
+ this.fireTrack('trackstart', p.downEvent, p);
+ this.fireTrack('track', inEvent, p);
}
- }
- if (p.tracking) {
+ } else {
this.fireTrack('track', inEvent, p);
- this.fireTrack('trackx', inEvent, p);
- this.fireTrack('tracky', inEvent, p);
}
p.lastMoveEvent = inEvent;
}
@@ -1826,11 +1837,6 @@ window.PolymerGestures = {};
'move',
'up',
],
- exposes: [
- 'hold',
- 'holdpulse',
- 'release'
- ],
heldPointer: null,
holdJob: null,
pulse: function() {
@@ -1937,9 +1943,6 @@ window.PolymerGestures = {};
'down',
'up'
],
- exposes: [
- 'tap'
- ],
down: function(inEvent) {
if (inEvent.isPrimary && !inEvent.tapPrevented) {
pointermap.set(inEvent.pointerId, {
@@ -3324,21 +3327,6 @@ window.PolymerGestures = {};
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));
@@ -3350,8 +3338,6 @@ window.PolymerGestures = {};
consequent = getFn(consequent);
alternate = getFn(alternate);
- this.dynamicDeps = true;
-
return function(model, observer, filterRegistry) {
return test(model, observer, filterRegistry) ?
consequent(model, observer, filterRegistry) :
@@ -3667,18 +3653,6 @@ window.PolymerGestures = {};
* 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
@@ -3980,13 +3954,10 @@ if (typeof window.Polymer === 'function') {
(function(scope) {
- function noopHandler(value) {
- return value;
- }
-
var typeHandlers = {
- string: noopHandler,
- 'undefined': noopHandler,
+ string: function(value) {
+ return value;
+ },
date: function(value) {
return new Date(Date.parse(value) || Date.now());
},
@@ -4127,15 +4098,13 @@ 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 === null || detail === undefined ? {} : detail;
+ var detail = 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);
@@ -4232,7 +4201,8 @@ if (typeof window.Polymer === 'function') {
// by default supports 1 thing being bound.
for (var type in events) {
var methodName = events[type];
- PolymerGestures.addEventListener(this, type, this.element.getEventHandler(this, this, methodName));
+ this.addEventListener(type, this.element.getEventHandler(this, this,
+ methodName));
}
},
// call 'method' or function method on 'obj' with 'args', if the method exists
@@ -4253,10 +4223,6 @@ if (typeof window.Polymer === 'function') {
scope.api.instance.events = events;
- // alias PolymerGestures event listener logic
- scope.addEventListener = PolymerGestures.addEventListener;
- scope.removeEventListener = PolymerGestures.removeEventListener;
-
})(Polymer);
/*
@@ -4773,7 +4739,9 @@ if (typeof window.Polymer === 'function') {
}
this.created();
this.prepareElement();
- if (!this.ownerDocument.isStagingDocument) {
+ // TODO(sorvell): replace when ShadowDOMPolyfill issue is corrected
+ // https://github.com/Polymer/ShadowDOM/issues/420
+ if (!this.ownerDocument.isStagingDocument || window.ShadowDOMPolyfill) {
this.makeElementReady();
}
},
@@ -4788,6 +4756,7 @@ 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();
@@ -4812,6 +4781,9 @@ 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();
@@ -4928,6 +4900,8 @@ 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) {
@@ -4992,8 +4966,7 @@ if (typeof window.Polymer === 'function') {
// imports
var log = window.logFlags || {};
- var hasShadowDOMPolyfill = window.ShadowDOMPolyfill;
-
+
// magic words
var STYLE_SCOPE_ATTRIBUTE = 'element';
@@ -5041,7 +5014,7 @@ if (typeof window.Polymer === 'function') {
if (!scope) {
return;
}
- if (hasShadowDOMPolyfill) {
+ if (window.ShadowDOMPolyfill) {
cssText = shimCssText(cssText, scope.host);
}
var style = this.element.cssTextToScopeStyle(cssText,
@@ -5063,7 +5036,7 @@ if (typeof window.Polymer === 'function') {
return cache[name];
},
styleCacheForScope: function(scope) {
- if (hasShadowDOMPolyfill) {
+ if (window.ShadowDOMPolyfill) {
var scopeName = scope.host ? scope.host.localName : scope.localName;
return polyfillScopeStyleCache[scopeName] || (polyfillScopeStyleCache[scopeName] = {});
} else {
@@ -5248,8 +5221,6 @@ 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';
@@ -5422,7 +5393,7 @@ scope.api.declaration.path = path;
if (scope === document) {
scope = document.head;
}
- if (hasShadowDOMPolyfill) {
+ if (window.ShadowDOMPolyfill) {
scope = document.head;
}
// TODO(sorvell): necessary for IE
@@ -5563,7 +5534,7 @@ scope.api.declaration.path = path;
return function(model, node, oneTime) {
var handler = events.getEventHandler(undefined, node, pathString);
- PolymerGestures.addEventListener(node, eventType, handler);
+ node.addEventListener(eventType, handler);
if (oneTime)
return;
@@ -5580,7 +5551,7 @@ scope.api.declaration.path = path;
open: bindingValue,
discardChanges: bindingValue,
close: function() {
- PolymerGestures.removeEventListener(node, eventType, handler);
+ node.removeEventListener(eventType, handler);
}
};
};
@@ -5671,53 +5642,40 @@ 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
//
- // `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
+ requireProperties: function(propertyDescriptors, prototype, base) {
+ // 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 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;
+ 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;
}
- // only set a value if one is specified
- if (value !== undefined) {
- prototype[n] = value;
+ if (prototype[n] === undefined) {
+ prototype[n] = this.valueForDescriptor(propertyDescriptor);
}
}
},
+ 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) {
@@ -5763,12 +5721,14 @@ 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);
}
}
+
}
};
@@ -5805,27 +5765,35 @@ scope.api.declaration.path = path;
},
publishAttributes: function(prototype, base) {
- // merge names from 'attributes' attribute into the 'publish' object
+ // merge names from 'attributes' attribute
var attributes = this.getAttribute(ATTRIBUTES_ATTRIBUTE);
if (attributes) {
- // 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 = {});
+ // get properties to publish
+ 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();
- // looks weird, but causes n to exist on `publish` if it does not;
- // a more careful test would need expensive `in` operator
+ // if the user hasn't specified a value, we want to use the
+ // default, unless a superclass has already chosen one
if (n && publish[n] === undefined) {
- 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;
+ }
}
}
}
@@ -5932,8 +5900,6 @@ scope.api.declaration.path = path;
var isBase = scope.isBase;
var extend = scope.extend;
- var hasShadowDOMPolyfill = window.ShadowDOMPolyfill;
-
// prototype api
var prototype = {
@@ -6020,7 +5986,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 (hasShadowDOMPolyfill) {
+ if (window.ShadowDOMPolyfill) {
Platform.ShadowCSS.shimStyling(this.templateContent(), name, extendee);
}
// allow custom element access to the declarative context
@@ -6290,6 +6256,9 @@ 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) {
« no previous file with comments | « pkg/polymer/lib/src/js/polymer/polymer.js ('k') | pkg/polymer/lib/src/js/polymer/polymer.concat.js.map » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698