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

Side by Side Diff: chrome/browser/resources/md_downloads/crisper.js

Issue 1428833005: MD Downloads: track downloads in C++, dispatch discrete JS updates (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: moar testz Created 5 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2015 The Chromium Authors. All rights reserved. 1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 if (typeof Polymer == 'undefined') 5 if (typeof Polymer == 'undefined')
6 Polymer = {dom: 'shadow'}; 6 Polymer = {dom: 'shadow'};
7 else 7 else
8 console.error('Polymer is already defined.'); 8 console.error('Polymer is already defined.');
9 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 9 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
10 // Use of this source code is governed by a BSD-style license that can be 10 // Use of this source code is governed by a BSD-style license that can be
(...skipping 1543 matching lines...) Expand 10 before | Expand all | Expand 10 after
1554 }, 1554 },
1555 1555
1556 /** @param {string} id ID of the download that the user started dragging. */ 1556 /** @param {string} id ID of the download that the user started dragging. */
1557 drag: chromeSendWithId('drag'), 1557 drag: chromeSendWithId('drag'),
1558 1558
1559 /** 1559 /**
1560 * @return {boolean} Whether the user is currently searching for downloads 1560 * @return {boolean} Whether the user is currently searching for downloads
1561 * (i.e. has a non-empty search term). 1561 * (i.e. has a non-empty search term).
1562 */ 1562 */
1563 isSearching: function() { 1563 isSearching: function() {
1564 return this.searchText_.length > 0; 1564 return (this.searchText_ || '').length > 0;
1565 }, 1565 },
1566 1566
1567 /** Opens the current local destination for downloads. */ 1567 /** Opens the current local destination for downloads. */
1568 openDownloadsFolder: chrome.send.bind(chrome, 'openDownloadsFolder'), 1568 openDownloadsFolder: chrome.send.bind(chrome, 'openDownloadsFolder'),
1569 1569
1570 /** 1570 /**
1571 * @param {string} id ID of the download to run locally on the user's box. 1571 * @param {string} id ID of the download to run locally on the user's box.
1572 */ 1572 */
1573 openFile: chromeSendWithId('openFile'), 1573 openFile: chromeSendWithId('openFile'),
1574 1574
(...skipping 14 matching lines...) Expand all
1589 1589
1590 /** @param {string} searchText What to search for. */ 1590 /** @param {string} searchText What to search for. */
1591 search: function(searchText) { 1591 search: function(searchText) {
1592 if (this.searchText_ == searchText) 1592 if (this.searchText_ == searchText)
1593 return; 1593 return;
1594 1594
1595 this.searchText_ = searchText; 1595 this.searchText_ = searchText;
1596 1596
1597 // Split quoted terms (e.g., 'The "lazy" dog' => ['The', 'lazy', 'dog']). 1597 // Split quoted terms (e.g., 'The "lazy" dog' => ['The', 'lazy', 'dog']).
1598 function trim(s) { return s.trim(); } 1598 function trim(s) { return s.trim(); }
1599 chrome.send('getDownloads', searchText.split(/"([^"]*)"/).map(trim)); 1599 chrome.send('getDownloads',
1600 searchText ? searchText.split(/"([^"]*)"/).map(trim) : []);
1600 }, 1601 },
1601 1602
1602 /** 1603 /**
1603 * Shows the local folder a finished download resides in. 1604 * Shows the local folder a finished download resides in.
1604 * @param {string} id ID of the download to show. 1605 * @param {string} id ID of the download to show.
1605 */ 1606 */
1606 show: chromeSendWithId('show'), 1607 show: chromeSendWithId('show'),
1607 1608
1608 /** Undo download removal. */ 1609 /** Undo download removal. */
1609 undo: chrome.send.bind(chrome, 'undo'), 1610 undo: chrome.send.bind(chrome, 'undo'),
(...skipping 428 matching lines...) Expand 10 before | Expand all | Expand 10 after
2038 } 2039 }
2039 return m; 2040 return m;
2040 } 2041 }
2041 } 2042 }
2042 }); 2043 });
2043 var cePolyfill = window.CustomElements && !CustomElements.useNative; 2044 var cePolyfill = window.CustomElements && !CustomElements.useNative;
2044 document.registerElement('dom-module', DomModule); 2045 document.registerElement('dom-module', DomModule);
2045 function forceDocumentUpgrade() { 2046 function forceDocumentUpgrade() {
2046 if (cePolyfill) { 2047 if (cePolyfill) {
2047 var script = document._currentScript || document.currentScript; 2048 var script = document._currentScript || document.currentScript;
2048 var doc = script && script.ownerDocument; 2049 var doc = script && script.ownerDocument || document;
2049 if (doc) { 2050 if (doc) {
2050 CustomElements.upgradeAll(doc); 2051 CustomElements.upgradeAll(doc);
2051 } 2052 }
2052 } 2053 }
2053 } 2054 }
2054 }()); 2055 }());
2055 Polymer.Base._addFeature({ 2056 Polymer.Base._addFeature({
2056 _prepIs: function () { 2057 _prepIs: function () {
2057 if (!this.is) { 2058 if (!this.is) {
2058 var module = (document._currentScript || document.currentScript).parentNode; 2059 var module = (document._currentScript || document.currentScript).parentNode;
(...skipping 291 matching lines...) Expand 10 before | Expand all | Expand 10 after
2350 debouncer.complete(); 2351 debouncer.complete();
2351 } 2352 }
2352 }, 2353 },
2353 cancelDebouncer: function (jobName) { 2354 cancelDebouncer: function (jobName) {
2354 var debouncer = this._debouncers[jobName]; 2355 var debouncer = this._debouncers[jobName];
2355 if (debouncer) { 2356 if (debouncer) {
2356 debouncer.stop(); 2357 debouncer.stop();
2357 } 2358 }
2358 } 2359 }
2359 }); 2360 });
2360 Polymer.version = '1.1.5'; 2361 Polymer.version = '1.2.1';
2361 Polymer.Base._addFeature({ 2362 Polymer.Base._addFeature({
2362 _registerFeatures: function () { 2363 _registerFeatures: function () {
2363 this._prepIs(); 2364 this._prepIs();
2364 this._prepAttributes(); 2365 this._prepAttributes();
2365 this._prepBehaviors(); 2366 this._prepBehaviors();
2366 this._prepConstructor(); 2367 this._prepConstructor();
2367 }, 2368 },
2368 _prepBehavior: function (b) { 2369 _prepBehavior: function (b) {
2369 this._addHostAttributes(b.hostAttributes); 2370 this._addHostAttributes(b.hostAttributes);
2370 }, 2371 },
(...skipping 260 matching lines...) Expand 10 before | Expand all | Expand 10 after
2631 }, 2632 },
2632 calculateSplices: function (current, previous) { 2633 calculateSplices: function (current, previous) {
2633 return this.calcSplices(current, 0, current.length, previous, 0, previous.length ); 2634 return this.calcSplices(current, 0, current.length, previous, 0, previous.length );
2634 }, 2635 },
2635 equals: function (currentValue, previousValue) { 2636 equals: function (currentValue, previousValue) {
2636 return currentValue === previousValue; 2637 return currentValue === previousValue;
2637 } 2638 }
2638 }; 2639 };
2639 return new ArraySplice(); 2640 return new ArraySplice();
2640 }(); 2641 }();
2641 Polymer.EventApi = function () {
2642 var Settings = Polymer.Settings;
2643 var EventApi = function (event) {
2644 this.event = event;
2645 };
2646 if (Settings.useShadow) {
2647 EventApi.prototype = {
2648 get rootTarget() {
2649 return this.event.path[0];
2650 },
2651 get localTarget() {
2652 return this.event.target;
2653 },
2654 get path() {
2655 return this.event.path;
2656 }
2657 };
2658 } else {
2659 EventApi.prototype = {
2660 get rootTarget() {
2661 return this.event.target;
2662 },
2663 get localTarget() {
2664 var current = this.event.currentTarget;
2665 var currentRoot = current && Polymer.dom(current).getOwnerRoot();
2666 var p$ = this.path;
2667 for (var i = 0; i < p$.length; i++) {
2668 if (Polymer.dom(p$[i]).getOwnerRoot() === currentRoot) {
2669 return p$[i];
2670 }
2671 }
2672 },
2673 get path() {
2674 if (!this.event._path) {
2675 var path = [];
2676 var o = this.rootTarget;
2677 while (o) {
2678 path.push(o);
2679 o = Polymer.dom(o).parentNode || o.host;
2680 }
2681 path.push(window);
2682 this.event._path = path;
2683 }
2684 return this.event._path;
2685 }
2686 };
2687 }
2688 var factory = function (event) {
2689 if (!event.__eventApi) {
2690 event.__eventApi = new EventApi(event);
2691 }
2692 return event.__eventApi;
2693 };
2694 return { factory: factory };
2695 }();
2696 Polymer.domInnerHTML = function () { 2642 Polymer.domInnerHTML = function () {
2697 var escapeAttrRegExp = /[&\u00A0"]/g; 2643 var escapeAttrRegExp = /[&\u00A0"]/g;
2698 var escapeDataRegExp = /[&\u00A0<>]/g; 2644 var escapeDataRegExp = /[&\u00A0<>]/g;
2699 function escapeReplace(c) { 2645 function escapeReplace(c) {
2700 switch (c) { 2646 switch (c) {
2701 case '&': 2647 case '&':
2702 return '&amp;'; 2648 return '&amp;';
2703 case '<': 2649 case '<':
2704 return '&lt;'; 2650 return '&lt;';
2705 case '>': 2651 case '>':
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after
2811 this.node = wrap(node); 2757 this.node = wrap(node);
2812 if (this.patch) { 2758 if (this.patch) {
2813 this.patch(); 2759 this.patch();
2814 } 2760 }
2815 }; 2761 };
2816 } 2762 }
2817 DomApi.prototype = { 2763 DomApi.prototype = {
2818 flush: function () { 2764 flush: function () {
2819 Polymer.dom.flush(); 2765 Polymer.dom.flush();
2820 }, 2766 },
2767 deepContains: function (node) {
2768 if (this.node.contains(node)) {
2769 return true;
2770 }
2771 var n = node;
2772 var wrappedDocument = wrap(document);
2773 while (n && n !== wrappedDocument && n !== this.node) {
2774 n = Polymer.dom(n).parentNode || n.host;
2775 }
2776 return n === this.node;
2777 },
2821 _lazyDistribute: function (host) { 2778 _lazyDistribute: function (host) {
2822 if (host.shadyRoot && host.shadyRoot._distributionClean) { 2779 if (host.shadyRoot && host.shadyRoot._distributionClean) {
2823 host.shadyRoot._distributionClean = false; 2780 host.shadyRoot._distributionClean = false;
2824 Polymer.dom.addDebouncer(host.debounce('_distribute', host._distributeContent)); 2781 Polymer.dom.addDebouncer(host.debounce('_distribute', host._distributeContent));
2825 } 2782 }
2826 }, 2783 },
2827 appendChild: function (node) { 2784 appendChild: function (node) {
2828 return this._addNode(node); 2785 return this._addNode(node);
2829 }, 2786 },
2830 insertBefore: function (node, ref_node) { 2787 insertBefore: function (node, ref_node) {
2831 return this._addNode(node, ref_node); 2788 return this._addNode(node, ref_node);
2832 }, 2789 },
2833 _addNode: function (node, ref_node) { 2790 _addNode: function (node, ref_node) {
2834 this._removeNodeFromHost(node, true); 2791 this._removeNodeFromParent(node);
2835 var addedInsertionPoint; 2792 var addedInsertionPoint;
2836 var root = this.getOwnerRoot(); 2793 var root = this.getOwnerRoot();
2837 if (root) { 2794 if (root) {
2838 addedInsertionPoint = this._maybeAddInsertionPoint(node, this.node); 2795 addedInsertionPoint = this._maybeAddInsertionPoint(node, this.node);
2839 } 2796 }
2840 if (this._nodeHasLogicalChildren(this.node)) { 2797 if (this._nodeHasLogicalChildren(this.node)) {
2841 if (ref_node) { 2798 if (ref_node) {
2842 var children = this.childNodes; 2799 var children = this.childNodes;
2843 var index = children.indexOf(ref_node); 2800 var index = children.indexOf(ref_node);
2844 if (index < 0) { 2801 if (index < 0) {
(...skipping 11 matching lines...) Expand all
2856 addToComposedParent(container, node, ref_node); 2813 addToComposedParent(container, node, ref_node);
2857 if (ref_node) { 2814 if (ref_node) {
2858 nativeInsertBefore.call(container, node, ref_node); 2815 nativeInsertBefore.call(container, node, ref_node);
2859 } else { 2816 } else {
2860 nativeAppendChild.call(container, node); 2817 nativeAppendChild.call(container, node);
2861 } 2818 }
2862 } 2819 }
2863 if (addedInsertionPoint) { 2820 if (addedInsertionPoint) {
2864 this._updateInsertionPoints(root.host); 2821 this._updateInsertionPoints(root.host);
2865 } 2822 }
2823 this.notifyObserver();
2866 return node; 2824 return node;
2867 }, 2825 },
2868 removeChild: function (node) { 2826 removeChild: function (node) {
2869 if (factory(node).parentNode !== this.node) { 2827 if (factory(node).parentNode !== this.node) {
2870 console.warn('The node to be removed is not a child of this node', node); 2828 console.warn('The node to be removed is not a child of this node', node);
2871 } 2829 }
2872 this._removeNodeFromHost(node); 2830 this._removeNodeFromHost(node);
2873 if (!this._maybeDistribute(node, this.node)) { 2831 if (!this._maybeDistribute(node, this.node)) {
2874 var container = this.node._isShadyRoot ? this.node.host : this.node; 2832 var container = this.node._isShadyRoot ? this.node.host : this.node;
2875 if (container === node.parentNode) { 2833 if (container === node.parentNode) {
2876 removeFromComposedParent(container, node); 2834 removeFromComposedParent(container, node);
2877 nativeRemoveChild.call(container, node); 2835 nativeRemoveChild.call(container, node);
2878 } 2836 }
2879 } 2837 }
2838 this.notifyObserver();
2880 return node; 2839 return node;
2881 }, 2840 },
2882 replaceChild: function (node, ref_node) { 2841 replaceChild: function (node, ref_node) {
2883 this.insertBefore(node, ref_node); 2842 this.insertBefore(node, ref_node);
2884 this.removeChild(ref_node); 2843 this.removeChild(ref_node);
2885 return node; 2844 return node;
2886 }, 2845 },
2887 _hasCachedOwnerRoot: function (node) { 2846 _hasCachedOwnerRoot: function (node) {
2888 return Boolean(node._ownerShadyRoot !== undefined); 2847 return Boolean(node._ownerShadyRoot !== undefined);
2889 }, 2848 },
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after
2962 saveLightChildrenIfNeeded(c); 2921 saveLightChildrenIfNeeded(c);
2963 saveLightChildrenIfNeeded(factory(c).parentNode); 2922 saveLightChildrenIfNeeded(factory(c).parentNode);
2964 } 2923 }
2965 }, 2924 },
2966 _nodeHasLogicalChildren: function (node) { 2925 _nodeHasLogicalChildren: function (node) {
2967 return Boolean(node._lightChildren !== undefined); 2926 return Boolean(node._lightChildren !== undefined);
2968 }, 2927 },
2969 _parentNeedsDistribution: function (parent) { 2928 _parentNeedsDistribution: function (parent) {
2970 return parent && parent.shadyRoot && hasInsertionPoint(parent.shadyRoot); 2929 return parent && parent.shadyRoot && hasInsertionPoint(parent.shadyRoot);
2971 }, 2930 },
2931 _removeNodeFromParent: function (node) {
2932 var parent = node._lightParent || node.parentNode;
2933 if (parent && hasDomApi(parent)) {
2934 factory(parent).notifyObserver();
2935 }
2936 this._removeNodeFromHost(node, true);
2937 },
2972 _removeNodeFromHost: function (node, ensureComposedRemoval) { 2938 _removeNodeFromHost: function (node, ensureComposedRemoval) {
2973 var hostNeedsDist; 2939 var hostNeedsDist;
2974 var root; 2940 var root;
2975 var parent = node._lightParent; 2941 var parent = node._lightParent;
2976 if (parent) { 2942 if (parent) {
2977 factory(node)._distributeParent(); 2943 factory(node)._distributeParent();
2978 root = this._ownerShadyRootForNode(node); 2944 root = this._ownerShadyRootForNode(node);
2979 if (root) { 2945 if (root) {
2980 root.host._elementRemove(node); 2946 root.host._elementRemove(node);
2981 hostNeedsDist = this._removeDistributedChildren(root, node); 2947 hostNeedsDist = this._removeDistributedChildren(root, node);
2982 } 2948 }
2983 this._removeLogicalInfo(node, node._lightParent); 2949 this._removeLogicalInfo(node, parent);
2984 } 2950 }
2985 this._removeOwnerShadyRoot(node); 2951 this._removeOwnerShadyRoot(node);
2986 if (root && hostNeedsDist) { 2952 if (root && hostNeedsDist) {
2987 this._updateInsertionPoints(root.host); 2953 this._updateInsertionPoints(root.host);
2988 this._lazyDistribute(root.host); 2954 this._lazyDistribute(root.host);
2989 } else if (ensureComposedRemoval) { 2955 } else if (ensureComposedRemoval) {
2990 removeFromComposedParent(getComposedParent(node), node); 2956 removeFromComposedParent(getComposedParent(node), node);
2991 } 2957 }
2992 }, 2958 },
2993 _removeDistributedChildren: function (root, container) { 2959 _removeDistributedChildren: function (root, container) {
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after
3092 } 3058 }
3093 this._queryElements(factory(node).childNodes, matcher, list); 3059 this._queryElements(factory(node).childNodes, matcher, list);
3094 }, 3060 },
3095 getDestinationInsertionPoints: function () { 3061 getDestinationInsertionPoints: function () {
3096 return this.node._destinationInsertionPoints || []; 3062 return this.node._destinationInsertionPoints || [];
3097 }, 3063 },
3098 getDistributedNodes: function () { 3064 getDistributedNodes: function () {
3099 return this.node._distributedNodes || []; 3065 return this.node._distributedNodes || [];
3100 }, 3066 },
3101 queryDistributedElements: function (selector) { 3067 queryDistributedElements: function (selector) {
3102 var c$ = this.childNodes; 3068 var c$ = this.getEffectiveChildNodes();
3103 var list = []; 3069 var list = [];
3104 this._distributedFilter(selector, c$, list);
3105 for (var i = 0, l = c$.length, c; i < l && (c = c$[i]); i++) { 3070 for (var i = 0, l = c$.length, c; i < l && (c = c$[i]); i++) {
3106 if (c.localName === CONTENT) { 3071 if (c.nodeType === Node.ELEMENT_NODE && matchesSelector.call(c, selector)) {
3107 this._distributedFilter(selector, factory(c).getDistributedNodes(), list); 3072 list.push(c);
3108 } 3073 }
3109 } 3074 }
3110 return list; 3075 return list;
3111 }, 3076 },
3112 _distributedFilter: function (selector, list, results) { 3077 getEffectiveChildNodes: function () {
3113 results = results || []; 3078 var list = [];
3114 for (var i = 0, l = list.length, d; i < l && (d = list[i]); i++) { 3079 var c$ = this.childNodes;
3115 if (d.nodeType === Node.ELEMENT_NODE && d.localName !== CONTENT && matchesSelect or.call(d, selector)) { 3080 for (var i = 0, l = c$.length, c; i < l && (c = c$[i]); i++) {
3116 results.push(d); 3081 if (c.localName === CONTENT) {
3082 var d$ = factory(c).getDistributedNodes();
3083 for (var j = 0; j < d$.length; j++) {
3084 list.push(d$[j]);
3085 }
3086 } else {
3087 list.push(c);
3117 } 3088 }
3118 } 3089 }
3119 return results; 3090 return list;
3120 }, 3091 },
3121 _clear: function () { 3092 _clear: function () {
3122 while (this.childNodes.length) { 3093 while (this.childNodes.length) {
3123 this.removeChild(this.childNodes[0]); 3094 this.removeChild(this.childNodes[0]);
3124 } 3095 }
3125 }, 3096 },
3126 setAttribute: function (name, value) { 3097 setAttribute: function (name, value) {
3127 this.node.setAttribute(name, value); 3098 this.node.setAttribute(name, value);
3128 this._distributeParent(); 3099 this._distributeParent();
3129 }, 3100 },
(...skipping 23 matching lines...) Expand all
3153 var n = nativeImportNode.call(doc, externalNode, false); 3124 var n = nativeImportNode.call(doc, externalNode, false);
3154 if (deep) { 3125 if (deep) {
3155 var c$ = factory(externalNode).childNodes; 3126 var c$ = factory(externalNode).childNodes;
3156 var d = factory(n); 3127 var d = factory(n);
3157 for (var i = 0, nc; i < c$.length; i++) { 3128 for (var i = 0, nc; i < c$.length; i++) {
3158 nc = factory(doc).importNode(c$[i], true); 3129 nc = factory(doc).importNode(c$[i], true);
3159 d.appendChild(nc); 3130 d.appendChild(nc);
3160 } 3131 }
3161 } 3132 }
3162 return n; 3133 return n;
3134 },
3135 observeNodes: function (callback) {
3136 if (callback) {
3137 if (!this.observer) {
3138 this.observer = this.node.localName === CONTENT ? new DomApi.DistributedNodesObs erver(this) : new DomApi.EffectiveNodesObserver(this);
3163 } 3139 }
3164 }; 3140 return this.observer.addListener(callback);
3165 Object.defineProperty(DomApi.prototype, 'classList', {
3166 get: function () {
3167 if (!this._classList) {
3168 this._classList = new DomApi.ClassList(this);
3169 } 3141 }
3170 return this._classList;
3171 }, 3142 },
3172 configurable: true 3143 unobserveNodes: function (handle) {
3173 }); 3144 if (this.observer) {
3174 DomApi.ClassList = function (host) { 3145 this.observer.removeListener(handle);
3175 this.domApi = host; 3146 }
3176 this.node = host.node;
3177 };
3178 DomApi.ClassList.prototype = {
3179 add: function () {
3180 this.node.classList.add.apply(this.node.classList, arguments);
3181 this.domApi._distributeParent();
3182 }, 3147 },
3183 remove: function () { 3148 notifyObserver: function () {
3184 this.node.classList.remove.apply(this.node.classList, arguments); 3149 if (this.observer) {
3185 this.domApi._distributeParent(); 3150 this.observer.notify();
3186 }, 3151 }
3187 toggle: function () {
3188 this.node.classList.toggle.apply(this.node.classList, arguments);
3189 this.domApi._distributeParent();
3190 },
3191 contains: function () {
3192 return this.node.classList.contains.apply(this.node.classList, arguments);
3193 } 3152 }
3194 }; 3153 };
3195 if (!Settings.useShadow) { 3154 if (!Settings.useShadow) {
3196 Object.defineProperties(DomApi.prototype, { 3155 Object.defineProperties(DomApi.prototype, {
3197 childNodes: { 3156 childNodes: {
3198 get: function () { 3157 get: function () {
3199 var c$ = getLightChildren(this.node); 3158 var c$ = getLightChildren(this.node);
3200 return Array.isArray(c$) ? c$ : Array.prototype.slice.call(c$); 3159 return Array.isArray(c$) ? c$ : Array.prototype.slice.call(c$);
3201 }, 3160 },
3202 configurable: true 3161 configurable: true
(...skipping 161 matching lines...) Expand 10 before | Expand all | Expand 10 after
3364 DomApi.prototype.getDestinationInsertionPoints = function () { 3323 DomApi.prototype.getDestinationInsertionPoints = function () {
3365 var n$ = this.node.getDestinationInsertionPoints && this.node.getDestinationInse rtionPoints(); 3324 var n$ = this.node.getDestinationInsertionPoints && this.node.getDestinationInse rtionPoints();
3366 return n$ ? Array.prototype.slice.call(n$) : []; 3325 return n$ ? Array.prototype.slice.call(n$) : [];
3367 }; 3326 };
3368 DomApi.prototype.getDistributedNodes = function () { 3327 DomApi.prototype.getDistributedNodes = function () {
3369 var n$ = this.node.getDistributedNodes && this.node.getDistributedNodes(); 3328 var n$ = this.node.getDistributedNodes && this.node.getDistributedNodes();
3370 return n$ ? Array.prototype.slice.call(n$) : []; 3329 return n$ ? Array.prototype.slice.call(n$) : [];
3371 }; 3330 };
3372 DomApi.prototype._distributeParent = function () { 3331 DomApi.prototype._distributeParent = function () {
3373 }; 3332 };
3333 var nativeForwards = [
3334 'appendChild',
3335 'insertBefore',
3336 'removeChild',
3337 'replaceChild'
3338 ];
3339 nativeForwards.forEach(function (forward) {
3340 DomApi.prototype[forward] = function () {
3341 return this.node[forward].apply(this.node, arguments);
3342 };
3343 });
3374 Object.defineProperties(DomApi.prototype, { 3344 Object.defineProperties(DomApi.prototype, {
3375 childNodes: { 3345 childNodes: {
3376 get: function () { 3346 get: function () {
3377 return Array.prototype.slice.call(this.node.childNodes); 3347 return Array.prototype.slice.call(this.node.childNodes);
3378 }, 3348 },
3379 configurable: true 3349 configurable: true
3380 }, 3350 },
3381 children: { 3351 children: {
3382 get: function () { 3352 get: function () {
3383 return Array.prototype.slice.call(this.node.children); 3353 return Array.prototype.slice.call(this.node.children);
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
3417 forwardProperties.forEach(function (name) { 3387 forwardProperties.forEach(function (name) {
3418 Object.defineProperty(DomApi.prototype, name, { 3388 Object.defineProperty(DomApi.prototype, name, {
3419 get: function () { 3389 get: function () {
3420 return this.node[name]; 3390 return this.node[name];
3421 }, 3391 },
3422 configurable: true 3392 configurable: true
3423 }); 3393 });
3424 }); 3394 });
3425 } 3395 }
3426 var CONTENT = 'content'; 3396 var CONTENT = 'content';
3427 var factory = function (node, patch) { 3397 function factory(node, patch) {
3428 node = node || document; 3398 node = node || document;
3429 if (!node.__domApi) { 3399 if (!node.__domApi) {
3430 node.__domApi = new DomApi(node, patch); 3400 node.__domApi = new DomApi(node, patch);
3431 } 3401 }
3432 return node.__domApi; 3402 return node.__domApi;
3433 }; 3403 }
3404 ;
3405 function hasDomApi(node) {
3406 return Boolean(node.__domApi);
3407 }
3434 Polymer.dom = function (obj, patch) { 3408 Polymer.dom = function (obj, patch) {
3435 if (obj instanceof Event) { 3409 if (obj instanceof Event) {
3436 return Polymer.EventApi.factory(obj); 3410 return Polymer.EventApi.factory(obj);
3437 } else { 3411 } else {
3438 return factory(obj, patch); 3412 return factory(obj, patch);
3439 } 3413 }
3440 }; 3414 };
3441 Polymer.Base.extend(Polymer.dom, {
3442 _flushGuard: 0,
3443 _FLUSH_MAX: 100,
3444 _needsTakeRecords: !Polymer.Settings.useNativeCustomElements,
3445 _debouncers: [],
3446 _finishDebouncer: null,
3447 flush: function () {
3448 for (var i = 0; i < this._debouncers.length; i++) {
3449 this._debouncers[i].complete();
3450 }
3451 if (this._finishDebouncer) {
3452 this._finishDebouncer.complete();
3453 }
3454 this._flushPolyfills();
3455 if (this._debouncers.length && this._flushGuard < this._FLUSH_MAX) {
3456 this._flushGuard++;
3457 this.flush();
3458 } else {
3459 if (this._flushGuard >= this._FLUSH_MAX) {
3460 console.warn('Polymer.dom.flush aborted. Flush may not be complete.');
3461 }
3462 this._flushGuard = 0;
3463 }
3464 },
3465 _flushPolyfills: function () {
3466 if (this._needsTakeRecords) {
3467 CustomElements.takeRecords();
3468 }
3469 },
3470 addDebouncer: function (debouncer) {
3471 this._debouncers.push(debouncer);
3472 this._finishDebouncer = Polymer.Debounce(this._finishDebouncer, this._finishFlus h);
3473 },
3474 _finishFlush: function () {
3475 Polymer.dom._debouncers = [];
3476 }
3477 });
3478 function getLightChildren(node) { 3415 function getLightChildren(node) {
3479 var children = node._lightChildren; 3416 var children = node._lightChildren;
3480 return children ? children : node.childNodes; 3417 return children ? children : node.childNodes;
3481 } 3418 }
3482 function getComposedChildren(node) { 3419 function getComposedChildren(node) {
3483 if (!node._composedChildren) { 3420 if (!node._composedChildren) {
3484 node._composedChildren = Array.prototype.slice.call(node.childNodes); 3421 node._composedChildren = Array.prototype.slice.call(node.childNodes);
3485 } 3422 }
3486 return node._composedChildren; 3423 return node._composedChildren;
3487 } 3424 }
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
3531 var matchesSelector = p.matches || p.matchesSelector || p.mozMatchesSelector || p.msMatchesSelector || p.oMatchesSelector || p.webkitMatchesSelector; 3468 var matchesSelector = p.matches || p.matchesSelector || p.mozMatchesSelector || p.msMatchesSelector || p.oMatchesSelector || p.webkitMatchesSelector;
3532 return { 3469 return {
3533 getLightChildren: getLightChildren, 3470 getLightChildren: getLightChildren,
3534 getComposedParent: getComposedParent, 3471 getComposedParent: getComposedParent,
3535 getComposedChildren: getComposedChildren, 3472 getComposedChildren: getComposedChildren,
3536 removeFromComposedParent: removeFromComposedParent, 3473 removeFromComposedParent: removeFromComposedParent,
3537 saveLightChildrenIfNeeded: saveLightChildrenIfNeeded, 3474 saveLightChildrenIfNeeded: saveLightChildrenIfNeeded,
3538 matchesSelector: matchesSelector, 3475 matchesSelector: matchesSelector,
3539 hasInsertionPoint: hasInsertionPoint, 3476 hasInsertionPoint: hasInsertionPoint,
3540 ctor: DomApi, 3477 ctor: DomApi,
3541 factory: factory 3478 factory: factory,
3542 }; 3479 hasDomApi: hasDomApi
3480 };
3481 }();
3482 Polymer.Base.extend(Polymer.dom, {
3483 _flushGuard: 0,
3484 _FLUSH_MAX: 100,
3485 _needsTakeRecords: !Polymer.Settings.useNativeCustomElements,
3486 _debouncers: [],
3487 _staticFlushList: [],
3488 _finishDebouncer: null,
3489 flush: function () {
3490 this._flushGuard = 0;
3491 this._prepareFlush();
3492 while (this._debouncers.length && this._flushGuard < this._FLUSH_MAX) {
3493 for (var i = 0; i < this._debouncers.length; i++) {
3494 this._debouncers[i].complete();
3495 }
3496 if (this._finishDebouncer) {
3497 this._finishDebouncer.complete();
3498 }
3499 this._prepareFlush();
3500 this._flushGuard++;
3501 }
3502 if (this._flushGuard >= this._FLUSH_MAX) {
3503 console.warn('Polymer.dom.flush aborted. Flush may not be complete.');
3504 }
3505 },
3506 _prepareFlush: function () {
3507 if (this._needsTakeRecords) {
3508 CustomElements.takeRecords();
3509 }
3510 for (var i = 0; i < this._staticFlushList.length; i++) {
3511 this._staticFlushList[i]();
3512 }
3513 },
3514 addStaticFlush: function (fn) {
3515 this._staticFlushList.push(fn);
3516 },
3517 removeStaticFlush: function (fn) {
3518 var i = this._staticFlushList.indexOf(fn);
3519 if (i >= 0) {
3520 this._staticFlushList.splice(i, 1);
3521 }
3522 },
3523 addDebouncer: function (debouncer) {
3524 this._debouncers.push(debouncer);
3525 this._finishDebouncer = Polymer.Debounce(this._finishDebouncer, this._finishFlus h);
3526 },
3527 _finishFlush: function () {
3528 Polymer.dom._debouncers = [];
3529 }
3530 });
3531 Polymer.EventApi = function () {
3532 'use strict';
3533 var DomApi = Polymer.DomApi.ctor;
3534 var Settings = Polymer.Settings;
3535 DomApi.Event = function (event) {
3536 this.event = event;
3537 };
3538 if (Settings.useShadow) {
3539 DomApi.Event.prototype = {
3540 get rootTarget() {
3541 return this.event.path[0];
3542 },
3543 get localTarget() {
3544 return this.event.target;
3545 },
3546 get path() {
3547 return this.event.path;
3548 }
3549 };
3550 } else {
3551 DomApi.Event.prototype = {
3552 get rootTarget() {
3553 return this.event.target;
3554 },
3555 get localTarget() {
3556 var current = this.event.currentTarget;
3557 var currentRoot = current && Polymer.dom(current).getOwnerRoot();
3558 var p$ = this.path;
3559 for (var i = 0; i < p$.length; i++) {
3560 if (Polymer.dom(p$[i]).getOwnerRoot() === currentRoot) {
3561 return p$[i];
3562 }
3563 }
3564 },
3565 get path() {
3566 if (!this.event._path) {
3567 var path = [];
3568 var o = this.rootTarget;
3569 while (o) {
3570 path.push(o);
3571 o = Polymer.dom(o).parentNode || o.host;
3572 }
3573 path.push(window);
3574 this.event._path = path;
3575 }
3576 return this.event._path;
3577 }
3578 };
3579 }
3580 var factory = function (event) {
3581 if (!event.__eventApi) {
3582 event.__eventApi = new DomApi.Event(event);
3583 }
3584 return event.__eventApi;
3585 };
3586 return { factory: factory };
3543 }(); 3587 }();
3544 (function () { 3588 (function () {
3589 'use strict';
3590 var DomApi = Polymer.DomApi.ctor;
3591 Object.defineProperty(DomApi.prototype, 'classList', {
3592 get: function () {
3593 if (!this._classList) {
3594 this._classList = new DomApi.ClassList(this);
3595 }
3596 return this._classList;
3597 },
3598 configurable: true
3599 });
3600 DomApi.ClassList = function (host) {
3601 this.domApi = host;
3602 this.node = host.node;
3603 };
3604 DomApi.ClassList.prototype = {
3605 add: function () {
3606 this.node.classList.add.apply(this.node.classList, arguments);
3607 this.domApi._distributeParent();
3608 },
3609 remove: function () {
3610 this.node.classList.remove.apply(this.node.classList, arguments);
3611 this.domApi._distributeParent();
3612 },
3613 toggle: function () {
3614 this.node.classList.toggle.apply(this.node.classList, arguments);
3615 this.domApi._distributeParent();
3616 },
3617 contains: function () {
3618 return this.node.classList.contains.apply(this.node.classList, arguments);
3619 }
3620 };
3621 }());
3622 (function () {
3623 'use strict';
3624 var DomApi = Polymer.DomApi.ctor;
3625 var Settings = Polymer.Settings;
3626 var hasDomApi = Polymer.DomApi.hasDomApi;
3627 DomApi.EffectiveNodesObserver = function (domApi) {
3628 this.domApi = domApi;
3629 this.node = this.domApi.node;
3630 this._listeners = [];
3631 };
3632 DomApi.EffectiveNodesObserver.prototype = {
3633 addListener: function (callback) {
3634 if (!this._isSetup) {
3635 this._setup();
3636 this._isSetup = true;
3637 }
3638 var listener = {
3639 fn: callback,
3640 _nodes: []
3641 };
3642 this._listeners.push(listener);
3643 this._scheduleNotify();
3644 return listener;
3645 },
3646 removeListener: function (handle) {
3647 var i = this._listeners.indexOf(handle);
3648 if (i >= 0) {
3649 this._listeners.splice(i, 1);
3650 handle._nodes = [];
3651 }
3652 if (!this._hasListeners()) {
3653 this._cleanup();
3654 this._isSetup = false;
3655 }
3656 },
3657 _setup: function () {
3658 this._observeContentElements(this.domApi.childNodes);
3659 },
3660 _cleanup: function () {
3661 this._unobserveContentElements(this.domApi.childNodes);
3662 },
3663 _hasListeners: function () {
3664 return Boolean(this._listeners.length);
3665 },
3666 _scheduleNotify: function () {
3667 if (this._debouncer) {
3668 this._debouncer.stop();
3669 }
3670 this._debouncer = Polymer.Debounce(this._debouncer, this._notify);
3671 this._debouncer.context = this;
3672 Polymer.dom.addDebouncer(this._debouncer);
3673 },
3674 notify: function () {
3675 if (this._hasListeners()) {
3676 this._scheduleNotify();
3677 }
3678 },
3679 _notify: function (mxns) {
3680 this._beforeCallListeners();
3681 this._callListeners();
3682 },
3683 _beforeCallListeners: function () {
3684 this._updateContentElements();
3685 },
3686 _updateContentElements: function () {
3687 this._observeContentElements(this.domApi.childNodes);
3688 },
3689 _observeContentElements: function (elements) {
3690 for (var i = 0, n; i < elements.length && (n = elements[i]); i++) {
3691 if (this._isContent(n)) {
3692 n.__observeNodesMap = n.__observeNodesMap || new WeakMap();
3693 if (!n.__observeNodesMap.has(this)) {
3694 n.__observeNodesMap.set(this, this._observeContent(n));
3695 }
3696 }
3697 }
3698 },
3699 _observeContent: function (content) {
3700 var h = Polymer.dom(content).observeNodes(this._scheduleNotify.bind(this));
3701 h._avoidChangeCalculation = true;
3702 return h;
3703 },
3704 _unobserveContentElements: function (elements) {
3705 for (var i = 0, n, h; i < elements.length && (n = elements[i]); i++) {
3706 if (this._isContent(n)) {
3707 h = n.__observeNodesMap.get(this);
3708 if (h) {
3709 Polymer.dom(n).unobserveNodes(h);
3710 n.__observeNodesMap.delete(this);
3711 }
3712 }
3713 }
3714 },
3715 _isContent: function (node) {
3716 return node.localName === 'content';
3717 },
3718 _callListeners: function () {
3719 var o$ = this._listeners;
3720 var nodes = this._getEffectiveNodes();
3721 for (var i = 0, o; i < o$.length && (o = o$[i]); i++) {
3722 var info = this._generateListenerInfo(o, nodes);
3723 if (info || o._alwaysNotify) {
3724 this._callListener(o, info);
3725 }
3726 }
3727 },
3728 _getEffectiveNodes: function () {
3729 return this.domApi.getEffectiveChildNodes();
3730 },
3731 _generateListenerInfo: function (listener, newNodes) {
3732 if (listener._avoidChangeCalculation) {
3733 return true;
3734 }
3735 var oldNodes = listener._nodes;
3736 var info = {
3737 target: this.node,
3738 addedNodes: [],
3739 removedNodes: []
3740 };
3741 var splices = Polymer.ArraySplice.calculateSplices(newNodes, oldNodes);
3742 for (var i = 0, s; i < splices.length && (s = splices[i]); i++) {
3743 for (var j = 0, n; j < s.removed.length && (n = s.removed[j]); j++) {
3744 info.removedNodes.push(n);
3745 }
3746 }
3747 for (var i = 0, s; i < splices.length && (s = splices[i]); i++) {
3748 for (var j = s.index; j < s.index + s.addedCount; j++) {
3749 info.addedNodes.push(newNodes[j]);
3750 }
3751 }
3752 listener._nodes = newNodes;
3753 if (info.addedNodes.length || info.removedNodes.length) {
3754 return info;
3755 }
3756 },
3757 _callListener: function (listener, info) {
3758 return listener.fn.call(this.node, info);
3759 },
3760 enableShadowAttributeTracking: function () {
3761 }
3762 };
3763 if (Settings.useShadow) {
3764 var baseSetup = DomApi.EffectiveNodesObserver.prototype._setup;
3765 var baseCleanup = DomApi.EffectiveNodesObserver.prototype._cleanup;
3766 var beforeCallListeners = DomApi.EffectiveNodesObserver.prototype._beforeCallLis teners;
3767 Polymer.Base.extend(DomApi.EffectiveNodesObserver.prototype, {
3768 _setup: function () {
3769 if (!this._observer) {
3770 var self = this;
3771 this._mutationHandler = function (mxns) {
3772 if (mxns && mxns.length) {
3773 self._scheduleNotify();
3774 }
3775 };
3776 this._observer = new MutationObserver(this._mutationHandler);
3777 this._boundFlush = this._flush.bind(this);
3778 Polymer.dom.addStaticFlush(this._boundFlush);
3779 this._observer.observe(this.node, { childList: true });
3780 }
3781 baseSetup.call(this);
3782 },
3783 _cleanup: function () {
3784 this._observer.disconnect();
3785 this._observer = null;
3786 this._mutationHandler = null;
3787 Polymer.dom.removeStaticFlush(this._boundFlush);
3788 baseCleanup.call(this);
3789 },
3790 _flush: function () {
3791 if (this._observer) {
3792 this._mutationHandler(this._observer.takeRecords());
3793 }
3794 },
3795 enableShadowAttributeTracking: function () {
3796 if (this._observer) {
3797 this._makeContentListenersAlwaysNotify();
3798 this._observer.disconnect();
3799 this._observer.observe(this.node, {
3800 childList: true,
3801 attributes: true,
3802 subtree: true
3803 });
3804 var root = this.domApi.getOwnerRoot();
3805 var host = root && root.host;
3806 if (host && Polymer.dom(host).observer) {
3807 Polymer.dom(host).observer.enableShadowAttributeTracking();
3808 }
3809 }
3810 },
3811 _makeContentListenersAlwaysNotify: function () {
3812 for (var i = 0, h; i < this._listeners.length; i++) {
3813 h = this._listeners[i];
3814 h._alwaysNotify = h._isContentListener;
3815 }
3816 }
3817 });
3818 }
3819 }());
3820 (function () {
3821 'use strict';
3822 var DomApi = Polymer.DomApi.ctor;
3823 var Settings = Polymer.Settings;
3824 DomApi.DistributedNodesObserver = function (domApi) {
3825 DomApi.EffectiveNodesObserver.call(this, domApi);
3826 };
3827 DomApi.DistributedNodesObserver.prototype = Object.create(DomApi.EffectiveNodesO bserver.prototype);
3828 Polymer.Base.extend(DomApi.DistributedNodesObserver.prototype, {
3829 _setup: function () {
3830 },
3831 _cleanup: function () {
3832 },
3833 _beforeCallListeners: function () {
3834 },
3835 _getEffectiveNodes: function () {
3836 return this.domApi.getDistributedNodes();
3837 }
3838 });
3839 if (Settings.useShadow) {
3840 Polymer.Base.extend(DomApi.DistributedNodesObserver.prototype, {
3841 _setup: function () {
3842 if (!this._observer) {
3843 var root = this.domApi.getOwnerRoot();
3844 var host = root && root.host;
3845 if (host) {
3846 this._observer = Polymer.dom(host).observeNodes(this._scheduleNotify.bind(this)) ;
3847 this._observer._isContentListener = true;
3848 if (this._hasAttrSelect()) {
3849 Polymer.dom(host).observer.enableShadowAttributeTracking();
3850 }
3851 }
3852 }
3853 },
3854 _hasAttrSelect: function () {
3855 var select = this.node.getAttribute('select');
3856 return select && select.match(/[[.]+/);
3857 },
3858 _cleanup: function () {
3859 var root = this.domApi.getOwnerRoot();
3860 var host = root && root.host;
3861 if (host) {
3862 Polymer.dom(host).unobserveNodes(this._observer);
3863 }
3864 this._observer = null;
3865 }
3866 });
3867 }
3868 }());
3869 (function () {
3870 var hasDomApi = Polymer.DomApi.hasDomApi;
3545 Polymer.Base._addFeature({ 3871 Polymer.Base._addFeature({
3546 _prepShady: function () { 3872 _prepShady: function () {
3547 this._useContent = this._useContent || Boolean(this._template); 3873 this._useContent = this._useContent || Boolean(this._template);
3548 }, 3874 },
3549 _poolContent: function () { 3875 _poolContent: function () {
3550 if (this._useContent) { 3876 if (this._useContent) {
3551 saveLightChildrenIfNeeded(this); 3877 saveLightChildrenIfNeeded(this);
3552 } 3878 }
3553 }, 3879 },
3554 _setupRoot: function () { 3880 _setupRoot: function () {
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
3605 for (var i = 0, l = c$.length, c; i < l && (c = c$[i]); i++) { 3931 for (var i = 0, l = c$.length, c; i < l && (c = c$[i]); i++) {
3606 c._distributeContent(); 3932 c._distributeContent();
3607 } 3933 }
3608 this.shadyRoot._dirtyRoots = []; 3934 this.shadyRoot._dirtyRoots = [];
3609 }, 3935 },
3610 _finishDistribute: function () { 3936 _finishDistribute: function () {
3611 if (this._useContent) { 3937 if (this._useContent) {
3612 this.shadyRoot._distributionClean = true; 3938 this.shadyRoot._distributionClean = true;
3613 if (hasInsertionPoint(this.shadyRoot)) { 3939 if (hasInsertionPoint(this.shadyRoot)) {
3614 this._composeTree(); 3940 this._composeTree();
3941 notifyContentObservers(this.shadyRoot);
3615 } else { 3942 } else {
3616 if (!this.shadyRoot._hasDistributed) { 3943 if (!this.shadyRoot._hasDistributed) {
3617 this.textContent = ''; 3944 this.textContent = '';
3618 this._composedChildren = null; 3945 this._composedChildren = null;
3619 this.appendChild(this.shadyRoot); 3946 this.appendChild(this.shadyRoot);
3620 } else { 3947 } else {
3621 var children = this._composeNode(this); 3948 var children = this._composeNode(this);
3622 this._updateChildNodes(this, children); 3949 this._updateChildNodes(this, children);
3623 } 3950 }
3624 } 3951 }
3952 if (!this.shadyRoot._hasDistributed) {
3953 notifyInitialDistribution(this);
3954 }
3625 this.shadyRoot._hasDistributed = true; 3955 this.shadyRoot._hasDistributed = true;
3626 } 3956 }
3627 }, 3957 },
3628 elementMatches: function (selector, node) { 3958 elementMatches: function (selector, node) {
3629 node = node || this; 3959 node = node || this;
3630 return matchesSelector.call(node, selector); 3960 return matchesSelector.call(node, selector);
3631 }, 3961 },
3632 _resetDistribution: function () { 3962 _resetDistribution: function () {
3633 var children = getLightChildren(this); 3963 var children = getLightChildren(this);
3634 for (var i = 0; i < children.length; i++) { 3964 for (var i = 0; i < children.length; i++) {
(...skipping 197 matching lines...) Expand 10 before | Expand all | Expand 10 after
3832 } 4162 }
3833 function hostNeedsRedistribution(host) { 4163 function hostNeedsRedistribution(host) {
3834 var c$ = Polymer.dom(host).children; 4164 var c$ = Polymer.dom(host).children;
3835 for (var i = 0, c; i < c$.length; i++) { 4165 for (var i = 0, c; i < c$.length; i++) {
3836 c = c$[i]; 4166 c = c$[i];
3837 if (c.localName === 'content') { 4167 if (c.localName === 'content') {
3838 return host.domHost; 4168 return host.domHost;
3839 } 4169 }
3840 } 4170 }
3841 } 4171 }
4172 function notifyContentObservers(root) {
4173 for (var i = 0, c; i < root._insertionPoints.length; i++) {
4174 c = root._insertionPoints[i];
4175 if (hasDomApi(c)) {
4176 Polymer.dom(c).notifyObserver();
4177 }
4178 }
4179 }
4180 function notifyInitialDistribution(host) {
4181 if (hasDomApi(host)) {
4182 Polymer.dom(host).notifyObserver();
4183 }
4184 }
3842 var needsUpgrade = window.CustomElements && !CustomElements.useNative; 4185 var needsUpgrade = window.CustomElements && !CustomElements.useNative;
3843 function upgradeLightChildren(children) { 4186 function upgradeLightChildren(children) {
3844 if (needsUpgrade && children) { 4187 if (needsUpgrade && children) {
3845 for (var i = 0; i < children.length; i++) { 4188 for (var i = 0; i < children.length; i++) {
3846 CustomElements.upgrade(children[i]); 4189 CustomElements.upgrade(children[i]);
3847 } 4190 }
3848 } 4191 }
3849 } 4192 }
3850 }()); 4193 }());
3851 if (Polymer.Settings.useShadow) { 4194 if (Polymer.Settings.useShadow) {
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
3897 Polymer.Annotations = { 4240 Polymer.Annotations = {
3898 parseAnnotations: function (template) { 4241 parseAnnotations: function (template) {
3899 var list = []; 4242 var list = [];
3900 var content = template._content || template.content; 4243 var content = template._content || template.content;
3901 this._parseNodeAnnotations(content, list); 4244 this._parseNodeAnnotations(content, list);
3902 return list; 4245 return list;
3903 }, 4246 },
3904 _parseNodeAnnotations: function (node, list) { 4247 _parseNodeAnnotations: function (node, list) {
3905 return node.nodeType === Node.TEXT_NODE ? this._parseTextNodeAnnotation(node, li st) : this._parseElementAnnotations(node, list); 4248 return node.nodeType === Node.TEXT_NODE ? this._parseTextNodeAnnotation(node, li st) : this._parseElementAnnotations(node, list);
3906 }, 4249 },
3907 _testEscape: function (value) { 4250 _bindingRegex: /([^{[]*)({{|\[\[)([^}\]]*)(?:]]|}})/g,
3908 var escape = value.slice(0, 2); 4251 _parseBindings: function (text) {
3909 if (escape === '{{' || escape === '[[') { 4252 var re = this._bindingRegex;
3910 return escape; 4253 var parts = [];
4254 var m, lastIndex;
4255 while ((m = re.exec(text)) !== null) {
4256 if (m[1]) {
4257 parts.push({ literal: m[1] });
4258 }
4259 var mode = m[2][0];
4260 var value = m[3].trim();
4261 var negate = false;
4262 if (value[0] == '!') {
4263 negate = true;
4264 value = value.substring(1).trim();
4265 }
4266 var customEvent, notifyEvent, colon;
4267 if (mode == '{' && (colon = value.indexOf('::')) > 0) {
4268 notifyEvent = value.substring(colon + 2);
4269 value = value.substring(0, colon);
4270 customEvent = true;
4271 }
4272 parts.push({
4273 compoundIndex: parts.length,
4274 value: value,
4275 mode: mode,
4276 negate: negate,
4277 event: notifyEvent,
4278 customEvent: customEvent
4279 });
4280 lastIndex = re.lastIndex;
4281 }
4282 if (lastIndex && lastIndex < text.length) {
4283 var literal = text.substring(lastIndex);
4284 if (literal) {
4285 parts.push({ literal: literal });
4286 }
4287 }
4288 if (parts.length) {
4289 return parts;
3911 } 4290 }
3912 }, 4291 },
4292 _literalFromParts: function (parts) {
4293 var s = '';
4294 for (var i = 0; i < parts.length; i++) {
4295 var literal = parts[i].literal;
4296 s += literal || '';
4297 }
4298 return s;
4299 },
3913 _parseTextNodeAnnotation: function (node, list) { 4300 _parseTextNodeAnnotation: function (node, list) {
3914 var v = node.textContent; 4301 var parts = this._parseBindings(node.textContent);
3915 var escape = this._testEscape(v); 4302 if (parts) {
3916 if (escape) { 4303 node.textContent = this._literalFromParts(parts) || ' ';
3917 node.textContent = ' ';
3918 var annote = { 4304 var annote = {
3919 bindings: [{ 4305 bindings: [{
3920 kind: 'text', 4306 kind: 'text',
3921 mode: escape[0], 4307 name: 'textContent',
3922 value: v.slice(2, -2).trim() 4308 parts: parts,
4309 isCompound: parts.length !== 1
3923 }] 4310 }]
3924 }; 4311 };
3925 list.push(annote); 4312 list.push(annote);
3926 return annote; 4313 return annote;
3927 } 4314 }
3928 }, 4315 },
3929 _parseElementAnnotations: function (element, list) { 4316 _parseElementAnnotations: function (element, list) {
3930 var annote = { 4317 var annote = {
3931 bindings: [], 4318 bindings: [],
3932 events: [] 4319 events: []
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
3974 content.appendChild(node.content); 4361 content.appendChild(node.content);
3975 list.push({ 4362 list.push({
3976 bindings: Polymer.nar, 4363 bindings: Polymer.nar,
3977 events: Polymer.nar, 4364 events: Polymer.nar,
3978 templateContent: content, 4365 templateContent: content,
3979 parent: parent, 4366 parent: parent,
3980 index: index 4367 index: index
3981 }); 4368 });
3982 }, 4369 },
3983 _parseNodeAttributeAnnotations: function (node, annotation) { 4370 _parseNodeAttributeAnnotations: function (node, annotation) {
3984 for (var i = node.attributes.length - 1, a; a = node.attributes[i]; i--) { 4371 var attrs = Array.prototype.slice.call(node.attributes);
3985 var n = a.name, v = a.value; 4372 for (var i = attrs.length - 1, a; a = attrs[i]; i--) {
3986 if (n === 'id' && !this._testEscape(v)) { 4373 var n = a.name;
3987 annotation.id = v; 4374 var v = a.value;
3988 } else if (n.slice(0, 3) === 'on-') { 4375 var b;
4376 if (n.slice(0, 3) === 'on-') {
3989 node.removeAttribute(n); 4377 node.removeAttribute(n);
3990 annotation.events.push({ 4378 annotation.events.push({
3991 name: n.slice(3), 4379 name: n.slice(3),
3992 value: v 4380 value: v
3993 }); 4381 });
3994 } else { 4382 } else if (b = this._parseNodeAttributeAnnotation(node, n, v)) {
3995 var b = this._parseNodeAttributeAnnotation(node, n, v);
3996 if (b) {
3997 annotation.bindings.push(b); 4383 annotation.bindings.push(b);
3998 } 4384 } else if (n === 'id') {
4385 annotation.id = v;
3999 } 4386 }
4000 } 4387 }
4001 }, 4388 },
4002 _parseNodeAttributeAnnotation: function (node, n, v) { 4389 _parseNodeAttributeAnnotation: function (node, name, value) {
4003 var escape = this._testEscape(v); 4390 var parts = this._parseBindings(value);
4004 if (escape) { 4391 if (parts) {
4005 var customEvent; 4392 var origName = name;
4006 var name = n;
4007 var mode = escape[0];
4008 v = v.slice(2, -2).trim();
4009 var not = false;
4010 if (v[0] == '!') {
4011 v = v.substring(1);
4012 not = true;
4013 }
4014 var kind = 'property'; 4393 var kind = 'property';
4015 if (n[n.length - 1] == '$') { 4394 if (name[name.length - 1] == '$') {
4016 name = n.slice(0, -1); 4395 name = name.slice(0, -1);
4017 kind = 'attribute'; 4396 kind = 'attribute';
4018 } 4397 }
4019 var notifyEvent, colon; 4398 var literal = this._literalFromParts(parts);
4020 if (mode == '{' && (colon = v.indexOf('::')) > 0) { 4399 if (literal && kind == 'attribute') {
4021 notifyEvent = v.substring(colon + 2); 4400 node.setAttribute(name, literal);
4022 v = v.substring(0, colon);
4023 customEvent = true;
4024 } 4401 }
4025 if (node.localName == 'input' && n == 'value') { 4402 if (node.localName == 'input' && name == 'value') {
4026 node.setAttribute(n, ''); 4403 node.setAttribute(origName, '');
4027 } 4404 }
4028 node.removeAttribute(n); 4405 node.removeAttribute(origName);
4029 if (kind === 'property') { 4406 if (kind === 'property') {
4030 name = Polymer.CaseMap.dashToCamelCase(name); 4407 name = Polymer.CaseMap.dashToCamelCase(name);
4031 } 4408 }
4032 return { 4409 return {
4033 kind: kind, 4410 kind: kind,
4034 mode: mode,
4035 name: name, 4411 name: name,
4036 value: v, 4412 parts: parts,
4037 negate: not, 4413 literal: literal,
4038 event: notifyEvent, 4414 isCompound: parts.length !== 1
4039 customEvent: customEvent
4040 }; 4415 };
4041 } 4416 }
4042 }, 4417 },
4043 _localSubTree: function (node, host) { 4418 _localSubTree: function (node, host) {
4044 return node === host ? node.childNodes : node._lightChildren || node.childNodes; 4419 return node === host ? node.childNodes : node._lightChildren || node.childNodes;
4045 }, 4420 },
4046 findAnnotatedNode: function (root, annote) { 4421 findAnnotatedNode: function (root, annote) {
4047 var parent = annote.parent && Polymer.Annotations.findAnnotatedNode(root, annote .parent); 4422 var parent = annote.parent && Polymer.Annotations.findAnnotatedNode(root, annote .parent);
4048 return !parent ? root : Polymer.Annotations._localSubTree(parent, root)[annote.i ndex]; 4423 return !parent ? root : Polymer.Annotations._localSubTree(parent, root)[annote.i ndex];
4049 } 4424 }
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after
4120 } 4495 }
4121 this._processAnnotations(this._notes); 4496 this._processAnnotations(this._notes);
4122 Polymer.Annotations.prepElement = null; 4497 Polymer.Annotations.prepElement = null;
4123 } 4498 }
4124 }, 4499 },
4125 _processAnnotations: function (notes) { 4500 _processAnnotations: function (notes) {
4126 for (var i = 0; i < notes.length; i++) { 4501 for (var i = 0; i < notes.length; i++) {
4127 var note = notes[i]; 4502 var note = notes[i];
4128 for (var j = 0; j < note.bindings.length; j++) { 4503 for (var j = 0; j < note.bindings.length; j++) {
4129 var b = note.bindings[j]; 4504 var b = note.bindings[j];
4130 b.signature = this._parseMethod(b.value); 4505 for (var k = 0; k < b.parts.length; k++) {
4131 if (!b.signature) { 4506 var p = b.parts[k];
4132 b.model = this._modelForPath(b.value); 4507 if (!p.literal) {
4508 p.signature = this._parseMethod(p.value);
4509 if (!p.signature) {
4510 p.model = this._modelForPath(p.value);
4511 }
4512 }
4133 } 4513 }
4134 } 4514 }
4135 if (note.templateContent) { 4515 if (note.templateContent) {
4136 this._processAnnotations(note.templateContent._notes); 4516 this._processAnnotations(note.templateContent._notes);
4137 var pp = note.templateContent._parentProps = this._discoverTemplateParentProps(n ote.templateContent._notes); 4517 var pp = note.templateContent._parentProps = this._discoverTemplateParentProps(n ote.templateContent._notes);
4138 var bindings = []; 4518 var bindings = [];
4139 for (var prop in pp) { 4519 for (var prop in pp) {
4140 bindings.push({ 4520 bindings.push({
4141 index: note.index, 4521 index: note.index,
4142 kind: 'property', 4522 kind: 'property',
4523 name: '_parent_' + prop,
4524 parts: [{
4143 mode: '{', 4525 mode: '{',
4144 name: '_parent_' + prop,
4145 model: prop, 4526 model: prop,
4146 value: prop 4527 value: prop
4528 }]
4147 }); 4529 });
4148 } 4530 }
4149 note.bindings = note.bindings.concat(bindings); 4531 note.bindings = note.bindings.concat(bindings);
4150 } 4532 }
4151 } 4533 }
4152 }, 4534 },
4153 _discoverTemplateParentProps: function (notes) { 4535 _discoverTemplateParentProps: function (notes) {
4154 var pp = {}; 4536 var pp = {};
4155 notes.forEach(function (n) { 4537 notes.forEach(function (n) {
4156 n.bindings.forEach(function (b) { 4538 n.bindings.forEach(function (b) {
4157 if (b.signature) { 4539 b.parts.forEach(function (p) {
4158 var args = b.signature.args; 4540 if (p.signature) {
4541 var args = p.signature.args;
4159 for (var k = 0; k < args.length; k++) { 4542 for (var k = 0; k < args.length; k++) {
4160 pp[args[k].model] = true; 4543 pp[args[k].model] = true;
4161 } 4544 }
4162 } else { 4545 } else {
4163 pp[b.model] = true; 4546 pp[p.model] = true;
4164 } 4547 }
4165 }); 4548 });
4549 });
4166 if (n.templateContent) { 4550 if (n.templateContent) {
4167 var tpp = n.templateContent._parentProps; 4551 var tpp = n.templateContent._parentProps;
4168 Polymer.Base.mixin(pp, tpp); 4552 Polymer.Base.mixin(pp, tpp);
4169 } 4553 }
4170 }); 4554 });
4171 return pp; 4555 return pp;
4172 }, 4556 },
4173 _prepElement: function (element) { 4557 _prepElement: function (element) {
4174 Polymer.ResolveUrl.resolveAttrs(element, this._template.ownerDocument); 4558 Polymer.ResolveUrl.resolveAttrs(element, this._template.ownerDocument);
4175 }, 4559 },
4176 _findAnnotatedNode: Polymer.Annotations.findAnnotatedNode, 4560 _findAnnotatedNode: Polymer.Annotations.findAnnotatedNode,
4177 _marshalAnnotationReferences: function () { 4561 _marshalAnnotationReferences: function () {
4178 if (this._template) { 4562 if (this._template) {
4179 this._marshalIdNodes(); 4563 this._marshalIdNodes();
4180 this._marshalAnnotatedNodes(); 4564 this._marshalAnnotatedNodes();
4181 this._marshalAnnotatedListeners(); 4565 this._marshalAnnotatedListeners();
4182 } 4566 }
4183 }, 4567 },
4184 _configureAnnotationReferences: function () { 4568 _configureAnnotationReferences: function (config) {
4185 this._configureTemplateContent(); 4569 var notes = this._notes;
4570 var nodes = this._nodes;
4571 for (var i = 0; i < notes.length; i++) {
4572 var note = notes[i];
4573 var node = nodes[i];
4574 this._configureTemplateContent(note, node);
4575 this._configureCompoundBindings(note, node);
4576 }
4186 }, 4577 },
4187 _configureTemplateContent: function () { 4578 _configureTemplateContent: function (note, node) {
4188 this._notes.forEach(function (note, i) {
4189 if (note.templateContent) { 4579 if (note.templateContent) {
4190 this._nodes[i]._content = note.templateContent; 4580 node._content = note.templateContent;
4191 } 4581 }
4192 }, this); 4582 },
4583 _configureCompoundBindings: function (note, node) {
4584 var bindings = note.bindings;
4585 for (var i = 0; i < bindings.length; i++) {
4586 var binding = bindings[i];
4587 if (binding.isCompound) {
4588 var storage = node.__compoundStorage__ || (node.__compoundStorage__ = {});
4589 var parts = binding.parts;
4590 var literals = new Array(parts.length);
4591 for (var j = 0; j < parts.length; j++) {
4592 literals[j] = parts[j].literal;
4593 }
4594 var name = binding.name;
4595 storage[name] = literals;
4596 if (binding.literal && binding.kind == 'property') {
4597 if (node._configValue) {
4598 node._configValue(name, binding.literal);
4599 } else {
4600 node[name] = binding.literal;
4601 }
4602 }
4603 }
4604 }
4193 }, 4605 },
4194 _marshalIdNodes: function () { 4606 _marshalIdNodes: function () {
4195 this.$ = {}; 4607 this.$ = {};
4196 this._notes.forEach(function (a) { 4608 this._notes.forEach(function (a) {
4197 if (a.id) { 4609 if (a.id) {
4198 this.$[a.id] = this._findAnnotatedNode(this.root, a); 4610 this.$[a.id] = this._findAnnotatedNode(this.root, a);
4199 } 4611 }
4200 }, this); 4612 }, this);
4201 }, 4613 },
4202 _marshalAnnotatedNodes: function () { 4614 _marshalAnnotatedNodes: function () {
(...skipping 771 matching lines...) Expand 10 before | Expand all | Expand 10 after
4974 this._lastVal += i; 5386 this._lastVal += i;
4975 this._twiddle.textContent = this._twiddleContent++; 5387 this._twiddle.textContent = this._twiddleContent++;
4976 throw e; 5388 throw e;
4977 } 5389 }
4978 } 5390 }
4979 } 5391 }
4980 this._callbacks.splice(0, len); 5392 this._callbacks.splice(0, len);
4981 this._lastVal += len; 5393 this._lastVal += len;
4982 } 5394 }
4983 }; 5395 };
4984 new (window.MutationObserver || JsMutationObserver)(Polymer.Async._atEndOfMicrot ask.bind(Polymer.Async)).observe(Polymer.Async._twiddle, { characterData: true } ); 5396 new window.MutationObserver(function () {
5397 Polymer.Async._atEndOfMicrotask();
5398 }).observe(Polymer.Async._twiddle, { characterData: true });
4985 Polymer.Debounce = function () { 5399 Polymer.Debounce = function () {
4986 var Async = Polymer.Async; 5400 var Async = Polymer.Async;
4987 var Debouncer = function (context) { 5401 var Debouncer = function (context) {
4988 this.context = context; 5402 this.context = context;
4989 this.boundComplete = this.complete.bind(this); 5403 this.boundComplete = this.complete.bind(this);
4990 }; 5404 };
4991 Debouncer.prototype = { 5405 Debouncer.prototype = {
4992 go: function (callback, wait) { 5406 go: function (callback, wait) {
4993 var h; 5407 var h;
4994 this.finish = function () { 5408 this.finish = function () {
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after
5056 } 5470 }
5057 }, 5471 },
5058 attributeFollows: function (name, toElement, fromElement) { 5472 attributeFollows: function (name, toElement, fromElement) {
5059 if (fromElement) { 5473 if (fromElement) {
5060 Polymer.dom(fromElement).removeAttribute(name); 5474 Polymer.dom(fromElement).removeAttribute(name);
5061 } 5475 }
5062 if (toElement) { 5476 if (toElement) {
5063 Polymer.dom(toElement).setAttribute(name, ''); 5477 Polymer.dom(toElement).setAttribute(name, '');
5064 } 5478 }
5065 }, 5479 },
5480 getEffectiveChildNodes: function () {
5481 return Polymer.dom(this).getEffectiveChildNodes();
5482 },
5483 getEffectiveChildren: function () {
5484 var list = Polymer.dom(this).getEffectiveChildNodes();
5485 return list.filter(function (n) {
5486 return n.nodeType === Node.ELEMENT_NODE;
5487 });
5488 },
5489 getEffectiveTextContent: function () {
5490 var cn = this.getEffectiveChildNodes();
5491 var tc = [];
5492 for (var i = 0, c; c = cn[i]; i++) {
5493 if (c.nodeType !== Node.COMMENT_NODE) {
5494 tc.push(Polymer.dom(c).textContent);
5495 }
5496 }
5497 return tc.join('');
5498 },
5499 queryEffectiveChildren: function (slctr) {
5500 var e$ = Polymer.dom(this).queryDistributedElements(slctr);
5501 return e$ && e$[0];
5502 },
5503 queryAllEffectiveChildren: function (slctr) {
5504 return Polymer.dom(this).queryAllDistributedElements(slctr);
5505 },
5066 getContentChildNodes: function (slctr) { 5506 getContentChildNodes: function (slctr) {
5067 var content = Polymer.dom(this.root).querySelector(slctr || 'content'); 5507 var content = Polymer.dom(this.root).querySelector(slctr || 'content');
5068 return content ? Polymer.dom(content).getDistributedNodes() : []; 5508 return content ? Polymer.dom(content).getDistributedNodes() : [];
5069 }, 5509 },
5070 getContentChildren: function (slctr) { 5510 getContentChildren: function (slctr) {
5071 return this.getContentChildNodes(slctr).filter(function (n) { 5511 return this.getContentChildNodes(slctr).filter(function (n) {
5072 return n.nodeType === Node.ELEMENT_NODE; 5512 return n.nodeType === Node.ELEMENT_NODE;
5073 }); 5513 });
5074 }, 5514 },
5075 fire: function (type, detail, options) { 5515 fire: function (type, detail, options) {
(...skipping 17 matching lines...) Expand all
5093 Polymer.Async.cancel(handle); 5533 Polymer.Async.cancel(handle);
5094 }, 5534 },
5095 arrayDelete: function (path, item) { 5535 arrayDelete: function (path, item) {
5096 var index; 5536 var index;
5097 if (Array.isArray(path)) { 5537 if (Array.isArray(path)) {
5098 index = path.indexOf(item); 5538 index = path.indexOf(item);
5099 if (index >= 0) { 5539 if (index >= 0) {
5100 return path.splice(index, 1); 5540 return path.splice(index, 1);
5101 } 5541 }
5102 } else { 5542 } else {
5103 var arr = this.get(path); 5543 var arr = this._get(path);
5104 index = arr.indexOf(item); 5544 index = arr.indexOf(item);
5105 if (index >= 0) { 5545 if (index >= 0) {
5106 return this.splice(path, index, 1); 5546 return this.splice(path, index, 1);
5107 } 5547 }
5108 } 5548 }
5109 }, 5549 },
5110 transform: function (transform, node) { 5550 transform: function (transform, node) {
5111 node = node || this; 5551 node = node || this;
5112 node.style.webkitTransform = transform; 5552 node.style.webkitTransform = transform;
5113 node.style.transform = transform; 5553 node.style.transform = transform;
(...skipping 18 matching lines...) Expand all
5132 create: function (tag, props) { 5572 create: function (tag, props) {
5133 var elt = document.createElement(tag); 5573 var elt = document.createElement(tag);
5134 if (props) { 5574 if (props) {
5135 for (var n in props) { 5575 for (var n in props) {
5136 elt[n] = props[n]; 5576 elt[n] = props[n];
5137 } 5577 }
5138 } 5578 }
5139 return elt; 5579 return elt;
5140 }, 5580 },
5141 isLightDescendant: function (node) { 5581 isLightDescendant: function (node) {
5142 return this.contains(node) && Polymer.dom(this).getOwnerRoot() === Polymer.dom(n ode).getOwnerRoot(); 5582 return this !== node && this.contains(node) && Polymer.dom(this).getOwnerRoot() === Polymer.dom(node).getOwnerRoot();
5143 }, 5583 },
5144 isLocalDescendant: function (node) { 5584 isLocalDescendant: function (node) {
5145 return this.root === Polymer.dom(node).getOwnerRoot(); 5585 return this.root === Polymer.dom(node).getOwnerRoot();
5146 } 5586 }
5147 }); 5587 });
5148 Polymer.Bind = { 5588 Polymer.Bind = {
5149 prepareModel: function (model) { 5589 prepareModel: function (model) {
5150 model._propertyEffects = {}; 5590 model._propertyEffects = {};
5151 model._bindListeners = []; 5591 model._bindListeners = [];
5152 Polymer.Base.mixin(model, this._modelApi); 5592 Polymer.Base.mixin(model, this._modelApi);
(...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after
5275 _isStructured: function (path) { 5715 _isStructured: function (path) {
5276 return path.indexOf('.') > 0; 5716 return path.indexOf('.') > 0;
5277 }, 5717 },
5278 _isEventBogus: function (e, target) { 5718 _isEventBogus: function (e, target) {
5279 return e.path && e.path[0] !== target; 5719 return e.path && e.path[0] !== target;
5280 }, 5720 },
5281 _notedListenerFactory: function (property, path, isStructured, bogusTest) { 5721 _notedListenerFactory: function (property, path, isStructured, bogusTest) {
5282 return function (e, target) { 5722 return function (e, target) {
5283 if (!bogusTest(e, target)) { 5723 if (!bogusTest(e, target)) {
5284 if (e.detail && e.detail.path) { 5724 if (e.detail && e.detail.path) {
5285 this.notifyPath(this._fixPath(path, property, e.detail.path), e.detail.value); 5725 this._notifyPath(this._fixPath(path, property, e.detail.path), e.detail.value);
5286 } else { 5726 } else {
5287 var value = target[property]; 5727 var value = target[property];
5288 if (!isStructured) { 5728 if (!isStructured) {
5289 this[path] = target[property]; 5729 this[path] = target[property];
5290 } else { 5730 } else {
5291 if (this.__data__[path] != value) { 5731 if (this.__data__[path] != value) {
5292 this.set(path, value); 5732 this.set(path, value);
5293 } 5733 }
5294 } 5734 }
5295 } 5735 }
5296 } 5736 }
5297 }; 5737 };
5298 }, 5738 },
5299 prepareInstance: function (inst) { 5739 prepareInstance: function (inst) {
5300 inst.__data__ = Object.create(null); 5740 inst.__data__ = Object.create(null);
5301 }, 5741 },
5302 setupBindListeners: function (inst) { 5742 setupBindListeners: function (inst) {
5303 inst._bindListeners.forEach(function (info) { 5743 inst._bindListeners.forEach(function (info) {
5304 var node = inst._nodes[info.index]; 5744 var node = inst._nodes[info.index];
5305 node.addEventListener(info.event, inst._notifyListener.bind(inst, info.changedFn )); 5745 node.addEventListener(info.event, inst._notifyListener.bind(inst, info.changedFn ));
5306 }); 5746 });
5307 } 5747 }
5308 }; 5748 };
5309 Polymer.Base.extend(Polymer.Bind, { 5749 Polymer.Base.extend(Polymer.Bind, {
5310 _shouldAddListener: function (effect) { 5750 _shouldAddListener: function (effect) {
5311 return effect.name && effect.mode === '{' && !effect.negate && effect.kind != 'a ttribute'; 5751 return effect.name && effect.kind != 'attribute' && effect.kind != 'text' && !ef fect.isCompound && effect.parts[0].mode === '{' && !effect.parts[0].negate;
5312 }, 5752 },
5313 _annotationEffect: function (source, value, effect) { 5753 _annotationEffect: function (source, value, effect) {
5314 if (source != effect.value) { 5754 if (source != effect.value) {
5315 value = this.get(effect.value); 5755 value = this._get(effect.value);
5316 this.__data__[effect.value] = value; 5756 this.__data__[effect.value] = value;
5317 } 5757 }
5318 var calc = effect.negate ? !value : value; 5758 var calc = effect.negate ? !value : value;
5319 if (!effect.customEvent || this._nodes[effect.index][effect.name] !== calc) { 5759 if (!effect.customEvent || this._nodes[effect.index][effect.name] !== calc) {
5320 return this._applyEffectValue(calc, effect); 5760 return this._applyEffectValue(effect, calc);
5321 } 5761 }
5322 }, 5762 },
5323 _reflectEffect: function (source) { 5763 _reflectEffect: function (source) {
5324 this.reflectPropertyToAttribute(source); 5764 this.reflectPropertyToAttribute(source);
5325 }, 5765 },
5326 _notifyEffect: function (source, value, effect, old, fromAbove) { 5766 _notifyEffect: function (source, value, effect, old, fromAbove) {
5327 if (!fromAbove) { 5767 if (!fromAbove) {
5328 this._notifyChange(source); 5768 this._notifyChange(source);
5329 } 5769 }
5330 }, 5770 },
(...skipping 17 matching lines...) Expand all
5348 } 5788 }
5349 } else { 5789 } else {
5350 this._warn(this._logf('_complexObserverEffect', 'observer method `' + effect.met hod + '` not defined')); 5790 this._warn(this._logf('_complexObserverEffect', 'observer method `' + effect.met hod + '` not defined'));
5351 } 5791 }
5352 }, 5792 },
5353 _computeEffect: function (source, value, effect) { 5793 _computeEffect: function (source, value, effect) {
5354 var args = Polymer.Bind._marshalArgs(this.__data__, effect, source, value); 5794 var args = Polymer.Bind._marshalArgs(this.__data__, effect, source, value);
5355 if (args) { 5795 if (args) {
5356 var fn = this[effect.method]; 5796 var fn = this[effect.method];
5357 if (fn) { 5797 if (fn) {
5358 this.__setProperty(effect.property, fn.apply(this, args)); 5798 this.__setProperty(effect.name, fn.apply(this, args));
5359 } else { 5799 } else {
5360 this._warn(this._logf('_computeEffect', 'compute method `' + effect.method + '` not defined')); 5800 this._warn(this._logf('_computeEffect', 'compute method `' + effect.method + '` not defined'));
5361 } 5801 }
5362 } 5802 }
5363 }, 5803 },
5364 _annotatedComputationEffect: function (source, value, effect) { 5804 _annotatedComputationEffect: function (source, value, effect) {
5365 var computedHost = this._rootDataHost || this; 5805 var computedHost = this._rootDataHost || this;
5366 var fn = computedHost[effect.method]; 5806 var fn = computedHost[effect.method];
5367 if (fn) { 5807 if (fn) {
5368 var args = Polymer.Bind._marshalArgs(this.__data__, effect, source, value); 5808 var args = Polymer.Bind._marshalArgs(this.__data__, effect, source, value);
5369 if (args) { 5809 if (args) {
5370 var computedvalue = fn.apply(computedHost, args); 5810 var computedvalue = fn.apply(computedHost, args);
5371 if (effect.negate) { 5811 if (effect.negate) {
5372 computedvalue = !computedvalue; 5812 computedvalue = !computedvalue;
5373 } 5813 }
5374 this._applyEffectValue(computedvalue, effect); 5814 this._applyEffectValue(effect, computedvalue);
5375 } 5815 }
5376 } else { 5816 } else {
5377 computedHost._warn(computedHost._logf('_annotatedComputationEffect', 'compute me thod `' + effect.method + '` not defined')); 5817 computedHost._warn(computedHost._logf('_annotatedComputationEffect', 'compute me thod `' + effect.method + '` not defined'));
5378 } 5818 }
5379 }, 5819 },
5380 _marshalArgs: function (model, effect, path, value) { 5820 _marshalArgs: function (model, effect, path, value) {
5381 var values = []; 5821 var values = [];
5382 var args = effect.args; 5822 var args = effect.args;
5383 for (var i = 0, l = args.length; i < l; i++) { 5823 for (var i = 0, l = args.length; i < l; i++) {
5384 var arg = args[i]; 5824 var arg = args[i];
5385 var name = arg.name; 5825 var name = arg.name;
5386 var v; 5826 var v;
5387 if (arg.literal) { 5827 if (arg.literal) {
5388 v = arg.value; 5828 v = arg.value;
5389 } else if (arg.structured) { 5829 } else if (arg.structured) {
5390 v = Polymer.Base.get(name, model); 5830 v = Polymer.Base._get(name, model);
5391 } else { 5831 } else {
5392 v = model[name]; 5832 v = model[name];
5393 } 5833 }
5394 if (args.length > 1 && v === undefined) { 5834 if (args.length > 1 && v === undefined) {
5395 return; 5835 return;
5396 } 5836 }
5397 if (arg.wildcard) { 5837 if (arg.wildcard) {
5398 var baseChanged = name.indexOf(path + '.') === 0; 5838 var baseChanged = name.indexOf(path + '.') === 0;
5399 var matches = effect.trigger.name.indexOf(name) === 0 && !baseChanged; 5839 var matches = effect.trigger.name.indexOf(name) === 0 && !baseChanged;
5400 values[i] = { 5840 values[i] = {
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
5443 } 5883 }
5444 } 5884 }
5445 }, 5885 },
5446 _addComputedEffect: function (name, expression) { 5886 _addComputedEffect: function (name, expression) {
5447 var sig = this._parseMethod(expression); 5887 var sig = this._parseMethod(expression);
5448 sig.args.forEach(function (arg) { 5888 sig.args.forEach(function (arg) {
5449 this._addPropertyEffect(arg.model, 'compute', { 5889 this._addPropertyEffect(arg.model, 'compute', {
5450 method: sig.method, 5890 method: sig.method,
5451 args: sig.args, 5891 args: sig.args,
5452 trigger: arg, 5892 trigger: arg,
5453 property: name 5893 name: name
5454 }); 5894 });
5455 }, this); 5895 }, this);
5456 }, 5896 },
5457 _addObserverEffect: function (property, observer) { 5897 _addObserverEffect: function (property, observer) {
5458 this._addPropertyEffect(property, 'observer', { 5898 this._addPropertyEffect(property, 'observer', {
5459 method: observer, 5899 method: observer,
5460 property: property 5900 property: property
5461 }); 5901 });
5462 }, 5902 },
5463 _addComplexObserverEffects: function (observers) { 5903 _addComplexObserverEffects: function (observers) {
(...skipping 17 matching lines...) Expand all
5481 this._nodes = []; 5921 this._nodes = [];
5482 notes.forEach(function (note) { 5922 notes.forEach(function (note) {
5483 var index = this._nodes.push(note) - 1; 5923 var index = this._nodes.push(note) - 1;
5484 note.bindings.forEach(function (binding) { 5924 note.bindings.forEach(function (binding) {
5485 this._addAnnotationEffect(binding, index); 5925 this._addAnnotationEffect(binding, index);
5486 }, this); 5926 }, this);
5487 }, this); 5927 }, this);
5488 }, 5928 },
5489 _addAnnotationEffect: function (note, index) { 5929 _addAnnotationEffect: function (note, index) {
5490 if (Polymer.Bind._shouldAddListener(note)) { 5930 if (Polymer.Bind._shouldAddListener(note)) {
5491 Polymer.Bind._addAnnotatedListener(this, index, note.name, note.value, note.even t); 5931 Polymer.Bind._addAnnotatedListener(this, index, note.name, note.parts[0].value, note.parts[0].event);
5492 } 5932 }
5493 if (note.signature) { 5933 for (var i = 0; i < note.parts.length; i++) {
5494 this._addAnnotatedComputationEffect(note, index); 5934 var part = note.parts[i];
5495 } else { 5935 if (part.signature) {
5496 note.index = index; 5936 this._addAnnotatedComputationEffect(note, part, index);
5497 this._addPropertyEffect(note.model, 'annotation', note); 5937 } else if (!part.literal) {
5938 this._addPropertyEffect(part.model, 'annotation', {
5939 kind: note.kind,
5940 index: index,
5941 name: note.name,
5942 value: part.value,
5943 isCompound: note.isCompound,
5944 compoundIndex: part.compoundIndex,
5945 event: part.event,
5946 customEvent: part.customEvent,
5947 negate: part.negate
5948 });
5949 }
5498 } 5950 }
5499 }, 5951 },
5500 _addAnnotatedComputationEffect: function (note, index) { 5952 _addAnnotatedComputationEffect: function (note, part, index) {
5501 var sig = note.signature; 5953 var sig = part.signature;
5502 if (sig.static) { 5954 if (sig.static) {
5503 this.__addAnnotatedComputationEffect('__static__', index, note, sig, null); 5955 this.__addAnnotatedComputationEffect('__static__', index, note, part, null);
5504 } else { 5956 } else {
5505 sig.args.forEach(function (arg) { 5957 sig.args.forEach(function (arg) {
5506 if (!arg.literal) { 5958 if (!arg.literal) {
5507 this.__addAnnotatedComputationEffect(arg.model, index, note, sig, arg); 5959 this.__addAnnotatedComputationEffect(arg.model, index, note, part, arg);
5508 } 5960 }
5509 }, this); 5961 }, this);
5510 } 5962 }
5511 }, 5963 },
5512 __addAnnotatedComputationEffect: function (property, index, note, sig, trigger) { 5964 __addAnnotatedComputationEffect: function (property, index, note, part, trigger) {
5513 this._addPropertyEffect(property, 'annotatedComputation', { 5965 this._addPropertyEffect(property, 'annotatedComputation', {
5514 index: index, 5966 index: index,
5967 isCompound: note.isCompound,
5968 compoundIndex: part.compoundIndex,
5515 kind: note.kind, 5969 kind: note.kind,
5516 property: note.name, 5970 name: note.name,
5517 negate: note.negate, 5971 negate: part.negate,
5518 method: sig.method, 5972 method: part.signature.method,
5519 args: sig.args, 5973 args: part.signature.args,
5520 trigger: trigger 5974 trigger: trigger
5521 }); 5975 });
5522 }, 5976 },
5523 _parseMethod: function (expression) { 5977 _parseMethod: function (expression) {
5524 var m = expression.match(/([^\s]+)\((.*)\)/); 5978 var m = expression.match(/([^\s]+)\((.*)\)/);
5525 if (m) { 5979 if (m) {
5526 var sig = { 5980 var sig = {
5527 method: m[1], 5981 method: m[1],
5528 static: true 5982 static: true
5529 }; 5983 };
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
5578 a.name = arg.slice(0, -2); 6032 a.name = arg.slice(0, -2);
5579 } 6033 }
5580 } 6034 }
5581 } 6035 }
5582 return a; 6036 return a;
5583 }, 6037 },
5584 _marshalInstanceEffects: function () { 6038 _marshalInstanceEffects: function () {
5585 Polymer.Bind.prepareInstance(this); 6039 Polymer.Bind.prepareInstance(this);
5586 Polymer.Bind.setupBindListeners(this); 6040 Polymer.Bind.setupBindListeners(this);
5587 }, 6041 },
5588 _applyEffectValue: function (value, info) { 6042 _applyEffectValue: function (info, value) {
5589 var node = this._nodes[info.index]; 6043 var node = this._nodes[info.index];
5590 var property = info.property || info.name || 'textContent'; 6044 var property = info.name;
6045 if (info.isCompound) {
6046 var storage = node.__compoundStorage__[property];
6047 storage[info.compoundIndex] = value;
6048 value = storage.join('');
6049 }
5591 if (info.kind == 'attribute') { 6050 if (info.kind == 'attribute') {
5592 this.serializeValueToAttribute(value, property, node); 6051 this.serializeValueToAttribute(value, property, node);
5593 } else { 6052 } else {
5594 if (property === 'className') { 6053 if (property === 'className') {
5595 value = this._scopeElementClass(node, value); 6054 value = this._scopeElementClass(node, value);
5596 } 6055 }
5597 if (property === 'textContent' || node.localName == 'input' && property == 'valu e') { 6056 if (property === 'textContent' || node.localName == 'input' && property == 'valu e') {
5598 value = value == undefined ? '' : value; 6057 value = value == undefined ? '' : value;
5599 } 6058 }
5600 return node[property] = value; 6059 return node[property] = value;
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
5660 } 6119 }
5661 } 6120 }
5662 }, 6121 },
5663 _distributeConfig: function (config) { 6122 _distributeConfig: function (config) {
5664 var fx$ = this._propertyEffects; 6123 var fx$ = this._propertyEffects;
5665 if (fx$) { 6124 if (fx$) {
5666 for (var p in config) { 6125 for (var p in config) {
5667 var fx = fx$[p]; 6126 var fx = fx$[p];
5668 if (fx) { 6127 if (fx) {
5669 for (var i = 0, l = fx.length, x; i < l && (x = fx[i]); i++) { 6128 for (var i = 0, l = fx.length, x; i < l && (x = fx[i]); i++) {
5670 if (x.kind === 'annotation') { 6129 if (x.kind === 'annotation' && !x.isCompound) {
5671 var node = this._nodes[x.effect.index]; 6130 var node = this._nodes[x.effect.index];
5672 if (node._configValue) { 6131 if (node._configValue) {
5673 var value = p === x.effect.value ? config[p] : this.get(x.effect.value, config); 6132 var value = p === x.effect.value ? config[p] : this._get(x.effect.value, config) ;
5674 node._configValue(x.effect.name, value); 6133 node._configValue(x.effect.name, value);
5675 } 6134 }
5676 } 6135 }
5677 } 6136 }
5678 } 6137 }
5679 } 6138 }
5680 } 6139 }
5681 }, 6140 },
5682 _afterClientsReady: function () { 6141 _afterClientsReady: function () {
5683 this._executeStaticEffects(); 6142 this._executeStaticEffects();
(...skipping 26 matching lines...) Expand all
5710 for (var i = 0, l = h$.length, h; i < l && (h = h$[i]); i++) { 6169 for (var i = 0, l = h$.length, h; i < l && (h = h$[i]); i++) {
5711 h[0].call(this, h[1], h[2]); 6170 h[0].call(this, h[1], h[2]);
5712 } 6171 }
5713 this._handlers = []; 6172 this._handlers = [];
5714 } 6173 }
5715 }); 6174 });
5716 (function () { 6175 (function () {
5717 'use strict'; 6176 'use strict';
5718 Polymer.Base._addFeature({ 6177 Polymer.Base._addFeature({
5719 notifyPath: function (path, value, fromAbove) { 6178 notifyPath: function (path, value, fromAbove) {
6179 var info = {};
6180 this._get(path, this, info);
6181 this._notifyPath(info.path, value, fromAbove);
6182 },
6183 _notifyPath: function (path, value, fromAbove) {
5720 var old = this._propertySetter(path, value); 6184 var old = this._propertySetter(path, value);
5721 if (old !== value && (old === old || value === value)) { 6185 if (old !== value && (old === old || value === value)) {
5722 this._pathEffector(path, value); 6186 this._pathEffector(path, value);
5723 if (!fromAbove) { 6187 if (!fromAbove) {
5724 this._notifyPath(path, value); 6188 this._notifyPathUp(path, value);
5725 } 6189 }
5726 return true; 6190 return true;
5727 } 6191 }
5728 }, 6192 },
5729 _getPathParts: function (path) { 6193 _getPathParts: function (path) {
5730 if (Array.isArray(path)) { 6194 if (Array.isArray(path)) {
5731 var parts = []; 6195 var parts = [];
5732 for (var i = 0; i < path.length; i++) { 6196 for (var i = 0; i < path.length; i++) {
5733 var args = path[i].toString().split('.'); 6197 var args = path[i].toString().split('.');
5734 for (var j = 0; j < args.length; j++) { 6198 for (var j = 0; j < args.length; j++) {
5735 parts.push(args[j]); 6199 parts.push(args[j]);
5736 } 6200 }
5737 } 6201 }
5738 return parts; 6202 return parts;
5739 } else { 6203 } else {
5740 return path.toString().split('.'); 6204 return path.toString().split('.');
5741 } 6205 }
5742 }, 6206 },
5743 set: function (path, value, root) { 6207 set: function (path, value, root) {
5744 var prop = root || this; 6208 var prop = root || this;
5745 var parts = this._getPathParts(path); 6209 var parts = this._getPathParts(path);
5746 var array; 6210 var array;
5747 var last = parts[parts.length - 1]; 6211 var last = parts[parts.length - 1];
5748 if (parts.length > 1) { 6212 if (parts.length > 1) {
5749 for (var i = 0; i < parts.length - 1; i++) { 6213 for (var i = 0; i < parts.length - 1; i++) {
5750 var part = parts[i]; 6214 var part = parts[i];
6215 if (array && part[0] == '#') {
6216 prop = Polymer.Collection.get(array).getItem(part);
6217 } else {
5751 prop = prop[part]; 6218 prop = prop[part];
5752 if (array && parseInt(part) == part) { 6219 if (array && parseInt(part, 10) == part) {
5753 parts[i] = Polymer.Collection.get(array).getKey(prop); 6220 parts[i] = Polymer.Collection.get(array).getKey(prop);
5754 } 6221 }
6222 }
5755 if (!prop) { 6223 if (!prop) {
5756 return; 6224 return;
5757 } 6225 }
5758 array = Array.isArray(prop) ? prop : null; 6226 array = Array.isArray(prop) ? prop : null;
5759 } 6227 }
5760 if (array && parseInt(last) == last) { 6228 if (array) {
5761 var coll = Polymer.Collection.get(array); 6229 var coll = Polymer.Collection.get(array);
6230 if (last[0] == '#') {
6231 var key = last;
6232 var old = coll.getItem(key);
6233 last = array.indexOf(old);
6234 coll.setItem(key, value);
6235 } else if (parseInt(last, 10) == last) {
5762 var old = prop[last]; 6236 var old = prop[last];
5763 var key = coll.getKey(old); 6237 var key = coll.getKey(old);
5764 parts[i] = key; 6238 parts[i] = key;
5765 coll.setItem(key, value); 6239 coll.setItem(key, value);
5766 } 6240 }
6241 }
5767 prop[last] = value; 6242 prop[last] = value;
5768 if (!root) { 6243 if (!root) {
5769 this.notifyPath(parts.join('.'), value); 6244 this._notifyPath(parts.join('.'), value);
5770 } 6245 }
5771 } else { 6246 } else {
5772 prop[path] = value; 6247 prop[path] = value;
5773 } 6248 }
5774 }, 6249 },
5775 get: function (path, root) { 6250 get: function (path, root) {
6251 return this._get(path, root);
6252 },
6253 _get: function (path, root, info) {
5776 var prop = root || this; 6254 var prop = root || this;
5777 var parts = this._getPathParts(path); 6255 var parts = this._getPathParts(path);
5778 var last = parts.pop(); 6256 var array;
5779 while (parts.length) { 6257 for (var i = 0; i < parts.length; i++) {
5780 prop = prop[parts.shift()];
5781 if (!prop) { 6258 if (!prop) {
5782 return; 6259 return;
5783 } 6260 }
6261 var part = parts[i];
6262 if (array && part[0] == '#') {
6263 prop = Polymer.Collection.get(array).getItem(part);
6264 } else {
6265 prop = prop[part];
6266 if (info && array && parseInt(part, 10) == part) {
6267 parts[i] = Polymer.Collection.get(array).getKey(prop);
5784 } 6268 }
5785 return prop[last]; 6269 }
6270 array = Array.isArray(prop) ? prop : null;
6271 }
6272 if (info) {
6273 info.path = parts.join('.');
6274 }
6275 return prop;
5786 }, 6276 },
5787 _pathEffector: function (path, value) { 6277 _pathEffector: function (path, value) {
5788 var model = this._modelForPath(path); 6278 var model = this._modelForPath(path);
5789 var fx$ = this._propertyEffects[model]; 6279 var fx$ = this._propertyEffects[model];
5790 if (fx$) { 6280 if (fx$) {
5791 fx$.forEach(function (fx) { 6281 fx$.forEach(function (fx) {
5792 var fxFn = this['_' + fx.kind + 'PathEffect']; 6282 var fxFn = this['_' + fx.kind + 'PathEffect'];
5793 if (fxFn) { 6283 if (fxFn) {
5794 fxFn.call(this, path, value, fx.effect); 6284 fxFn.call(this, path, value, fx.effect);
5795 } 6285 }
5796 }, this); 6286 }, this);
5797 } 6287 }
5798 if (this._boundPaths) { 6288 if (this._boundPaths) {
5799 this._notifyBoundPaths(path, value); 6289 this._notifyBoundPaths(path, value);
5800 } 6290 }
5801 }, 6291 },
5802 _annotationPathEffect: function (path, value, effect) { 6292 _annotationPathEffect: function (path, value, effect) {
5803 if (effect.value === path || effect.value.indexOf(path + '.') === 0) { 6293 if (effect.value === path || effect.value.indexOf(path + '.') === 0) {
5804 Polymer.Bind._annotationEffect.call(this, path, value, effect); 6294 Polymer.Bind._annotationEffect.call(this, path, value, effect);
5805 } else if (path.indexOf(effect.value + '.') === 0 && !effect.negate) { 6295 } else if (path.indexOf(effect.value + '.') === 0 && !effect.negate) {
5806 var node = this._nodes[effect.index]; 6296 var node = this._nodes[effect.index];
5807 if (node && node.notifyPath) { 6297 if (node && node._notifyPath) {
5808 var p = this._fixPath(effect.name, effect.value, path); 6298 var p = this._fixPath(effect.name, effect.value, path);
5809 node.notifyPath(p, value, true); 6299 node._notifyPath(p, value, true);
5810 } 6300 }
5811 } 6301 }
5812 }, 6302 },
5813 _complexObserverPathEffect: function (path, value, effect) { 6303 _complexObserverPathEffect: function (path, value, effect) {
5814 if (this._pathMatchesEffect(path, effect)) { 6304 if (this._pathMatchesEffect(path, effect)) {
5815 Polymer.Bind._complexObserverEffect.call(this, path, value, effect); 6305 Polymer.Bind._complexObserverEffect.call(this, path, value, effect);
5816 } 6306 }
5817 }, 6307 },
5818 _computePathEffect: function (path, value, effect) { 6308 _computePathEffect: function (path, value, effect) {
5819 if (this._pathMatchesEffect(path, effect)) { 6309 if (this._pathMatchesEffect(path, effect)) {
(...skipping 19 matching lines...) Expand all
5839 }, 6329 },
5840 unlinkPaths: function (path) { 6330 unlinkPaths: function (path) {
5841 if (this._boundPaths) { 6331 if (this._boundPaths) {
5842 delete this._boundPaths[path]; 6332 delete this._boundPaths[path];
5843 } 6333 }
5844 }, 6334 },
5845 _notifyBoundPaths: function (path, value) { 6335 _notifyBoundPaths: function (path, value) {
5846 for (var a in this._boundPaths) { 6336 for (var a in this._boundPaths) {
5847 var b = this._boundPaths[a]; 6337 var b = this._boundPaths[a];
5848 if (path.indexOf(a + '.') == 0) { 6338 if (path.indexOf(a + '.') == 0) {
5849 this.notifyPath(this._fixPath(b, a, path), value); 6339 this._notifyPath(this._fixPath(b, a, path), value);
5850 } else if (path.indexOf(b + '.') == 0) { 6340 } else if (path.indexOf(b + '.') == 0) {
5851 this.notifyPath(this._fixPath(a, b, path), value); 6341 this._notifyPath(this._fixPath(a, b, path), value);
5852 } 6342 }
5853 } 6343 }
5854 }, 6344 },
5855 _fixPath: function (property, root, path) { 6345 _fixPath: function (property, root, path) {
5856 return property + path.slice(root.length); 6346 return property + path.slice(root.length);
5857 }, 6347 },
5858 _notifyPath: function (path, value) { 6348 _notifyPathUp: function (path, value) {
5859 var rootName = this._modelForPath(path); 6349 var rootName = this._modelForPath(path);
5860 var dashCaseName = Polymer.CaseMap.camelToDashCase(rootName); 6350 var dashCaseName = Polymer.CaseMap.camelToDashCase(rootName);
5861 var eventName = dashCaseName + this._EVENT_CHANGED; 6351 var eventName = dashCaseName + this._EVENT_CHANGED;
5862 this.fire(eventName, { 6352 this.fire(eventName, {
5863 path: path, 6353 path: path,
5864 value: value 6354 value: value
5865 }, { bubbles: false }); 6355 }, { bubbles: false });
5866 }, 6356 },
5867 _modelForPath: function (path) { 6357 _modelForPath: function (path) {
5868 var dot = path.indexOf('.'); 6358 var dot = path.indexOf('.');
5869 return dot < 0 ? path : path.slice(0, dot); 6359 return dot < 0 ? path : path.slice(0, dot);
5870 }, 6360 },
5871 _EVENT_CHANGED: '-changed', 6361 _EVENT_CHANGED: '-changed',
6362 notifySplices: function (path, splices) {
6363 var info = {};
6364 var array = this._get(path, this, info);
6365 this._notifySplices(array, info.path, splices);
6366 },
6367 _notifySplices: function (array, path, splices) {
6368 var change = {
6369 keySplices: Polymer.Collection.applySplices(array, splices),
6370 indexSplices: splices
6371 };
6372 if (!array.hasOwnProperty('splices')) {
6373 Object.defineProperty(array, 'splices', {
6374 configurable: true,
6375 writable: true
6376 });
6377 }
6378 array.splices = change;
6379 this._notifyPath(path + '.splices', change);
6380 this._notifyPath(path + '.length', array.length);
6381 change.keySplices = null;
6382 change.indexSplices = null;
6383 },
5872 _notifySplice: function (array, path, index, added, removed) { 6384 _notifySplice: function (array, path, index, added, removed) {
5873 var splices = [{ 6385 this._notifySplices(array, path, [{
5874 index: index, 6386 index: index,
5875 addedCount: added, 6387 addedCount: added,
5876 removed: removed, 6388 removed: removed,
5877 object: array, 6389 object: array,
5878 type: 'splice' 6390 type: 'splice'
5879 }]; 6391 }]);
5880 var change = {
5881 keySplices: Polymer.Collection.applySplices(array, splices),
5882 indexSplices: splices
5883 };
5884 this.set(path + '.splices', change);
5885 if (added != removed.length) {
5886 this.notifyPath(path + '.length', array.length);
5887 }
5888 change.keySplices = null;
5889 change.indexSplices = null;
5890 }, 6392 },
5891 push: function (path) { 6393 push: function (path) {
5892 var array = this.get(path); 6394 var info = {};
6395 var array = this._get(path, this, info);
5893 var args = Array.prototype.slice.call(arguments, 1); 6396 var args = Array.prototype.slice.call(arguments, 1);
5894 var len = array.length; 6397 var len = array.length;
5895 var ret = array.push.apply(array, args); 6398 var ret = array.push.apply(array, args);
5896 if (args.length) { 6399 if (args.length) {
5897 this._notifySplice(array, path, len, args.length, []); 6400 this._notifySplice(array, info.path, len, args.length, []);
5898 } 6401 }
5899 return ret; 6402 return ret;
5900 }, 6403 },
5901 pop: function (path) { 6404 pop: function (path) {
5902 var array = this.get(path); 6405 var info = {};
6406 var array = this._get(path, this, info);
5903 var hadLength = Boolean(array.length); 6407 var hadLength = Boolean(array.length);
5904 var args = Array.prototype.slice.call(arguments, 1); 6408 var args = Array.prototype.slice.call(arguments, 1);
5905 var ret = array.pop.apply(array, args); 6409 var ret = array.pop.apply(array, args);
5906 if (hadLength) { 6410 if (hadLength) {
5907 this._notifySplice(array, path, array.length, 0, [ret]); 6411 this._notifySplice(array, info.path, array.length, 0, [ret]);
5908 } 6412 }
5909 return ret; 6413 return ret;
5910 }, 6414 },
5911 splice: function (path, start, deleteCount) { 6415 splice: function (path, start, deleteCount) {
5912 var array = this.get(path); 6416 var info = {};
6417 var array = this._get(path, this, info);
5913 if (start < 0) { 6418 if (start < 0) {
5914 start = array.length - Math.floor(-start); 6419 start = array.length - Math.floor(-start);
5915 } else { 6420 } else {
5916 start = Math.floor(start); 6421 start = Math.floor(start);
5917 } 6422 }
5918 if (!start) { 6423 if (!start) {
5919 start = 0; 6424 start = 0;
5920 } 6425 }
5921 var args = Array.prototype.slice.call(arguments, 1); 6426 var args = Array.prototype.slice.call(arguments, 1);
5922 var ret = array.splice.apply(array, args); 6427 var ret = array.splice.apply(array, args);
5923 var addedCount = Math.max(args.length - 2, 0); 6428 var addedCount = Math.max(args.length - 2, 0);
5924 if (addedCount || ret.length) { 6429 if (addedCount || ret.length) {
5925 this._notifySplice(array, path, start, addedCount, ret); 6430 this._notifySplice(array, info.path, start, addedCount, ret);
5926 } 6431 }
5927 return ret; 6432 return ret;
5928 }, 6433 },
5929 shift: function (path) { 6434 shift: function (path) {
5930 var array = this.get(path); 6435 var info = {};
6436 var array = this._get(path, this, info);
5931 var hadLength = Boolean(array.length); 6437 var hadLength = Boolean(array.length);
5932 var args = Array.prototype.slice.call(arguments, 1); 6438 var args = Array.prototype.slice.call(arguments, 1);
5933 var ret = array.shift.apply(array, args); 6439 var ret = array.shift.apply(array, args);
5934 if (hadLength) { 6440 if (hadLength) {
5935 this._notifySplice(array, path, 0, 0, [ret]); 6441 this._notifySplice(array, info.path, 0, 0, [ret]);
5936 } 6442 }
5937 return ret; 6443 return ret;
5938 }, 6444 },
5939 unshift: function (path) { 6445 unshift: function (path) {
5940 var array = this.get(path); 6446 var info = {};
6447 var array = this._get(path, this, info);
5941 var args = Array.prototype.slice.call(arguments, 1); 6448 var args = Array.prototype.slice.call(arguments, 1);
5942 var ret = array.unshift.apply(array, args); 6449 var ret = array.unshift.apply(array, args);
5943 if (args.length) { 6450 if (args.length) {
5944 this._notifySplice(array, path, 0, args.length, []); 6451 this._notifySplice(array, info.path, 0, args.length, []);
5945 } 6452 }
5946 return ret; 6453 return ret;
5947 }, 6454 },
5948 prepareModelNotifyPath: function (model) { 6455 prepareModelNotifyPath: function (model) {
5949 this.mixin(model, { 6456 this.mixin(model, {
5950 fire: Polymer.Base.fire, 6457 fire: Polymer.Base.fire,
5951 notifyPath: Polymer.Base.notifyPath, 6458 notifyPath: Polymer.Base.notifyPath,
6459 _get: Polymer.Base._get,
5952 _EVENT_CHANGED: Polymer.Base._EVENT_CHANGED, 6460 _EVENT_CHANGED: Polymer.Base._EVENT_CHANGED,
5953 _notifyPath: Polymer.Base._notifyPath, 6461 _notifyPath: Polymer.Base._notifyPath,
6462 _notifyPathUp: Polymer.Base._notifyPathUp,
5954 _pathEffector: Polymer.Base._pathEffector, 6463 _pathEffector: Polymer.Base._pathEffector,
5955 _annotationPathEffect: Polymer.Base._annotationPathEffect, 6464 _annotationPathEffect: Polymer.Base._annotationPathEffect,
5956 _complexObserverPathEffect: Polymer.Base._complexObserverPathEffect, 6465 _complexObserverPathEffect: Polymer.Base._complexObserverPathEffect,
5957 _annotatedComputationPathEffect: Polymer.Base._annotatedComputationPathEffect, 6466 _annotatedComputationPathEffect: Polymer.Base._annotatedComputationPathEffect,
5958 _computePathEffect: Polymer.Base._computePathEffect, 6467 _computePathEffect: Polymer.Base._computePathEffect,
5959 _modelForPath: Polymer.Base._modelForPath, 6468 _modelForPath: Polymer.Base._modelForPath,
5960 _pathMatchesEffect: Polymer.Base._pathMatchesEffect, 6469 _pathMatchesEffect: Polymer.Base._pathMatchesEffect,
5961 _notifyBoundPaths: Polymer.Base._notifyBoundPaths 6470 _notifyBoundPaths: Polymer.Base._notifyBoundPaths,
6471 _getPathParts: Polymer.Base._getPathParts
5962 }); 6472 });
5963 } 6473 }
5964 }); 6474 });
5965 }()); 6475 }());
5966 Polymer.Base._addFeature({ 6476 Polymer.Base._addFeature({
5967 resolveUrl: function (url) { 6477 resolveUrl: function (url) {
5968 var module = Polymer.DomModule.import(this.is); 6478 var module = Polymer.DomModule.import(this.is);
5969 var root = ''; 6479 var root = '';
5970 if (module) { 6480 if (module) {
5971 var assetPath = module.getAttribute('assetpath') || ''; 6481 var assetPath = module.getAttribute('assetpath') || '';
(...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after
6088 KEYFRAMES_RULE: 7, 6598 KEYFRAMES_RULE: 7,
6089 MEDIA_RULE: 4, 6599 MEDIA_RULE: 4,
6090 MIXIN_RULE: 1000 6600 MIXIN_RULE: 1000
6091 }, 6601 },
6092 OPEN_BRACE: '{', 6602 OPEN_BRACE: '{',
6093 CLOSE_BRACE: '}', 6603 CLOSE_BRACE: '}',
6094 _rx: { 6604 _rx: {
6095 comments: /\/\*[^*]*\*+([^\/*][^*]*\*+)*\//gim, 6605 comments: /\/\*[^*]*\*+([^\/*][^*]*\*+)*\//gim,
6096 port: /@import[^;]*;/gim, 6606 port: /@import[^;]*;/gim,
6097 customProp: /(?:^|[\s;])--[^;{]*?:[^{};]*?(?:[;\n]|$)/gim, 6607 customProp: /(?:^|[\s;])--[^;{]*?:[^{};]*?(?:[;\n]|$)/gim,
6098 mixinProp: /(?:^|[\s;])--[^;{]*?:[^{;]*?{[^}]*?}(?:[;\n]|$)?/gim, 6608 mixinProp: /(?:^|[\s;])?--[^;{]*?:[^{;]*?{[^}]*?}(?:[;\n]|$)?/gim,
6099 mixinApply: /@apply[\s]*\([^)]*?\)[\s]*(?:[;\n]|$)?/gim, 6609 mixinApply: /@apply[\s]*\([^)]*?\)[\s]*(?:[;\n]|$)?/gim,
6100 varApply: /[^;:]*?:[^;]*var[^;]*(?:[;\n]|$)?/gim, 6610 varApply: /[^;:]*?:[^;]*var[^;]*(?:[;\n]|$)?/gim,
6101 keyframesRule: /^@[^\s]*keyframes/ 6611 keyframesRule: /^@[^\s]*keyframes/
6102 }, 6612 },
6103 VAR_START: '--', 6613 VAR_START: '--',
6104 MEDIA_START: '@media', 6614 MEDIA_START: '@media',
6105 AT_START: '@' 6615 AT_START: '@'
6106 }; 6616 };
6107 return api; 6617 return api;
6108 }(); 6618 }();
(...skipping 682 matching lines...) Expand 10 before | Expand all | Expand 10 after
6791 mixinCustomStyle: function (props, customStyle) { 7301 mixinCustomStyle: function (props, customStyle) {
6792 var v; 7302 var v;
6793 for (var i in customStyle) { 7303 for (var i in customStyle) {
6794 v = customStyle[i]; 7304 v = customStyle[i];
6795 if (v || v === 0) { 7305 if (v || v === 0) {
6796 props[i] = v; 7306 props[i] = v;
6797 } 7307 }
6798 } 7308 }
6799 }, 7309 },
6800 rx: { 7310 rx: {
6801 VAR_ASSIGN: /(?:^|[;\n]\s*)(--[\w-]*?):\s*(?:([^;{]*)|{([^}]*)})(?:(?=[;\n])|$)/ gi, 7311 VAR_ASSIGN: /(?:^|[;\s{]\s*)(--[\w-]*?)\s*:\s*(?:([^;{]*)|{([^}]*)})(?:(?=[;\s}] )|$)/gi,
6802 MIXIN_MATCH: /(?:^|\W+)@apply[\s]*\(([^)]*)\)/i, 7312 MIXIN_MATCH: /(?:^|\W+)@apply[\s]*\(([^)]*)\)/i,
6803 VAR_MATCH: /(^|\W+)var\([\s]*([^,)]*)[\s]*,?[\s]*((?:[^,)]*)|(?:[^;]*\([^;)]*\)) )[\s]*?\)/gi, 7313 VAR_MATCH: /(^|\W+)var\([\s]*([^,)]*)[\s]*,?[\s]*((?:[^,)]*)|(?:[^;]*\([^;)]*\)) )[\s]*?\)/gi,
6804 VAR_CAPTURE: /\([\s]*(--[^,\s)]*)(?:,[\s]*(--[^,\s)]*))?(?:\)|,)/gi, 7314 VAR_CAPTURE: /\([\s]*(--[^,\s)]*)(?:,[\s]*(--[^,\s)]*))?(?:\)|,)/gi,
6805 IS_VAR: /^--/, 7315 IS_VAR: /^--/,
6806 BRACKETED: /\{[^}]*\}/g, 7316 BRACKETED: /\{[^}]*\}/g,
6807 HOST_PREFIX: '(?:^|[^.#[:])', 7317 HOST_PREFIX: '(?:^|[^.#[:])',
6808 HOST_SUFFIX: '($|[.:[\\s>+~])' 7318 HOST_SUFFIX: '($|[.:[\\s>+~])'
6809 }, 7319 },
6810 HOST_SELECTORS: [':host'], 7320 HOST_SELECTORS: [':host'],
6811 SCOPE_SELECTORS: [':root'], 7321 SCOPE_SELECTORS: [':root'],
(...skipping 363 matching lines...) Expand 10 before | Expand all | Expand 10 after
7175 this._prepParentProperties(this.ctor.prototype, template); 7685 this._prepParentProperties(this.ctor.prototype, template);
7176 return; 7686 return;
7177 } 7687 }
7178 var archetype = Object.create(Polymer.Base); 7688 var archetype = Object.create(Polymer.Base);
7179 this._customPrepAnnotations(archetype, template); 7689 this._customPrepAnnotations(archetype, template);
7180 this._prepParentProperties(archetype, template); 7690 this._prepParentProperties(archetype, template);
7181 archetype._prepEffects(); 7691 archetype._prepEffects();
7182 this._customPrepEffects(archetype); 7692 this._customPrepEffects(archetype);
7183 archetype._prepBehaviors(); 7693 archetype._prepBehaviors();
7184 archetype._prepBindings(); 7694 archetype._prepBindings();
7185 archetype._notifyPath = this._notifyPathImpl; 7695 archetype._notifyPathUp = this._notifyPathUpImpl;
7186 archetype._scopeElementClass = this._scopeElementClassImpl; 7696 archetype._scopeElementClass = this._scopeElementClassImpl;
7187 archetype.listen = this._listenImpl; 7697 archetype.listen = this._listenImpl;
7188 archetype._showHideChildren = this._showHideChildrenImpl; 7698 archetype._showHideChildren = this._showHideChildrenImpl;
7189 var _constructor = this._constructorImpl; 7699 var _constructor = this._constructorImpl;
7190 var ctor = function TemplateInstance(model, host) { 7700 var ctor = function TemplateInstance(model, host) {
7191 _constructor.call(this, model, host); 7701 _constructor.call(this, model, host);
7192 }; 7702 };
7193 ctor.prototype = archetype; 7703 ctor.prototype = archetype;
7194 archetype.constructor = ctor; 7704 archetype.constructor = ctor;
7195 template._content._ctor = ctor; 7705 template._content._ctor = ctor;
(...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after
7313 template._propertySetter(n, val); 7823 template._propertySetter(n, val);
7314 } 7824 }
7315 }); 7825 });
7316 }, 7826 },
7317 _showHideChildren: function (hidden) { 7827 _showHideChildren: function (hidden) {
7318 }, 7828 },
7319 _forwardInstancePath: function (inst, path, value) { 7829 _forwardInstancePath: function (inst, path, value) {
7320 }, 7830 },
7321 _forwardInstanceProp: function (inst, prop, value) { 7831 _forwardInstanceProp: function (inst, prop, value) {
7322 }, 7832 },
7323 _notifyPathImpl: function (path, value) { 7833 _notifyPathUpImpl: function (path, value) {
7324 var dataHost = this.dataHost; 7834 var dataHost = this.dataHost;
7325 var dot = path.indexOf('.'); 7835 var dot = path.indexOf('.');
7326 var root = dot < 0 ? path : path.slice(0, dot); 7836 var root = dot < 0 ? path : path.slice(0, dot);
7327 dataHost._forwardInstancePath.call(dataHost, this, path, value); 7837 dataHost._forwardInstancePath.call(dataHost, this, path, value);
7328 if (root in dataHost._parentProps) { 7838 if (root in dataHost._parentProps) {
7329 dataHost._templatized.notifyPath(dataHost._parentPropPrefix + path, value); 7839 dataHost._templatized.notifyPath(dataHost._parentPropPrefix + path, value);
7330 } 7840 }
7331 }, 7841 },
7332 _pathEffectorImpl: function (path, value, fromAbove) { 7842 _pathEffectorImpl: function (path, value, fromAbove) {
7333 if (this._forwardParentPath) { 7843 if (this._forwardParentPath) {
7334 if (path.indexOf(this._parentPropPrefix) === 0) { 7844 if (path.indexOf(this._parentPropPrefix) === 0) {
7335 var subPath = path.substring(this._parentPropPrefix.length); 7845 var subPath = path.substring(this._parentPropPrefix.length);
7846 var model = this._modelForPath(subPath);
7847 if (model in this._parentProps) {
7336 this._forwardParentPath(subPath, value); 7848 this._forwardParentPath(subPath, value);
7337 } 7849 }
7338 } 7850 }
7851 }
7339 Polymer.Base._pathEffector.call(this._templatized, path, value, fromAbove); 7852 Polymer.Base._pathEffector.call(this._templatized, path, value, fromAbove);
7340 }, 7853 },
7341 _constructorImpl: function (model, host) { 7854 _constructorImpl: function (model, host) {
7342 this._rootDataHost = host._getRootDataHost(); 7855 this._rootDataHost = host._getRootDataHost();
7343 this._setupConfigure(model); 7856 this._setupConfigure(model);
7344 this._pushHost(host); 7857 this._pushHost(host);
7345 this.root = this.instanceTemplate(this._template); 7858 this.root = this.instanceTemplate(this._template);
7346 this.root.__noContent = !this._notes._hasContent; 7859 this.root.__noContent = !this._notes._hasContent;
7347 this.root.__styleScoped = true; 7860 this.root.__styleScoped = true;
7348 this._popHost(); 7861 this._popHost();
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after
7431 } 7944 }
7432 } 7945 }
7433 }, 7946 },
7434 add: function (item) { 7947 add: function (item) {
7435 var key = this.store.push(item) - 1; 7948 var key = this.store.push(item) - 1;
7436 if (item && typeof item == 'object') { 7949 if (item && typeof item == 'object') {
7437 this.omap.set(item, key); 7950 this.omap.set(item, key);
7438 } else { 7951 } else {
7439 this.pmap[item] = key; 7952 this.pmap[item] = key;
7440 } 7953 }
7441 return key; 7954 return '#' + key;
7442 }, 7955 },
7443 removeKey: function (key) { 7956 removeKey: function (key) {
7957 key = this._parseKey(key);
7444 this._removeFromMap(this.store[key]); 7958 this._removeFromMap(this.store[key]);
7445 delete this.store[key]; 7959 delete this.store[key];
7446 }, 7960 },
7447 _removeFromMap: function (item) { 7961 _removeFromMap: function (item) {
7448 if (item && typeof item == 'object') { 7962 if (item && typeof item == 'object') {
7449 this.omap.delete(item); 7963 this.omap.delete(item);
7450 } else { 7964 } else {
7451 delete this.pmap[item]; 7965 delete this.pmap[item];
7452 } 7966 }
7453 }, 7967 },
7454 remove: function (item) { 7968 remove: function (item) {
7455 var key = this.getKey(item); 7969 var key = this.getKey(item);
7456 this.removeKey(key); 7970 this.removeKey(key);
7457 return key; 7971 return key;
7458 }, 7972 },
7459 getKey: function (item) { 7973 getKey: function (item) {
7974 var key;
7460 if (item && typeof item == 'object') { 7975 if (item && typeof item == 'object') {
7461 return this.omap.get(item); 7976 key = this.omap.get(item);
7462 } else { 7977 } else {
7463 return this.pmap[item]; 7978 key = this.pmap[item];
7979 }
7980 if (key != undefined) {
7981 return '#' + key;
7464 } 7982 }
7465 }, 7983 },
7466 getKeys: function () { 7984 getKeys: function () {
7467 return Object.keys(this.store); 7985 return Object.keys(this.store).map(function (key) {
7986 return '#' + key;
7987 });
7988 },
7989 _parseKey: function (key) {
7990 if (key[0] == '#') {
7991 return key.slice(1);
7992 }
7993 throw new Error('unexpected key ' + key);
7468 }, 7994 },
7469 setItem: function (key, item) { 7995 setItem: function (key, item) {
7996 key = this._parseKey(key);
7470 var old = this.store[key]; 7997 var old = this.store[key];
7471 if (old) { 7998 if (old) {
7472 this._removeFromMap(old); 7999 this._removeFromMap(old);
7473 } 8000 }
7474 if (item && typeof item == 'object') { 8001 if (item && typeof item == 'object') {
7475 this.omap.set(item, key); 8002 this.omap.set(item, key);
7476 } else { 8003 } else {
7477 this.pmap[item] = key; 8004 this.pmap[item] = key;
7478 } 8005 }
7479 this.store[key] = item; 8006 this.store[key] = item;
7480 }, 8007 },
7481 getItem: function (key) { 8008 getItem: function (key) {
8009 key = this._parseKey(key);
7482 return this.store[key]; 8010 return this.store[key];
7483 }, 8011 },
7484 getItems: function () { 8012 getItems: function () {
7485 var items = [], store = this.store; 8013 var items = [], store = this.store;
7486 for (var key in store) { 8014 for (var key in store) {
7487 items.push(store[key]); 8015 items.push(store[key]);
7488 } 8016 }
7489 return items; 8017 return items;
7490 }, 8018 },
7491 _applySplices: function (splices) { 8019 _applySplices: function (splices) {
(...skipping 373 matching lines...) Expand 10 before | Expand all | Expand 10 after
7865 if (this._sortFn || this._filterFn) { 8393 if (this._sortFn || this._filterFn) {
7866 idx = this.items.indexOf(this.collection.getItem(inst.__key__)); 8394 idx = this.items.indexOf(this.collection.getItem(inst.__key__));
7867 } else { 8395 } else {
7868 idx = inst[this.indexAs]; 8396 idx = inst[this.indexAs];
7869 } 8397 }
7870 this.set('items.' + idx, value); 8398 this.set('items.' + idx, value);
7871 } 8399 }
7872 }, 8400 },
7873 _forwardInstancePath: function (inst, path, value) { 8401 _forwardInstancePath: function (inst, path, value) {
7874 if (path.indexOf(this.as + '.') === 0) { 8402 if (path.indexOf(this.as + '.') === 0) {
7875 this.notifyPath('items.' + inst.__key__ + '.' + path.slice(this.as.length + 1), value); 8403 this._notifyPath('items.' + inst.__key__ + '.' + path.slice(this.as.length + 1), value);
7876 } 8404 }
7877 }, 8405 },
7878 _forwardParentProp: function (prop, value) { 8406 _forwardParentProp: function (prop, value) {
7879 this._instances.forEach(function (inst) { 8407 this._instances.forEach(function (inst) {
7880 inst.__setProperty(prop, value, true); 8408 inst.__setProperty(prop, value, true);
7881 }, this); 8409 }, this);
7882 }, 8410 },
7883 _forwardParentPath: function (path, value) { 8411 _forwardParentPath: function (path, value) {
7884 this._instances.forEach(function (inst) { 8412 this._instances.forEach(function (inst) {
7885 inst.notifyPath(path, value, true); 8413 inst._notifyPath(path, value, true);
7886 }, this); 8414 }, this);
7887 }, 8415 },
7888 _forwardItemPath: function (path, value) { 8416 _forwardItemPath: function (path, value) {
7889 if (this._keyToInstIdx) { 8417 if (this._keyToInstIdx) {
7890 var dot = path.indexOf('.'); 8418 var dot = path.indexOf('.');
7891 var key = path.substring(0, dot < 0 ? path.length : dot); 8419 var key = path.substring(0, dot < 0 ? path.length : dot);
7892 var idx = this._keyToInstIdx[key]; 8420 var idx = this._keyToInstIdx[key];
7893 var inst = this._instances[idx]; 8421 var inst = this._instances[idx];
7894 if (inst) { 8422 if (inst) {
7895 if (dot >= 0) { 8423 if (dot >= 0) {
7896 path = this.as + '.' + path.substring(dot + 1); 8424 path = this.as + '.' + path.substring(dot + 1);
7897 inst.notifyPath(path, value, true); 8425 inst._notifyPath(path, value, true);
7898 } else { 8426 } else {
7899 inst.__setProperty(this.as, value, true); 8427 inst.__setProperty(this.as, value, true);
7900 } 8428 }
7901 } 8429 }
7902 } 8430 }
7903 }, 8431 },
7904 itemForElement: function (el) { 8432 itemForElement: function (el) {
7905 var instance = this.modelForElement(el); 8433 var instance = this.modelForElement(el);
7906 return instance && instance[this.as]; 8434 return instance && instance[this.as];
7907 }, 8435 },
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
7939 value: false 8467 value: false
7940 } 8468 }
7941 }, 8469 },
7942 clearSelection: function () { 8470 clearSelection: function () {
7943 if (Array.isArray(this.selected)) { 8471 if (Array.isArray(this.selected)) {
7944 for (var i = 0; i < this.selected.length; i++) { 8472 for (var i = 0; i < this.selected.length; i++) {
7945 this.unlinkPaths('selected.' + i); 8473 this.unlinkPaths('selected.' + i);
7946 } 8474 }
7947 } else { 8475 } else {
7948 this.unlinkPaths('selected'); 8476 this.unlinkPaths('selected');
8477 this.unlinkPaths('selectedItem');
7949 } 8478 }
7950 if (this.multi) { 8479 if (this.multi) {
7951 if (!this.selected || this.selected.length) { 8480 if (!this.selected || this.selected.length) {
7952 this.selected = []; 8481 this.selected = [];
7953 this._selectedColl = Polymer.Collection.get(this.selected); 8482 this._selectedColl = Polymer.Collection.get(this.selected);
7954 } 8483 }
7955 } else { 8484 } else {
7956 this.selected = null; 8485 this.selected = null;
7957 this._selectedColl = null; 8486 this._selectedColl = null;
7958 } 8487 }
(...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after
8078 this._instance._showHideChildren(hidden); 8607 this._instance._showHideChildren(hidden);
8079 } 8608 }
8080 }, 8609 },
8081 _forwardParentProp: function (prop, value) { 8610 _forwardParentProp: function (prop, value) {
8082 if (this._instance) { 8611 if (this._instance) {
8083 this._instance[prop] = value; 8612 this._instance[prop] = value;
8084 } 8613 }
8085 }, 8614 },
8086 _forwardParentPath: function (path, value) { 8615 _forwardParentPath: function (path, value) {
8087 if (this._instance) { 8616 if (this._instance) {
8088 this._instance.notifyPath(path, value, true); 8617 this._instance._notifyPath(path, value, true);
8089 } 8618 }
8090 } 8619 }
8091 }); 8620 });
8092 Polymer({ 8621 Polymer({
8093 is: 'dom-bind', 8622 is: 'dom-bind',
8094 extends: 'template', 8623 extends: 'template',
8095 created: function () { 8624 created: function () {
8096 Polymer.RenderStatus.whenReady(this._markImportsReady.bind(this)); 8625 Polymer.RenderStatus.whenReady(this._markImportsReady.bind(this));
8097 }, 8626 },
8098 _ensureReady: function () { 8627 _ensureReady: function () {
(...skipping 460 matching lines...) Expand 10 before | Expand all | Expand 10 after
8559 _itemsRendered: false, 9088 _itemsRendered: false,
8560 9089
8561 /** 9090 /**
8562 * The bottom of the physical content. 9091 * The bottom of the physical content.
8563 */ 9092 */
8564 get _physicalBottom() { 9093 get _physicalBottom() {
8565 return this._physicalTop + this._physicalSize; 9094 return this._physicalTop + this._physicalSize;
8566 }, 9095 },
8567 9096
8568 /** 9097 /**
9098 * The bottom of the scroll.
9099 */
9100 get _scrollBottom() {
9101 return this._scrollPosition + this._viewportSize;
9102 },
9103
9104 /**
8569 * The n-th item rendered in the last physical item. 9105 * The n-th item rendered in the last physical item.
8570 */ 9106 */
8571 get _virtualEnd() { 9107 get _virtualEnd() {
8572 return this._virtualStartVal + this._physicalCount - 1; 9108 return this._virtualStartVal + this._physicalCount - 1;
8573 }, 9109 },
8574 9110
8575 /** 9111 /**
8576 * The lowest n-th value for an item such that it can be rendered in `_physi calStart`. 9112 * The lowest n-th value for an item such that it can be rendered in `_physi calStart`.
8577 */ 9113 */
8578 _minVirtualStart: 0, 9114 _minVirtualStart: 0,
(...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after
8713 var scrollerStyle = window.getComputedStyle(this._scroller); 9249 var scrollerStyle = window.getComputedStyle(this._scroller);
8714 this._scrollerPaddingTop = parseInt(scrollerStyle['padding-top'], 10); 9250 this._scrollerPaddingTop = parseInt(scrollerStyle['padding-top'], 10);
8715 this._viewportSize = this._scroller.offsetHeight; 9251 this._viewportSize = this._scroller.offsetHeight;
8716 }, 9252 },
8717 9253
8718 /** 9254 /**
8719 * Update the models, the position of the 9255 * Update the models, the position of the
8720 * items in the viewport and recycle tiles as needed. 9256 * items in the viewport and recycle tiles as needed.
8721 */ 9257 */
8722 _refresh: function() { 9258 _refresh: function() {
8723 var SCROLL_DIRECTION_UP = -1;
8724 var SCROLL_DIRECTION_DOWN = 1;
8725 var SCROLL_DIRECTION_NONE = 0;
8726
8727 // clamp the `scrollTop` value 9259 // clamp the `scrollTop` value
8728 // IE 10|11 scrollTop may go above `_maxScrollTop` 9260 // IE 10|11 scrollTop may go above `_maxScrollTop`
8729 // iOS `scrollTop` may go below 0 and above `_maxScrollTop` 9261 // iOS `scrollTop` may go below 0 and above `_maxScrollTop`
8730 var scrollTop = Math.max(0, Math.min(this._maxScrollTop, this._scroller.sc rollTop)); 9262 var scrollTop = Math.max(0, Math.min(this._maxScrollTop, this._scroller.sc rollTop));
8731 9263 var tileHeight, tileTop, kth, recycledTileSet, scrollBottom;
8732 var tileHeight, kth, recycledTileSet;
8733 var ratio = this._ratio; 9264 var ratio = this._ratio;
8734 var delta = scrollTop - this._scrollPosition; 9265 var delta = scrollTop - this._scrollPosition;
8735 var direction = SCROLL_DIRECTION_NONE;
8736 var recycledTiles = 0; 9266 var recycledTiles = 0;
8737 var hiddenContentSize = this._hiddenContentSize; 9267 var hiddenContentSize = this._hiddenContentSize;
8738 var currentRatio = ratio; 9268 var currentRatio = ratio;
8739 var movingUp = []; 9269 var movingUp = [];
8740 9270
8741 // track the last `scrollTop` 9271 // track the last `scrollTop`
8742 this._scrollPosition = scrollTop; 9272 this._scrollPosition = scrollTop;
8743 9273
8744 // clear cached visible index 9274 // clear cached visible index
8745 this._firstVisibleIndexVal = null; 9275 this._firstVisibleIndexVal = null;
8746 9276
9277 scrollBottom = this._scrollBottom;
9278
8747 // random access 9279 // random access
8748 if (Math.abs(delta) > this._physicalSize) { 9280 if (Math.abs(delta) > this._physicalSize) {
8749 this._physicalTop += delta; 9281 this._physicalTop += delta;
8750 direction = SCROLL_DIRECTION_NONE;
8751 recycledTiles = Math.round(delta / this._physicalAverage); 9282 recycledTiles = Math.round(delta / this._physicalAverage);
8752 } 9283 }
8753 // scroll up 9284 // scroll up
8754 else if (delta < 0) { 9285 else if (delta < 0) {
8755 var topSpace = scrollTop - this._physicalTop; 9286 var topSpace = scrollTop - this._physicalTop;
8756 var virtualStart = this._virtualStart; 9287 var virtualStart = this._virtualStart;
9288 var physicalBottom = this._physicalBottom;
8757 9289
8758 direction = SCROLL_DIRECTION_UP;
8759 recycledTileSet = []; 9290 recycledTileSet = [];
8760 9291
8761 kth = this._physicalEnd; 9292 kth = this._physicalEnd;
8762 currentRatio = topSpace / hiddenContentSize; 9293 currentRatio = topSpace / hiddenContentSize;
8763 9294
8764 // move tiles from bottom to top 9295 // move tiles from bottom to top
8765 while ( 9296 while (
8766 // approximate `currentRatio` to `ratio` 9297 // approximate `currentRatio` to `ratio`
8767 currentRatio < ratio && 9298 currentRatio < ratio &&
8768 // recycle less physical items than the total 9299 // recycle less physical items than the total
8769 recycledTiles < this._physicalCount && 9300 recycledTiles < this._physicalCount &&
8770 // ensure that these recycled tiles are needed 9301 // ensure that these recycled tiles are needed
8771 virtualStart - recycledTiles > 0 9302 virtualStart - recycledTiles > 0 &&
9303 // ensure that the tile is not visible
9304 physicalBottom - this._physicalSizes[kth] > scrollBottom
8772 ) { 9305 ) {
8773 9306
8774 tileHeight = this._physicalSizes[kth] || this._physicalAverage; 9307 tileHeight = this._physicalSizes[kth];
8775 currentRatio += tileHeight / hiddenContentSize; 9308 currentRatio += tileHeight / hiddenContentSize;
8776 9309 physicalBottom -= tileHeight;
8777 recycledTileSet.push(kth); 9310 recycledTileSet.push(kth);
8778 recycledTiles++; 9311 recycledTiles++;
8779 kth = (kth === 0) ? this._physicalCount - 1 : kth - 1; 9312 kth = (kth === 0) ? this._physicalCount - 1 : kth - 1;
8780 } 9313 }
8781 9314
8782 movingUp = recycledTileSet; 9315 movingUp = recycledTileSet;
8783 recycledTiles = -recycledTiles; 9316 recycledTiles = -recycledTiles;
8784
8785 } 9317 }
8786 // scroll down 9318 // scroll down
8787 else if (delta > 0) { 9319 else if (delta > 0) {
8788 var bottomSpace = this._physicalBottom - (scrollTop + this._viewportSize ); 9320 var bottomSpace = this._physicalBottom - scrollBottom;
8789 var virtualEnd = this._virtualEnd; 9321 var virtualEnd = this._virtualEnd;
8790 var lastVirtualItemIndex = this._virtualCount-1; 9322 var lastVirtualItemIndex = this._virtualCount-1;
8791 9323
8792 direction = SCROLL_DIRECTION_DOWN;
8793 recycledTileSet = []; 9324 recycledTileSet = [];
8794 9325
8795 kth = this._physicalStart; 9326 kth = this._physicalStart;
8796 currentRatio = bottomSpace / hiddenContentSize; 9327 currentRatio = bottomSpace / hiddenContentSize;
8797 9328
8798 // move tiles from top to bottom 9329 // move tiles from top to bottom
8799 while ( 9330 while (
8800 // approximate `currentRatio` to `ratio` 9331 // approximate `currentRatio` to `ratio`
8801 currentRatio < ratio && 9332 currentRatio < ratio &&
8802 // recycle less physical items than the total 9333 // recycle less physical items than the total
8803 recycledTiles < this._physicalCount && 9334 recycledTiles < this._physicalCount &&
8804 // ensure that these recycled tiles are needed 9335 // ensure that these recycled tiles are needed
8805 virtualEnd + recycledTiles < lastVirtualItemIndex 9336 virtualEnd + recycledTiles < lastVirtualItemIndex &&
9337 // ensure that the tile is not visible
9338 this._physicalTop + this._physicalSizes[kth] < scrollTop
8806 ) { 9339 ) {
8807 9340
8808 tileHeight = this._physicalSizes[kth] || this._physicalAverage; 9341 tileHeight = this._physicalSizes[kth];
8809 currentRatio += tileHeight / hiddenContentSize; 9342 currentRatio += tileHeight / hiddenContentSize;
8810 9343
8811 this._physicalTop += tileHeight; 9344 this._physicalTop += tileHeight;
8812 recycledTileSet.push(kth); 9345 recycledTileSet.push(kth);
8813 recycledTiles++; 9346 recycledTiles++;
8814 kth = (kth + 1) % this._physicalCount; 9347 kth = (kth + 1) % this._physicalCount;
8815 } 9348 }
8816 } 9349 }
8817 9350
8818 if (recycledTiles !== 0) { 9351 if (recycledTiles === 0) {
9352 // If the list ever reach this case, the physical average is not signifi cant enough
9353 // to create all the items needed to cover the entire viewport.
9354 // e.g. A few items have a height that differs from the average by serve ral order of magnitude.
9355 if (this._increasePoolIfNeeded()) {
9356 // yield and set models to the new items
9357 this.async(this._update);
9358 }
9359 } else {
8819 this._virtualStart = this._virtualStart + recycledTiles; 9360 this._virtualStart = this._virtualStart + recycledTiles;
8820 this._update(recycledTileSet, movingUp); 9361 this._update(recycledTileSet, movingUp);
8821 } 9362 }
8822 }, 9363 },
8823 9364
8824 /** 9365 /**
8825 * Update the list of items, starting from the `_virtualStartVal` item. 9366 * Update the list of items, starting from the `_virtualStartVal` item.
8826 * @param {!Array<number>=} itemSet 9367 * @param {!Array<number>=} itemSet
8827 * @param {!Array<number>=} movingUp 9368 * @param {!Array<number>=} movingUp
8828 */ 9369 */
(...skipping 11 matching lines...) Expand all
8840 } 9381 }
8841 } 9382 }
8842 // update the position of the items 9383 // update the position of the items
8843 this._positionItems(); 9384 this._positionItems();
8844 9385
8845 // set the scroller size 9386 // set the scroller size
8846 this._updateScrollerSize(); 9387 this._updateScrollerSize();
8847 9388
8848 // increase the pool of physical items if needed 9389 // increase the pool of physical items if needed
8849 if (this._increasePoolIfNeeded()) { 9390 if (this._increasePoolIfNeeded()) {
8850 // set models to the new items 9391 // yield set models to the new items
8851 this.async(this._update); 9392 this.async(this._update);
8852 } 9393 }
8853 }, 9394 },
8854 9395
8855 /** 9396 /**
8856 * Creates a pool of DOM elements and attaches them to the local dom. 9397 * Creates a pool of DOM elements and attaches them to the local dom.
8857 */ 9398 */
8858 _createPool: function(size) { 9399 _createPool: function(size) {
8859 var physicalItems = new Array(size); 9400 var physicalItems = new Array(size);
8860 9401
8861 this._ensureTemplatized(); 9402 this._ensureTemplatized();
8862 9403
8863 for (var i = 0; i < size; i++) { 9404 for (var i = 0; i < size; i++) {
8864 var inst = this.stamp(null); 9405 var inst = this.stamp(null);
8865 9406
8866 // First element child is item; Safari doesn't support children[0] 9407 // First element child is item; Safari doesn't support children[0]
8867 // on a doc fragment 9408 // on a doc fragment
8868 physicalItems[i] = inst.root.querySelector('*'); 9409 physicalItems[i] = inst.root.querySelector('*');
8869 Polymer.dom(this).appendChild(inst.root); 9410 Polymer.dom(this).appendChild(inst.root);
8870 } 9411 }
8871 9412
8872 return physicalItems; 9413 return physicalItems;
8873 }, 9414 },
8874 9415
8875 /** 9416 /**
8876 * Increases the pool size. That is, the physical items in the DOM. 9417 * Increases the pool of physical items only if needed.
8877 * This function will allocate additional physical items 9418 * This function will allocate additional physical items
8878 * (limited by `MAX_PHYSICAL_COUNT`) if the content size is shorter than 9419 * (limited by `MAX_PHYSICAL_COUNT`) if the content size is shorter than
8879 * `_optPhysicalSize` 9420 * `_optPhysicalSize`
8880 * 9421 *
8881 * @return boolean 9422 * @return boolean
8882 */ 9423 */
8883 _increasePoolIfNeeded: function() { 9424 _increasePoolIfNeeded: function() {
8884 if (this._physicalSize >= this._optPhysicalSize || this._physicalAverage = == 0) { 9425 if (this._physicalAverage === 0) {
8885 return false; 9426 return false;
8886 } 9427 }
9428 if (this._physicalBottom < this._scrollBottom || this._physicalTop > this. _scrollPosition) {
9429 return this._increasePool(1);
9430 }
9431 if (this._physicalSize < this._optPhysicalSize) {
9432 return this._increasePool(Math.round((this._optPhysicalSize - this._phys icalSize) * 1.2 / this._physicalAverage));
9433 }
9434 return false;
9435 },
8887 9436
8888 // the estimated number of physical items that we will need to reach 9437 /**
8889 // the cap established by `_optPhysicalSize`. 9438 * Increases the pool size.
8890 var missingItems = Math.round( 9439 */
8891 (this._optPhysicalSize - this._physicalSize) * 1.2 / this._physicalAve rage 9440 _increasePool: function(missingItems) {
8892 );
8893
8894 // limit the size 9441 // limit the size
8895 var nextPhysicalCount = Math.min( 9442 var nextPhysicalCount = Math.min(
8896 this._physicalCount + missingItems, 9443 this._physicalCount + missingItems,
8897 this._virtualCount, 9444 this._virtualCount,
8898 MAX_PHYSICAL_COUNT 9445 MAX_PHYSICAL_COUNT
8899 ); 9446 );
8900 9447
8901 var prevPhysicalCount = this._physicalCount; 9448 var prevPhysicalCount = this._physicalCount;
8902 var delta = nextPhysicalCount - prevPhysicalCount; 9449 var delta = nextPhysicalCount - prevPhysicalCount;
8903 9450
8904 if (delta <= 0) { 9451 if (delta <= 0) {
8905 return false; 9452 return false;
8906 } 9453 }
8907 9454
8908 var newPhysicalItems = this._createPool(delta); 9455 [].push.apply(this._physicalItems, this._createPool(delta));
8909 var emptyArray = new Array(delta); 9456 [].push.apply(this._physicalSizes, new Array(delta));
8910
8911 [].push.apply(this._physicalItems, newPhysicalItems);
8912 [].push.apply(this._physicalSizes, emptyArray);
8913 9457
8914 this._physicalCount = prevPhysicalCount + delta; 9458 this._physicalCount = prevPhysicalCount + delta;
8915 9459
8916 return true; 9460 return true;
8917 }, 9461 },
8918 9462
8919 /** 9463 /**
8920 * Render a new list of items. This method does exactly the same as `update` , 9464 * Render a new list of items. This method does exactly the same as `update` ,
8921 * but it also ensures that only one `update` cycle is created. 9465 * but it also ensures that only one `update` cycle is created.
8922 */ 9466 */
(...skipping 374 matching lines...) Expand 10 before | Expand all | Expand 10 after
9297 this._updateScrollerSize(true); 9841 this._updateScrollerSize(true);
9298 9842
9299 // update the position of the items 9843 // update the position of the items
9300 this._positionItems(); 9844 this._positionItems();
9301 9845
9302 // set the new scroll position 9846 // set the new scroll position
9303 this._resetScrollPosition(this._physicalTop + targetOffsetTop + 1); 9847 this._resetScrollPosition(this._physicalTop + targetOffsetTop + 1);
9304 9848
9305 // increase the pool of physical items if needed 9849 // increase the pool of physical items if needed
9306 if (this._increasePoolIfNeeded()) { 9850 if (this._increasePoolIfNeeded()) {
9307 // set models to the new items 9851 // yield set models to the new items
9308 this.async(this._update); 9852 this.async(this._update);
9309 } 9853 }
9310
9311 // clear cached visible index 9854 // clear cached visible index
9312 this._firstVisibleIndexVal = null; 9855 this._firstVisibleIndexVal = null;
9313 }, 9856 },
9314 9857
9315 /** 9858 /**
9316 * Reset the physical average and the average count. 9859 * Reset the physical average and the average count.
9317 */ 9860 */
9318 _resetAverage: function() { 9861 _resetAverage: function() {
9319 this._physicalAverage = 0; 9862 this._physicalAverage = 0;
9320 this._physicalAverageCount = 0; 9863 this._physicalAverageCount = 0;
(...skipping 410 matching lines...) Expand 10 before | Expand all | Expand 10 after
9731 } 10274 }
9732 10275
9733 }); 10276 });
9734 10277
9735 })(); 10278 })();
9736 (function() { 10279 (function() {
9737 10280
9738 // monostate data 10281 // monostate data
9739 var metaDatas = {}; 10282 var metaDatas = {};
9740 var metaArrays = {}; 10283 var metaArrays = {};
10284 var singleton = null;
9741 10285
9742 Polymer.IronMeta = Polymer({ 10286 Polymer.IronMeta = Polymer({
9743 10287
9744 is: 'iron-meta', 10288 is: 'iron-meta',
9745 10289
9746 properties: { 10290 properties: {
9747 10291
9748 /** 10292 /**
9749 * The type of meta-data. All meta-data of the same type is stored 10293 * The type of meta-data. All meta-data of the same type is stored
9750 * together. 10294 * together.
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
9783 /** 10327 /**
9784 * Array of all meta-data values for the given type. 10328 * Array of all meta-data values for the given type.
9785 */ 10329 */
9786 list: { 10330 list: {
9787 type: Array, 10331 type: Array,
9788 notify: true 10332 notify: true
9789 } 10333 }
9790 10334
9791 }, 10335 },
9792 10336
10337 hostAttributes: {
10338 hidden: true
10339 },
10340
9793 /** 10341 /**
9794 * Only runs if someone invokes the factory/constructor directly 10342 * Only runs if someone invokes the factory/constructor directly
9795 * e.g. `new Polymer.IronMeta()` 10343 * e.g. `new Polymer.IronMeta()`
10344 *
10345 * @param {{type: (string|undefined), key: (string|undefined), value}=} co nfig
9796 */ 10346 */
9797 factoryImpl: function(config) { 10347 factoryImpl: function(config) {
9798 if (config) { 10348 if (config) {
9799 for (var n in config) { 10349 for (var n in config) {
9800 switch(n) { 10350 switch(n) {
9801 case 'type': 10351 case 'type':
9802 case 'key': 10352 case 'key':
9803 case 'value': 10353 case 'value':
9804 this[n] = config[n]; 10354 this[n] = config[n];
9805 break; 10355 break;
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after
9877 if (key in data) { 10427 if (key in data) {
9878 var value = data[key]; 10428 var value = data[key];
9879 delete data[key]; 10429 delete data[key];
9880 this.arrayDelete(list, value); 10430 this.arrayDelete(list, value);
9881 } 10431 }
9882 } 10432 }
9883 } 10433 }
9884 10434
9885 }); 10435 });
9886 10436
10437 Polymer.IronMeta.getIronMeta = function getIronMeta() {
10438 if (singleton === null) {
10439 singleton = new Polymer.IronMeta();
10440 }
10441 return singleton;
10442 };
10443
9887 /** 10444 /**
9888 `iron-meta-query` can be used to access infomation stored in `iron-meta`. 10445 `iron-meta-query` can be used to access infomation stored in `iron-meta`.
9889 10446
9890 Examples: 10447 Examples:
9891 10448
9892 If I create an instance like this: 10449 If I create an instance like this:
9893 10450
9894 <iron-meta key="info" value="foo/bar"></iron-meta> 10451 <iron-meta key="info" value="foo/bar"></iron-meta>
9895 10452
9896 Note that value="foo/bar" is the metadata I've defined. I could define more 10453 Note that value="foo/bar" is the metadata I've defined. I could define more
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
9943 list: { 10500 list: {
9944 type: Array, 10501 type: Array,
9945 notify: true 10502 notify: true
9946 } 10503 }
9947 10504
9948 }, 10505 },
9949 10506
9950 /** 10507 /**
9951 * Actually a factory method, not a true constructor. Only runs if 10508 * Actually a factory method, not a true constructor. Only runs if
9952 * someone invokes it directly (via `new Polymer.IronMeta()`); 10509 * someone invokes it directly (via `new Polymer.IronMeta()`);
10510 *
10511 * @param {{type: (string|undefined), key: (string|undefined)}=} config
9953 */ 10512 */
9954 factoryImpl: function(config) { 10513 factoryImpl: function(config) {
9955 if (config) { 10514 if (config) {
9956 for (var n in config) { 10515 for (var n in config) {
9957 switch(n) { 10516 switch(n) {
9958 case 'type': 10517 case 'type':
9959 case 'key': 10518 case 'key':
9960 this[n] = config[n]; 10519 this[n] = config[n];
9961 break; 10520 break;
9962 } 10521 }
(...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after
10079 } 10638 }
10080 } 10639 }
10081 10640
10082 }); 10641 });
10083 /** 10642 /**
10084 * The `iron-iconset-svg` element allows users to define their own icon sets 10643 * The `iron-iconset-svg` element allows users to define their own icon sets
10085 * that contain svg icons. The svg icon elements should be children of the 10644 * that contain svg icons. The svg icon elements should be children of the
10086 * `iron-iconset-svg` element. Multiple icons should be given distinct id's. 10645 * `iron-iconset-svg` element. Multiple icons should be given distinct id's.
10087 * 10646 *
10088 * Using svg elements to create icons has a few advantages over traditional 10647 * Using svg elements to create icons has a few advantages over traditional
10089 * bitmap graphics like jpg or png. Icons that use svg are vector based so the y 10648 * bitmap graphics like jpg or png. Icons that use svg are vector based so
10090 * are resolution independent and should look good on any device. They are 10649 * they are resolution independent and should look good on any device. They
10091 * stylable via css. Icons can be themed, colorized, and even animated. 10650 * are stylable via css. Icons can be themed, colorized, and even animated.
10092 * 10651 *
10093 * Example: 10652 * Example:
10094 * 10653 *
10095 * <iron-iconset-svg name="my-svg-icons" size="24"> 10654 * <iron-iconset-svg name="my-svg-icons" size="24">
10096 * <svg> 10655 * <svg>
10097 * <defs> 10656 * <defs>
10098 * <g id="shape"> 10657 * <g id="shape">
10099 * <rect x="50" y="50" width="50" height="50" /> 10658 * <rect x="12" y="0" width="12" height="24" />
10100 * <circle cx="50" cy="50" r="50" /> 10659 * <circle cx="12" cy="12" r="12" />
10101 * </g> 10660 * </g>
10102 * </defs> 10661 * </defs>
10103 * </svg> 10662 * </svg>
10104 * </iron-iconset-svg> 10663 * </iron-iconset-svg>
10105 * 10664 *
10106 * This will automatically register the icon set "my-svg-icons" to the iconset 10665 * This will automatically register the icon set "my-svg-icons" to the iconset
10107 * database. To use these icons from within another element, make a 10666 * database. To use these icons from within another element, make a
10108 * `iron-iconset` element and call the `byId` method 10667 * `iron-iconset` element and call the `byId` method
10109 * to retrieve a given iconset. To apply a particular icon inside an 10668 * to retrieve a given iconset. To apply a particular icon inside an
10110 * element use the `applyIcon` method. For example: 10669 * element use the `applyIcon` method. For example:
10111 * 10670 *
10112 * iconset.applyIcon(iconNode, 'car'); 10671 * iconset.applyIcon(iconNode, 'car');
10113 * 10672 *
10114 * @element iron-iconset-svg 10673 * @element iron-iconset-svg
10115 * @demo demo/index.html 10674 * @demo demo/index.html
10675 * @implements {Polymer.Iconset}
10116 */ 10676 */
10117 Polymer({ 10677 Polymer({
10118
10119 is: 'iron-iconset-svg', 10678 is: 'iron-iconset-svg',
10120 10679
10121 properties: { 10680 properties: {
10122 10681
10123 /** 10682 /**
10124 * The name of the iconset. 10683 * The name of the iconset.
10125 *
10126 * @attribute name
10127 * @type string
10128 */ 10684 */
10129 name: { 10685 name: {
10130 type: String, 10686 type: String,
10131 observer: '_nameChanged' 10687 observer: '_nameChanged'
10132 }, 10688 },
10133 10689
10134 /** 10690 /**
10135 * The size of an individual icon. Note that icons must be square. 10691 * The size of an individual icon. Note that icons must be square.
10136 *
10137 * @attribute iconSize
10138 * @type number
10139 * @default 24
10140 */ 10692 */
10141 size: { 10693 size: {
10142 type: Number, 10694 type: Number,
10143 value: 24 10695 value: 24
10144 } 10696 }
10145 10697
10146 }, 10698 },
10147 10699
10700 attached: function() {
10701 this.style.display = 'none';
10702 },
10703
10148 /** 10704 /**
10149 * Construct an array of all icon names in this iconset. 10705 * Construct an array of all icon names in this iconset.
10150 * 10706 *
10151 * @return {!Array} Array of icon names. 10707 * @return {!Array} Array of icon names.
10152 */ 10708 */
10153 getIconNames: function() { 10709 getIconNames: function() {
10154 this._icons = this._createIconMap(); 10710 this._icons = this._createIconMap();
10155 return Object.keys(this._icons).map(function(n) { 10711 return Object.keys(this._icons).map(function(n) {
10156 return this.name + ':' + n; 10712 return this.name + ':' + n;
10157 }, this); 10713 }, this);
10158 }, 10714 },
10159 10715
10160 /** 10716 /**
10161 * Applies an icon to the given element. 10717 * Applies an icon to the given element.
10162 * 10718 *
10163 * An svg icon is prepended to the element's shadowRoot if it exists, 10719 * An svg icon is prepended to the element's shadowRoot if it exists,
10164 * otherwise to the element itself. 10720 * otherwise to the element itself.
10165 * 10721 *
10166 * @method applyIcon 10722 * @method applyIcon
10167 * @param {Element} element Element to which the icon is applied. 10723 * @param {Element} element Element to which the icon is applied.
10168 * @param {string} iconName Name of the icon to apply. 10724 * @param {string} iconName Name of the icon to apply.
10169 * @return {Element} The svg element which renders the icon. 10725 * @return {?Element} The svg element which renders the icon.
10170 */ 10726 */
10171 applyIcon: function(element, iconName) { 10727 applyIcon: function(element, iconName) {
10172 // insert svg element into shadow root, if it exists 10728 // insert svg element into shadow root, if it exists
10173 element = element.root || element; 10729 element = element.root || element;
10174 // Remove old svg element 10730 // Remove old svg element
10175 this.removeIcon(element); 10731 this.removeIcon(element);
10176 // install new svg element 10732 // install new svg element
10177 var svg = this._cloneIcon(iconName); 10733 var svg = this._cloneIcon(iconName);
10178 if (svg) { 10734 if (svg) {
10179 var pde = Polymer.dom(element); 10735 var pde = Polymer.dom(element);
(...skipping 319 matching lines...) Expand 10 before | Expand all | Expand 10 after
10499 /** 11055 /**
10500 * The HTMLElement that will be firing relevant KeyboardEvents. 11056 * The HTMLElement that will be firing relevant KeyboardEvents.
10501 */ 11057 */
10502 keyEventTarget: { 11058 keyEventTarget: {
10503 type: Object, 11059 type: Object,
10504 value: function() { 11060 value: function() {
10505 return this; 11061 return this;
10506 } 11062 }
10507 }, 11063 },
10508 11064
11065 /**
11066 * If true, this property will cause the implementing element to
11067 * automatically stop propagation on any handled KeyboardEvents.
11068 */
11069 stopKeyboardEventPropagation: {
11070 type: Boolean,
11071 value: false
11072 },
11073
10509 _boundKeyHandlers: { 11074 _boundKeyHandlers: {
10510 type: Array, 11075 type: Array,
10511 value: function() { 11076 value: function() {
10512 return []; 11077 return [];
10513 } 11078 }
10514 }, 11079 },
10515 11080
10516 // We use this due to a limitation in IE10 where instances will have 11081 // We use this due to a limitation in IE10 where instances will have
10517 // own properties of everything on the "prototype". 11082 // own properties of everything on the "prototype".
10518 _imperativeKeyBindings: { 11083 _imperativeKeyBindings: {
(...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after
10642 keyHandlerTuple = this._boundKeyHandlers.pop(); 11207 keyHandlerTuple = this._boundKeyHandlers.pop();
10643 keyEventTarget = keyHandlerTuple[0]; 11208 keyEventTarget = keyHandlerTuple[0];
10644 eventName = keyHandlerTuple[1]; 11209 eventName = keyHandlerTuple[1];
10645 boundKeyHandler = keyHandlerTuple[2]; 11210 boundKeyHandler = keyHandlerTuple[2];
10646 11211
10647 keyEventTarget.removeEventListener(eventName, boundKeyHandler); 11212 keyEventTarget.removeEventListener(eventName, boundKeyHandler);
10648 } 11213 }
10649 }, 11214 },
10650 11215
10651 _onKeyBindingEvent: function(keyBindings, event) { 11216 _onKeyBindingEvent: function(keyBindings, event) {
11217 if (this.stopKeyboardEventPropagation) {
11218 event.stopPropagation();
11219 }
11220
10652 keyBindings.forEach(function(keyBinding) { 11221 keyBindings.forEach(function(keyBinding) {
10653 var keyCombo = keyBinding[0]; 11222 var keyCombo = keyBinding[0];
10654 var handlerName = keyBinding[1]; 11223 var handlerName = keyBinding[1];
10655 11224
10656 if (!event.defaultPrevented && keyComboMatchesEvent(keyCombo, event)) { 11225 if (!event.defaultPrevented && keyComboMatchesEvent(keyCombo, event)) {
10657 this._triggerKeyHandler(keyCombo, handlerName, event); 11226 this._triggerKeyHandler(keyCombo, handlerName, event);
10658 } 11227 }
10659 }, this); 11228 }, this);
10660 }, 11229 },
10661 11230
10662 _triggerKeyHandler: function(keyCombo, handlerName, keyboardEvent) { 11231 _triggerKeyHandler: function(keyCombo, handlerName, keyboardEvent) {
10663 var detail = Object.create(keyCombo); 11232 var detail = Object.create(keyCombo);
10664 detail.keyboardEvent = keyboardEvent; 11233 detail.keyboardEvent = keyboardEvent;
10665 11234 var event = new CustomEvent(keyCombo.event, {
10666 this[handlerName].call(this, new CustomEvent(keyCombo.event, { 11235 detail: detail,
10667 detail: detail 11236 cancelable: true
10668 })); 11237 });
11238 this[handlerName].call(this, event);
11239 if (event.defaultPrevented) {
11240 keyboardEvent.preventDefault();
11241 }
10669 } 11242 }
10670 }; 11243 };
10671 })(); 11244 })();
10672 /** 11245 /**
10673 * @demo demo/index.html 11246 * @demo demo/index.html
10674 * @polymerBehavior 11247 * @polymerBehavior
10675 */ 11248 */
10676 Polymer.IronControlState = { 11249 Polymer.IronControlState = {
10677 11250
10678 properties: { 11251 properties: {
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
10722 }, 11295 },
10723 11296
10724 _focusBlurHandler: function(event) { 11297 _focusBlurHandler: function(event) {
10725 // NOTE(cdata): if we are in ShadowDOM land, `event.target` will 11298 // NOTE(cdata): if we are in ShadowDOM land, `event.target` will
10726 // eventually become `this` due to retargeting; if we are not in 11299 // eventually become `this` due to retargeting; if we are not in
10727 // ShadowDOM land, `event.target` will eventually become `this` due 11300 // ShadowDOM land, `event.target` will eventually become `this` due
10728 // to the second conditional which fires a synthetic event (that is also 11301 // to the second conditional which fires a synthetic event (that is also
10729 // handled). In either case, we can disregard `event.path`. 11302 // handled). In either case, we can disregard `event.path`.
10730 11303
10731 if (event.target === this) { 11304 if (event.target === this) {
10732 var focused = event.type === 'focus'; 11305 this._setFocused(event.type === 'focus');
10733 this._setFocused(focused); 11306 } else if (!this.shadowRoot && !this.isLightDescendant(event.target)) {
10734 } else if (!this.shadowRoot) {
10735 this.fire(event.type, {sourceEvent: event}, { 11307 this.fire(event.type, {sourceEvent: event}, {
10736 node: this, 11308 node: this,
10737 bubbles: event.bubbles, 11309 bubbles: event.bubbles,
10738 cancelable: event.cancelable 11310 cancelable: event.cancelable
10739 }); 11311 });
10740 } 11312 }
10741 }, 11313 },
10742 11314
10743 _disabledChanged: function(disabled, old) { 11315 _disabledChanged: function(disabled, old) {
10744 this.setAttribute('aria-disabled', disabled ? 'true' : 'false'); 11316 this.setAttribute('aria-disabled', disabled ? 'true' : 'false');
(...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after
10875 this._setPointerDown(true); 11447 this._setPointerDown(true);
10876 this._setPressed(true); 11448 this._setPressed(true);
10877 this._setReceivedFocusFromKeyboard(false); 11449 this._setReceivedFocusFromKeyboard(false);
10878 }, 11450 },
10879 11451
10880 _upHandler: function() { 11452 _upHandler: function() {
10881 this._setPointerDown(false); 11453 this._setPointerDown(false);
10882 this._setPressed(false); 11454 this._setPressed(false);
10883 }, 11455 },
10884 11456
11457 __isFocusedLightDescendant: function(target) {
11458 var root = Polymer.dom(this).getOwnerRoot() || document;
11459 var focusedElement = root.activeElement;
11460
11461 // TODO(noms): remove the `this !== target` check once polymer#2610 is fix ed.
11462 return this !== target && this.isLightDescendant(target) && target == focu sedElement;
11463 },
11464
11465 /**
11466 * @param {!KeyboardEvent} event .
11467 */
10885 _spaceKeyDownHandler: function(event) { 11468 _spaceKeyDownHandler: function(event) {
10886 var keyboardEvent = event.detail.keyboardEvent; 11469 var keyboardEvent = event.detail.keyboardEvent;
11470 var target = Polymer.dom(keyboardEvent).localTarget;
11471
11472 // Ignore the event if this is coming from a focused light child, since th at
11473 // element will deal with it.
11474 if (this.__isFocusedLightDescendant(target))
11475 return;
11476
10887 keyboardEvent.preventDefault(); 11477 keyboardEvent.preventDefault();
10888 keyboardEvent.stopImmediatePropagation(); 11478 keyboardEvent.stopImmediatePropagation();
10889 this._setPressed(true); 11479 this._setPressed(true);
10890 }, 11480 },
10891 11481
10892 _spaceKeyUpHandler: function() { 11482 /**
11483 * @param {!KeyboardEvent} event .
11484 */
11485 _spaceKeyUpHandler: function(event) {
11486 var keyboardEvent = event.detail.keyboardEvent;
11487 var target = Polymer.dom(keyboardEvent).localTarget;
11488
11489 // Ignore the event if this is coming from a focused light child, since th at
11490 // element will deal with it.
11491 if (this.__isFocusedLightDescendant(target))
11492 return;
11493
10893 if (this.pressed) { 11494 if (this.pressed) {
10894 this._asyncClick(); 11495 this._asyncClick();
10895 } 11496 }
10896 this._setPressed(false); 11497 this._setPressed(false);
10897 }, 11498 },
10898 11499
10899 // trigger click asynchronously, the asynchrony is useful to allow one 11500 // trigger click asynchronously, the asynchrony is useful to allow one
10900 // event handler to unwind before triggering another event 11501 // event handler to unwind before triggering another event
10901 _asyncClick: function() { 11502 _asyncClick: function() {
10902 this.async(function() { 11503 this.async(function() {
(...skipping 756 matching lines...) Expand 10 before | Expand all | Expand 10 after
11659 _noinkChanged: function(noink) { 12260 _noinkChanged: function(noink) {
11660 if (this.hasRipple()) { 12261 if (this.hasRipple()) {
11661 this._ripple.noink = noink; 12262 this._ripple.noink = noink;
11662 } 12263 }
11663 } 12264 }
11664 12265
11665 }; 12266 };
11666 /** 12267 /**
11667 * `Polymer.PaperInkyFocusBehavior` implements a ripple when the element has k eyboard focus. 12268 * `Polymer.PaperInkyFocusBehavior` implements a ripple when the element has k eyboard focus.
11668 * 12269 *
11669 * @polymerBehavior Polymer.PaperInkyFocusBehaviorImpl 12270 * @polymerBehavior Polymer.PaperInkyFocusBehavior
11670 */ 12271 */
11671 Polymer.PaperInkyFocusBehaviorImpl = { 12272 Polymer.PaperInkyFocusBehaviorImpl = {
11672 12273
11673 observers: [ 12274 observers: [
11674 '_focusedChanged(receivedFocusFromKeyboard)' 12275 '_focusedChanged(receivedFocusFromKeyboard)'
11675 ], 12276 ],
11676 12277
11677 _focusedChanged: function(receivedFocusFromKeyboard) { 12278 _focusedChanged: function(receivedFocusFromKeyboard) {
11678 if (receivedFocusFromKeyboard) { 12279 if (receivedFocusFromKeyboard) {
11679 this.ensureRipple(); 12280 this.ensureRipple();
(...skipping 17 matching lines...) Expand all
11697 Polymer.PaperInkyFocusBehavior = [ 12298 Polymer.PaperInkyFocusBehavior = [
11698 Polymer.IronButtonState, 12299 Polymer.IronButtonState,
11699 Polymer.IronControlState, 12300 Polymer.IronControlState,
11700 Polymer.PaperRippleBehavior, 12301 Polymer.PaperRippleBehavior,
11701 Polymer.PaperInkyFocusBehaviorImpl 12302 Polymer.PaperInkyFocusBehaviorImpl
11702 ]; 12303 ];
11703 Polymer({ 12304 Polymer({
11704 is: 'paper-material', 12305 is: 'paper-material',
11705 12306
11706 properties: { 12307 properties: {
11707
11708 /** 12308 /**
11709 * The z-depth of this element, from 0-5. Setting to 0 will remove the 12309 * The z-depth of this element, from 0-5. Setting to 0 will remove the
11710 * shadow, and each increasing number greater than 0 will be "deeper" 12310 * shadow, and each increasing number greater than 0 will be "deeper"
11711 * than the last. 12311 * than the last.
11712 * 12312 *
11713 * @attribute elevation 12313 * @attribute elevation
11714 * @type number 12314 * @type number
11715 * @default 1 12315 * @default 1
11716 */ 12316 */
11717 elevation: { 12317 elevation: {
(...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after
11839 }, 12439 },
11840 12440
11841 _calculateElevation: function() { 12441 _calculateElevation: function() {
11842 if (!this.raised) { 12442 if (!this.raised) {
11843 this.elevation = 0; 12443 this.elevation = 0;
11844 } else { 12444 } else {
11845 Polymer.PaperButtonBehaviorImpl._calculateElevation.apply(this); 12445 Polymer.PaperButtonBehaviorImpl._calculateElevation.apply(this);
11846 } 12446 }
11847 } 12447 }
11848 }); 12448 });
11849 /** 12449 /**
11850 * `iron-range-behavior` provides the behavior for something with a minimum to m aximum range. 12450 * `iron-range-behavior` provides the behavior for something with a minimum to m aximum range.
11851 * 12451 *
11852 * @demo demo/index.html 12452 * @demo demo/index.html
11853 * @polymerBehavior 12453 * @polymerBehavior
11854 */ 12454 */
11855 Polymer.IronRangeBehavior = { 12455 Polymer.IronRangeBehavior = {
11856 12456
11857 properties: { 12457 properties: {
11858 12458
11859 /** 12459 /**
11860 * The number that represents the current value. 12460 * The number that represents the current value.
11861 */ 12461 */
11862 value: { 12462 value: {
11863 type: Number, 12463 type: Number,
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
11912 return (this._clampValue(value) - this.min) / (this.max - this.min); 12512 return (this._clampValue(value) - this.min) / (this.max - this.min);
11913 }, 12513 },
11914 12514
11915 _clampValue: function(value) { 12515 _clampValue: function(value) {
11916 return Math.min(this.max, Math.max(this.min, this._calcStep(value))); 12516 return Math.min(this.max, Math.max(this.min, this._calcStep(value)));
11917 }, 12517 },
11918 12518
11919 _calcStep: function(value) { 12519 _calcStep: function(value) {
11920 /** 12520 /**
11921 * if we calculate the step using 12521 * if we calculate the step using
11922 * `Math.round(value / step) * step` we may hit a precision point issue 12522 * `Math.round(value / step) * step` we may hit a precision point issue
11923 * eg. 0.1 * 0.2 = 0.020000000000000004 12523 * eg. 0.1 * 0.2 = 0.020000000000000004
11924 * http://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html 12524 * http://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html
11925 * 12525 *
11926 * as a work around we can divide by the reciprocal of `step` 12526 * as a work around we can divide by the reciprocal of `step`
11927 */ 12527 */
11928 // polymer/issues/2493 12528 // polymer/issues/2493
11929 value = parseFloat(value); 12529 value = parseFloat(value);
11930 return this.step ? (Math.round((value + this.min) / this.step) / (1 / this.s tep)) - this.min : value; 12530 return this.step ? (Math.round((value + this.min) / this.step) -
12531 (this.min / this.step)) / (1 / this.step) : value;
11931 }, 12532 },
11932 12533
11933 _validateValue: function() { 12534 _validateValue: function() {
11934 var v = this._clampValue(this.value); 12535 var v = this._clampValue(this.value);
11935 this.value = this.oldValue = isNaN(v) ? this.oldValue : v; 12536 this.value = this.oldValue = isNaN(v) ? this.oldValue : v;
11936 return this.value !== v; 12537 return this.value !== v;
11937 }, 12538 },
11938 12539
11939 _update: function() { 12540 _update: function() {
11940 this._validateValue(); 12541 this._validateValue();
(...skipping 434 matching lines...) Expand 10 before | Expand all | Expand 10 after
12375 12976
12376 return { 12977 return {
12377 InkyTextButton: InkyTextButton, 12978 InkyTextButton: InkyTextButton,
12378 Item: Item, 12979 Item: Item,
12379 }; 12980 };
12380 }); 12981 });
12381 Polymer({ 12982 Polymer({
12382 is: 'paper-item', 12983 is: 'paper-item',
12383 12984
12384 hostAttributes: { 12985 hostAttributes: {
12385 role: 'listitem', 12986 role: 'option',
12386 tabindex: '0' 12987 tabindex: '0'
12387 }, 12988 },
12388 12989
12389 behaviors: [ 12990 behaviors: [
12390 Polymer.IronControlState, 12991 Polymer.IronControlState,
12391 Polymer.IronButtonState 12992 Polymer.IronButtonState
12392 ] 12993 ]
12393 }); 12994 });
12394 /** 12995 /**
12395 * @param {!Function} selectCallback 12996 * @param {!Function} selectCallback
(...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after
12535 /** 13136 /**
12536 * Gets or sets the selected element. The default is to use the index of t he item. 13137 * Gets or sets the selected element. The default is to use the index of t he item.
12537 */ 13138 */
12538 selected: { 13139 selected: {
12539 type: String, 13140 type: String,
12540 notify: true 13141 notify: true
12541 }, 13142 },
12542 13143
12543 /** 13144 /**
12544 * Returns the currently selected item. 13145 * Returns the currently selected item.
13146 *
13147 * @type {?Object}
12545 */ 13148 */
12546 selectedItem: { 13149 selectedItem: {
12547 type: Object, 13150 type: Object,
12548 readOnly: true, 13151 readOnly: true,
12549 notify: true 13152 notify: true
12550 }, 13153 },
12551 13154
12552 /** 13155 /**
12553 * The event that fires from items when they are selected. Selectable 13156 * The event that fires from items when they are selected. Selectable
12554 * will listen for this event from items and update the selection state. 13157 * will listen for this event from items and update the selection state.
(...skipping 21 matching lines...) Expand all
12576 13179
12577 /** 13180 /**
12578 * The attribute to set on elements when selected. 13181 * The attribute to set on elements when selected.
12579 */ 13182 */
12580 selectedAttribute: { 13183 selectedAttribute: {
12581 type: String, 13184 type: String,
12582 value: null 13185 value: null
12583 }, 13186 },
12584 13187
12585 /** 13188 /**
13189 * The list of items from which a selection can be made.
13190 */
13191 items: {
13192 type: Array,
13193 readOnly: true,
13194 value: function() {
13195 return [];
13196 }
13197 },
13198
13199 /**
12586 * The set of excluded elements where the key is the `localName` 13200 * The set of excluded elements where the key is the `localName`
12587 * of the element that will be ignored from the item list. 13201 * of the element that will be ignored from the item list.
12588 * 13202 *
12589 * @type {object}
12590 * @default {template: 1} 13203 * @default {template: 1}
12591 */ 13204 */
12592 _excludedLocalNames: { 13205 _excludedLocalNames: {
12593 type: Object, 13206 type: Object,
12594 value: function() { 13207 value: function() {
12595 return { 13208 return {
12596 'template': 1 13209 'template': 1
12597 }; 13210 };
12598 } 13211 }
12599 } 13212 }
12600 }, 13213 },
12601 13214
12602 observers: [ 13215 observers: [
12603 '_updateSelected(attrForSelected, selected)' 13216 '_updateSelected(attrForSelected, selected)'
12604 ], 13217 ],
12605 13218
12606 created: function() { 13219 created: function() {
12607 this._bindFilterItem = this._filterItem.bind(this); 13220 this._bindFilterItem = this._filterItem.bind(this);
12608 this._selection = new Polymer.IronSelection(this._applySelection.bind(this )); 13221 this._selection = new Polymer.IronSelection(this._applySelection.bind(this ));
12609 // TODO(cdata): When polymer/polymer#2535 lands, we do not need to do this
12610 // book keeping anymore:
12611 this.__listeningForActivate = false;
12612 }, 13222 },
12613 13223
12614 attached: function() { 13224 attached: function() {
12615 this._observer = this._observeItems(this); 13225 this._observer = this._observeItems(this);
12616 this._contentObserver = this._observeContent(this); 13226 this._updateItems();
12617 if (!this.selectedItem && this.selected) { 13227 if (!this._shouldUpdateSelection) {
12618 this._updateSelected(this.attrForSelected,this.selected) 13228 this._updateSelected(this.attrForSelected,this.selected)
12619 } 13229 }
12620 this._addListener(this.activateEvent); 13230 this._addListener(this.activateEvent);
12621 }, 13231 },
12622 13232
12623 detached: function() { 13233 detached: function() {
12624 if (this._observer) { 13234 if (this._observer) {
12625 this._observer.disconnect(); 13235 Polymer.dom(this).unobserveNodes(this._observer);
12626 }
12627 if (this._contentObserver) {
12628 this._contentObserver.disconnect();
12629 } 13236 }
12630 this._removeListener(this.activateEvent); 13237 this._removeListener(this.activateEvent);
12631 }, 13238 },
12632 13239
12633 /** 13240 /**
12634 * Returns an array of selectable items.
12635 *
12636 * @property items
12637 * @type Array
12638 */
12639 get items() {
12640 var nodes = Polymer.dom(this).queryDistributedElements(this.selectable || '*');
12641 return Array.prototype.filter.call(nodes, this._bindFilterItem);
12642 },
12643
12644 /**
12645 * Returns the index of the given item. 13241 * Returns the index of the given item.
12646 * 13242 *
12647 * @method indexOf 13243 * @method indexOf
12648 * @param {Object} item 13244 * @param {Object} item
12649 * @returns Returns the index of the item 13245 * @returns Returns the index of the item
12650 */ 13246 */
12651 indexOf: function(item) { 13247 indexOf: function(item) {
12652 return this.items.indexOf(item); 13248 return this.items.indexOf(item);
12653 }, 13249 },
12654 13250
(...skipping 21 matching lines...) Expand all
12676 /** 13272 /**
12677 * Selects the next item. 13273 * Selects the next item.
12678 * 13274 *
12679 * @method selectNext 13275 * @method selectNext
12680 */ 13276 */
12681 selectNext: function() { 13277 selectNext: function() {
12682 var index = (Number(this._valueToIndex(this.selected)) + 1) % this.items.l ength; 13278 var index = (Number(this._valueToIndex(this.selected)) + 1) % this.items.l ength;
12683 this.selected = this._indexToValue(index); 13279 this.selected = this._indexToValue(index);
12684 }, 13280 },
12685 13281
13282 get _shouldUpdateSelection() {
13283 return this.selected != null;
13284 },
13285
12686 _addListener: function(eventName) { 13286 _addListener: function(eventName) {
12687 if (!this.isAttached || this.__listeningForActivate) {
12688 return;
12689 }
12690
12691 this.__listeningForActivate = true;
12692 this.listen(this, eventName, '_activateHandler'); 13287 this.listen(this, eventName, '_activateHandler');
12693 }, 13288 },
12694 13289
12695 _removeListener: function(eventName) { 13290 _removeListener: function(eventName) {
12696 this.unlisten(this, eventName, '_activateHandler'); 13291 this.unlisten(this, eventName, '_activateHandler');
12697 this.__listeningForActivate = false;
12698 }, 13292 },
12699 13293
12700 _activateEventChanged: function(eventName, old) { 13294 _activateEventChanged: function(eventName, old) {
12701 this._removeListener(old); 13295 this._removeListener(old);
12702 this._addListener(eventName); 13296 this._addListener(eventName);
12703 }, 13297 },
12704 13298
13299 _updateItems: function() {
13300 var nodes = Polymer.dom(this).queryDistributedElements(this.selectable || '*');
13301 nodes = Array.prototype.filter.call(nodes, this._bindFilterItem);
13302 this._setItems(nodes);
13303 },
13304
12705 _updateSelected: function() { 13305 _updateSelected: function() {
12706 this._selectSelected(this.selected); 13306 this._selectSelected(this.selected);
12707 }, 13307 },
12708 13308
12709 _selectSelected: function(selected) { 13309 _selectSelected: function(selected) {
12710 this._selection.select(this._valueToItem(this.selected)); 13310 this._selection.select(this._valueToItem(this.selected));
12711 }, 13311 },
12712 13312
12713 _filterItem: function(node) { 13313 _filterItem: function(node) {
12714 return !this._excludedLocalNames[node.localName]; 13314 return !this._excludedLocalNames[node.localName];
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
12753 this.toggleAttribute(this.selectedAttribute, isSelected, item); 13353 this.toggleAttribute(this.selectedAttribute, isSelected, item);
12754 } 13354 }
12755 this._selectionChange(); 13355 this._selectionChange();
12756 this.fire('iron-' + (isSelected ? 'select' : 'deselect'), {item: item}); 13356 this.fire('iron-' + (isSelected ? 'select' : 'deselect'), {item: item});
12757 }, 13357 },
12758 13358
12759 _selectionChange: function() { 13359 _selectionChange: function() {
12760 this._setSelectedItem(this._selection.get()); 13360 this._setSelectedItem(this._selection.get());
12761 }, 13361 },
12762 13362
12763 // observe content changes under the given node.
12764 _observeContent: function(node) {
12765 var content = node.querySelector('content');
12766 if (content && content.parentElement === node) {
12767 return this._observeItems(node.domHost);
12768 }
12769 },
12770
12771 // observe items change under the given node. 13363 // observe items change under the given node.
12772 _observeItems: function(node) { 13364 _observeItems: function(node) {
12773 // TODO(cdata): Update this when we get distributed children changed. 13365 return Polymer.dom(node).observeNodes(function(mutations) {
12774 var observer = new MutationObserver(function(mutations) {
12775 // Let other interested parties know about the change so that 13366 // Let other interested parties know about the change so that
12776 // we don't have to recreate mutation observers everywher. 13367 // we don't have to recreate mutation observers everywher.
12777 this.fire('iron-items-changed', mutations, { 13368 this.fire('iron-items-changed', mutations, {
12778 bubbles: false, 13369 bubbles: false,
12779 cancelable: false 13370 cancelable: false
12780 }); 13371 });
12781 13372
12782 if (this.selected != null) { 13373 this._updateItems();
13374
13375 if (this._shouldUpdateSelection) {
12783 this._updateSelected(); 13376 this._updateSelected();
12784 } 13377 }
12785 }.bind(this));
12786 observer.observe(node, {
12787 childList: true,
12788 subtree: true
12789 }); 13378 });
12790 return observer;
12791 }, 13379 },
12792 13380
12793 _activateHandler: function(e) { 13381 _activateHandler: function(e) {
12794 var t = e.target; 13382 var t = e.target;
12795 var items = this.items; 13383 var items = this.items;
12796 while (t && t != this) { 13384 while (t && t != this) {
12797 var i = items.indexOf(t); 13385 var i = items.indexOf(t);
12798 if (i >= 0) { 13386 if (i >= 0) {
12799 var value = this._indexToValue(i); 13387 var value = this._indexToValue(i);
12800 this._itemActivate(value, t); 13388 this._itemActivate(value, t);
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after
12865 } 13453 }
12866 } else { 13454 } else {
12867 this.selected = value; 13455 this.selected = value;
12868 } 13456 }
12869 }, 13457 },
12870 13458
12871 multiChanged: function(multi) { 13459 multiChanged: function(multi) {
12872 this._selection.multi = multi; 13460 this._selection.multi = multi;
12873 }, 13461 },
12874 13462
13463 get _shouldUpdateSelection() {
13464 return this.selected != null ||
13465 (this.selectedValues != null && this.selectedValues.length);
13466 },
13467
12875 _updateSelected: function() { 13468 _updateSelected: function() {
12876 if (this.multi) { 13469 if (this.multi) {
12877 this._selectMulti(this.selectedValues); 13470 this._selectMulti(this.selectedValues);
12878 } else { 13471 } else {
12879 this._selectSelected(this.selected); 13472 this._selectSelected(this.selected);
12880 } 13473 }
12881 }, 13474 },
12882 13475
12883 _selectMulti: function(values) { 13476 _selectMulti: function(values) {
12884 this._selection.clear(); 13477 this._selection.clear();
(...skipping 524 matching lines...) Expand 10 before | Expand all | Expand 10 after
13409 */ 14002 */
13410 constrain: function() { 14003 constrain: function() {
13411 var info = this._fitInfo; 14004 var info = this._fitInfo;
13412 // position at (0px, 0px) if not already positioned, so we can measure the natural size. 14005 // position at (0px, 0px) if not already positioned, so we can measure the natural size.
13413 if (!this._fitInfo.positionedBy.vertically) { 14006 if (!this._fitInfo.positionedBy.vertically) {
13414 this.style.top = '0px'; 14007 this.style.top = '0px';
13415 } 14008 }
13416 if (!this._fitInfo.positionedBy.horizontally) { 14009 if (!this._fitInfo.positionedBy.horizontally) {
13417 this.style.left = '0px'; 14010 this.style.left = '0px';
13418 } 14011 }
14012 if (!this._fitInfo.positionedBy.vertically || !this._fitInfo.positionedBy. horizontally) {
14013 // need position:fixed to properly size the element
14014 this.style.position = 'fixed';
14015 }
13419 // need border-box for margin/padding 14016 // need border-box for margin/padding
13420 this.sizingTarget.style.boxSizing = 'border-box'; 14017 this.sizingTarget.style.boxSizing = 'border-box';
13421 // constrain the width and height if not already set 14018 // constrain the width and height if not already set
13422 var rect = this.getBoundingClientRect(); 14019 var rect = this.getBoundingClientRect();
13423 if (!info.sizedBy.height) { 14020 if (!info.sizedBy.height) {
13424 this._sizeDimension(rect, info.positionedBy.vertically, 'top', 'bottom', 'Height'); 14021 this._sizeDimension(rect, info.positionedBy.vertically, 'top', 'bottom', 'Height');
13425 } 14022 }
13426 if (!info.sizedBy.width) { 14023 if (!info.sizedBy.width) {
13427 this._sizeDimension(rect, info.positionedBy.horizontally, 'left', 'right ', 'Width'); 14024 this._sizeDimension(rect, info.positionedBy.horizontally, 'left', 'right ', 'Width');
13428 } 14025 }
(...skipping 1971 matching lines...) Expand 10 before | Expand all | Expand 10 after
15400 _altChanged: function(newValue, oldValue) { 15997 _altChanged: function(newValue, oldValue) {
15401 var label = this.getAttribute('aria-label'); 15998 var label = this.getAttribute('aria-label');
15402 15999
15403 // Don't stomp over a user-set aria-label. 16000 // Don't stomp over a user-set aria-label.
15404 if (!label || oldValue == label) { 16001 if (!label || oldValue == label) {
15405 this.setAttribute('aria-label', newValue); 16002 this.setAttribute('aria-label', newValue);
15406 } 16003 }
15407 } 16004 }
15408 }); 16005 });
15409 /** 16006 /**
15410 * Use `Polymer.IronValidatableBehavior` to implement an element that validate s user input. 16007 * `Use Polymer.IronValidatableBehavior` to implement an element that validate s user input.
16008 * Use the related `Polymer.IronValidatorBehavior` to add custom validation lo gic to an iron-input.
16009 *
16010 * By default, an `<iron-form>` element validates its fields when the user pre sses the submit button.
16011 * To validate a form imperatively, call the form's `validate()` method, which in turn will
16012 * call `validate()` on all its children. By using `Polymer.IronValidatableBeh avior`, your
16013 * custom element will get a public `validate()`, which
16014 * will return the validity of the element, and a corresponding `invalid` attr ibute,
16015 * which can be used for styling.
16016 *
16017 * To implement the custom validation logic of your element, you must override
16018 * the protected `_getValidity()` method of this behaviour, rather than `valid ate()`.
16019 * See [this](https://github.com/PolymerElements/iron-form/blob/master/demo/si mple-element.html)
16020 * for an example.
15411 * 16021 *
15412 * ### Accessibility 16022 * ### Accessibility
15413 * 16023 *
15414 * Changing the `invalid` property, either manually or by calling `validate()` will update the 16024 * Changing the `invalid` property, either manually or by calling `validate()` will update the
15415 * `aria-invalid` attribute. 16025 * `aria-invalid` attribute.
15416 * 16026 *
15417 * @demo demo/index.html 16027 * @demo demo/index.html
15418 * @polymerBehavior 16028 * @polymerBehavior
15419 */ 16029 */
15420 Polymer.IronValidatableBehavior = { 16030 Polymer.IronValidatableBehavior = {
(...skipping 455 matching lines...) Expand 10 before | Expand all | Expand 10 after
15876 } 16486 }
15877 }, 16487 },
15878 16488
15879 attached: function() { 16489 attached: function() {
15880 // Only validate when attached if the input already has a value. 16490 // Only validate when attached if the input already has a value.
15881 if (this._inputElementValue != '') { 16491 if (this._inputElementValue != '') {
15882 this._handleValueAndAutoValidate(this._inputElement); 16492 this._handleValueAndAutoValidate(this._inputElement);
15883 } else { 16493 } else {
15884 this._handleValue(this._inputElement); 16494 this._handleValue(this._inputElement);
15885 } 16495 }
16496
16497 this._numberOfPrefixNodes = 0;
16498 this._prefixObserver = Polymer.dom(this.$.prefix).observeNodes(
16499 function(mutations) {
16500 // Keep track whether there's at least one prefix node, since it
16501 // affects laying out the floating label.
16502 this._numberOfPrefixNodes += mutations.addedNodes.length -
16503 mutations.removedNodes.length;
16504 }.bind(this));
16505 },
16506
16507 detached: function() {
16508 if (this._prefixObserver) {
16509 Polymer.dom(this.$.prefix).unobserveNodes(this._prefixObserver);
16510 }
15886 }, 16511 },
15887 16512
15888 _onAddonAttached: function(event) { 16513 _onAddonAttached: function(event) {
15889 if (!this._addons) { 16514 if (!this._addons) {
15890 this._addons = []; 16515 this._addons = [];
15891 } 16516 }
15892 var target = event.target; 16517 var target = event.target;
15893 if (this._addons.indexOf(target) === -1) { 16518 if (this._addons.indexOf(target) === -1) {
15894 this._addons.push(target); 16519 this._addons.push(target);
15895 if (this.isAttached) { 16520 if (this.isAttached) {
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after
15972 if (!noLabelFloat) { 16597 if (!noLabelFloat) {
15973 var label = this.querySelector('label'); 16598 var label = this.querySelector('label');
15974 16599
15975 if (alwaysFloatLabel || _inputHasContent) { 16600 if (alwaysFloatLabel || _inputHasContent) {
15976 cls += ' label-is-floating'; 16601 cls += ' label-is-floating';
15977 if (invalid) { 16602 if (invalid) {
15978 cls += ' is-invalid'; 16603 cls += ' is-invalid';
15979 } else if (focused) { 16604 } else if (focused) {
15980 cls += " label-is-highlighted"; 16605 cls += " label-is-highlighted";
15981 } 16606 }
15982 // The label might have a horizontal offset if a prefix element exists 16607 // If a prefix element exists, the label has a horizontal offset
15983 // which needs to be undone when displayed as a floating label. 16608 // which needs to be undone when displayed as a floating label.
15984 if (Polymer.dom(this.$.prefix).getDistributedNodes().length > 0 && 16609 if (this._numberOfPrefixNodes > 0) {
15985 label && label.offsetParent) { 16610 this.$.labelAndInputContainer.style.position = 'static';
15986 label.style.left = -label.offsetParent.offsetLeft + 'px';
15987 } 16611 }
15988 } else { 16612 } else {
15989 // When the label is not floating, it should overlap the input element . 16613 // When the label is not floating, it should overlap the input element .
15990 if (label) { 16614 if (label) {
15991 label.style.left = 0; 16615 this.$.labelAndInputContainer.style.position = 'relative';
15992 } 16616 }
15993 } 16617 }
15994 } else { 16618 } else {
15995 if (_inputHasContent) { 16619 if (_inputHasContent) {
15996 cls += ' label-is-hidden'; 16620 cls += ' label-is-hidden';
15997 } 16621 }
15998 } 16622 }
15999 return cls; 16623 return cls;
16000 }, 16624 },
16001 16625
(...skipping 191 matching lines...) Expand 10 before | Expand all | Expand 10 after
16193 // Copyright 2015 The Chromium Authors. All rights reserved. 16817 // Copyright 2015 The Chromium Authors. All rights reserved.
16194 // Use of this source code is governed by a BSD-style license that can be 16818 // Use of this source code is governed by a BSD-style license that can be
16195 // found in the LICENSE file. 16819 // found in the LICENSE file.
16196 16820
16197 cr.define('downloads', function() { 16821 cr.define('downloads', function() {
16198 var Manager = Polymer({ 16822 var Manager = Polymer({
16199 is: 'downloads-manager', 16823 is: 'downloads-manager',
16200 16824
16201 properties: { 16825 properties: {
16202 hasDownloads_: { 16826 hasDownloads_: {
16827 observer: 'hasDownloadsChanged_',
16203 type: Boolean, 16828 type: Boolean,
16204 value: false,
16205 }, 16829 },
16206 16830
16207 items_: { 16831 items_: {
16208 type: Array, 16832 type: Array,
16833 value: function() { return []; },
16209 }, 16834 },
16210 }, 16835 },
16211 16836
16837 observers: [
16838 'itemsChanged_(items_.*)',
16839 ],
16840
16841 /** @private */
16842 clearAll_: function() {
16843 this.set('items_', []);
16844 },
16845
16846 /** @private */
16847 hasDownloadsChanged_: function() {
16848 if (loadTimeData.getBoolean('allowDeletingHistory'))
16849 this.$.toolbar.downloadsShowing = this.hasDownloads_;
16850
16851 if (this.hasDownloads_) {
16852 this.$['downloads-list'].fire('iron-resize');
16853 } else {
16854 var isSearching = downloads.ActionService.getInstance().isSearching();
16855 var messageToShow = isSearching ? 'noSearchResults' : 'noDownloads';
16856 this.$['no-downloads'].querySelector('span').textContent =
16857 loadTimeData.getString(messageToShow);
16858 }
16859 },
16860
16861 /**
16862 * @param {number} index
16863 * @param {!Array<!downloads.Data>} list
16864 * @private
16865 */
16866 insertItems_: function(index, list) {
16867 this.splice.apply(this, ['items_', index, 0].concat(list));
16868 this.updateHideDates_(index, index + list.length);
16869 this.$.panel.classList.remove('loading');
16870 },
16871
16872 /** @private */
16873 itemsChanged_: function() {
16874 this.hasDownloads_ = this.size_() > 0;
16875 },
16876
16212 /** 16877 /**
16213 * @param {Event} e 16878 * @param {Event} e
16214 * @private 16879 * @private
16215 */ 16880 */
16216 onCanExecute_: function(e) { 16881 onCanExecute_: function(e) {
16217 e = /** @type {cr.ui.CanExecuteEvent} */(e); 16882 e = /** @type {cr.ui.CanExecuteEvent} */(e);
16218 switch (e.command.id) { 16883 switch (e.command.id) {
16219 case 'undo-command': 16884 case 'undo-command':
16220 e.canExecute = this.$.toolbar.canUndo(); 16885 e.canExecute = this.$.toolbar.canUndo();
16221 break; 16886 break;
(...skipping 18 matching lines...) Expand all
16240 onLoad_: function() { 16905 onLoad_: function() {
16241 cr.ui.decorate('command', cr.ui.Command); 16906 cr.ui.decorate('command', cr.ui.Command);
16242 document.addEventListener('canExecute', this.onCanExecute_.bind(this)); 16907 document.addEventListener('canExecute', this.onCanExecute_.bind(this));
16243 document.addEventListener('command', this.onCommand_.bind(this)); 16908 document.addEventListener('command', this.onCommand_.bind(this));
16244 16909
16245 // Shows all downloads. 16910 // Shows all downloads.
16246 downloads.ActionService.getInstance().search(''); 16911 downloads.ActionService.getInstance().search('');
16247 }, 16912 },
16248 16913
16249 /** 16914 /**
16915 * @param {number} index
16916 * @private
16917 */
16918 removeItem_: function(index) {
16919 this.splice('items_', index, 1);
16920 this.updateHideDates_(index, index);
16921 },
16922
16923 /**
16250 * @return {number} The number of downloads shown on the page. 16924 * @return {number} The number of downloads shown on the page.
16251 * @private 16925 * @private
16252 */ 16926 */
16253 size_: function() { 16927 size_: function() {
16254 return this.items_.length; 16928 return this.items_.length;
16255 }, 16929 },
16256 16930
16257 /** 16931 /**
16258 * Called when all items need to be updated. 16932 * @param {number} start
16259 * @param {!Array<!downloads.Data>} list A list of new download data. 16933 * @param {number} end
16260 * @private 16934 * @private
16261 */ 16935 */
16262 updateAll_: function(list) { 16936 updateHideDates_: function(start, end) {
16263 /** @private {!Object<number>} */ 16937 for (var i = start; i <= end; ++i) {
16264 this.idToIndex_ = {}; 16938 var current = this.items_[i];
16265 16939 if (!current)
16266 for (var i = 0; i < list.length; ++i) { 16940 continue;
16267 var data = list[i]; 16941 var prev = this.items_[i - 1];
16268 16942 current.hideDate = !!prev && prev.date_string == current.date_string;
16269 this.idToIndex_[data.id] = data.index = i;
16270
16271 var prev = list[i - 1];
16272 data.hideDate = !!prev && prev.date_string == data.date_string;
16273 } 16943 }
16274
16275 // TODO(dbeam): this resets the scroll position, which is a huge bummer.
16276 // Removing something from the bottom of the list should not scroll you
16277 // back to the top. The grand plan is to restructure how the C++ sends the
16278 // JS data so that it only gets updates (rather than the most recent set
16279 // of items). TL;DR - we can't ship with this bug.
16280 this.items_ = list;
16281
16282 var hasDownloads = this.size_() > 0;
16283 if (!hasDownloads) {
16284 var isSearching = downloads.ActionService.getInstance().isSearching();
16285 var messageToShow = isSearching ? 'noSearchResults' : 'noDownloads';
16286 this.$['no-downloads'].querySelector('span').textContent =
16287 loadTimeData.getString(messageToShow);
16288 }
16289 this.hasDownloads_ = hasDownloads;
16290
16291 if (loadTimeData.getBoolean('allowDeletingHistory'))
16292 this.$.toolbar.downloadsShowing = this.hasDownloads_;
16293
16294 this.$.panel.classList.remove('loading');
16295 }, 16944 },
16296 16945
16297 /** 16946 /**
16947 * @param {number} index
16298 * @param {!downloads.Data} data 16948 * @param {!downloads.Data} data
16299 * @private 16949 * @private
16300 */ 16950 */
16301 updateItem_: function(data) { 16951 updateItem_: function(index, data) {
16302 var index = this.idToIndex_[data.id];
16303 this.set('items_.' + index, data); 16952 this.set('items_.' + index, data);
16304 this.$['downloads-list'].updateSizeForItem(index); 16953 this.$['downloads-list'].updateSizeForItem(index);
16305 }, 16954 },
16306 }); 16955 });
16307 16956
16308 Manager.size = function() { 16957 Manager.clearAll = function() {
16309 return document.querySelector('downloads-manager').size_(); 16958 Manager.get().clearAll_();
16310 }; 16959 };
16311 16960
16312 Manager.updateAll = function(list) { 16961 /** @return {downloads.Manager} */
16313 document.querySelector('downloads-manager').updateAll_(list); 16962 Manager.get = function() {
16963 return document.querySelector('downloads-manager');
16314 }; 16964 };
16315 16965
16316 Manager.updateItem = function(item) { 16966 Manager.insertItems = function(index, list) {
16317 document.querySelector('downloads-manager').updateItem_(item); 16967 Manager.get().insertItems_(index, list);
16318 }; 16968 };
16319 16969
16320 Manager.onLoad = function() { 16970 Manager.onLoad = function() {
16321 document.querySelector('downloads-manager').onLoad_(); 16971 Manager.get().onLoad_();
16972 };
16973
16974 Manager.removeItem = function(index) {
16975 Manager.get().removeItem_(index);
16976 };
16977
16978 Manager.size = function() {
16979 return Manager.get().size_();
16980 };
16981
16982 Manager.updateItem = function(index, data) {
16983 Manager.get().updateItem_(index, data);
16322 }; 16984 };
16323 16985
16324 return {Manager: Manager}; 16986 return {Manager: Manager};
16325 }); 16987 });
16326 // Copyright 2015 The Chromium Authors. All rights reserved. 16988 // Copyright 2015 The Chromium Authors. All rights reserved.
16327 // Use of this source code is governed by a BSD-style license that can be 16989 // Use of this source code is governed by a BSD-style license that can be
16328 // found in the LICENSE file. 16990 // found in the LICENSE file.
16329 16991
16330 window.addEventListener('load', downloads.Manager.onLoad); 16992 window.addEventListener('load', downloads.Manager.onLoad);
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698