Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 (function() { | 1 (function() { |
| 2 | 2 |
| 3 var IOS = navigator.userAgent.match(/iP(?:hone|ad;(?: U;)? CPU) OS (\d+)/); | 3 var IOS = navigator.userAgent.match(/iP(?:hone|ad;(?: U;)? CPU) OS (\d+)/); |
| 4 var IOS_TOUCH_SCROLLING = IOS && IOS[1] >= 8; | 4 var IOS_TOUCH_SCROLLING = IOS && IOS[1] >= 8; |
| 5 var DEFAULT_PHYSICAL_COUNT = 3; | 5 var DEFAULT_PHYSICAL_COUNT = 3; |
| 6 var HIDDEN_Y = '-10000px'; | 6 var HIDDEN_Y = '-10000px'; |
| 7 var ITEM_WIDTH = 0; | 7 var ITEM_WIDTH = 0; |
| 8 var ITEM_HEIGHT = 1; | 8 var ITEM_HEIGHT = 1; |
| 9 var SECRET_TABINDEX = -100; | 9 var SECRET_TABINDEX = -100; |
| 10 | 10 |
| (...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 119 * This value can be computed using the position returned by `getBoundingC lientRect()` | 119 * This value can be computed using the position returned by `getBoundingC lientRect()` |
| 120 * although it's preferred to use a constant value when possible. | 120 * although it's preferred to use a constant value when possible. |
| 121 * | 121 * |
| 122 * This property is useful when an external scrolling element is used and there's | 122 * This property is useful when an external scrolling element is used and there's |
| 123 * some offset between the scrolling element and the list. | 123 * some offset between the scrolling element and the list. |
| 124 * For example: a header is placed above the list. | 124 * For example: a header is placed above the list. |
| 125 */ | 125 */ |
| 126 scrollOffset: { | 126 scrollOffset: { |
| 127 type: Number, | 127 type: Number, |
| 128 value: 0 | 128 value: 0 |
| 129 }, | |
| 130 | |
| 131 /** | |
| 132 * If set to true, focus on an element will be preserved after rerender. | |
| 133 */ | |
| 134 preserveFocus: { | |
| 135 type: Boolean, | |
| 136 value: false | |
| 129 } | 137 } |
| 130 }, | 138 }, |
| 131 | 139 |
| 132 observers: [ | 140 observers: [ |
| 133 '_itemsChanged(items.*)', | 141 '_itemsChanged(items.*)', |
| 134 '_selectionEnabledChanged(selectionEnabled)', | 142 '_selectionEnabledChanged(selectionEnabled)', |
| 135 '_multiSelectionChanged(multiSelection)', | 143 '_multiSelectionChanged(multiSelection)', |
| 136 '_setOverflow(scrollTarget, scrollOffset)' | 144 '_setOverflow(scrollTarget, scrollOffset)' |
| 137 ], | 145 ], |
| 138 | 146 |
| (...skipping 748 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 887 } | 895 } |
| 888 el._templateInstance[this.as] = value; | 896 el._templateInstance[this.as] = value; |
| 889 } | 897 } |
| 890 }, | 898 }, |
| 891 | 899 |
| 892 /** | 900 /** |
| 893 * Called when the items have changed. That is, ressignments | 901 * Called when the items have changed. That is, ressignments |
| 894 * to `items`, splices or updates to a single item. | 902 * to `items`, splices or updates to a single item. |
| 895 */ | 903 */ |
| 896 _itemsChanged: function(change) { | 904 _itemsChanged: function(change) { |
| 905 var rendering = ['items', 'items.splices'].includes(change.path); | |
|
dpapad
2017/05/23 22:19:43
Nit (optional): Maybe use a regex instead (to avoi
scottchen
2017/05/24 21:34:35
Done.
| |
| 906 var lastFocusedIndex, focusedElement; | |
| 907 if (rendering && this.preserveFocus) { | |
| 908 lastFocusedIndex = this._focusedIndex; | |
| 909 focusedElement = this.querySelector('* /deep/ *:focus'); | |
| 910 } | |
| 911 | |
| 912 var preservingFocus = rendering && this.preserveFocus && focusedElement; | |
| 913 | |
| 897 if (change.path === 'items') { | 914 if (change.path === 'items') { |
| 898 this._virtualStart = 0; | 915 this._virtualStart = 0; |
| 899 this._physicalTop = 0; | 916 this._physicalTop = 0; |
| 900 this._virtualCount = this.items ? this.items.length : 0; | 917 this._virtualCount = this.items ? this.items.length : 0; |
| 901 this._collection = this.items ? Polymer.Collection.get(this.items) : nul l; | 918 this._collection = this.items ? Polymer.Collection.get(this.items) : nul l; |
| 902 this._physicalIndexForKey = {}; | 919 this._physicalIndexForKey = {}; |
| 903 this._firstVisibleIndexVal = null; | 920 this._firstVisibleIndexVal = null; |
| 904 this._lastVisibleIndexVal = null; | 921 this._lastVisibleIndexVal = null; |
| 905 this._physicalCount = this._physicalCount || 0; | 922 this._physicalCount = this._physicalCount || 0; |
| 906 this._physicalItems = this._physicalItems || []; | 923 this._physicalItems = this._physicalItems || []; |
| 907 this._physicalSizes = this._physicalSizes || []; | 924 this._physicalSizes = this._physicalSizes || []; |
| 908 this._physicalStart = 0; | 925 this._physicalStart = 0; |
| 909 if (this._scrollTop > this._scrollOffset) { | 926 if (this._scrollTop > this._scrollOffset && !preservingFocus) { |
| 910 this._resetScrollPosition(0); | 927 this._resetScrollPosition(0); |
| 911 } | 928 } |
| 912 this._removeFocusedItem(); | 929 this._removeFocusedItem(); |
| 913 this._debounceTemplate(this._render); | 930 this._debounceTemplate(this._render); |
| 914 | |
| 915 } else if (change.path === 'items.splices') { | 931 } else if (change.path === 'items.splices') { |
| 916 this._adjustVirtualIndex(change.value.indexSplices); | 932 this._adjustVirtualIndex(change.value.indexSplices); |
| 917 this._virtualCount = this.items ? this.items.length : 0; | 933 this._virtualCount = this.items ? this.items.length : 0; |
| 918 | 934 |
| 919 this._debounceTemplate(this._render); | 935 this._debounceTemplate(this._render); |
| 920 } else { | 936 } else { |
| 921 this._forwardItemPath(change.path.split('.').slice(1).join('.'), change. value); | 937 this._forwardItemPath(change.path.split('.').slice(1).join('.'), change. value); |
| 922 } | 938 } |
| 939 | |
| 940 // If the list was in focus when updated, preserve the focus on item. | |
| 941 if (preservingFocus) { | |
| 942 Polymer.dom.flush(); | |
| 943 focusedElement.blur(); // paper- elements breaks when focused twice. | |
| 944 this._focusPhysicalItem( | |
| 945 Math.min(this.items.length - 1, lastFocusedIndex)); | |
| 946 if (!this._isIndexVisible(this._focusedIndex)) { | |
| 947 this.scrollToIndex(this._focusedIndex); | |
| 948 } | |
|
stevenjb
2017/05/09 17:14:00
Can we do something like:
var idx = Math.min(this
scottchen
2017/05/22 22:57:31
This would not work as intended:
focusedElement
stevenjb
2017/05/22 23:14:54
It's been a while, but I think I was being hand-wa
scottchen
2017/05/23 21:43:49
focusedItem at this point is already reset to 0 (t
stevenjb
2017/05/23 21:53:47
OK, lgtm then
| |
| 949 } | |
| 923 }, | 950 }, |
| 924 | 951 |
| 925 /** | 952 /** |
| 926 * @param {!Array<!PolymerSplice>} splices | 953 * @param {!Array<!PolymerSplice>} splices |
| 927 */ | 954 */ |
| 928 _adjustVirtualIndex: function(splices) { | 955 _adjustVirtualIndex: function(splices) { |
| 929 splices.forEach(function(splice) { | 956 splices.forEach(function(splice) { |
| 930 // deselect removed items | 957 // deselect removed items |
| 931 splice.removed.forEach(this._removeItem, this); | 958 splice.removed.forEach(this._removeItem, this); |
| 932 // We only need to care about changes happening above the current positi on | 959 // We only need to care about changes happening above the current positi on |
| (...skipping 666 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1599 this._focusPhysicalItem(this._focusedIndex + 1); | 1626 this._focusPhysicalItem(this._focusedIndex + 1); |
| 1600 }, | 1627 }, |
| 1601 | 1628 |
| 1602 _didEnter: function(e) { | 1629 _didEnter: function(e) { |
| 1603 this._focusPhysicalItem(this._focusedIndex); | 1630 this._focusPhysicalItem(this._focusedIndex); |
| 1604 this._selectionHandler(e.detail.keyboardEvent); | 1631 this._selectionHandler(e.detail.keyboardEvent); |
| 1605 } | 1632 } |
| 1606 }); | 1633 }); |
| 1607 | 1634 |
| 1608 })(); | 1635 })(); |
| OLD | NEW |