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

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

Issue 469823002: Roll polymer to 0.3.5 (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: style nit Created 6 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View 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 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) {
« 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