3 /** @polymerBehavior */
4 Polymer
.IronSelectableBehavior
= {
9 * If you want to use the attribute value of an element for `selected` instead of the index,
10 * set this to the name of the attribute.
12 * @attribute attrForSelected
21 * Gets or sets the selected element. The default is to use the index of the item.
32 * Returns the currently selected item.
34 * @attribute selectedItem
44 * The event that fires from items when they are selected. Selectable
45 * will listen for this event from items and update the selection state.
46 * Set to empty string to listen to no events.
48 * @attribute activateEvent
55 observer
: '_activateEventChanged'
59 * This is a CSS selector sting. If this is set, only items that matches the CSS selector
62 * @attribute selectable
68 * The class to set on elements when selected.
70 * @attribute selectedClass
75 value
: 'iron-selected'
79 * The attribute to set on elements when selected.
81 * @attribute selectedAttribute
92 '_updateSelected(attrForSelected, selected)'
100 this._bindFilterItem
= this._filterItem
.bind(this);
101 this._selection
= new Polymer
.IronSelection(this._applySelection
.bind(this));
104 attached: function() {
105 this._observer
= this._observeItems(this);
106 this._contentObserver
= this._observeContent(this);
109 detached: function() {
110 if (this._observer
) {
111 this._observer
.disconnect();
113 if (this._contentObserver
) {
114 this._contentObserver
.disconnect();
116 this._removeListener(this.activateEvent
);
120 * Returns an array of selectable items.
126 var nodes
= Polymer
.dom(this).queryDistributedElements(this.selectable
|| '*');
127 return Array
.prototype.filter
.call(nodes
, this._bindFilterItem
);
131 * Returns the index of the given item.
134 * @param {Object} item
135 * @returns Returns the index of the item
137 indexOf: function(item
) {
138 return this.items
.indexOf(item
);
142 * Selects the given value.
145 * @param {string} value the value to select.
147 select: function(value
) {
148 this.selected
= value
;
152 * Selects the previous item.
154 * @method selectPrevious
156 selectPrevious: function() {
157 var length
= this.items
.length
;
158 var index
= (Number(this._valueToIndex(this.selected
)) - 1 + length
) % length
;
159 this.selected
= this._indexToValue(index
);
163 * Selects the next item.
167 selectNext: function() {
168 var index
= (Number(this._valueToIndex(this.selected
)) + 1) % this.items
.length
;
169 this.selected
= this._indexToValue(index
);
172 _addListener: function(eventName
) {
173 this.listen(this, eventName
, '_activateHandler');
176 _removeListener: function(eventName
) {
177 // There is no unlisten yet...
178 // https://github.com/Polymer/polymer/issues/1639
179 //this.removeEventListener(eventName, this._bindActivateHandler);
182 _activateEventChanged: function(eventName
, old
) {
183 this._removeListener(old
);
184 this._addListener(eventName
);
187 _updateSelected: function() {
188 this._selectSelected(this.selected
);
191 _selectSelected: function(selected
) {
192 this._selection
.select(this._valueToItem(this.selected
));
195 _filterItem: function(node
) {
196 return !this.excludedLocalNames
[node
.localName
];
199 _valueToItem: function(value
) {
200 return (value
== null) ? null : this.items
[this._valueToIndex(value
)];
203 _valueToIndex: function(value
) {
204 if (this.attrForSelected
) {
205 for (var i
= 0, item
; item
= this.items
[i
]; i
++) {
206 if (this._valueForItem(item
) == value
) {
211 return Number(value
);
215 _indexToValue: function(index
) {
216 if (this.attrForSelected
) {
217 var item
= this.items
[index
];
219 return this._valueForItem(item
);
226 _valueForItem: function(item
) {
227 return item
[this.attrForSelected
] || item
.getAttribute(this.attrForSelected
);
230 _applySelection: function(item
, isSelected
) {
231 if (this.selectedClass
) {
232 this.toggleClass(this.selectedClass
, isSelected
, item
);
234 if (this.selectedAttribute
) {
235 this.toggleAttribute(this.selectedAttribute
, isSelected
, item
);
237 this._selectionChange();
238 this.fire('iron-' + (isSelected
? 'select' : 'deselect'), {item
: item
});
241 _selectionChange: function() {
242 this._setSelectedItem(this._selection
.get());
245 // observe content changes under the given node.
246 _observeContent: function(node
) {
247 var content
= node
.querySelector('content');
248 if (content
&& content
.parentElement
=== node
) {
249 return this._observeItems(node
.domHost
);
253 // observe items change under the given node.
254 _observeItems: function(node
) {
255 var observer
= new MutationObserver(function() {
256 if (this.selected
!= null) {
257 this._updateSelected();
260 observer
.observe(node
, {
267 _activateHandler: function(e
) {
268 // TODO: remove this when https://github.com/Polymer/polymer/issues/1639 is fixed so we
269 // can just remove the old event listener.
270 if (e
.type
!== this.activateEvent
) {
274 var items
= this.items
;
275 while (t
&& t
!= this) {
276 var i
= items
.indexOf(t
);
278 var value
= this._indexToValue(i
);
279 this._itemActivate(value
, t
);
286 _itemActivate: function(value
, item
) {
287 if (!this.fire('iron-activate',
288 {selected
: value
, item
: item
}, {cancelable
: true}).defaultPrevented
) {