text: /** @polymerBehavior */
    Polymer.IronSelectableBehavior = {
  
        /**
         * Fired when iron-selector is activated (selected or deselected).
         * It is fired before the selected items are changed.
         * Cancel the event to abort selection.
         *
         * @event iron-activate
         */
  
        /**
         * Fired when an item is selected
         *
         * @event iron-select
         */
  
        /**
         * Fired when an item is deselected
         *
         * @event iron-deselect
         */
  
        /**
         * Fired when the list of selectable items changes (e.g., items are
         * added or removed). The detail of the event is a list of mutation
         * records that describe what changed.
         *
         * @event iron-items-changed
         */
  
      properties: {
  
        /**
         * If you want to use the attribute value of an element for `selected` instead of the index,
         * set this to the name of the attribute.
         */
        attrForSelected: {
          type: String,
          value: null
        },
  
        /**
         * Gets or sets the selected element. The default is to use the index of the item.
         */
        selected: {
          type: String,
          notify: true
        },
  
        /**
         * Returns the currently selected item.
         *
         * @type {?Object}
         */
        selectedItem: {
          type: Object,
          readOnly: true,
          notify: true
        },
  
        /**
         * The event that fires from items when they are selected. Selectable
         * will listen for this event from items and update the selection state.
         * Set to empty string to listen to no events.
         */
        activateEvent: {
          type: String,
          value: 'tap',
          observer: '_activateEventChanged'
        },
  
        /**
         * This is a CSS selector string.  If this is set, only items that match the CSS selector
         * are selectable.
         */
        selectable: String,
  
        /**
         * The class to set on elements when selected.
         */
        selectedClass: {
          type: String,
          value: 'iron-selected'
        },
  
        /**
         * The attribute to set on elements when selected.
         */
        selectedAttribute: {
          type: String,
          value: null
        },
  
        /**
         * The list of items from which a selection can be made.
         */
        items: {
          type: Array,
          readOnly: true,
          value: function() {
            return [];
          }
        },
  
        /**
         * The set of excluded elements where the key is the `localName`
         * of the element that will be ignored from the item list.
         *
         * @default {template: 1}
         */
        _excludedLocalNames: {
          type: Object,
          value: function() {
            return {
              'template': 1
            };
          }
        }
      },
  
      observers: [
        '_updateSelected(attrForSelected, selected)'
      ],
  
      created: function() {
        this._bindFilterItem = this._filterItem.bind(this);
        this._selection = new Polymer.IronSelection(this._applySelection.bind(this));
      },
  
      attached: function() {
        this._observer = this._observeItems(this);
        this._updateItems();
        if (!this._shouldUpdateSelection) {
          this._updateSelected(this.attrForSelected,this.selected)
        }
        this._addListener(this.activateEvent);
      },
  
      detached: function() {
        if (this._observer) {
          Polymer.dom(this).unobserveNodes(this._observer);
        }
        this._removeListener(this.activateEvent);
      },
  
      /**
       * Returns the index of the given item.
       *
       * @method indexOf
       * @param {Object} item
       * @returns Returns the index of the item
       */
      indexOf: function(item) {
        return this.items.indexOf(item);
      },
  
      /**
       * Selects the given value.
       *
       * @method select
       * @param {string} value the value to select.
       */
      select: function(value) {
        this.selected = value;
      },
  
      /**
       * Selects the previous item.
       *
       * @method selectPrevious
       */
      selectPrevious: function() {
        var length = this.items.length;
        var index = (Number(this._valueToIndex(this.selected)) - 1 + length) % length;
        this.selected = this._indexToValue(index);
      },
  
      /**
       * Selects the next item.
       *
       * @method selectNext
       */
      selectNext: function() {
        var index = (Number(this._valueToIndex(this.selected)) + 1) % this.items.length;
        this.selected = this._indexToValue(index);
      },
  
      get _shouldUpdateSelection() {
        return this.selected != null;
      },
  
      _addListener: function(eventName) {
        this.listen(this, eventName, '_activateHandler');
      },
  
      _removeListener: function(eventName) {
        this.unlisten(this, eventName, '_activateHandler');
      },
  
      _activateEventChanged: function(eventName, old) {
        this._removeListener(old);
        this._addListener(eventName);
      },
  
      _updateItems: function() {
        var nodes = Polymer.dom(this).queryDistributedElements(this.selectable || '*');
        nodes = Array.prototype.filter.call(nodes, this._bindFilterItem);
        this._setItems(nodes);
      },
  
      _updateSelected: function() {
        this._selectSelected(this.selected);
      },
  
      _selectSelected: function(selected) {
        this._selection.select(this._valueToItem(this.selected));
      },
  
      _filterItem: function(node) {
        return !this._excludedLocalNames[node.localName];
      },
  
      _valueToItem: function(value) {
        return (value == null) ? null : this.items[this._valueToIndex(value)];
      },
  
      _valueToIndex: function(value) {
        if (this.attrForSelected) {
          for (var i = 0, item; item = this.items[i]; i++) {
            if (this._valueForItem(item) == value) {
              return i;
            }
          }
        } else {
          return Number(value);
        }
      },
  
      _indexToValue: function(index) {
        if (this.attrForSelected) {
          var item = this.items[index];
          if (item) {
            return this._valueForItem(item);
          }
        } else {
          return index;
        }
      },
  
      _valueForItem: function(item) {
        return item[this.attrForSelected] || item.getAttribute(this.attrForSelected);
      },
  
      _applySelection: function(item, isSelected) {
        if (this.selectedClass) {
          this.toggleClass(this.selectedClass, isSelected, item);
        }
        if (this.selectedAttribute) {
          this.toggleAttribute(this.selectedAttribute, isSelected, item);
        }
        this._selectionChange();
        this.fire('iron-' + (isSelected ? 'select' : 'deselect'), {item: item});
      },
  
      _selectionChange: function() {
        this._setSelectedItem(this._selection.get());
      },
  
      // observe items change under the given node.
      _observeItems: function(node) {
        return Polymer.dom(node).observeNodes(function(mutations) {
          // Let other interested parties know about the change so that
          // we don't have to recreate mutation observers everywher.
          this.fire('iron-items-changed', mutations, {
            bubbles: false,
            cancelable: false
          });
  
          this._updateItems();
  
          if (this._shouldUpdateSelection) {
            this._updateSelected();
          }
        });
      },
  
      _activateHandler: function(e) {
        var t = e.target;
        var items = this.items;
        while (t && t != this) {
          var i = items.indexOf(t);
          if (i >= 0) {
            var value = this._indexToValue(i);
            this._itemActivate(value, t);
            return;
          }
          t = t.parentNode;
        }
      },
  
      _itemActivate: function(value, item) {
        if (!this.fire('iron-activate',
            {selected: value, item: item}, {cancelable: true}).defaultPrevented) {
          this.select(value);
        }
      }
  
    };