| Index: chrome/browser/resources/md_downloads/crisper.js
|
| diff --git a/chrome/browser/resources/md_downloads/crisper.js b/chrome/browser/resources/md_downloads/crisper.js
|
| index 49ea6974f7a2836f59d20dad47cf5299136340f7..0c58ef74c1549000c61eb61302eb53ce0c2f335f 100644
|
| --- a/chrome/browser/resources/md_downloads/crisper.js
|
| +++ b/chrome/browser/resources/md_downloads/crisper.js
|
| @@ -1465,12 +1465,15 @@ function elide(original, maxLength) {
|
| * @return {T} A non-null |condition|.
|
| */
|
| function assert(condition, opt_message) {
|
| - 'use strict';
|
| if (!condition) {
|
| - var msg = 'Assertion failed';
|
| + var message = 'Assertion failed';
|
| if (opt_message)
|
| - msg = msg + ': ' + opt_message;
|
| - throw new Error(msg);
|
| + message = message + ': ' + opt_message;
|
| + var error = new Error(message);
|
| + var global = function() { return this; }();
|
| + if (global.traceAssertionsForTesting)
|
| + console.warn(error.stack);
|
| + throw error;
|
| }
|
| return condition;
|
| }
|
| @@ -1497,7 +1500,7 @@ function assert(condition, opt_message) {
|
| * @param {string=} opt_message A message to show when this is hit.
|
| */
|
| function assertNotReached(opt_message) {
|
| - throw new Error(opt_message || 'Unreachable code hit');
|
| + assert(false, opt_message || 'Unreachable code hit');
|
| }
|
|
|
| /**
|
| @@ -1508,10 +1511,8 @@ function assertNotReached(opt_message) {
|
| * @template T
|
| */
|
| function assertInstanceof(value, type, opt_message) {
|
| - if (!(value instanceof type)) {
|
| - throw new Error(opt_message ||
|
| - value + ' is not a[n] ' + (type.name || typeof type));
|
| - }
|
| + assert(value instanceof type,
|
| + opt_message || value + ' is not a[n] ' + (type.name || typeof type));
|
| return value;
|
| };
|
| // Copyright 2015 The Chromium Authors. All rights reserved.
|
| @@ -1561,7 +1562,7 @@ cr.define('downloads', function() {
|
| * (i.e. has a non-empty search term).
|
| */
|
| isSearching: function() {
|
| - return this.searchText_.length > 0;
|
| + return (this.searchText_ || '').length > 0;
|
| },
|
|
|
| /** Opens the current local destination for downloads. */
|
| @@ -1594,9 +1595,16 @@ cr.define('downloads', function() {
|
|
|
| this.searchText_ = searchText;
|
|
|
| - // Split quoted terms (e.g., 'The "lazy" dog' => ['The', 'lazy', 'dog']).
|
| + /**
|
| + * @param {string} s
|
| + * @return {string} |s| without whitespace at the ends (trimmed).
|
| + */
|
| function trim(s) { return s.trim(); }
|
| - chrome.send('getDownloads', searchText.split(/"([^"]*)"/).map(trim));
|
| +
|
| + // Split quoted terms (e.g., 'The "lazy" dog' => ['The', 'lazy', 'dog']).
|
| + var terms = searchText ? searchText.split(/"([^"]*)"/).map(trim) : [];
|
| +
|
| + chrome.send('getDownloads', terms);
|
| },
|
|
|
| /**
|
| @@ -2045,7 +2053,7 @@ document.registerElement('dom-module', DomModule);
|
| function forceDocumentUpgrade() {
|
| if (cePolyfill) {
|
| var script = document._currentScript || document.currentScript;
|
| -var doc = script && script.ownerDocument;
|
| +var doc = script && script.ownerDocument || document;
|
| if (doc) {
|
| CustomElements.upgradeAll(doc);
|
| }
|
| @@ -2357,7 +2365,7 @@ debouncer.stop();
|
| }
|
| }
|
| });
|
| -Polymer.version = '1.1.5';
|
| +Polymer.version = '1.2.1';
|
| Polymer.Base._addFeature({
|
| _registerFeatures: function () {
|
| this._prepIs();
|
| @@ -2638,61 +2646,6 @@ return currentValue === previousValue;
|
| };
|
| return new ArraySplice();
|
| }();
|
| -Polymer.EventApi = function () {
|
| -var Settings = Polymer.Settings;
|
| -var EventApi = function (event) {
|
| -this.event = event;
|
| -};
|
| -if (Settings.useShadow) {
|
| -EventApi.prototype = {
|
| -get rootTarget() {
|
| -return this.event.path[0];
|
| -},
|
| -get localTarget() {
|
| -return this.event.target;
|
| -},
|
| -get path() {
|
| -return this.event.path;
|
| -}
|
| -};
|
| -} else {
|
| -EventApi.prototype = {
|
| -get rootTarget() {
|
| -return this.event.target;
|
| -},
|
| -get localTarget() {
|
| -var current = this.event.currentTarget;
|
| -var currentRoot = current && Polymer.dom(current).getOwnerRoot();
|
| -var p$ = this.path;
|
| -for (var i = 0; i < p$.length; i++) {
|
| -if (Polymer.dom(p$[i]).getOwnerRoot() === currentRoot) {
|
| -return p$[i];
|
| -}
|
| -}
|
| -},
|
| -get path() {
|
| -if (!this.event._path) {
|
| -var path = [];
|
| -var o = this.rootTarget;
|
| -while (o) {
|
| -path.push(o);
|
| -o = Polymer.dom(o).parentNode || o.host;
|
| -}
|
| -path.push(window);
|
| -this.event._path = path;
|
| -}
|
| -return this.event._path;
|
| -}
|
| -};
|
| -}
|
| -var factory = function (event) {
|
| -if (!event.__eventApi) {
|
| -event.__eventApi = new EventApi(event);
|
| -}
|
| -return event.__eventApi;
|
| -};
|
| -return { factory: factory };
|
| -}();
|
| Polymer.domInnerHTML = function () {
|
| var escapeAttrRegExp = /[&\u00A0"]/g;
|
| var escapeDataRegExp = /[&\u00A0<>]/g;
|
| @@ -2818,6 +2771,17 @@ DomApi.prototype = {
|
| flush: function () {
|
| Polymer.dom.flush();
|
| },
|
| +deepContains: function (node) {
|
| +if (this.node.contains(node)) {
|
| +return true;
|
| +}
|
| +var n = node;
|
| +var wrappedDocument = wrap(document);
|
| +while (n && n !== wrappedDocument && n !== this.node) {
|
| +n = Polymer.dom(n).parentNode || n.host;
|
| +}
|
| +return n === this.node;
|
| +},
|
| _lazyDistribute: function (host) {
|
| if (host.shadyRoot && host.shadyRoot._distributionClean) {
|
| host.shadyRoot._distributionClean = false;
|
| @@ -2831,7 +2795,7 @@ insertBefore: function (node, ref_node) {
|
| return this._addNode(node, ref_node);
|
| },
|
| _addNode: function (node, ref_node) {
|
| -this._removeNodeFromHost(node, true);
|
| +this._removeNodeFromParent(node);
|
| var addedInsertionPoint;
|
| var root = this.getOwnerRoot();
|
| if (root) {
|
| @@ -2863,6 +2827,7 @@ nativeAppendChild.call(container, node);
|
| if (addedInsertionPoint) {
|
| this._updateInsertionPoints(root.host);
|
| }
|
| +this.notifyObserver();
|
| return node;
|
| },
|
| removeChild: function (node) {
|
| @@ -2877,6 +2842,7 @@ removeFromComposedParent(container, node);
|
| nativeRemoveChild.call(container, node);
|
| }
|
| }
|
| +this.notifyObserver();
|
| return node;
|
| },
|
| replaceChild: function (node, ref_node) {
|
| @@ -2969,6 +2935,13 @@ return Boolean(node._lightChildren !== undefined);
|
| _parentNeedsDistribution: function (parent) {
|
| return parent && parent.shadyRoot && hasInsertionPoint(parent.shadyRoot);
|
| },
|
| +_removeNodeFromParent: function (node) {
|
| +var parent = node._lightParent || node.parentNode;
|
| +if (parent && hasDomApi(parent)) {
|
| +factory(parent).notifyObserver();
|
| +}
|
| +this._removeNodeFromHost(node, true);
|
| +},
|
| _removeNodeFromHost: function (node, ensureComposedRemoval) {
|
| var hostNeedsDist;
|
| var root;
|
| @@ -2980,7 +2953,7 @@ if (root) {
|
| root.host._elementRemove(node);
|
| hostNeedsDist = this._removeDistributedChildren(root, node);
|
| }
|
| -this._removeLogicalInfo(node, node._lightParent);
|
| +this._removeLogicalInfo(node, parent);
|
| }
|
| this._removeOwnerShadyRoot(node);
|
| if (root && hostNeedsDist) {
|
| @@ -3099,24 +3072,29 @@ getDistributedNodes: function () {
|
| return this.node._distributedNodes || [];
|
| },
|
| queryDistributedElements: function (selector) {
|
| -var c$ = this.childNodes;
|
| +var c$ = this.getEffectiveChildNodes();
|
| var list = [];
|
| -this._distributedFilter(selector, c$, list);
|
| for (var i = 0, l = c$.length, c; i < l && (c = c$[i]); i++) {
|
| -if (c.localName === CONTENT) {
|
| -this._distributedFilter(selector, factory(c).getDistributedNodes(), list);
|
| +if (c.nodeType === Node.ELEMENT_NODE && matchesSelector.call(c, selector)) {
|
| +list.push(c);
|
| }
|
| }
|
| return list;
|
| },
|
| -_distributedFilter: function (selector, list, results) {
|
| -results = results || [];
|
| -for (var i = 0, l = list.length, d; i < l && (d = list[i]); i++) {
|
| -if (d.nodeType === Node.ELEMENT_NODE && d.localName !== CONTENT && matchesSelector.call(d, selector)) {
|
| -results.push(d);
|
| +getEffectiveChildNodes: function () {
|
| +var list = [];
|
| +var c$ = this.childNodes;
|
| +for (var i = 0, l = c$.length, c; i < l && (c = c$[i]); i++) {
|
| +if (c.localName === CONTENT) {
|
| +var d$ = factory(c).getDistributedNodes();
|
| +for (var j = 0; j < d$.length; j++) {
|
| +list.push(d$[j]);
|
| +}
|
| +} else {
|
| +list.push(c);
|
| }
|
| }
|
| -return results;
|
| +return list;
|
| },
|
| _clear: function () {
|
| while (this.childNodes.length) {
|
| @@ -3160,36 +3138,24 @@ d.appendChild(nc);
|
| }
|
| }
|
| return n;
|
| +},
|
| +observeNodes: function (callback) {
|
| +if (callback) {
|
| +if (!this.observer) {
|
| +this.observer = this.node.localName === CONTENT ? new DomApi.DistributedNodesObserver(this) : new DomApi.EffectiveNodesObserver(this);
|
| }
|
| -};
|
| -Object.defineProperty(DomApi.prototype, 'classList', {
|
| -get: function () {
|
| -if (!this._classList) {
|
| -this._classList = new DomApi.ClassList(this);
|
| +return this.observer.addListener(callback);
|
| }
|
| -return this._classList;
|
| },
|
| -configurable: true
|
| -});
|
| -DomApi.ClassList = function (host) {
|
| -this.domApi = host;
|
| -this.node = host.node;
|
| -};
|
| -DomApi.ClassList.prototype = {
|
| -add: function () {
|
| -this.node.classList.add.apply(this.node.classList, arguments);
|
| -this.domApi._distributeParent();
|
| -},
|
| -remove: function () {
|
| -this.node.classList.remove.apply(this.node.classList, arguments);
|
| -this.domApi._distributeParent();
|
| -},
|
| -toggle: function () {
|
| -this.node.classList.toggle.apply(this.node.classList, arguments);
|
| -this.domApi._distributeParent();
|
| +unobserveNodes: function (handle) {
|
| +if (this.observer) {
|
| +this.observer.removeListener(handle);
|
| +}
|
| },
|
| -contains: function () {
|
| -return this.node.classList.contains.apply(this.node.classList, arguments);
|
| +notifyObserver: function () {
|
| +if (this.observer) {
|
| +this.observer.notify();
|
| +}
|
| }
|
| };
|
| if (!Settings.useShadow) {
|
| @@ -3371,6 +3337,17 @@ return n$ ? Array.prototype.slice.call(n$) : [];
|
| };
|
| DomApi.prototype._distributeParent = function () {
|
| };
|
| +var nativeForwards = [
|
| +'appendChild',
|
| +'insertBefore',
|
| +'removeChild',
|
| +'replaceChild'
|
| +];
|
| +nativeForwards.forEach(function (forward) {
|
| +DomApi.prototype[forward] = function () {
|
| +return this.node[forward].apply(this.node, arguments);
|
| +};
|
| +});
|
| Object.defineProperties(DomApi.prototype, {
|
| childNodes: {
|
| get: function () {
|
| @@ -3424,13 +3401,17 @@ configurable: true
|
| });
|
| }
|
| var CONTENT = 'content';
|
| -var factory = function (node, patch) {
|
| +function factory(node, patch) {
|
| node = node || document;
|
| if (!node.__domApi) {
|
| node.__domApi = new DomApi(node, patch);
|
| }
|
| return node.__domApi;
|
| -};
|
| +}
|
| +;
|
| +function hasDomApi(node) {
|
| +return Boolean(node.__domApi);
|
| +}
|
| Polymer.dom = function (obj, patch) {
|
| if (obj instanceof Event) {
|
| return Polymer.EventApi.factory(obj);
|
| @@ -3438,43 +3419,6 @@ return Polymer.EventApi.factory(obj);
|
| return factory(obj, patch);
|
| }
|
| };
|
| -Polymer.Base.extend(Polymer.dom, {
|
| -_flushGuard: 0,
|
| -_FLUSH_MAX: 100,
|
| -_needsTakeRecords: !Polymer.Settings.useNativeCustomElements,
|
| -_debouncers: [],
|
| -_finishDebouncer: null,
|
| -flush: function () {
|
| -for (var i = 0; i < this._debouncers.length; i++) {
|
| -this._debouncers[i].complete();
|
| -}
|
| -if (this._finishDebouncer) {
|
| -this._finishDebouncer.complete();
|
| -}
|
| -this._flushPolyfills();
|
| -if (this._debouncers.length && this._flushGuard < this._FLUSH_MAX) {
|
| -this._flushGuard++;
|
| -this.flush();
|
| -} else {
|
| -if (this._flushGuard >= this._FLUSH_MAX) {
|
| -console.warn('Polymer.dom.flush aborted. Flush may not be complete.');
|
| -}
|
| -this._flushGuard = 0;
|
| -}
|
| -},
|
| -_flushPolyfills: function () {
|
| -if (this._needsTakeRecords) {
|
| -CustomElements.takeRecords();
|
| -}
|
| -},
|
| -addDebouncer: function (debouncer) {
|
| -this._debouncers.push(debouncer);
|
| -this._finishDebouncer = Polymer.Debounce(this._finishDebouncer, this._finishFlush);
|
| -},
|
| -_finishFlush: function () {
|
| -Polymer.dom._debouncers = [];
|
| -}
|
| -});
|
| function getLightChildren(node) {
|
| var children = node._lightChildren;
|
| return children ? children : node.childNodes;
|
| @@ -3538,10 +3482,399 @@ saveLightChildrenIfNeeded: saveLightChildrenIfNeeded,
|
| matchesSelector: matchesSelector,
|
| hasInsertionPoint: hasInsertionPoint,
|
| ctor: DomApi,
|
| -factory: factory
|
| +factory: factory,
|
| +hasDomApi: hasDomApi
|
| };
|
| }();
|
| +Polymer.Base.extend(Polymer.dom, {
|
| +_flushGuard: 0,
|
| +_FLUSH_MAX: 100,
|
| +_needsTakeRecords: !Polymer.Settings.useNativeCustomElements,
|
| +_debouncers: [],
|
| +_staticFlushList: [],
|
| +_finishDebouncer: null,
|
| +flush: function () {
|
| +this._flushGuard = 0;
|
| +this._prepareFlush();
|
| +while (this._debouncers.length && this._flushGuard < this._FLUSH_MAX) {
|
| +for (var i = 0; i < this._debouncers.length; i++) {
|
| +this._debouncers[i].complete();
|
| +}
|
| +if (this._finishDebouncer) {
|
| +this._finishDebouncer.complete();
|
| +}
|
| +this._prepareFlush();
|
| +this._flushGuard++;
|
| +}
|
| +if (this._flushGuard >= this._FLUSH_MAX) {
|
| +console.warn('Polymer.dom.flush aborted. Flush may not be complete.');
|
| +}
|
| +},
|
| +_prepareFlush: function () {
|
| +if (this._needsTakeRecords) {
|
| +CustomElements.takeRecords();
|
| +}
|
| +for (var i = 0; i < this._staticFlushList.length; i++) {
|
| +this._staticFlushList[i]();
|
| +}
|
| +},
|
| +addStaticFlush: function (fn) {
|
| +this._staticFlushList.push(fn);
|
| +},
|
| +removeStaticFlush: function (fn) {
|
| +var i = this._staticFlushList.indexOf(fn);
|
| +if (i >= 0) {
|
| +this._staticFlushList.splice(i, 1);
|
| +}
|
| +},
|
| +addDebouncer: function (debouncer) {
|
| +this._debouncers.push(debouncer);
|
| +this._finishDebouncer = Polymer.Debounce(this._finishDebouncer, this._finishFlush);
|
| +},
|
| +_finishFlush: function () {
|
| +Polymer.dom._debouncers = [];
|
| +}
|
| +});
|
| +Polymer.EventApi = function () {
|
| +'use strict';
|
| +var DomApi = Polymer.DomApi.ctor;
|
| +var Settings = Polymer.Settings;
|
| +DomApi.Event = function (event) {
|
| +this.event = event;
|
| +};
|
| +if (Settings.useShadow) {
|
| +DomApi.Event.prototype = {
|
| +get rootTarget() {
|
| +return this.event.path[0];
|
| +},
|
| +get localTarget() {
|
| +return this.event.target;
|
| +},
|
| +get path() {
|
| +return this.event.path;
|
| +}
|
| +};
|
| +} else {
|
| +DomApi.Event.prototype = {
|
| +get rootTarget() {
|
| +return this.event.target;
|
| +},
|
| +get localTarget() {
|
| +var current = this.event.currentTarget;
|
| +var currentRoot = current && Polymer.dom(current).getOwnerRoot();
|
| +var p$ = this.path;
|
| +for (var i = 0; i < p$.length; i++) {
|
| +if (Polymer.dom(p$[i]).getOwnerRoot() === currentRoot) {
|
| +return p$[i];
|
| +}
|
| +}
|
| +},
|
| +get path() {
|
| +if (!this.event._path) {
|
| +var path = [];
|
| +var o = this.rootTarget;
|
| +while (o) {
|
| +path.push(o);
|
| +o = Polymer.dom(o).parentNode || o.host;
|
| +}
|
| +path.push(window);
|
| +this.event._path = path;
|
| +}
|
| +return this.event._path;
|
| +}
|
| +};
|
| +}
|
| +var factory = function (event) {
|
| +if (!event.__eventApi) {
|
| +event.__eventApi = new DomApi.Event(event);
|
| +}
|
| +return event.__eventApi;
|
| +};
|
| +return { factory: factory };
|
| +}();
|
| +(function () {
|
| +'use strict';
|
| +var DomApi = Polymer.DomApi.ctor;
|
| +Object.defineProperty(DomApi.prototype, 'classList', {
|
| +get: function () {
|
| +if (!this._classList) {
|
| +this._classList = new DomApi.ClassList(this);
|
| +}
|
| +return this._classList;
|
| +},
|
| +configurable: true
|
| +});
|
| +DomApi.ClassList = function (host) {
|
| +this.domApi = host;
|
| +this.node = host.node;
|
| +};
|
| +DomApi.ClassList.prototype = {
|
| +add: function () {
|
| +this.node.classList.add.apply(this.node.classList, arguments);
|
| +this.domApi._distributeParent();
|
| +},
|
| +remove: function () {
|
| +this.node.classList.remove.apply(this.node.classList, arguments);
|
| +this.domApi._distributeParent();
|
| +},
|
| +toggle: function () {
|
| +this.node.classList.toggle.apply(this.node.classList, arguments);
|
| +this.domApi._distributeParent();
|
| +},
|
| +contains: function () {
|
| +return this.node.classList.contains.apply(this.node.classList, arguments);
|
| +}
|
| +};
|
| +}());
|
| (function () {
|
| +'use strict';
|
| +var DomApi = Polymer.DomApi.ctor;
|
| +var Settings = Polymer.Settings;
|
| +var hasDomApi = Polymer.DomApi.hasDomApi;
|
| +DomApi.EffectiveNodesObserver = function (domApi) {
|
| +this.domApi = domApi;
|
| +this.node = this.domApi.node;
|
| +this._listeners = [];
|
| +};
|
| +DomApi.EffectiveNodesObserver.prototype = {
|
| +addListener: function (callback) {
|
| +if (!this._isSetup) {
|
| +this._setup();
|
| +this._isSetup = true;
|
| +}
|
| +var listener = {
|
| +fn: callback,
|
| +_nodes: []
|
| +};
|
| +this._listeners.push(listener);
|
| +this._scheduleNotify();
|
| +return listener;
|
| +},
|
| +removeListener: function (handle) {
|
| +var i = this._listeners.indexOf(handle);
|
| +if (i >= 0) {
|
| +this._listeners.splice(i, 1);
|
| +handle._nodes = [];
|
| +}
|
| +if (!this._hasListeners()) {
|
| +this._cleanup();
|
| +this._isSetup = false;
|
| +}
|
| +},
|
| +_setup: function () {
|
| +this._observeContentElements(this.domApi.childNodes);
|
| +},
|
| +_cleanup: function () {
|
| +this._unobserveContentElements(this.domApi.childNodes);
|
| +},
|
| +_hasListeners: function () {
|
| +return Boolean(this._listeners.length);
|
| +},
|
| +_scheduleNotify: function () {
|
| +if (this._debouncer) {
|
| +this._debouncer.stop();
|
| +}
|
| +this._debouncer = Polymer.Debounce(this._debouncer, this._notify);
|
| +this._debouncer.context = this;
|
| +Polymer.dom.addDebouncer(this._debouncer);
|
| +},
|
| +notify: function () {
|
| +if (this._hasListeners()) {
|
| +this._scheduleNotify();
|
| +}
|
| +},
|
| +_notify: function (mxns) {
|
| +this._beforeCallListeners();
|
| +this._callListeners();
|
| +},
|
| +_beforeCallListeners: function () {
|
| +this._updateContentElements();
|
| +},
|
| +_updateContentElements: function () {
|
| +this._observeContentElements(this.domApi.childNodes);
|
| +},
|
| +_observeContentElements: function (elements) {
|
| +for (var i = 0, n; i < elements.length && (n = elements[i]); i++) {
|
| +if (this._isContent(n)) {
|
| +n.__observeNodesMap = n.__observeNodesMap || new WeakMap();
|
| +if (!n.__observeNodesMap.has(this)) {
|
| +n.__observeNodesMap.set(this, this._observeContent(n));
|
| +}
|
| +}
|
| +}
|
| +},
|
| +_observeContent: function (content) {
|
| +var h = Polymer.dom(content).observeNodes(this._scheduleNotify.bind(this));
|
| +h._avoidChangeCalculation = true;
|
| +return h;
|
| +},
|
| +_unobserveContentElements: function (elements) {
|
| +for (var i = 0, n, h; i < elements.length && (n = elements[i]); i++) {
|
| +if (this._isContent(n)) {
|
| +h = n.__observeNodesMap.get(this);
|
| +if (h) {
|
| +Polymer.dom(n).unobserveNodes(h);
|
| +n.__observeNodesMap.delete(this);
|
| +}
|
| +}
|
| +}
|
| +},
|
| +_isContent: function (node) {
|
| +return node.localName === 'content';
|
| +},
|
| +_callListeners: function () {
|
| +var o$ = this._listeners;
|
| +var nodes = this._getEffectiveNodes();
|
| +for (var i = 0, o; i < o$.length && (o = o$[i]); i++) {
|
| +var info = this._generateListenerInfo(o, nodes);
|
| +if (info || o._alwaysNotify) {
|
| +this._callListener(o, info);
|
| +}
|
| +}
|
| +},
|
| +_getEffectiveNodes: function () {
|
| +return this.domApi.getEffectiveChildNodes();
|
| +},
|
| +_generateListenerInfo: function (listener, newNodes) {
|
| +if (listener._avoidChangeCalculation) {
|
| +return true;
|
| +}
|
| +var oldNodes = listener._nodes;
|
| +var info = {
|
| +target: this.node,
|
| +addedNodes: [],
|
| +removedNodes: []
|
| +};
|
| +var splices = Polymer.ArraySplice.calculateSplices(newNodes, oldNodes);
|
| +for (var i = 0, s; i < splices.length && (s = splices[i]); i++) {
|
| +for (var j = 0, n; j < s.removed.length && (n = s.removed[j]); j++) {
|
| +info.removedNodes.push(n);
|
| +}
|
| +}
|
| +for (var i = 0, s; i < splices.length && (s = splices[i]); i++) {
|
| +for (var j = s.index; j < s.index + s.addedCount; j++) {
|
| +info.addedNodes.push(newNodes[j]);
|
| +}
|
| +}
|
| +listener._nodes = newNodes;
|
| +if (info.addedNodes.length || info.removedNodes.length) {
|
| +return info;
|
| +}
|
| +},
|
| +_callListener: function (listener, info) {
|
| +return listener.fn.call(this.node, info);
|
| +},
|
| +enableShadowAttributeTracking: function () {
|
| +}
|
| +};
|
| +if (Settings.useShadow) {
|
| +var baseSetup = DomApi.EffectiveNodesObserver.prototype._setup;
|
| +var baseCleanup = DomApi.EffectiveNodesObserver.prototype._cleanup;
|
| +var beforeCallListeners = DomApi.EffectiveNodesObserver.prototype._beforeCallListeners;
|
| +Polymer.Base.extend(DomApi.EffectiveNodesObserver.prototype, {
|
| +_setup: function () {
|
| +if (!this._observer) {
|
| +var self = this;
|
| +this._mutationHandler = function (mxns) {
|
| +if (mxns && mxns.length) {
|
| +self._scheduleNotify();
|
| +}
|
| +};
|
| +this._observer = new MutationObserver(this._mutationHandler);
|
| +this._boundFlush = this._flush.bind(this);
|
| +Polymer.dom.addStaticFlush(this._boundFlush);
|
| +this._observer.observe(this.node, { childList: true });
|
| +}
|
| +baseSetup.call(this);
|
| +},
|
| +_cleanup: function () {
|
| +this._observer.disconnect();
|
| +this._observer = null;
|
| +this._mutationHandler = null;
|
| +Polymer.dom.removeStaticFlush(this._boundFlush);
|
| +baseCleanup.call(this);
|
| +},
|
| +_flush: function () {
|
| +if (this._observer) {
|
| +this._mutationHandler(this._observer.takeRecords());
|
| +}
|
| +},
|
| +enableShadowAttributeTracking: function () {
|
| +if (this._observer) {
|
| +this._makeContentListenersAlwaysNotify();
|
| +this._observer.disconnect();
|
| +this._observer.observe(this.node, {
|
| +childList: true,
|
| +attributes: true,
|
| +subtree: true
|
| +});
|
| +var root = this.domApi.getOwnerRoot();
|
| +var host = root && root.host;
|
| +if (host && Polymer.dom(host).observer) {
|
| +Polymer.dom(host).observer.enableShadowAttributeTracking();
|
| +}
|
| +}
|
| +},
|
| +_makeContentListenersAlwaysNotify: function () {
|
| +for (var i = 0, h; i < this._listeners.length; i++) {
|
| +h = this._listeners[i];
|
| +h._alwaysNotify = h._isContentListener;
|
| +}
|
| +}
|
| +});
|
| +}
|
| +}());
|
| +(function () {
|
| +'use strict';
|
| +var DomApi = Polymer.DomApi.ctor;
|
| +var Settings = Polymer.Settings;
|
| +DomApi.DistributedNodesObserver = function (domApi) {
|
| +DomApi.EffectiveNodesObserver.call(this, domApi);
|
| +};
|
| +DomApi.DistributedNodesObserver.prototype = Object.create(DomApi.EffectiveNodesObserver.prototype);
|
| +Polymer.Base.extend(DomApi.DistributedNodesObserver.prototype, {
|
| +_setup: function () {
|
| +},
|
| +_cleanup: function () {
|
| +},
|
| +_beforeCallListeners: function () {
|
| +},
|
| +_getEffectiveNodes: function () {
|
| +return this.domApi.getDistributedNodes();
|
| +}
|
| +});
|
| +if (Settings.useShadow) {
|
| +Polymer.Base.extend(DomApi.DistributedNodesObserver.prototype, {
|
| +_setup: function () {
|
| +if (!this._observer) {
|
| +var root = this.domApi.getOwnerRoot();
|
| +var host = root && root.host;
|
| +if (host) {
|
| +this._observer = Polymer.dom(host).observeNodes(this._scheduleNotify.bind(this));
|
| +this._observer._isContentListener = true;
|
| +if (this._hasAttrSelect()) {
|
| +Polymer.dom(host).observer.enableShadowAttributeTracking();
|
| +}
|
| +}
|
| +}
|
| +},
|
| +_hasAttrSelect: function () {
|
| +var select = this.node.getAttribute('select');
|
| +return select && select.match(/[[.]+/);
|
| +},
|
| +_cleanup: function () {
|
| +var root = this.domApi.getOwnerRoot();
|
| +var host = root && root.host;
|
| +if (host) {
|
| +Polymer.dom(host).unobserveNodes(this._observer);
|
| +}
|
| +this._observer = null;
|
| +}
|
| +});
|
| +}
|
| +}());
|
| +(function () {
|
| +var hasDomApi = Polymer.DomApi.hasDomApi;
|
| Polymer.Base._addFeature({
|
| _prepShady: function () {
|
| this._useContent = this._useContent || Boolean(this._template);
|
| @@ -3612,6 +3945,7 @@ if (this._useContent) {
|
| this.shadyRoot._distributionClean = true;
|
| if (hasInsertionPoint(this.shadyRoot)) {
|
| this._composeTree();
|
| +notifyContentObservers(this.shadyRoot);
|
| } else {
|
| if (!this.shadyRoot._hasDistributed) {
|
| this.textContent = '';
|
| @@ -3622,6 +3956,9 @@ var children = this._composeNode(this);
|
| this._updateChildNodes(this, children);
|
| }
|
| }
|
| +if (!this.shadyRoot._hasDistributed) {
|
| +notifyInitialDistribution(this);
|
| +}
|
| this.shadyRoot._hasDistributed = true;
|
| }
|
| },
|
| @@ -3839,6 +4176,19 @@ return host.domHost;
|
| }
|
| }
|
| }
|
| +function notifyContentObservers(root) {
|
| +for (var i = 0, c; i < root._insertionPoints.length; i++) {
|
| +c = root._insertionPoints[i];
|
| +if (hasDomApi(c)) {
|
| +Polymer.dom(c).notifyObserver();
|
| +}
|
| +}
|
| +}
|
| +function notifyInitialDistribution(host) {
|
| +if (hasDomApi(host)) {
|
| +Polymer.dom(host).notifyObserver();
|
| +}
|
| +}
|
| var needsUpgrade = window.CustomElements && !CustomElements.useNative;
|
| function upgradeLightChildren(children) {
|
| if (needsUpgrade && children) {
|
| @@ -3904,22 +4254,66 @@ return list;
|
| _parseNodeAnnotations: function (node, list) {
|
| return node.nodeType === Node.TEXT_NODE ? this._parseTextNodeAnnotation(node, list) : this._parseElementAnnotations(node, list);
|
| },
|
| -_testEscape: function (value) {
|
| -var escape = value.slice(0, 2);
|
| -if (escape === '{{' || escape === '[[') {
|
| -return escape;
|
| +_bindingRegex: /([^{[]*)({{|\[\[)([^}\]]*)(?:]]|}})/g,
|
| +_parseBindings: function (text) {
|
| +var re = this._bindingRegex;
|
| +var parts = [];
|
| +var m, lastIndex;
|
| +while ((m = re.exec(text)) !== null) {
|
| +if (m[1]) {
|
| +parts.push({ literal: m[1] });
|
| +}
|
| +var mode = m[2][0];
|
| +var value = m[3].trim();
|
| +var negate = false;
|
| +if (value[0] == '!') {
|
| +negate = true;
|
| +value = value.substring(1).trim();
|
| +}
|
| +var customEvent, notifyEvent, colon;
|
| +if (mode == '{' && (colon = value.indexOf('::')) > 0) {
|
| +notifyEvent = value.substring(colon + 2);
|
| +value = value.substring(0, colon);
|
| +customEvent = true;
|
| +}
|
| +parts.push({
|
| +compoundIndex: parts.length,
|
| +value: value,
|
| +mode: mode,
|
| +negate: negate,
|
| +event: notifyEvent,
|
| +customEvent: customEvent
|
| +});
|
| +lastIndex = re.lastIndex;
|
| +}
|
| +if (lastIndex && lastIndex < text.length) {
|
| +var literal = text.substring(lastIndex);
|
| +if (literal) {
|
| +parts.push({ literal: literal });
|
| +}
|
| +}
|
| +if (parts.length) {
|
| +return parts;
|
| +}
|
| +},
|
| +_literalFromParts: function (parts) {
|
| +var s = '';
|
| +for (var i = 0; i < parts.length; i++) {
|
| +var literal = parts[i].literal;
|
| +s += literal || '';
|
| }
|
| +return s;
|
| },
|
| _parseTextNodeAnnotation: function (node, list) {
|
| -var v = node.textContent;
|
| -var escape = this._testEscape(v);
|
| -if (escape) {
|
| -node.textContent = ' ';
|
| +var parts = this._parseBindings(node.textContent);
|
| +if (parts) {
|
| +node.textContent = this._literalFromParts(parts) || ' ';
|
| var annote = {
|
| bindings: [{
|
| kind: 'text',
|
| -mode: escape[0],
|
| -value: v.slice(2, -2).trim()
|
| +name: 'textContent',
|
| +parts: parts,
|
| +isCompound: parts.length !== 1
|
| }]
|
| };
|
| list.push(annote);
|
| @@ -3981,62 +4375,50 @@ index: index
|
| });
|
| },
|
| _parseNodeAttributeAnnotations: function (node, annotation) {
|
| -for (var i = node.attributes.length - 1, a; a = node.attributes[i]; i--) {
|
| -var n = a.name, v = a.value;
|
| -if (n === 'id' && !this._testEscape(v)) {
|
| -annotation.id = v;
|
| -} else if (n.slice(0, 3) === 'on-') {
|
| +var attrs = Array.prototype.slice.call(node.attributes);
|
| +for (var i = attrs.length - 1, a; a = attrs[i]; i--) {
|
| +var n = a.name;
|
| +var v = a.value;
|
| +var b;
|
| +if (n.slice(0, 3) === 'on-') {
|
| node.removeAttribute(n);
|
| annotation.events.push({
|
| name: n.slice(3),
|
| value: v
|
| });
|
| -} else {
|
| -var b = this._parseNodeAttributeAnnotation(node, n, v);
|
| -if (b) {
|
| +} else if (b = this._parseNodeAttributeAnnotation(node, n, v)) {
|
| annotation.bindings.push(b);
|
| -}
|
| +} else if (n === 'id') {
|
| +annotation.id = v;
|
| }
|
| }
|
| },
|
| -_parseNodeAttributeAnnotation: function (node, n, v) {
|
| -var escape = this._testEscape(v);
|
| -if (escape) {
|
| -var customEvent;
|
| -var name = n;
|
| -var mode = escape[0];
|
| -v = v.slice(2, -2).trim();
|
| -var not = false;
|
| -if (v[0] == '!') {
|
| -v = v.substring(1);
|
| -not = true;
|
| -}
|
| +_parseNodeAttributeAnnotation: function (node, name, value) {
|
| +var parts = this._parseBindings(value);
|
| +if (parts) {
|
| +var origName = name;
|
| var kind = 'property';
|
| -if (n[n.length - 1] == '$') {
|
| -name = n.slice(0, -1);
|
| +if (name[name.length - 1] == '$') {
|
| +name = name.slice(0, -1);
|
| kind = 'attribute';
|
| }
|
| -var notifyEvent, colon;
|
| -if (mode == '{' && (colon = v.indexOf('::')) > 0) {
|
| -notifyEvent = v.substring(colon + 2);
|
| -v = v.substring(0, colon);
|
| -customEvent = true;
|
| +var literal = this._literalFromParts(parts);
|
| +if (literal && kind == 'attribute') {
|
| +node.setAttribute(name, literal);
|
| }
|
| -if (node.localName == 'input' && n == 'value') {
|
| -node.setAttribute(n, '');
|
| +if (node.localName == 'input' && name == 'value') {
|
| +node.setAttribute(origName, '');
|
| }
|
| -node.removeAttribute(n);
|
| +node.removeAttribute(origName);
|
| if (kind === 'property') {
|
| name = Polymer.CaseMap.dashToCamelCase(name);
|
| }
|
| return {
|
| kind: kind,
|
| -mode: mode,
|
| name: name,
|
| -value: v,
|
| -negate: not,
|
| -event: notifyEvent,
|
| -customEvent: customEvent
|
| +parts: parts,
|
| +literal: literal,
|
| +isCompound: parts.length !== 1
|
| };
|
| }
|
| },
|
| @@ -4127,9 +4509,14 @@ for (var i = 0; i < notes.length; i++) {
|
| var note = notes[i];
|
| for (var j = 0; j < note.bindings.length; j++) {
|
| var b = note.bindings[j];
|
| -b.signature = this._parseMethod(b.value);
|
| -if (!b.signature) {
|
| -b.model = this._modelForPath(b.value);
|
| +for (var k = 0; k < b.parts.length; k++) {
|
| +var p = b.parts[k];
|
| +if (!p.literal) {
|
| +p.signature = this._parseMethod(p.value);
|
| +if (!p.signature) {
|
| +p.model = this._modelForPath(p.value);
|
| +}
|
| +}
|
| }
|
| }
|
| if (note.templateContent) {
|
| @@ -4140,10 +4527,12 @@ for (var prop in pp) {
|
| bindings.push({
|
| index: note.index,
|
| kind: 'property',
|
| -mode: '{',
|
| name: '_parent_' + prop,
|
| +parts: [{
|
| +mode: '{',
|
| model: prop,
|
| value: prop
|
| +}]
|
| });
|
| }
|
| note.bindings = note.bindings.concat(bindings);
|
| @@ -4154,15 +4543,17 @@ _discoverTemplateParentProps: function (notes) {
|
| var pp = {};
|
| notes.forEach(function (n) {
|
| n.bindings.forEach(function (b) {
|
| -if (b.signature) {
|
| -var args = b.signature.args;
|
| +b.parts.forEach(function (p) {
|
| +if (p.signature) {
|
| +var args = p.signature.args;
|
| for (var k = 0; k < args.length; k++) {
|
| pp[args[k].model] = true;
|
| }
|
| } else {
|
| -pp[b.model] = true;
|
| +pp[p.model] = true;
|
| }
|
| });
|
| +});
|
| if (n.templateContent) {
|
| var tpp = n.templateContent._parentProps;
|
| Polymer.Base.mixin(pp, tpp);
|
| @@ -4181,15 +4572,43 @@ this._marshalAnnotatedNodes();
|
| this._marshalAnnotatedListeners();
|
| }
|
| },
|
| -_configureAnnotationReferences: function () {
|
| -this._configureTemplateContent();
|
| +_configureAnnotationReferences: function (config) {
|
| +var notes = this._notes;
|
| +var nodes = this._nodes;
|
| +for (var i = 0; i < notes.length; i++) {
|
| +var note = notes[i];
|
| +var node = nodes[i];
|
| +this._configureTemplateContent(note, node);
|
| +this._configureCompoundBindings(note, node);
|
| +}
|
| },
|
| -_configureTemplateContent: function () {
|
| -this._notes.forEach(function (note, i) {
|
| +_configureTemplateContent: function (note, node) {
|
| if (note.templateContent) {
|
| -this._nodes[i]._content = note.templateContent;
|
| +node._content = note.templateContent;
|
| +}
|
| +},
|
| +_configureCompoundBindings: function (note, node) {
|
| +var bindings = note.bindings;
|
| +for (var i = 0; i < bindings.length; i++) {
|
| +var binding = bindings[i];
|
| +if (binding.isCompound) {
|
| +var storage = node.__compoundStorage__ || (node.__compoundStorage__ = {});
|
| +var parts = binding.parts;
|
| +var literals = new Array(parts.length);
|
| +for (var j = 0; j < parts.length; j++) {
|
| +literals[j] = parts[j].literal;
|
| +}
|
| +var name = binding.name;
|
| +storage[name] = literals;
|
| +if (binding.literal && binding.kind == 'property') {
|
| +if (node._configValue) {
|
| +node._configValue(name, binding.literal);
|
| +} else {
|
| +node[name] = binding.literal;
|
| +}
|
| +}
|
| +}
|
| }
|
| -}, this);
|
| },
|
| _marshalIdNodes: function () {
|
| this.$ = {};
|
| @@ -4981,7 +5400,9 @@ this._callbacks.splice(0, len);
|
| this._lastVal += len;
|
| }
|
| };
|
| -new (window.MutationObserver || JsMutationObserver)(Polymer.Async._atEndOfMicrotask.bind(Polymer.Async)).observe(Polymer.Async._twiddle, { characterData: true });
|
| +new window.MutationObserver(function () {
|
| +Polymer.Async._atEndOfMicrotask();
|
| +}).observe(Polymer.Async._twiddle, { characterData: true });
|
| Polymer.Debounce = function () {
|
| var Async = Polymer.Async;
|
| var Debouncer = function (context) {
|
| @@ -5063,6 +5484,32 @@ if (toElement) {
|
| Polymer.dom(toElement).setAttribute(name, '');
|
| }
|
| },
|
| +getEffectiveChildNodes: function () {
|
| +return Polymer.dom(this).getEffectiveChildNodes();
|
| +},
|
| +getEffectiveChildren: function () {
|
| +var list = Polymer.dom(this).getEffectiveChildNodes();
|
| +return list.filter(function (n) {
|
| +return n.nodeType === Node.ELEMENT_NODE;
|
| +});
|
| +},
|
| +getEffectiveTextContent: function () {
|
| +var cn = this.getEffectiveChildNodes();
|
| +var tc = [];
|
| +for (var i = 0, c; c = cn[i]; i++) {
|
| +if (c.nodeType !== Node.COMMENT_NODE) {
|
| +tc.push(Polymer.dom(c).textContent);
|
| +}
|
| +}
|
| +return tc.join('');
|
| +},
|
| +queryEffectiveChildren: function (slctr) {
|
| +var e$ = Polymer.dom(this).queryDistributedElements(slctr);
|
| +return e$ && e$[0];
|
| +},
|
| +queryAllEffectiveChildren: function (slctr) {
|
| +return Polymer.dom(this).queryAllDistributedElements(slctr);
|
| +},
|
| getContentChildNodes: function (slctr) {
|
| var content = Polymer.dom(this.root).querySelector(slctr || 'content');
|
| return content ? Polymer.dom(content).getDistributedNodes() : [];
|
| @@ -5100,7 +5547,7 @@ if (index >= 0) {
|
| return path.splice(index, 1);
|
| }
|
| } else {
|
| -var arr = this.get(path);
|
| +var arr = this._get(path);
|
| index = arr.indexOf(item);
|
| if (index >= 0) {
|
| return this.splice(path, index, 1);
|
| @@ -5139,7 +5586,7 @@ elt[n] = props[n];
|
| return elt;
|
| },
|
| isLightDescendant: function (node) {
|
| -return this.contains(node) && Polymer.dom(this).getOwnerRoot() === Polymer.dom(node).getOwnerRoot();
|
| +return this !== node && this.contains(node) && Polymer.dom(this).getOwnerRoot() === Polymer.dom(node).getOwnerRoot();
|
| },
|
| isLocalDescendant: function (node) {
|
| return this.root === Polymer.dom(node).getOwnerRoot();
|
| @@ -5282,7 +5729,7 @@ _notedListenerFactory: function (property, path, isStructured, bogusTest) {
|
| return function (e, target) {
|
| if (!bogusTest(e, target)) {
|
| if (e.detail && e.detail.path) {
|
| -this.notifyPath(this._fixPath(path, property, e.detail.path), e.detail.value);
|
| +this._notifyPath(this._fixPath(path, property, e.detail.path), e.detail.value);
|
| } else {
|
| var value = target[property];
|
| if (!isStructured) {
|
| @@ -5308,16 +5755,16 @@ node.addEventListener(info.event, inst._notifyListener.bind(inst, info.changedFn
|
| };
|
| Polymer.Base.extend(Polymer.Bind, {
|
| _shouldAddListener: function (effect) {
|
| -return effect.name && effect.mode === '{' && !effect.negate && effect.kind != 'attribute';
|
| +return effect.name && effect.kind != 'attribute' && effect.kind != 'text' && !effect.isCompound && effect.parts[0].mode === '{' && !effect.parts[0].negate;
|
| },
|
| _annotationEffect: function (source, value, effect) {
|
| if (source != effect.value) {
|
| -value = this.get(effect.value);
|
| +value = this._get(effect.value);
|
| this.__data__[effect.value] = value;
|
| }
|
| var calc = effect.negate ? !value : value;
|
| if (!effect.customEvent || this._nodes[effect.index][effect.name] !== calc) {
|
| -return this._applyEffectValue(calc, effect);
|
| +return this._applyEffectValue(effect, calc);
|
| }
|
| },
|
| _reflectEffect: function (source) {
|
| @@ -5355,7 +5802,7 @@ var args = Polymer.Bind._marshalArgs(this.__data__, effect, source, value);
|
| if (args) {
|
| var fn = this[effect.method];
|
| if (fn) {
|
| -this.__setProperty(effect.property, fn.apply(this, args));
|
| +this.__setProperty(effect.name, fn.apply(this, args));
|
| } else {
|
| this._warn(this._logf('_computeEffect', 'compute method `' + effect.method + '` not defined'));
|
| }
|
| @@ -5371,7 +5818,7 @@ var computedvalue = fn.apply(computedHost, args);
|
| if (effect.negate) {
|
| computedvalue = !computedvalue;
|
| }
|
| -this._applyEffectValue(computedvalue, effect);
|
| +this._applyEffectValue(effect, computedvalue);
|
| }
|
| } else {
|
| computedHost._warn(computedHost._logf('_annotatedComputationEffect', 'compute method `' + effect.method + '` not defined'));
|
| @@ -5387,7 +5834,7 @@ var v;
|
| if (arg.literal) {
|
| v = arg.value;
|
| } else if (arg.structured) {
|
| -v = Polymer.Base.get(name, model);
|
| +v = Polymer.Base._get(name, model);
|
| } else {
|
| v = model[name];
|
| }
|
| @@ -5450,7 +5897,7 @@ this._addPropertyEffect(arg.model, 'compute', {
|
| method: sig.method,
|
| args: sig.args,
|
| trigger: arg,
|
| -property: name
|
| +name: name
|
| });
|
| }, this);
|
| },
|
| @@ -5488,35 +5935,49 @@ this._addAnnotationEffect(binding, index);
|
| },
|
| _addAnnotationEffect: function (note, index) {
|
| if (Polymer.Bind._shouldAddListener(note)) {
|
| -Polymer.Bind._addAnnotatedListener(this, index, note.name, note.value, note.event);
|
| +Polymer.Bind._addAnnotatedListener(this, index, note.name, note.parts[0].value, note.parts[0].event);
|
| +}
|
| +for (var i = 0; i < note.parts.length; i++) {
|
| +var part = note.parts[i];
|
| +if (part.signature) {
|
| +this._addAnnotatedComputationEffect(note, part, index);
|
| +} else if (!part.literal) {
|
| +this._addPropertyEffect(part.model, 'annotation', {
|
| +kind: note.kind,
|
| +index: index,
|
| +name: note.name,
|
| +value: part.value,
|
| +isCompound: note.isCompound,
|
| +compoundIndex: part.compoundIndex,
|
| +event: part.event,
|
| +customEvent: part.customEvent,
|
| +negate: part.negate
|
| +});
|
| }
|
| -if (note.signature) {
|
| -this._addAnnotatedComputationEffect(note, index);
|
| -} else {
|
| -note.index = index;
|
| -this._addPropertyEffect(note.model, 'annotation', note);
|
| }
|
| },
|
| -_addAnnotatedComputationEffect: function (note, index) {
|
| -var sig = note.signature;
|
| +_addAnnotatedComputationEffect: function (note, part, index) {
|
| +var sig = part.signature;
|
| if (sig.static) {
|
| -this.__addAnnotatedComputationEffect('__static__', index, note, sig, null);
|
| +this.__addAnnotatedComputationEffect('__static__', index, note, part, null);
|
| } else {
|
| sig.args.forEach(function (arg) {
|
| if (!arg.literal) {
|
| -this.__addAnnotatedComputationEffect(arg.model, index, note, sig, arg);
|
| +this.__addAnnotatedComputationEffect(arg.model, index, note, part, arg);
|
| }
|
| }, this);
|
| }
|
| },
|
| -__addAnnotatedComputationEffect: function (property, index, note, sig, trigger) {
|
| +__addAnnotatedComputationEffect: function (property, index, note, part, trigger) {
|
| this._addPropertyEffect(property, 'annotatedComputation', {
|
| index: index,
|
| +isCompound: note.isCompound,
|
| +compoundIndex: part.compoundIndex,
|
| kind: note.kind,
|
| -property: note.name,
|
| -negate: note.negate,
|
| -method: sig.method,
|
| -args: sig.args,
|
| +name: note.name,
|
| +negate: part.negate,
|
| +method: part.signature.method,
|
| +args: part.signature.args,
|
| trigger: trigger
|
| });
|
| },
|
| @@ -5585,9 +6046,14 @@ _marshalInstanceEffects: function () {
|
| Polymer.Bind.prepareInstance(this);
|
| Polymer.Bind.setupBindListeners(this);
|
| },
|
| -_applyEffectValue: function (value, info) {
|
| +_applyEffectValue: function (info, value) {
|
| var node = this._nodes[info.index];
|
| -var property = info.property || info.name || 'textContent';
|
| +var property = info.name;
|
| +if (info.isCompound) {
|
| +var storage = node.__compoundStorage__[property];
|
| +storage[info.compoundIndex] = value;
|
| +value = storage.join('');
|
| +}
|
| if (info.kind == 'attribute') {
|
| this.serializeValueToAttribute(value, property, node);
|
| } else {
|
| @@ -5667,10 +6133,10 @@ for (var p in config) {
|
| var fx = fx$[p];
|
| if (fx) {
|
| for (var i = 0, l = fx.length, x; i < l && (x = fx[i]); i++) {
|
| -if (x.kind === 'annotation') {
|
| +if (x.kind === 'annotation' && !x.isCompound) {
|
| var node = this._nodes[x.effect.index];
|
| if (node._configValue) {
|
| -var value = p === x.effect.value ? config[p] : this.get(x.effect.value, config);
|
| +var value = p === x.effect.value ? config[p] : this._get(x.effect.value, config);
|
| node._configValue(x.effect.name, value);
|
| }
|
| }
|
| @@ -5717,11 +6183,16 @@ this._handlers = [];
|
| 'use strict';
|
| Polymer.Base._addFeature({
|
| notifyPath: function (path, value, fromAbove) {
|
| +var info = {};
|
| +this._get(path, this, info);
|
| +this._notifyPath(info.path, value, fromAbove);
|
| +},
|
| +_notifyPath: function (path, value, fromAbove) {
|
| var old = this._propertySetter(path, value);
|
| if (old !== value && (old === old || value === value)) {
|
| this._pathEffector(path, value);
|
| if (!fromAbove) {
|
| -this._notifyPath(path, value);
|
| +this._notifyPathUp(path, value);
|
| }
|
| return true;
|
| }
|
| @@ -5748,41 +6219,67 @@ var last = parts[parts.length - 1];
|
| if (parts.length > 1) {
|
| for (var i = 0; i < parts.length - 1; i++) {
|
| var part = parts[i];
|
| +if (array && part[0] == '#') {
|
| +prop = Polymer.Collection.get(array).getItem(part);
|
| +} else {
|
| prop = prop[part];
|
| -if (array && parseInt(part) == part) {
|
| +if (array && parseInt(part, 10) == part) {
|
| parts[i] = Polymer.Collection.get(array).getKey(prop);
|
| }
|
| +}
|
| if (!prop) {
|
| return;
|
| }
|
| array = Array.isArray(prop) ? prop : null;
|
| }
|
| -if (array && parseInt(last) == last) {
|
| +if (array) {
|
| var coll = Polymer.Collection.get(array);
|
| +if (last[0] == '#') {
|
| +var key = last;
|
| +var old = coll.getItem(key);
|
| +last = array.indexOf(old);
|
| +coll.setItem(key, value);
|
| +} else if (parseInt(last, 10) == last) {
|
| var old = prop[last];
|
| var key = coll.getKey(old);
|
| parts[i] = key;
|
| coll.setItem(key, value);
|
| }
|
| +}
|
| prop[last] = value;
|
| if (!root) {
|
| -this.notifyPath(parts.join('.'), value);
|
| +this._notifyPath(parts.join('.'), value);
|
| }
|
| } else {
|
| prop[path] = value;
|
| }
|
| },
|
| get: function (path, root) {
|
| +return this._get(path, root);
|
| +},
|
| +_get: function (path, root, info) {
|
| var prop = root || this;
|
| var parts = this._getPathParts(path);
|
| -var last = parts.pop();
|
| -while (parts.length) {
|
| -prop = prop[parts.shift()];
|
| +var array;
|
| +for (var i = 0; i < parts.length; i++) {
|
| if (!prop) {
|
| return;
|
| }
|
| +var part = parts[i];
|
| +if (array && part[0] == '#') {
|
| +prop = Polymer.Collection.get(array).getItem(part);
|
| +} else {
|
| +prop = prop[part];
|
| +if (info && array && parseInt(part, 10) == part) {
|
| +parts[i] = Polymer.Collection.get(array).getKey(prop);
|
| +}
|
| +}
|
| +array = Array.isArray(prop) ? prop : null;
|
| +}
|
| +if (info) {
|
| +info.path = parts.join('.');
|
| }
|
| -return prop[last];
|
| +return prop;
|
| },
|
| _pathEffector: function (path, value) {
|
| var model = this._modelForPath(path);
|
| @@ -5804,9 +6301,9 @@ if (effect.value === path || effect.value.indexOf(path + '.') === 0) {
|
| Polymer.Bind._annotationEffect.call(this, path, value, effect);
|
| } else if (path.indexOf(effect.value + '.') === 0 && !effect.negate) {
|
| var node = this._nodes[effect.index];
|
| -if (node && node.notifyPath) {
|
| +if (node && node._notifyPath) {
|
| var p = this._fixPath(effect.name, effect.value, path);
|
| -node.notifyPath(p, value, true);
|
| +node._notifyPath(p, value, true);
|
| }
|
| }
|
| },
|
| @@ -5846,16 +6343,16 @@ _notifyBoundPaths: function (path, value) {
|
| for (var a in this._boundPaths) {
|
| var b = this._boundPaths[a];
|
| if (path.indexOf(a + '.') == 0) {
|
| -this.notifyPath(this._fixPath(b, a, path), value);
|
| +this._notifyPath(this._fixPath(b, a, path), value);
|
| } else if (path.indexOf(b + '.') == 0) {
|
| -this.notifyPath(this._fixPath(a, b, path), value);
|
| +this._notifyPath(this._fixPath(a, b, path), value);
|
| }
|
| }
|
| },
|
| _fixPath: function (property, root, path) {
|
| return property + path.slice(root.length);
|
| },
|
| -_notifyPath: function (path, value) {
|
| +_notifyPathUp: function (path, value) {
|
| var rootName = this._modelForPath(path);
|
| var dashCaseName = Polymer.CaseMap.camelToDashCase(rootName);
|
| var eventName = dashCaseName + this._EVENT_CHANGED;
|
| @@ -5869,47 +6366,62 @@ var dot = path.indexOf('.');
|
| return dot < 0 ? path : path.slice(0, dot);
|
| },
|
| _EVENT_CHANGED: '-changed',
|
| -_notifySplice: function (array, path, index, added, removed) {
|
| -var splices = [{
|
| -index: index,
|
| -addedCount: added,
|
| -removed: removed,
|
| -object: array,
|
| -type: 'splice'
|
| -}];
|
| +notifySplices: function (path, splices) {
|
| +var info = {};
|
| +var array = this._get(path, this, info);
|
| +this._notifySplices(array, info.path, splices);
|
| +},
|
| +_notifySplices: function (array, path, splices) {
|
| var change = {
|
| keySplices: Polymer.Collection.applySplices(array, splices),
|
| indexSplices: splices
|
| };
|
| -this.set(path + '.splices', change);
|
| -if (added != removed.length) {
|
| -this.notifyPath(path + '.length', array.length);
|
| +if (!array.hasOwnProperty('splices')) {
|
| +Object.defineProperty(array, 'splices', {
|
| +configurable: true,
|
| +writable: true
|
| +});
|
| }
|
| +array.splices = change;
|
| +this._notifyPath(path + '.splices', change);
|
| +this._notifyPath(path + '.length', array.length);
|
| change.keySplices = null;
|
| change.indexSplices = null;
|
| },
|
| +_notifySplice: function (array, path, index, added, removed) {
|
| +this._notifySplices(array, path, [{
|
| +index: index,
|
| +addedCount: added,
|
| +removed: removed,
|
| +object: array,
|
| +type: 'splice'
|
| +}]);
|
| +},
|
| push: function (path) {
|
| -var array = this.get(path);
|
| +var info = {};
|
| +var array = this._get(path, this, info);
|
| var args = Array.prototype.slice.call(arguments, 1);
|
| var len = array.length;
|
| var ret = array.push.apply(array, args);
|
| if (args.length) {
|
| -this._notifySplice(array, path, len, args.length, []);
|
| +this._notifySplice(array, info.path, len, args.length, []);
|
| }
|
| return ret;
|
| },
|
| pop: function (path) {
|
| -var array = this.get(path);
|
| +var info = {};
|
| +var array = this._get(path, this, info);
|
| var hadLength = Boolean(array.length);
|
| var args = Array.prototype.slice.call(arguments, 1);
|
| var ret = array.pop.apply(array, args);
|
| if (hadLength) {
|
| -this._notifySplice(array, path, array.length, 0, [ret]);
|
| +this._notifySplice(array, info.path, array.length, 0, [ret]);
|
| }
|
| return ret;
|
| },
|
| splice: function (path, start, deleteCount) {
|
| -var array = this.get(path);
|
| +var info = {};
|
| +var array = this._get(path, this, info);
|
| if (start < 0) {
|
| start = array.length - Math.floor(-start);
|
| } else {
|
| @@ -5922,26 +6434,28 @@ var args = Array.prototype.slice.call(arguments, 1);
|
| var ret = array.splice.apply(array, args);
|
| var addedCount = Math.max(args.length - 2, 0);
|
| if (addedCount || ret.length) {
|
| -this._notifySplice(array, path, start, addedCount, ret);
|
| +this._notifySplice(array, info.path, start, addedCount, ret);
|
| }
|
| return ret;
|
| },
|
| shift: function (path) {
|
| -var array = this.get(path);
|
| +var info = {};
|
| +var array = this._get(path, this, info);
|
| var hadLength = Boolean(array.length);
|
| var args = Array.prototype.slice.call(arguments, 1);
|
| var ret = array.shift.apply(array, args);
|
| if (hadLength) {
|
| -this._notifySplice(array, path, 0, 0, [ret]);
|
| +this._notifySplice(array, info.path, 0, 0, [ret]);
|
| }
|
| return ret;
|
| },
|
| unshift: function (path) {
|
| -var array = this.get(path);
|
| +var info = {};
|
| +var array = this._get(path, this, info);
|
| var args = Array.prototype.slice.call(arguments, 1);
|
| var ret = array.unshift.apply(array, args);
|
| if (args.length) {
|
| -this._notifySplice(array, path, 0, args.length, []);
|
| +this._notifySplice(array, info.path, 0, args.length, []);
|
| }
|
| return ret;
|
| },
|
| @@ -5949,8 +6463,10 @@ prepareModelNotifyPath: function (model) {
|
| this.mixin(model, {
|
| fire: Polymer.Base.fire,
|
| notifyPath: Polymer.Base.notifyPath,
|
| +_get: Polymer.Base._get,
|
| _EVENT_CHANGED: Polymer.Base._EVENT_CHANGED,
|
| _notifyPath: Polymer.Base._notifyPath,
|
| +_notifyPathUp: Polymer.Base._notifyPathUp,
|
| _pathEffector: Polymer.Base._pathEffector,
|
| _annotationPathEffect: Polymer.Base._annotationPathEffect,
|
| _complexObserverPathEffect: Polymer.Base._complexObserverPathEffect,
|
| @@ -5958,7 +6474,8 @@ _annotatedComputationPathEffect: Polymer.Base._annotatedComputationPathEffect,
|
| _computePathEffect: Polymer.Base._computePathEffect,
|
| _modelForPath: Polymer.Base._modelForPath,
|
| _pathMatchesEffect: Polymer.Base._pathMatchesEffect,
|
| -_notifyBoundPaths: Polymer.Base._notifyBoundPaths
|
| +_notifyBoundPaths: Polymer.Base._notifyBoundPaths,
|
| +_getPathParts: Polymer.Base._getPathParts
|
| });
|
| }
|
| });
|
| @@ -6095,7 +6612,7 @@ _rx: {
|
| comments: /\/\*[^*]*\*+([^\/*][^*]*\*+)*\//gim,
|
| port: /@import[^;]*;/gim,
|
| customProp: /(?:^|[\s;])--[^;{]*?:[^{};]*?(?:[;\n]|$)/gim,
|
| -mixinProp: /(?:^|[\s;])--[^;{]*?:[^{;]*?{[^}]*?}(?:[;\n]|$)?/gim,
|
| +mixinProp: /(?:^|[\s;])?--[^;{]*?:[^{;]*?{[^}]*?}(?:[;\n]|$)?/gim,
|
| mixinApply: /@apply[\s]*\([^)]*?\)[\s]*(?:[;\n]|$)?/gim,
|
| varApply: /[^;:]*?:[^;]*var[^;]*(?:[;\n]|$)?/gim,
|
| keyframesRule: /^@[^\s]*keyframes/
|
| @@ -6798,7 +7315,7 @@ props[i] = v;
|
| }
|
| },
|
| rx: {
|
| -VAR_ASSIGN: /(?:^|[;\n]\s*)(--[\w-]*?):\s*(?:([^;{]*)|{([^}]*)})(?:(?=[;\n])|$)/gi,
|
| +VAR_ASSIGN: /(?:^|[;\s{]\s*)(--[\w-]*?)\s*:\s*(?:([^;{]*)|{([^}]*)})(?:(?=[;\s}])|$)/gi,
|
| MIXIN_MATCH: /(?:^|\W+)@apply[\s]*\(([^)]*)\)/i,
|
| VAR_MATCH: /(^|\W+)var\([\s]*([^,)]*)[\s]*,?[\s]*((?:[^,)]*)|(?:[^;]*\([^;)]*\)))[\s]*?\)/gi,
|
| VAR_CAPTURE: /\([\s]*(--[^,\s)]*)(?:,[\s]*(--[^,\s)]*))?(?:\)|,)/gi,
|
| @@ -7182,7 +7699,7 @@ archetype._prepEffects();
|
| this._customPrepEffects(archetype);
|
| archetype._prepBehaviors();
|
| archetype._prepBindings();
|
| -archetype._notifyPath = this._notifyPathImpl;
|
| +archetype._notifyPathUp = this._notifyPathUpImpl;
|
| archetype._scopeElementClass = this._scopeElementClassImpl;
|
| archetype.listen = this._listenImpl;
|
| archetype._showHideChildren = this._showHideChildrenImpl;
|
| @@ -7320,7 +7837,7 @@ _forwardInstancePath: function (inst, path, value) {
|
| },
|
| _forwardInstanceProp: function (inst, prop, value) {
|
| },
|
| -_notifyPathImpl: function (path, value) {
|
| +_notifyPathUpImpl: function (path, value) {
|
| var dataHost = this.dataHost;
|
| var dot = path.indexOf('.');
|
| var root = dot < 0 ? path : path.slice(0, dot);
|
| @@ -7333,9 +7850,12 @@ _pathEffectorImpl: function (path, value, fromAbove) {
|
| if (this._forwardParentPath) {
|
| if (path.indexOf(this._parentPropPrefix) === 0) {
|
| var subPath = path.substring(this._parentPropPrefix.length);
|
| +var model = this._modelForPath(subPath);
|
| +if (model in this._parentProps) {
|
| this._forwardParentPath(subPath, value);
|
| }
|
| }
|
| +}
|
| Polymer.Base._pathEffector.call(this._templatized, path, value, fromAbove);
|
| },
|
| _constructorImpl: function (model, host) {
|
| @@ -7438,9 +7958,10 @@ this.omap.set(item, key);
|
| } else {
|
| this.pmap[item] = key;
|
| }
|
| -return key;
|
| +return '#' + key;
|
| },
|
| removeKey: function (key) {
|
| +key = this._parseKey(key);
|
| this._removeFromMap(this.store[key]);
|
| delete this.store[key];
|
| },
|
| @@ -7457,16 +7978,29 @@ this.removeKey(key);
|
| return key;
|
| },
|
| getKey: function (item) {
|
| +var key;
|
| if (item && typeof item == 'object') {
|
| -return this.omap.get(item);
|
| +key = this.omap.get(item);
|
| } else {
|
| -return this.pmap[item];
|
| +key = this.pmap[item];
|
| +}
|
| +if (key != undefined) {
|
| +return '#' + key;
|
| }
|
| },
|
| getKeys: function () {
|
| -return Object.keys(this.store);
|
| +return Object.keys(this.store).map(function (key) {
|
| +return '#' + key;
|
| +});
|
| +},
|
| +_parseKey: function (key) {
|
| +if (key[0] == '#') {
|
| +return key.slice(1);
|
| +}
|
| +throw new Error('unexpected key ' + key);
|
| },
|
| setItem: function (key, item) {
|
| +key = this._parseKey(key);
|
| var old = this.store[key];
|
| if (old) {
|
| this._removeFromMap(old);
|
| @@ -7479,6 +8013,7 @@ this.pmap[item] = key;
|
| this.store[key] = item;
|
| },
|
| getItem: function (key) {
|
| +key = this._parseKey(key);
|
| return this.store[key];
|
| },
|
| getItems: function () {
|
| @@ -7872,7 +8407,7 @@ this.set('items.' + idx, value);
|
| },
|
| _forwardInstancePath: function (inst, path, value) {
|
| if (path.indexOf(this.as + '.') === 0) {
|
| -this.notifyPath('items.' + inst.__key__ + '.' + path.slice(this.as.length + 1), value);
|
| +this._notifyPath('items.' + inst.__key__ + '.' + path.slice(this.as.length + 1), value);
|
| }
|
| },
|
| _forwardParentProp: function (prop, value) {
|
| @@ -7882,7 +8417,7 @@ inst.__setProperty(prop, value, true);
|
| },
|
| _forwardParentPath: function (path, value) {
|
| this._instances.forEach(function (inst) {
|
| -inst.notifyPath(path, value, true);
|
| +inst._notifyPath(path, value, true);
|
| }, this);
|
| },
|
| _forwardItemPath: function (path, value) {
|
| @@ -7894,7 +8429,7 @@ var inst = this._instances[idx];
|
| if (inst) {
|
| if (dot >= 0) {
|
| path = this.as + '.' + path.substring(dot + 1);
|
| -inst.notifyPath(path, value, true);
|
| +inst._notifyPath(path, value, true);
|
| } else {
|
| inst.__setProperty(this.as, value, true);
|
| }
|
| @@ -7946,6 +8481,7 @@ this.unlinkPaths('selected.' + i);
|
| }
|
| } else {
|
| this.unlinkPaths('selected');
|
| +this.unlinkPaths('selectedItem');
|
| }
|
| if (this.multi) {
|
| if (!this.selected || this.selected.length) {
|
| @@ -8085,7 +8621,7 @@ this._instance[prop] = value;
|
| },
|
| _forwardParentPath: function (path, value) {
|
| if (this._instance) {
|
| -this._instance.notifyPath(path, value, true);
|
| +this._instance._notifyPath(path, value, true);
|
| }
|
| }
|
| });
|
| @@ -8566,6 +9102,13 @@ this.fire('dom-change');
|
| },
|
|
|
| /**
|
| + * The bottom of the scroll.
|
| + */
|
| + get _scrollBottom() {
|
| + return this._scrollPosition + this._viewportSize;
|
| + },
|
| +
|
| + /**
|
| * The n-th item rendered in the last physical item.
|
| */
|
| get _virtualEnd() {
|
| @@ -8720,19 +9263,13 @@ this.fire('dom-change');
|
| * items in the viewport and recycle tiles as needed.
|
| */
|
| _refresh: function() {
|
| - var SCROLL_DIRECTION_UP = -1;
|
| - var SCROLL_DIRECTION_DOWN = 1;
|
| - var SCROLL_DIRECTION_NONE = 0;
|
| -
|
| // clamp the `scrollTop` value
|
| // IE 10|11 scrollTop may go above `_maxScrollTop`
|
| // iOS `scrollTop` may go below 0 and above `_maxScrollTop`
|
| var scrollTop = Math.max(0, Math.min(this._maxScrollTop, this._scroller.scrollTop));
|
| -
|
| - var tileHeight, kth, recycledTileSet;
|
| + var tileHeight, tileTop, kth, recycledTileSet, scrollBottom;
|
| var ratio = this._ratio;
|
| var delta = scrollTop - this._scrollPosition;
|
| - var direction = SCROLL_DIRECTION_NONE;
|
| var recycledTiles = 0;
|
| var hiddenContentSize = this._hiddenContentSize;
|
| var currentRatio = ratio;
|
| @@ -8744,18 +9281,19 @@ this.fire('dom-change');
|
| // clear cached visible index
|
| this._firstVisibleIndexVal = null;
|
|
|
| + scrollBottom = this._scrollBottom;
|
| +
|
| // random access
|
| if (Math.abs(delta) > this._physicalSize) {
|
| this._physicalTop += delta;
|
| - direction = SCROLL_DIRECTION_NONE;
|
| recycledTiles = Math.round(delta / this._physicalAverage);
|
| }
|
| // scroll up
|
| else if (delta < 0) {
|
| var topSpace = scrollTop - this._physicalTop;
|
| var virtualStart = this._virtualStart;
|
| + var physicalBottom = this._physicalBottom;
|
|
|
| - direction = SCROLL_DIRECTION_UP;
|
| recycledTileSet = [];
|
|
|
| kth = this._physicalEnd;
|
| @@ -8768,12 +9306,14 @@ this.fire('dom-change');
|
| // recycle less physical items than the total
|
| recycledTiles < this._physicalCount &&
|
| // ensure that these recycled tiles are needed
|
| - virtualStart - recycledTiles > 0
|
| + virtualStart - recycledTiles > 0 &&
|
| + // ensure that the tile is not visible
|
| + physicalBottom - this._physicalSizes[kth] > scrollBottom
|
| ) {
|
|
|
| - tileHeight = this._physicalSizes[kth] || this._physicalAverage;
|
| + tileHeight = this._physicalSizes[kth];
|
| currentRatio += tileHeight / hiddenContentSize;
|
| -
|
| + physicalBottom -= tileHeight;
|
| recycledTileSet.push(kth);
|
| recycledTiles++;
|
| kth = (kth === 0) ? this._physicalCount - 1 : kth - 1;
|
| @@ -8781,15 +9321,13 @@ this.fire('dom-change');
|
|
|
| movingUp = recycledTileSet;
|
| recycledTiles = -recycledTiles;
|
| -
|
| }
|
| // scroll down
|
| else if (delta > 0) {
|
| - var bottomSpace = this._physicalBottom - (scrollTop + this._viewportSize);
|
| + var bottomSpace = this._physicalBottom - scrollBottom;
|
| var virtualEnd = this._virtualEnd;
|
| var lastVirtualItemIndex = this._virtualCount-1;
|
|
|
| - direction = SCROLL_DIRECTION_DOWN;
|
| recycledTileSet = [];
|
|
|
| kth = this._physicalStart;
|
| @@ -8802,10 +9340,12 @@ this.fire('dom-change');
|
| // recycle less physical items than the total
|
| recycledTiles < this._physicalCount &&
|
| // ensure that these recycled tiles are needed
|
| - virtualEnd + recycledTiles < lastVirtualItemIndex
|
| + virtualEnd + recycledTiles < lastVirtualItemIndex &&
|
| + // ensure that the tile is not visible
|
| + this._physicalTop + this._physicalSizes[kth] < scrollTop
|
| ) {
|
|
|
| - tileHeight = this._physicalSizes[kth] || this._physicalAverage;
|
| + tileHeight = this._physicalSizes[kth];
|
| currentRatio += tileHeight / hiddenContentSize;
|
|
|
| this._physicalTop += tileHeight;
|
| @@ -8815,7 +9355,15 @@ this.fire('dom-change');
|
| }
|
| }
|
|
|
| - if (recycledTiles !== 0) {
|
| + if (recycledTiles === 0) {
|
| + // If the list ever reach this case, the physical average is not significant enough
|
| + // to create all the items needed to cover the entire viewport.
|
| + // e.g. A few items have a height that differs from the average by serveral order of magnitude.
|
| + if (this._increasePoolIfNeeded()) {
|
| + // yield and set models to the new items
|
| + this.async(this._update);
|
| + }
|
| + } else {
|
| this._virtualStart = this._virtualStart + recycledTiles;
|
| this._update(recycledTileSet, movingUp);
|
| }
|
| @@ -8847,7 +9395,7 @@ this.fire('dom-change');
|
|
|
| // increase the pool of physical items if needed
|
| if (this._increasePoolIfNeeded()) {
|
| - // set models to the new items
|
| + // yield set models to the new items
|
| this.async(this._update);
|
| }
|
| },
|
| @@ -8873,7 +9421,7 @@ this.fire('dom-change');
|
| },
|
|
|
| /**
|
| - * Increases the pool size. That is, the physical items in the DOM.
|
| + * Increases the pool of physical items only if needed.
|
| * This function will allocate additional physical items
|
| * (limited by `MAX_PHYSICAL_COUNT`) if the content size is shorter than
|
| * `_optPhysicalSize`
|
| @@ -8881,16 +9429,22 @@ this.fire('dom-change');
|
| * @return boolean
|
| */
|
| _increasePoolIfNeeded: function() {
|
| - if (this._physicalSize >= this._optPhysicalSize || this._physicalAverage === 0) {
|
| + if (this._physicalAverage === 0) {
|
| return false;
|
| }
|
| + if (this._physicalBottom < this._scrollBottom || this._physicalTop > this._scrollPosition) {
|
| + return this._increasePool(1);
|
| + }
|
| + if (this._physicalSize < this._optPhysicalSize) {
|
| + return this._increasePool(Math.round((this._optPhysicalSize - this._physicalSize) * 1.2 / this._physicalAverage));
|
| + }
|
| + return false;
|
| + },
|
|
|
| - // the estimated number of physical items that we will need to reach
|
| - // the cap established by `_optPhysicalSize`.
|
| - var missingItems = Math.round(
|
| - (this._optPhysicalSize - this._physicalSize) * 1.2 / this._physicalAverage
|
| - );
|
| -
|
| + /**
|
| + * Increases the pool size.
|
| + */
|
| + _increasePool: function(missingItems) {
|
| // limit the size
|
| var nextPhysicalCount = Math.min(
|
| this._physicalCount + missingItems,
|
| @@ -8905,11 +9459,8 @@ this.fire('dom-change');
|
| return false;
|
| }
|
|
|
| - var newPhysicalItems = this._createPool(delta);
|
| - var emptyArray = new Array(delta);
|
| -
|
| - [].push.apply(this._physicalItems, newPhysicalItems);
|
| - [].push.apply(this._physicalSizes, emptyArray);
|
| + [].push.apply(this._physicalItems, this._createPool(delta));
|
| + [].push.apply(this._physicalSizes, new Array(delta));
|
|
|
| this._physicalCount = prevPhysicalCount + delta;
|
|
|
| @@ -9304,10 +9855,9 @@ this.fire('dom-change');
|
|
|
| // increase the pool of physical items if needed
|
| if (this._increasePoolIfNeeded()) {
|
| - // set models to the new items
|
| + // yield set models to the new items
|
| this.async(this._update);
|
| }
|
| -
|
| // clear cached visible index
|
| this._firstVisibleIndexVal = null;
|
| },
|
| @@ -9738,6 +10288,7 @@ this.fire('dom-change');
|
| // monostate data
|
| var metaDatas = {};
|
| var metaArrays = {};
|
| + var singleton = null;
|
|
|
| Polymer.IronMeta = Polymer({
|
|
|
| @@ -9790,9 +10341,15 @@ this.fire('dom-change');
|
|
|
| },
|
|
|
| + hostAttributes: {
|
| + hidden: true
|
| + },
|
| +
|
| /**
|
| * Only runs if someone invokes the factory/constructor directly
|
| * e.g. `new Polymer.IronMeta()`
|
| + *
|
| + * @param {{type: (string|undefined), key: (string|undefined), value}=} config
|
| */
|
| factoryImpl: function(config) {
|
| if (config) {
|
| @@ -9884,6 +10441,13 @@ this.fire('dom-change');
|
|
|
| });
|
|
|
| + Polymer.IronMeta.getIronMeta = function getIronMeta() {
|
| + if (singleton === null) {
|
| + singleton = new Polymer.IronMeta();
|
| + }
|
| + return singleton;
|
| + };
|
| +
|
| /**
|
| `iron-meta-query` can be used to access infomation stored in `iron-meta`.
|
|
|
| @@ -9950,6 +10514,8 @@ this.fire('dom-change');
|
| /**
|
| * Actually a factory method, not a true constructor. Only runs if
|
| * someone invokes it directly (via `new Polymer.IronMeta()`);
|
| + *
|
| + * @param {{type: (string|undefined), key: (string|undefined)}=} config
|
| */
|
| factoryImpl: function(config) {
|
| if (config) {
|
| @@ -10086,9 +10652,9 @@ Polymer({
|
| * `iron-iconset-svg` element. Multiple icons should be given distinct id's.
|
| *
|
| * Using svg elements to create icons has a few advantages over traditional
|
| - * bitmap graphics like jpg or png. Icons that use svg are vector based so they
|
| - * are resolution independent and should look good on any device. They are
|
| - * stylable via css. Icons can be themed, colorized, and even animated.
|
| + * bitmap graphics like jpg or png. Icons that use svg are vector based so
|
| + * they are resolution independent and should look good on any device. They
|
| + * are stylable via css. Icons can be themed, colorized, and even animated.
|
| *
|
| * Example:
|
| *
|
| @@ -10096,8 +10662,8 @@ Polymer({
|
| * <svg>
|
| * <defs>
|
| * <g id="shape">
|
| - * <rect x="50" y="50" width="50" height="50" />
|
| - * <circle cx="50" cy="50" r="50" />
|
| + * <rect x="12" y="0" width="12" height="24" />
|
| + * <circle cx="12" cy="12" r="12" />
|
| * </g>
|
| * </defs>
|
| * </svg>
|
| @@ -10113,18 +10679,15 @@ Polymer({
|
| *
|
| * @element iron-iconset-svg
|
| * @demo demo/index.html
|
| + * @implements {Polymer.Iconset}
|
| */
|
| Polymer({
|
| -
|
| is: 'iron-iconset-svg',
|
|
|
| properties: {
|
|
|
| /**
|
| * The name of the iconset.
|
| - *
|
| - * @attribute name
|
| - * @type string
|
| */
|
| name: {
|
| type: String,
|
| @@ -10133,10 +10696,6 @@ Polymer({
|
|
|
| /**
|
| * The size of an individual icon. Note that icons must be square.
|
| - *
|
| - * @attribute iconSize
|
| - * @type number
|
| - * @default 24
|
| */
|
| size: {
|
| type: Number,
|
| @@ -10145,6 +10704,10 @@ Polymer({
|
|
|
| },
|
|
|
| + attached: function() {
|
| + this.style.display = 'none';
|
| + },
|
| +
|
| /**
|
| * Construct an array of all icon names in this iconset.
|
| *
|
| @@ -10166,7 +10729,7 @@ Polymer({
|
| * @method applyIcon
|
| * @param {Element} element Element to which the icon is applied.
|
| * @param {string} iconName Name of the icon to apply.
|
| - * @return {Element} The svg element which renders the icon.
|
| + * @return {?Element} The svg element which renders the icon.
|
| */
|
| applyIcon: function(element, iconName) {
|
| // insert svg element into shadow root, if it exists
|
| @@ -10506,6 +11069,15 @@ Polymer({
|
| }
|
| },
|
|
|
| + /**
|
| + * If true, this property will cause the implementing element to
|
| + * automatically stop propagation on any handled KeyboardEvents.
|
| + */
|
| + stopKeyboardEventPropagation: {
|
| + type: Boolean,
|
| + value: false
|
| + },
|
| +
|
| _boundKeyHandlers: {
|
| type: Array,
|
| value: function() {
|
| @@ -10649,6 +11221,10 @@ Polymer({
|
| },
|
|
|
| _onKeyBindingEvent: function(keyBindings, event) {
|
| + if (this.stopKeyboardEventPropagation) {
|
| + event.stopPropagation();
|
| + }
|
| +
|
| keyBindings.forEach(function(keyBinding) {
|
| var keyCombo = keyBinding[0];
|
| var handlerName = keyBinding[1];
|
| @@ -10662,10 +11238,14 @@ Polymer({
|
| _triggerKeyHandler: function(keyCombo, handlerName, keyboardEvent) {
|
| var detail = Object.create(keyCombo);
|
| detail.keyboardEvent = keyboardEvent;
|
| -
|
| - this[handlerName].call(this, new CustomEvent(keyCombo.event, {
|
| - detail: detail
|
| - }));
|
| + var event = new CustomEvent(keyCombo.event, {
|
| + detail: detail,
|
| + cancelable: true
|
| + });
|
| + this[handlerName].call(this, event);
|
| + if (event.defaultPrevented) {
|
| + keyboardEvent.preventDefault();
|
| + }
|
| }
|
| };
|
| })();
|
| @@ -10729,9 +11309,8 @@ Polymer({
|
| // handled). In either case, we can disregard `event.path`.
|
|
|
| if (event.target === this) {
|
| - var focused = event.type === 'focus';
|
| - this._setFocused(focused);
|
| - } else if (!this.shadowRoot) {
|
| + this._setFocused(event.type === 'focus');
|
| + } else if (!this.shadowRoot && !this.isLightDescendant(event.target)) {
|
| this.fire(event.type, {sourceEvent: event}, {
|
| node: this,
|
| bubbles: event.bubbles,
|
| @@ -10882,14 +11461,43 @@ Polymer({
|
| this._setPressed(false);
|
| },
|
|
|
| + __isFocusedLightDescendant: function(target) {
|
| + var root = Polymer.dom(this).getOwnerRoot() || document;
|
| + var focusedElement = root.activeElement;
|
| +
|
| + // TODO(noms): remove the `this !== target` check once polymer#2610 is fixed.
|
| + return this !== target && this.isLightDescendant(target) && target == focusedElement;
|
| + },
|
| +
|
| + /**
|
| + * @param {!KeyboardEvent} event .
|
| + */
|
| _spaceKeyDownHandler: function(event) {
|
| var keyboardEvent = event.detail.keyboardEvent;
|
| + var target = Polymer.dom(keyboardEvent).localTarget;
|
| +
|
| + // Ignore the event if this is coming from a focused light child, since that
|
| + // element will deal with it.
|
| + if (this.__isFocusedLightDescendant(target))
|
| + return;
|
| +
|
| keyboardEvent.preventDefault();
|
| keyboardEvent.stopImmediatePropagation();
|
| this._setPressed(true);
|
| },
|
|
|
| - _spaceKeyUpHandler: function() {
|
| + /**
|
| + * @param {!KeyboardEvent} event .
|
| + */
|
| + _spaceKeyUpHandler: function(event) {
|
| + var keyboardEvent = event.detail.keyboardEvent;
|
| + var target = Polymer.dom(keyboardEvent).localTarget;
|
| +
|
| + // Ignore the event if this is coming from a focused light child, since that
|
| + // element will deal with it.
|
| + if (this.__isFocusedLightDescendant(target))
|
| + return;
|
| +
|
| if (this.pressed) {
|
| this._asyncClick();
|
| }
|
| @@ -11666,7 +12274,7 @@ Polymer({
|
| /**
|
| * `Polymer.PaperInkyFocusBehavior` implements a ripple when the element has keyboard focus.
|
| *
|
| - * @polymerBehavior Polymer.PaperInkyFocusBehaviorImpl
|
| + * @polymerBehavior Polymer.PaperInkyFocusBehavior
|
| */
|
| Polymer.PaperInkyFocusBehaviorImpl = {
|
|
|
| @@ -11704,7 +12312,6 @@ Polymer({
|
| is: 'paper-material',
|
|
|
| properties: {
|
| -
|
| /**
|
| * The z-depth of this element, from 0-5. Setting to 0 will remove the
|
| * shadow, and each increasing number greater than 0 will be "deeper"
|
| @@ -11846,11 +12453,11 @@ Polymer({
|
| }
|
| }
|
| });
|
| -/**
|
| +/**
|
| * `iron-range-behavior` provides the behavior for something with a minimum to maximum range.
|
| *
|
| * @demo demo/index.html
|
| - * @polymerBehavior
|
| + * @polymerBehavior
|
| */
|
| Polymer.IronRangeBehavior = {
|
|
|
| @@ -11919,7 +12526,7 @@ Polymer({
|
| _calcStep: function(value) {
|
| /**
|
| * if we calculate the step using
|
| - * `Math.round(value / step) * step` we may hit a precision point issue
|
| + * `Math.round(value / step) * step` we may hit a precision point issue
|
| * eg. 0.1 * 0.2 = 0.020000000000000004
|
| * http://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html
|
| *
|
| @@ -11927,7 +12534,8 @@ Polymer({
|
| */
|
| // polymer/issues/2493
|
| value = parseFloat(value);
|
| - return this.step ? (Math.round((value + this.min) / this.step) / (1 / this.step)) - this.min : value;
|
| + return this.step ? (Math.round((value + this.min) / this.step) -
|
| + (this.min / this.step)) / (1 / this.step) : value;
|
| },
|
|
|
| _validateValue: function() {
|
| @@ -12382,7 +12990,7 @@ Polymer({
|
| is: 'paper-item',
|
|
|
| hostAttributes: {
|
| - role: 'listitem',
|
| + role: 'option',
|
| tabindex: '0'
|
| },
|
|
|
| @@ -12542,6 +13150,8 @@ Polymer({
|
|
|
| /**
|
| * Returns the currently selected item.
|
| + *
|
| + * @type {?Object}
|
| */
|
| selectedItem: {
|
| type: Object,
|
| @@ -12583,10 +13193,20 @@ Polymer({
|
| },
|
|
|
| /**
|
| + * The list of items from which a selection can be made.
|
| + */
|
| + items: {
|
| + type: Array,
|
| + readOnly: true,
|
| + value: function() {
|
| + return [];
|
| + }
|
| + },
|
| +
|
| + /**
|
| * The set of excluded elements where the key is the `localName`
|
| * of the element that will be ignored from the item list.
|
| *
|
| - * @type {object}
|
| * @default {template: 1}
|
| */
|
| _excludedLocalNames: {
|
| @@ -12606,15 +13226,12 @@ Polymer({
|
| created: function() {
|
| this._bindFilterItem = this._filterItem.bind(this);
|
| this._selection = new Polymer.IronSelection(this._applySelection.bind(this));
|
| - // TODO(cdata): When polymer/polymer#2535 lands, we do not need to do this
|
| - // book keeping anymore:
|
| - this.__listeningForActivate = false;
|
| },
|
|
|
| attached: function() {
|
| this._observer = this._observeItems(this);
|
| - this._contentObserver = this._observeContent(this);
|
| - if (!this.selectedItem && this.selected) {
|
| + this._updateItems();
|
| + if (!this._shouldUpdateSelection) {
|
| this._updateSelected(this.attrForSelected,this.selected)
|
| }
|
| this._addListener(this.activateEvent);
|
| @@ -12622,26 +13239,12 @@ Polymer({
|
|
|
| detached: function() {
|
| if (this._observer) {
|
| - this._observer.disconnect();
|
| - }
|
| - if (this._contentObserver) {
|
| - this._contentObserver.disconnect();
|
| + Polymer.dom(this).unobserveNodes(this._observer);
|
| }
|
| this._removeListener(this.activateEvent);
|
| },
|
|
|
| /**
|
| - * Returns an array of selectable items.
|
| - *
|
| - * @property items
|
| - * @type Array
|
| - */
|
| - get items() {
|
| - var nodes = Polymer.dom(this).queryDistributedElements(this.selectable || '*');
|
| - return Array.prototype.filter.call(nodes, this._bindFilterItem);
|
| - },
|
| -
|
| - /**
|
| * Returns the index of the given item.
|
| *
|
| * @method indexOf
|
| @@ -12683,18 +13286,16 @@ Polymer({
|
| this.selected = this._indexToValue(index);
|
| },
|
|
|
| - _addListener: function(eventName) {
|
| - if (!this.isAttached || this.__listeningForActivate) {
|
| - return;
|
| - }
|
| + get _shouldUpdateSelection() {
|
| + return this.selected != null;
|
| + },
|
|
|
| - this.__listeningForActivate = true;
|
| + _addListener: function(eventName) {
|
| this.listen(this, eventName, '_activateHandler');
|
| },
|
|
|
| _removeListener: function(eventName) {
|
| this.unlisten(this, eventName, '_activateHandler');
|
| - this.__listeningForActivate = false;
|
| },
|
|
|
| _activateEventChanged: function(eventName, old) {
|
| @@ -12702,6 +13303,12 @@ Polymer({
|
| this._addListener(eventName);
|
| },
|
|
|
| + _updateItems: function() {
|
| + var nodes = Polymer.dom(this).queryDistributedElements(this.selectable || '*');
|
| + nodes = Array.prototype.filter.call(nodes, this._bindFilterItem);
|
| + this._setItems(nodes);
|
| + },
|
| +
|
| _updateSelected: function() {
|
| this._selectSelected(this.selected);
|
| },
|
| @@ -12760,18 +13367,9 @@ Polymer({
|
| this._setSelectedItem(this._selection.get());
|
| },
|
|
|
| - // observe content changes under the given node.
|
| - _observeContent: function(node) {
|
| - var content = node.querySelector('content');
|
| - if (content && content.parentElement === node) {
|
| - return this._observeItems(node.domHost);
|
| - }
|
| - },
|
| -
|
| // observe items change under the given node.
|
| _observeItems: function(node) {
|
| - // TODO(cdata): Update this when we get distributed children changed.
|
| - var observer = new MutationObserver(function(mutations) {
|
| + return Polymer.dom(node).observeNodes(function(mutations) {
|
| // Let other interested parties know about the change so that
|
| // we don't have to recreate mutation observers everywher.
|
| this.fire('iron-items-changed', mutations, {
|
| @@ -12779,15 +13377,12 @@ Polymer({
|
| cancelable: false
|
| });
|
|
|
| - if (this.selected != null) {
|
| + this._updateItems();
|
| +
|
| + if (this._shouldUpdateSelection) {
|
| this._updateSelected();
|
| }
|
| - }.bind(this));
|
| - observer.observe(node, {
|
| - childList: true,
|
| - subtree: true
|
| });
|
| - return observer;
|
| },
|
|
|
| _activateHandler: function(e) {
|
| @@ -12872,6 +13467,11 @@ Polymer({
|
| this._selection.multi = multi;
|
| },
|
|
|
| + get _shouldUpdateSelection() {
|
| + return this.selected != null ||
|
| + (this.selectedValues != null && this.selectedValues.length);
|
| + },
|
| +
|
| _updateSelected: function() {
|
| if (this.multi) {
|
| this._selectMulti(this.selectedValues);
|
| @@ -13416,6 +14016,10 @@ CSS properties | Action
|
| if (!this._fitInfo.positionedBy.horizontally) {
|
| this.style.left = '0px';
|
| }
|
| + if (!this._fitInfo.positionedBy.vertically || !this._fitInfo.positionedBy.horizontally) {
|
| + // need position:fixed to properly size the element
|
| + this.style.position = 'fixed';
|
| + }
|
| // need border-box for margin/padding
|
| this.sizingTarget.style.boxSizing = 'border-box';
|
| // constrain the width and height if not already set
|
| @@ -15407,7 +16011,20 @@ Polymer({
|
| }
|
| });
|
| /**
|
| - * Use `Polymer.IronValidatableBehavior` to implement an element that validates user input.
|
| + * `Use Polymer.IronValidatableBehavior` to implement an element that validates user input.
|
| + * Use the related `Polymer.IronValidatorBehavior` to add custom validation logic to an iron-input.
|
| + *
|
| + * By default, an `<iron-form>` element validates its fields when the user presses the submit button.
|
| + * To validate a form imperatively, call the form's `validate()` method, which in turn will
|
| + * call `validate()` on all its children. By using `Polymer.IronValidatableBehavior`, your
|
| + * custom element will get a public `validate()`, which
|
| + * will return the validity of the element, and a corresponding `invalid` attribute,
|
| + * which can be used for styling.
|
| + *
|
| + * To implement the custom validation logic of your element, you must override
|
| + * the protected `_getValidity()` method of this behaviour, rather than `validate()`.
|
| + * See [this](https://github.com/PolymerElements/iron-form/blob/master/demo/simple-element.html)
|
| + * for an example.
|
| *
|
| * ### Accessibility
|
| *
|
| @@ -15883,6 +16500,21 @@ Polymer({
|
| } else {
|
| this._handleValue(this._inputElement);
|
| }
|
| +
|
| + this._numberOfPrefixNodes = 0;
|
| + this._prefixObserver = Polymer.dom(this.$.prefix).observeNodes(
|
| + function(mutations) {
|
| + // Keep track whether there's at least one prefix node, since it
|
| + // affects laying out the floating label.
|
| + this._numberOfPrefixNodes += mutations.addedNodes.length -
|
| + mutations.removedNodes.length;
|
| + }.bind(this));
|
| + },
|
| +
|
| + detached: function() {
|
| + if (this._prefixObserver) {
|
| + Polymer.dom(this.$.prefix).unobserveNodes(this._prefixObserver);
|
| + }
|
| },
|
|
|
| _onAddonAttached: function(event) {
|
| @@ -15979,16 +16611,15 @@ Polymer({
|
| } else if (focused) {
|
| cls += " label-is-highlighted";
|
| }
|
| - // The label might have a horizontal offset if a prefix element exists
|
| + // If a prefix element exists, the label has a horizontal offset
|
| // which needs to be undone when displayed as a floating label.
|
| - if (Polymer.dom(this.$.prefix).getDistributedNodes().length > 0 &&
|
| - label && label.offsetParent) {
|
| - label.style.left = -label.offsetParent.offsetLeft + 'px';
|
| + if (this._numberOfPrefixNodes > 0) {
|
| + this.$.labelAndInputContainer.style.position = 'static';
|
| }
|
| } else {
|
| // When the label is not floating, it should overlap the input element.
|
| if (label) {
|
| - label.style.left = 0;
|
| + this.$.labelAndInputContainer.style.position = 'relative';
|
| }
|
| }
|
| } else {
|
| @@ -16200,15 +16831,56 @@ cr.define('downloads', function() {
|
|
|
| properties: {
|
| hasDownloads_: {
|
| + observer: 'hasDownloadsChanged_',
|
| type: Boolean,
|
| - value: false,
|
| },
|
|
|
| items_: {
|
| type: Array,
|
| + value: function() { return []; },
|
| },
|
| },
|
|
|
| + observers: [
|
| + 'itemsChanged_(items_.*)',
|
| + ],
|
| +
|
| + /** @private */
|
| + clearAll_: function() {
|
| + this.set('items_', []);
|
| + },
|
| +
|
| + /** @private */
|
| + hasDownloadsChanged_: function() {
|
| + if (loadTimeData.getBoolean('allowDeletingHistory'))
|
| + this.$.toolbar.downloadsShowing = this.hasDownloads_;
|
| +
|
| + if (this.hasDownloads_) {
|
| + this.$['downloads-list'].fire('iron-resize');
|
| + } else {
|
| + var isSearching = downloads.ActionService.getInstance().isSearching();
|
| + var messageToShow = isSearching ? 'noSearchResults' : 'noDownloads';
|
| + this.$['no-downloads'].querySelector('span').textContent =
|
| + loadTimeData.getString(messageToShow);
|
| + }
|
| + },
|
| +
|
| + /**
|
| + * @param {number} index
|
| + * @param {!Array<!downloads.Data>} list
|
| + * @private
|
| + */
|
| + insertItems_: function(index, list) {
|
| + this.splice.apply(this, ['items_', index, 0].concat(list));
|
| + this.updateHideDates_(index, index + list.length);
|
| + this.$.panel.classList.remove('loading');
|
| + },
|
| +
|
| + /** @private */
|
| + itemsChanged_: function() {
|
| + this.hasDownloads_ = this.items_.length > 0;
|
| + },
|
| +
|
| /**
|
| * @param {Event} e
|
| * @private
|
| @@ -16247,78 +16919,64 @@ cr.define('downloads', function() {
|
| },
|
|
|
| /**
|
| - * @return {number} The number of downloads shown on the page.
|
| + * @param {number} index
|
| * @private
|
| */
|
| - size_: function() {
|
| - return this.items_.length;
|
| + removeItem_: function(index) {
|
| + this.splice('items_', index, 1);
|
| + this.updateHideDates_(index, index);
|
| },
|
|
|
| /**
|
| - * Called when all items need to be updated.
|
| - * @param {!Array<!downloads.Data>} list A list of new download data.
|
| + * @param {number} start
|
| + * @param {number} end
|
| * @private
|
| */
|
| - updateAll_: function(list) {
|
| - /** @private {!Object<number>} */
|
| - this.idToIndex_ = {};
|
| -
|
| - for (var i = 0; i < list.length; ++i) {
|
| - var data = list[i];
|
| -
|
| - this.idToIndex_[data.id] = data.index = i;
|
| -
|
| - var prev = list[i - 1];
|
| - data.hideDate = !!prev && prev.date_string == data.date_string;
|
| + updateHideDates_: function(start, end) {
|
| + for (var i = start; i <= end; ++i) {
|
| + var current = this.items_[i];
|
| + if (!current)
|
| + continue;
|
| + var prev = this.items_[i - 1];
|
| + current.hideDate = !!prev && prev.date_string == current.date_string;
|
| }
|
| -
|
| - // TODO(dbeam): this resets the scroll position, which is a huge bummer.
|
| - // Removing something from the bottom of the list should not scroll you
|
| - // back to the top. The grand plan is to restructure how the C++ sends the
|
| - // JS data so that it only gets updates (rather than the most recent set
|
| - // of items). TL;DR - we can't ship with this bug.
|
| - this.items_ = list;
|
| -
|
| - var hasDownloads = this.size_() > 0;
|
| - if (!hasDownloads) {
|
| - var isSearching = downloads.ActionService.getInstance().isSearching();
|
| - var messageToShow = isSearching ? 'noSearchResults' : 'noDownloads';
|
| - this.$['no-downloads'].querySelector('span').textContent =
|
| - loadTimeData.getString(messageToShow);
|
| - }
|
| - this.hasDownloads_ = hasDownloads;
|
| -
|
| - if (loadTimeData.getBoolean('allowDeletingHistory'))
|
| - this.$.toolbar.downloadsShowing = this.hasDownloads_;
|
| -
|
| - this.$.panel.classList.remove('loading');
|
| },
|
|
|
| /**
|
| + * @param {number} index
|
| * @param {!downloads.Data} data
|
| * @private
|
| */
|
| - updateItem_: function(data) {
|
| - var index = this.idToIndex_[data.id];
|
| + updateItem_: function(index, data) {
|
| this.set('items_.' + index, data);
|
| + this.updateHideDates_(index, index);
|
| this.$['downloads-list'].updateSizeForItem(index);
|
| },
|
| });
|
|
|
| - Manager.size = function() {
|
| - return document.querySelector('downloads-manager').size_();
|
| + Manager.clearAll = function() {
|
| + Manager.get().clearAll_();
|
| };
|
|
|
| - Manager.updateAll = function(list) {
|
| - document.querySelector('downloads-manager').updateAll_(list);
|
| + /** @return {!downloads.Manager} */
|
| + Manager.get = function() {
|
| + return queryRequiredElement('downloads-manager');
|
| };
|
|
|
| - Manager.updateItem = function(item) {
|
| - document.querySelector('downloads-manager').updateItem_(item);
|
| + Manager.insertItems = function(index, list) {
|
| + Manager.get().insertItems_(index, list);
|
| };
|
|
|
| Manager.onLoad = function() {
|
| - document.querySelector('downloads-manager').onLoad_();
|
| + Manager.get().onLoad_();
|
| + };
|
| +
|
| + Manager.removeItem = function(index) {
|
| + Manager.get().removeItem_(index);
|
| + };
|
| +
|
| + Manager.updateItem = function(index, data) {
|
| + Manager.get().updateItem_(index, data);
|
| };
|
|
|
| return {Manager: Manager};
|
|
|