/**
@license
Copyright (c) 2015 The Polymer Project Authors. All rights reserved.
This code may only be used under the BSD style license found at
http://polymer.github.io/LICENSE.txt The complete set of authors may be found at
http://polymer.github.io/AUTHORS.txt The complete set of contributors may be
found at http://polymer.github.io/CONTRIBUTORS.txt Code distributed by Google as
part of the polymer project is also subject to an additional IP rights grant
found at http://polymer.github.io/PATENTS.txt
*/
import '../polymer/polymer_bundled.min.js';
import {IronSelectableBehavior} from './iron-selectable.js';
/**
* @polymerBehavior IronMultiSelectableBehavior
*/
export const IronMultiSelectableBehaviorImpl = {
properties: {
/**
* If true, multiple selections are allowed.
*/
multi: {type: Boolean, value: false, observer: 'multiChanged'},
/**
* Gets or sets the selected elements. This is used instead of `selected`
* when `multi` is true.
*/
selectedValues: {
type: Array,
notify: true,
value: function() {
return [];
}
},
/**
* Returns an array of currently selected items.
*/
selectedItems: {
type: Array,
readOnly: true,
notify: true,
value: function() {
return [];
}
},
},
observers: ['_updateSelected(selectedValues.splices)'],
/**
* Selects the given value. If the `multi` property is true, then the selected
* state of the `value` will be toggled; otherwise the `value` will be
* selected.
*
* @method select
* @param {string|number} value the value to select.
*/
select: function(value) {
if (this.multi) {
this._toggleSelected(value);
} else {
this.selected = value;
}
},
multiChanged: function(multi) {
this._selection.multi = multi;
this._updateSelected();
},
// UNUSED, FOR API COMPATIBILITY
get _shouldUpdateSelection() {
return this.selected != null ||
(this.selectedValues != null && this.selectedValues.length);
},
_updateAttrForSelected: function() {
if (!this.multi) {
IronSelectableBehavior._updateAttrForSelected.apply(this);
} else if (this.selectedItems && this.selectedItems.length > 0) {
this.selectedValues =
this.selectedItems
.map(
function(selectedItem) {
return this._indexToValue(this.indexOf(selectedItem));
},
this)
.filter(function(unfilteredValue) {
return unfilteredValue != null;
}, this);
}
},
_updateSelected: function() {
if (this.multi) {
this._selectMulti(this.selectedValues);
} else {
this._selectSelected(this.selected);
}
},
_selectMulti: function(values) {
values = values || [];
var selectedItems =
(this._valuesToItems(values) || []).filter(function(item) {
return item !== null && item !== undefined;
});
// clear all but the current selected items
this._selection.clear(selectedItems);
// select only those not selected yet
for (var i = 0; i < selectedItems.length; i++) {
this._selection.setItemSelected(selectedItems[i], true);
}
// Check for items, since this array is populated only when attached
if (this.fallbackSelection && !this._selection.get().length) {
var fallback = this._valueToItem(this.fallbackSelection);
if (fallback) {
this.select(this.fallbackSelection);
}
}
},
_selectionChange: function() {
var s = this._selection.get();
if (this.multi) {
this._setSelectedItems(s);
this._setSelectedItem(s.length ? s[0] : null);
} else {
if (s !== null && s !== undefined) {
this._setSelectedItems([s]);
this._setSelectedItem(s);
} else {
this._setSelectedItems([]);
this._setSelectedItem(null);
}
}
},
_toggleSelected: function(value) {
var i = this.selectedValues.indexOf(value);
var unselected = i < 0;
if (unselected) {
this.push('selectedValues', value);
} else {
this.splice('selectedValues', i, 1);
}
},
_valuesToItems: function(values) {
return (values == null) ? null : values.map(function(value) {
return this._valueToItem(value);
}, this);
}
};
/** @polymerBehavior */
export const IronMultiSelectableBehavior =
[IronSelectableBehavior, IronMultiSelectableBehaviorImpl];