OLD | NEW |
(Empty) | |
| 1 |
| 2 |
| 3 Polymer.IronSelectableBehavior = { |
| 4 |
| 5 properties: { |
| 6 |
| 7 /** |
| 8 * If you want to use the attribute value of an element for `selected` ins
tead of the index, |
| 9 * set this to the name of the attribute. |
| 10 * |
| 11 * @attribute attrForSelected |
| 12 * @type String |
| 13 */ |
| 14 attrForSelected: { |
| 15 type: String, |
| 16 value: null |
| 17 }, |
| 18 |
| 19 /** |
| 20 * Gets or sets the selected element. The default is to use the index of t
he item. |
| 21 * |
| 22 * @attribute selected |
| 23 * @type String |
| 24 */ |
| 25 selected: { |
| 26 type: String, |
| 27 notify: true |
| 28 }, |
| 29 |
| 30 /** |
| 31 * Returns the currently selected item. |
| 32 * |
| 33 * @attribute selectedItem |
| 34 * @type Object |
| 35 */ |
| 36 selectedItem: { |
| 37 type: Object, |
| 38 readOnly: true, |
| 39 notify: true |
| 40 }, |
| 41 |
| 42 /** |
| 43 * The event that fires from items when they are selected. Selectable |
| 44 * will listen for this event from items and update the selection state. |
| 45 * Set to empty string to listen to no events. |
| 46 * |
| 47 * @attribute activateEvent |
| 48 * @type String |
| 49 * @default 'click' |
| 50 */ |
| 51 activateEvent: { |
| 52 type: String, |
| 53 value: 'click', |
| 54 observer: '_activateEventChanged' |
| 55 }, |
| 56 |
| 57 /** |
| 58 * This is a CSS selector sting. If this is set, only items that matches
the CSS selector |
| 59 * are selectable. |
| 60 * |
| 61 * @attribute selectable |
| 62 * @type String |
| 63 */ |
| 64 selectable: String, |
| 65 |
| 66 /** |
| 67 * The class to set on elements when selected. |
| 68 * |
| 69 * @attribute selectedClass |
| 70 * @type String |
| 71 */ |
| 72 selectedClass: { |
| 73 type: String, |
| 74 value: 'iron-selected' |
| 75 }, |
| 76 |
| 77 /** |
| 78 * The attribute to set on elements when selected. |
| 79 * |
| 80 * @attribute selectedAttribute |
| 81 * @type String |
| 82 */ |
| 83 selectedAttribute: { |
| 84 type: String, |
| 85 value: null |
| 86 } |
| 87 |
| 88 }, |
| 89 |
| 90 observers: [ |
| 91 '_updateSelected(attrForSelected, selected)' |
| 92 ], |
| 93 |
| 94 excludedLocalNames: { |
| 95 'template': 1 |
| 96 }, |
| 97 |
| 98 created: function() { |
| 99 this._bindActivateHandler = this._activateHandler.bind(this); |
| 100 this._bindFilterItem = this._filterItem.bind(this); |
| 101 this._selection = new Polymer.IronSelection(this._applySelection.bind(this
)); |
| 102 }, |
| 103 |
| 104 attached: function() { |
| 105 this._observer = this._observeItems(this); |
| 106 this._contentObserver = this._observeContent(this); |
| 107 }, |
| 108 |
| 109 detached: function() { |
| 110 if (this._observer) { |
| 111 this._observer.disconnect(); |
| 112 } |
| 113 if (this._contentObserver) { |
| 114 this._contentObserver.disconnect(); |
| 115 } |
| 116 this._removeListener(this.activateEvent); |
| 117 }, |
| 118 |
| 119 /** |
| 120 * Returns an array of selectable items. |
| 121 * |
| 122 * @property items |
| 123 * @type Array |
| 124 */ |
| 125 get items() { |
| 126 var nodes = Polymer.dom(this).queryDistributedElements(this.selectable ||
'*'); |
| 127 return Array.prototype.filter.call(nodes, this._bindFilterItem); |
| 128 }, |
| 129 |
| 130 /** |
| 131 * Returns the index of the given item. |
| 132 * |
| 133 * @method indexOf |
| 134 * @param {Object} item |
| 135 * @returns Returns the index of the item |
| 136 */ |
| 137 indexOf: function(item) { |
| 138 return this.items.indexOf(item); |
| 139 }, |
| 140 |
| 141 /** |
| 142 * Selects the given value. |
| 143 * |
| 144 * @method select |
| 145 * @param {String} value the value to select. |
| 146 */ |
| 147 select: function(value) { |
| 148 this.selected = value; |
| 149 }, |
| 150 |
| 151 /** |
| 152 * Selects the previous item. |
| 153 * |
| 154 * @method selectPrevious |
| 155 */ |
| 156 selectPrevious: function() { |
| 157 var length = this.items.length; |
| 158 var index = (Number(this._valueToIndex(this.selected)) - 1 + length) % len
gth; |
| 159 this.selected = this._indexToValue(index); |
| 160 }, |
| 161 |
| 162 /** |
| 163 * Selects the next item. |
| 164 * |
| 165 * @method selectNext |
| 166 */ |
| 167 selectNext: function() { |
| 168 var index = (Number(this._valueToIndex(this.selected)) + 1) % this.items.l
ength; |
| 169 this.selected = this._indexToValue(index); |
| 170 }, |
| 171 |
| 172 _addListener: function(eventName) { |
| 173 this.addEventListener(eventName, this._bindActivateHandler); |
| 174 }, |
| 175 |
| 176 _removeListener: function(eventName) { |
| 177 this.removeEventListener(eventName, this._bindActivateHandler); |
| 178 }, |
| 179 |
| 180 _activateEventChanged: function(eventName, old) { |
| 181 this._removeListener(old); |
| 182 this._addListener(eventName); |
| 183 }, |
| 184 |
| 185 _updateSelected: function() { |
| 186 this._selectSelected(this.selected); |
| 187 }, |
| 188 |
| 189 _selectSelected: function(selected) { |
| 190 this._selection.select(this._valueToItem(this.selected)); |
| 191 }, |
| 192 |
| 193 _filterItem: function(node) { |
| 194 return !this.excludedLocalNames[node.localName]; |
| 195 }, |
| 196 |
| 197 _valueToItem: function(value) { |
| 198 return (value == null) ? null : this.items[this._valueToIndex(value)]; |
| 199 }, |
| 200 |
| 201 _valueToIndex: function(value) { |
| 202 if (this.attrForSelected) { |
| 203 for (var i = 0, item; item = this.items[i]; i++) { |
| 204 if (this._valueForItem(item) == value) { |
| 205 return i; |
| 206 } |
| 207 } |
| 208 } else { |
| 209 return Number(value); |
| 210 } |
| 211 }, |
| 212 |
| 213 _indexToValue: function(index) { |
| 214 if (this.attrForSelected) { |
| 215 var item = this.items[index]; |
| 216 if (item) { |
| 217 return this._valueForItem(item); |
| 218 } |
| 219 } else { |
| 220 return index; |
| 221 } |
| 222 }, |
| 223 |
| 224 _valueForItem: function(item) { |
| 225 return item[this.attrForSelected] || item.getAttribute(this.attrForSelecte
d); |
| 226 }, |
| 227 |
| 228 _applySelection: function(item, isSelected) { |
| 229 if (this.selectedClass) { |
| 230 this.toggleClass(this.selectedClass, isSelected, item); |
| 231 } |
| 232 if (this.selectedAttribute) { |
| 233 this.toggleAttribute(this.selectedAttribute, isSelected, item); |
| 234 } |
| 235 this._selectionChange(); |
| 236 this.fire('iron-' + (isSelected ? 'select' : 'deselect'), {item: item}); |
| 237 }, |
| 238 |
| 239 _selectionChange: function() { |
| 240 this._setSelectedItem(this._selection.get()); |
| 241 }, |
| 242 |
| 243 // observe content changes under the given node. |
| 244 _observeContent: function(node) { |
| 245 var content = node.querySelector('content'); |
| 246 if (content && content.parentElement === node) { |
| 247 return this._observeItems(node.host); |
| 248 } |
| 249 }, |
| 250 |
| 251 // observe items change under the given node. |
| 252 _observeItems: function(node) { |
| 253 var observer = new MutationObserver(function() { |
| 254 if (this.selected != null) { |
| 255 this._updateSelected(); |
| 256 } |
| 257 }.bind(this)); |
| 258 observer.observe(node, { |
| 259 childList: true, |
| 260 subtree: true |
| 261 }); |
| 262 return observer; |
| 263 }, |
| 264 |
| 265 _activateHandler: function(e) { |
| 266 var t = e.target; |
| 267 var items = this.items; |
| 268 while (t && t != this) { |
| 269 var i = items.indexOf(t); |
| 270 if (i >= 0) { |
| 271 var value = this._indexToValue(i); |
| 272 this._itemActivate(value, t); |
| 273 return; |
| 274 } |
| 275 t = t.parentNode; |
| 276 } |
| 277 }, |
| 278 |
| 279 _itemActivate: function(value, item) { |
| 280 if (!this.fire('iron-activate', |
| 281 {selected: value, item: item}, {cancelable: true}).defaultPrevented) { |
| 282 this.select(value); |
| 283 } |
| 284 } |
| 285 |
| 286 }; |
| 287 |
OLD | NEW |