| 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 0d97f534bc59706470301d6e993dc36f9d6a5dee..b9ea6b0405efb9e0286c92ff989c1817cbd88fed 100644
|
| --- a/pkg/polymer/lib/src/js/polymer/polymer.concat.js
|
| +++ b/pkg/polymer/lib/src/js/polymer/polymer.concat.js
|
| @@ -107,7 +107,7 @@ window.PolymerGestures = {};
|
| return s;
|
| },
|
| findTarget: function(inEvent) {
|
| - if (HAS_FULL_PATH && inEvent.path) {
|
| + if (HAS_FULL_PATH && inEvent.path && inEvent.path.length) {
|
| return inEvent.path[0];
|
| }
|
| var x = inEvent.clientX, y = inEvent.clientY;
|
| @@ -121,7 +121,7 @@ window.PolymerGestures = {};
|
| },
|
| findTouchAction: function(inEvent) {
|
| var n;
|
| - if (HAS_FULL_PATH && inEvent.path) {
|
| + if (HAS_FULL_PATH && inEvent.path && inEvent.path.length) {
|
| var path = inEvent.path;
|
| for (var i = 0; i < path.length; i++) {
|
| n = path[i];
|
| @@ -132,7 +132,7 @@ window.PolymerGestures = {};
|
| } else {
|
| n = inEvent.target;
|
| while(n) {
|
| - if (n.hasAttribute('touch-action')) {
|
| + if (n.nodeType === Node.ELEMENT_NODE && n.hasAttribute('touch-action')) {
|
| return n.getAttribute('touch-action');
|
| }
|
| n = n.parentNode || n.host;
|
| @@ -197,6 +197,20 @@ window.PolymerGestures = {};
|
| insideNode: function(node, x, y) {
|
| var rect = node.getBoundingClientRect();
|
| return (rect.left <= x) && (x <= rect.right) && (rect.top <= y) && (y <= rect.bottom);
|
| + },
|
| + path: function(event) {
|
| + var p;
|
| + if (HAS_FULL_PATH && event.path && event.path.length) {
|
| + p = event.path;
|
| + } else {
|
| + p = [];
|
| + var n = this.findTarget(event);
|
| + while (n) {
|
| + p.push(n);
|
| + n = n.parentNode || n.host;
|
| + }
|
| + }
|
| + return p;
|
| }
|
| };
|
| scope.targetFinding = target;
|
| @@ -607,6 +621,7 @@ window.PolymerGestures = {};
|
| * - pointercancel: a pointer will no longer generate events
|
| */
|
| var dispatcher = {
|
| + IS_IOS: false,
|
| pointermap: new scope.PointerMap(),
|
| requiredGestures: new scope.PointerMap(),
|
| eventMap: Object.create(null),
|
| @@ -686,6 +701,23 @@ window.PolymerGestures = {};
|
| this.fireEvent('up', inEvent);
|
| this.requiredGestures.delete(inEvent.pointerId);
|
| },
|
| + addGestureDependency: function(node, currentGestures) {
|
| + var gesturesWanted = node._pgEvents;
|
| + if (gesturesWanted) {
|
| + var gk = Object.keys(gesturesWanted);
|
| + for (var i = 0, r, ri, g; i < gk.length; i++) {
|
| + // gesture
|
| + g = gk[i];
|
| + if (gesturesWanted[g] > 0) {
|
| + // lookup gesture recognizer
|
| + r = this.dependencyMap[g];
|
| + // recognizer index
|
| + ri = r ? r.index : -1;
|
| + currentGestures[ri] = true;
|
| + }
|
| + }
|
| + }
|
| + },
|
| // LISTENER LOGIC
|
| eventHandler: function(inEvent) {
|
| // This is used to prevent multiple dispatch of events from
|
| @@ -699,21 +731,15 @@ window.PolymerGestures = {};
|
| if (!inEvent._handledByPG) {
|
| currentGestures = {};
|
| }
|
| - // map gesture names to ordered set of recognizers
|
| - var gesturesWanted = inEvent.currentTarget._pgEvents;
|
| - if (gesturesWanted) {
|
| - var gk = Object.keys(gesturesWanted);
|
| - for (var i = 0, r, ri, g; i < gk.length; i++) {
|
| - // gesture
|
| - g = gk[i];
|
| - if (gesturesWanted[g] > 0) {
|
| - // lookup gesture recognizer
|
| - r = this.dependencyMap[g];
|
| - // recognizer index
|
| - ri = r ? r.index : -1;
|
| - currentGestures[ri] = true;
|
| - }
|
| + // in IOS mode, there is only a listener on the document, so this is not re-entrant
|
| + if (this.IS_IOS) {
|
| + var nodes = scope.targetFinding.path(inEvent);
|
| + for (var i = 0, n; i < nodes.length; i++) {
|
| + n = nodes[i];
|
| + this.addGestureDependency(n, currentGestures);
|
| }
|
| + } else {
|
| + this.addGestureDependency(inEvent.currentTarget, currentGestures);
|
| }
|
| }
|
|
|
| @@ -988,6 +1014,9 @@ window.PolymerGestures = {};
|
| dispatcher.listen(target, this.events);
|
| },
|
| unregister: function(target) {
|
| + if (target === document) {
|
| + return;
|
| + }
|
| dispatcher.unlisten(target, this.events);
|
| },
|
| lastTouches: [],
|
| @@ -1086,6 +1115,7 @@ window.PolymerGestures = {};
|
|
|
| // handler block for native touch events
|
| var touchEvents = {
|
| + IS_IOS: false,
|
| events: [
|
| 'touchstart',
|
| 'touchmove',
|
| @@ -1098,13 +1128,14 @@ window.PolymerGestures = {};
|
| 'move'
|
| ],
|
| register: function(target, initial) {
|
| - if (initial) {
|
| - return;
|
| + if (this.IS_IOS ? initial : !initial) {
|
| + dispatcher.listen(target, this.events);
|
| }
|
| - dispatcher.listen(target, this.events);
|
| },
|
| unregister: function(target) {
|
| - dispatcher.unlisten(target, this.events);
|
| + if (!this.IS_IOS) {
|
| + dispatcher.unlisten(target, this.events);
|
| + }
|
| },
|
| scrollTypes: {
|
| EMITTER: 'none',
|
| @@ -1398,6 +1429,9 @@ window.PolymerGestures = {};
|
| dispatcher.listen(target, this.events);
|
| },
|
| unregister: function(target) {
|
| + if (target === document) {
|
| + return;
|
| + }
|
| dispatcher.unlisten(target, this.events);
|
| },
|
| POINTER_TYPES: [
|
| @@ -1480,6 +1514,9 @@ window.PolymerGestures = {};
|
| dispatcher.listen(target, this.events);
|
| },
|
| unregister: function(target) {
|
| + if (target === document) {
|
| + return;
|
| + }
|
| dispatcher.unlisten(target, this.events);
|
| },
|
| cleanup: function(id) {
|
| @@ -1533,6 +1570,7 @@ window.PolymerGestures = {};
|
| * Included are touch events (v1), mouse events, and MSPointerEvents.
|
| */
|
| (function(scope) {
|
| +
|
| var dispatcher = scope.dispatcher;
|
| var nav = window.navigator;
|
|
|
| @@ -1544,18 +1582,16 @@ window.PolymerGestures = {};
|
| 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(){});
|
| - }
|
| }
|
| }
|
| +
|
| + // Work around iOS bugs https://bugs.webkit.org/show_bug.cgi?id=135628 and https://bugs.webkit.org/show_bug.cgi?id=136506
|
| + var ua = navigator.userAgent;
|
| + var IS_IOS = ua.match(/iPad|iPhone|iPod/) && 'ontouchstart' in window;
|
| +
|
| + dispatcher.IS_IOS = IS_IOS;
|
| + scope.touchEvents.IS_IOS = IS_IOS;
|
| +
|
| dispatcher.register(document, true);
|
| })(window.PolymerGestures);
|
|
|
| @@ -3698,7 +3734,7 @@ window.PolymerGestures = {};
|
| * subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
|
| */
|
| Polymer = {
|
| - version: '0.4.0-d66a86e'
|
| + version: '0.4.1-d61654b'
|
| };
|
|
|
| /*
|
| @@ -3881,8 +3917,14 @@ function watchImportsLoad(callback, doc) {
|
|
|
| // NOTE: test for native imports loading is based on explicitly watching
|
| // all imports (see below).
|
| +// We cannot rely on this entirely without watching the entire document
|
| +// for import links. For perf reasons, currently only head is watched.
|
| +// Instead, we fallback to checking if the import property is available
|
| +// and the document is not itself loading.
|
| function isImportLoaded(link) {
|
| - return useNative ? link.__loaded : link.__importParsed;
|
| + return useNative ? link.__loaded ||
|
| + (link.import && link.import.readyState !== 'loading') :
|
| + link.__importParsed;
|
| }
|
|
|
| // TODO(sorvell): Workaround for
|
| @@ -4053,19 +4095,14 @@ scope.whenImportsReady = whenImportsReady;
|
|
|
| })(Platform);
|
|
|
| -// Copyright 2012 Google Inc.
|
| -//
|
| -// Licensed under the Apache License, Version 2.0 (the "License");
|
| -// you may not use this file except in compliance with the License.
|
| -// You may obtain a copy of the License at
|
| -//
|
| -// http://www.apache.org/licenses/LICENSE-2.0
|
| -//
|
| -// Unless required by applicable law or agreed to in writing, software
|
| -// distributed under the License is distributed on an "AS IS" BASIS,
|
| -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
| -// See the License for the specific language governing permissions and
|
| -// limitations under the License.
|
| +/*
|
| + * 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
|
| + */
|
|
|
| (function(global) {
|
| 'use strict';
|
| @@ -4125,7 +4162,7 @@ scope.whenImportsReady = whenImportsReady;
|
| // Firefox OS Apps do not allow eval. This feature detection is very hacky
|
| // but even if some other platform adds support for this function this code
|
| // will continue to work.
|
| - if (navigator.getDeviceStorage) {
|
| + if (typeof navigator != 'undefined' && navigator.getDeviceStorage) {
|
| return false;
|
| }
|
|
|
| @@ -4140,7 +4177,7 @@ scope.whenImportsReady = whenImportsReady;
|
| var hasEval = detectEval();
|
|
|
| function isIndex(s) {
|
| - return +s === s >>> 0;
|
| + return +s === s >>> 0 && s !== '';
|
| }
|
|
|
| function toNumber(s) {
|
| @@ -4854,26 +4891,12 @@ scope.whenImportsReady = whenImportsReady;
|
|
|
| var runningMicrotaskCheckpoint = false;
|
|
|
| - var hasDebugForceFullDelivery = hasObserve && hasEval && (function() {
|
| - try {
|
| - eval('%RunMicrotasks()');
|
| - return true;
|
| - } catch (ex) {
|
| - return false;
|
| - }
|
| - })();
|
| -
|
| global.Platform = global.Platform || {};
|
|
|
| global.Platform.performMicrotaskCheckpoint = function() {
|
| if (runningMicrotaskCheckpoint)
|
| return;
|
|
|
| - if (hasDebugForceFullDelivery) {
|
| - eval('%RunMicrotasks()');
|
| - return;
|
| - }
|
| -
|
| if (!collectObservers)
|
| return;
|
|
|
| @@ -8481,8 +8504,12 @@ scope.styleResolver = styleResolver;
|
| scope.api.instance.events = events;
|
|
|
| // alias PolymerGestures event listener logic
|
| - scope.addEventListener = PolymerGestures.addEventListener;
|
| - scope.removeEventListener = PolymerGestures.removeEventListener;
|
| + scope.addEventListener = function(node, eventType, handlerFn, capture) {
|
| + PolymerGestures.addEventListener(wrap(node), eventType, handlerFn, capture);
|
| + };
|
| + scope.removeEventListener = function(node, eventType, handlerFn, capture) {
|
| + PolymerGestures.removeEventListener(wrap(node), eventType, handlerFn, capture);
|
| + };
|
|
|
| })(Polymer);
|
|
|
| @@ -8734,15 +8761,27 @@ scope.styleResolver = styleResolver;
|
| bindToAccessor: function(name, observable, resolveFn) {
|
| var privateName = name + '_';
|
| var privateObservable = name + 'Observable_';
|
| + // Present for properties which are computed and published and have a
|
| + // bound value.
|
| + var privateComputedBoundValue = name + 'ComputedBoundObservable_';
|
|
|
| this[privateObservable] = observable;
|
| +
|
| var oldValue = this[privateName];
|
|
|
| var self = this;
|
| - var value = observable.open(function(value, oldValue) {
|
| + function updateValue(value, oldValue) {
|
| self[privateName] = value;
|
| +
|
| + var setObserveable = self[privateComputedBoundValue];
|
| + if (setObserveable && typeof setObserveable.setValue == 'function') {
|
| + setObserveable.setValue(value);
|
| + }
|
| +
|
| self.emitPropertyChangeRecord(name, value, oldValue);
|
| - });
|
| + }
|
| +
|
| + var value = observable.open(updateValue);
|
|
|
| if (resolveFn && !areSameValue(oldValue, value)) {
|
| var resolvedValue = resolveFn(oldValue, value);
|
| @@ -8753,13 +8792,13 @@ scope.styleResolver = styleResolver;
|
| }
|
| }
|
|
|
| - this[privateName] = value;
|
| - this.emitPropertyChangeRecord(name, value, oldValue);
|
| + updateValue(value, oldValue);
|
|
|
| var observer = {
|
| close: function() {
|
| observable.close();
|
| self[privateObservable] = undefined;
|
| + self[privateComputedBoundValue] = undefined;
|
| }
|
| };
|
| this.registerObserver(observer);
|
| @@ -8787,6 +8826,17 @@ scope.styleResolver = styleResolver;
|
| this[property] = observable;
|
| return;
|
| }
|
| + var computed = this.element.prototype.computed;
|
| +
|
| + // Binding an "out-only" value to a computed property. Note that
|
| + // since this observer isn't opened, it doesn't need to be closed on
|
| + // cleanup.
|
| + if (computed && computed[property]) {
|
| + var privateComputedBoundValue = property + 'ComputedBoundObservable_';
|
| + this[privateComputedBoundValue] = observable;
|
| + return;
|
| + }
|
| +
|
| return this.bindToAccessor(property, observable, resolveBindingValue);
|
| },
|
| invokeMethod: function(method, args) {
|
| @@ -9398,10 +9448,26 @@ scope.styleResolver = styleResolver;
|
| return prototypesByName[name];
|
| }
|
|
|
| + function instanceOfType(element, type) {
|
| + if (typeof type !== 'string') {
|
| + return false;
|
| + }
|
| + var proto = HTMLElement.getPrototypeForTag(type);
|
| + var ctor = proto && proto.constructor;
|
| + if (!ctor) {
|
| + return false;
|
| + }
|
| + if (CustomElements.instanceof) {
|
| + return CustomElements.instanceof(element, ctor);
|
| + }
|
| + return element instanceof ctor;
|
| + }
|
| +
|
| // exports
|
|
|
| scope.getRegisteredPrototype = getRegisteredPrototype;
|
| scope.waitingForPrototype = waitingForPrototype;
|
| + scope.instanceOfType = instanceOfType;
|
|
|
| // namespace shenanigans so we can expose our scope on the registration
|
| // function
|
| @@ -9957,7 +10023,7 @@ scope.api.declaration.path = path;
|
| }
|
| return map;
|
| },
|
| - createPropertyAccessor: function(name) {
|
| + createPropertyAccessor: function(name, ignoreWrites) {
|
| var proto = this.prototype;
|
|
|
| var privateName = name + '_';
|
| @@ -9973,6 +10039,10 @@ scope.api.declaration.path = path;
|
| return this[privateName];
|
| },
|
| set: function(value) {
|
| + if (ignoreWrites) {
|
| + return this[privateName];
|
| + }
|
| +
|
| var observable = this[privateObservable];
|
| if (observable) {
|
| observable.setValue(value);
|
| @@ -9989,16 +10059,20 @@ scope.api.declaration.path = path;
|
| });
|
| },
|
| createPropertyAccessors: function(prototype) {
|
| - var n$ = prototype._publishNames;
|
| + 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);
|
| + this.createPropertyAccessor(n, true);
|
| }
|
| }
|
| - var n$ = prototype._computedNames;
|
| + var n$ = prototype._publishNames;
|
| if (n$ && n$.length) {
|
| for (var i=0, l=n$.length, n, fn; (i<l) && (n=n$[i]); i++) {
|
| - this.createPropertyAccessor(n);
|
| + // If the property is computed and published, the accessor is created
|
| + // above.
|
| + if (!prototype.computed || !prototype.computed[n]) {
|
| + this.createPropertyAccessor(n);
|
| + }
|
| }
|
| }
|
| }
|
| @@ -10565,6 +10639,21 @@ scope.api.declaration.path = path;
|
| }
|
| }
|
| },
|
| +
|
| + /**
|
| + Returns a list of elements that have had polymer-elements created but
|
| + are not yet ready to register. The list is an array of element definitions.
|
| + */
|
| + waitingFor: function() {
|
| + var e$ = [];
|
| + for (var i=0, l=elements.length, e; (i<l) &&
|
| + (e=elements[i]); i++) {
|
| + if (e.__queue && !e.__queue.flushable) {
|
| + e$.push(e);
|
| + }
|
| + }
|
| + return e$;
|
| + },
|
|
|
| waitToReady: true
|
|
|
| @@ -10586,15 +10675,37 @@ scope.api.declaration.path = path;
|
|
|
| function whenReady(callback) {
|
| queue.waitToReady = true;
|
| - HTMLImports.whenImportsReady(function() {
|
| - queue.addReadyCallback(callback);
|
| - queue.waitToReady = false;
|
| - queue.check();
|
| + Platform.endOfMicrotask(function() {
|
| + HTMLImports.whenImportsReady(function() {
|
| + queue.addReadyCallback(callback);
|
| + queue.waitToReady = false;
|
| + queue.check();
|
| + });
|
| + });
|
| + }
|
| +
|
| + /**
|
| + Forces polymer to register any pending elements. Can be used to abort
|
| + waiting for elements that are partially defined.
|
| + @param timeout {Integer} Optional timeout in milliseconds
|
| + */
|
| + function forceReady(timeout) {
|
| + if (timeout === undefined) {
|
| + queue.ready();
|
| + return;
|
| + }
|
| + var handle = setTimeout(function() {
|
| + queue.ready();
|
| + }, timeout);
|
| + Polymer.whenReady(function() {
|
| + clearTimeout(handle);
|
| });
|
| }
|
|
|
| // exports
|
| scope.elements = elements;
|
| + scope.waitingFor = queue.waitingFor.bind(queue);
|
| + scope.forceReady = forceReady;
|
| scope.queue = queue;
|
| scope.whenReady = scope.whenPolymerReady = whenReady;
|
| })(Polymer);
|
|
|