1 /** @polymerBehavior */
2 Polymer.IronSelectableBehavior = {
7 * If you want to use the attribute value of an element for `selected` instead of the index,
8 * set this to the name of the attribute.
10 * @attribute attrForSelected
19 * Gets or sets the selected element. The default is to use the index of the item.
30 * Returns the currently selected item.
32 * @attribute selectedItem
42 * The event that fires from items when they are selected. Selectable
43 * will listen for this event from items and update the selection state.
44 * Set to empty string to listen to no events.
46 * @attribute activateEvent
53 observer: '_activateEventChanged'
57 * This is a CSS selector sting. If this is set, only items that matches the CSS selector
60 * @attribute selectable
66 * The class to set on elements when selected.
68 * @attribute selectedClass
73 value: 'iron-selected'
77 * The attribute to set on elements when selected.
79 * @attribute selectedAttribute
90 '_updateSelected(attrForSelected, selected)'
98 this._bindFilterItem = this._filterItem.bind(this);
99 this._selection = new Polymer.IronSelection(this._applySelection.bind(this));
102 attached: function() {
103 this._observer = this._observeItems(this);
104 this._contentObserver = this._observeContent(this);
107 detached: function() {
108 if (this._observer) {
109 this._observer.disconnect();
111 if (this._contentObserver) {
112 this._contentObserver.disconnect();
114 this._removeListener(this.activateEvent);
118 * Returns an array of selectable items.
124 var nodes = Polymer.dom(this).queryDistributedElements(this.selectable || '*');
125 return Array.prototype.filter.call(nodes, this._bindFilterItem);
129 * Returns the index of the given item.
132 * @param {Object} item
133 * @returns Returns the index of the item
135 indexOf: function(item) {
136 return this.items.indexOf(item);
140 * Selects the given value.
143 * @param {string} value the value to select.
145 select: function(value) {
146 this.selected = value;
150 * Selects the previous item.
152 * @method selectPrevious
154 selectPrevious: function() {
155 var length = this.items.length;
156 var index = (Number(this._valueToIndex(this.selected)) - 1 + length) % length;
157 this.selected = this._indexToValue(index);
161 * Selects the next item.
165 selectNext: function() {
166 var index = (Number(this._valueToIndex(this.selected)) + 1) % this.items.length;
167 this.selected = this._indexToValue(index);
170 _addListener: function(eventName) {
171 this.listen(this, eventName, '_activateHandler');
174 _removeListener: function(eventName) {
175 // There is no unlisten yet...
176 // https://github.com/Polymer/polymer/issues/1639
177 //this.removeEventListener(eventName, this._bindActivateHandler);
180 _activateEventChanged: function(eventName, old) {
181 this._removeListener(old);
182 this._addListener(eventName);
185 _updateSelected: function() {
186 this._selectSelected(this.selected);
189 _selectSelected: function(selected) {
190 this._selection.select(this._valueToItem(this.selected));
193 _filterItem: function(node) {
194 return !this.excludedLocalNames[node.localName];
197 _valueToItem: function(value) {
198 return (value == null) ? null : this.items[this._valueToIndex(value)];
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) {
209 return Number(value);
213 _indexToValue: function(index) {
214 if (this.attrForSelected) {
215 var item = this.items[index];
217 return this._valueForItem(item);
224 _valueForItem: function(item) {
225 return item[this.attrForSelected] || item.getAttribute(this.attrForSelected);
228 _applySelection: function(item, isSelected) {
229 if (this.selectedClass) {
230 this.toggleClass(this.selectedClass, isSelected, item);
232 if (this.selectedAttribute) {
233 this.toggleAttribute(this.selectedAttribute, isSelected, item);
235 this._selectionChange();
236 this.fire('iron-' + (isSelected ? 'select' : 'deselect'), {item: item});
239 _selectionChange: function() {
240 this._setSelectedItem(this._selection.get());
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.domHost);
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();
258 observer.observe(node, {
265 _activateHandler: function(e) {
266 // TODO: remove this when https://github.com/Polymer/polymer/issues/1639 is fixed so we
267 // can just remove the old event listener.
268 if (e.type !== this.activateEvent) {
272 var items = this.items;
273 while (t && t != this) {
274 var i = items.indexOf(t);
276 var value = this._indexToValue(i);
277 this._itemActivate(value, t);
284 _itemActivate: function(value, item) {
285 if (!this.fire('iron-activate',
286 {selected: value, item: item}, {cancelable: true}).defaultPrevented) {