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