| Index: resources/bookmark_manager/js/cr/ui/list.js
 | 
| ===================================================================
 | 
| --- resources/bookmark_manager/js/cr/ui/list.js	(revision 0)
 | 
| +++ resources/bookmark_manager/js/cr/ui/list.js	(revision 0)
 | 
| @@ -0,0 +1,235 @@
 | 
| +// Copyright (c) 2010 The Chromium Authors. All rights reserved.
 | 
| +// Use of this source code is governed by a BSD-style license that can be
 | 
| +// found in the LICENSE file.
 | 
| +
 | 
| +// require: listselectionmodel.js
 | 
| +
 | 
| +/**
 | 
| + * @fileoverview This implements a list control.
 | 
| + */
 | 
| +
 | 
| +cr.define('cr.ui', function() {
 | 
| +  const ListSelectionModel = cr.ui.ListSelectionModel;
 | 
| +
 | 
| +  /**
 | 
| +   * Creates a new list element.
 | 
| +   * @param {Object=} opt_propertyBag Optional properties.
 | 
| +   * @constructor
 | 
| +   * @extends {HTMLUListElement}
 | 
| +   */
 | 
| +  var List = cr.ui.define('list');
 | 
| +
 | 
| +  List.prototype = {
 | 
| +    __proto__: HTMLUListElement.prototype,
 | 
| +
 | 
| +    /**
 | 
| +     * The selection model to use.
 | 
| +     * @type {cr.ui.ListSelectionModel}
 | 
| +     */
 | 
| +    get selectionModel() {
 | 
| +      return this.selectionModel_;
 | 
| +    },
 | 
| +    set selectionModel(sm) {
 | 
| +      var oldSm = this.selectionModel_;
 | 
| +      if (oldSm == sm)
 | 
| +        return;
 | 
| +
 | 
| +      if (!this.boundHandleOnChange_) {
 | 
| +        this.boundHandleOnChange_ = cr.bind(this.handleOnChange_, this);
 | 
| +        this.boundHandleLeadChange_ = cr.bind(this.handleLeadChange_, this);
 | 
| +      }
 | 
| +
 | 
| +      if (oldSm) {
 | 
| +        oldSm.removeEventListener('change', this.boundHandleOnChange_);
 | 
| +        oldSm.removeEventListener('leadItemChange', this.boundHandleLeadChange_);
 | 
| +      }
 | 
| +
 | 
| +      this.selectionModel_ = sm;
 | 
| +
 | 
| +      if (sm) {
 | 
| +        sm.addEventListener('change', this.boundHandleOnChange_);
 | 
| +        sm.addEventListener('leadItemChange', this.boundHandleLeadChange_);
 | 
| +      }
 | 
| +    },
 | 
| +
 | 
| +    /**
 | 
| +     * Convenience alias for selectionModel.selectedItem
 | 
| +     * @type {cr.ui.ListItem}
 | 
| +     */
 | 
| +    get selectedItem() {
 | 
| +      return this.selectionModel.selectedItem;
 | 
| +    },
 | 
| +    set selectedItem(selectedItem) {
 | 
| +      this.selectionModel.selectedItem = selectedItem;
 | 
| +    },
 | 
| +
 | 
| +    /**
 | 
| +     * Convenience alias for selectionModel.selectedItems
 | 
| +     * @type {!Array<cr.ui.ListItem>}
 | 
| +     */
 | 
| +    get selectedItems() {
 | 
| +      return this.selectionModel.selectedItems;
 | 
| +    },
 | 
| +
 | 
| +    /**
 | 
| +     * The HTML elements representing the items. This is just all the element
 | 
| +     * children but subclasses may override this to filter out certain elements.
 | 
| +     * @type {HTMLCollection}
 | 
| +     */
 | 
| +    get items() {
 | 
| +      return this.children;
 | 
| +    },
 | 
| +
 | 
| +    add: function(listItem) {
 | 
| +      this.appendChild(listItem);
 | 
| +
 | 
| +      var uid = cr.getUid(listItem);
 | 
| +      this.uidToListItem_[uid] = listItem;
 | 
| +
 | 
| +      this.selectionModel.add(listItem);
 | 
| +    },
 | 
| +
 | 
| +    addAt: function(listItem, index) {
 | 
| +      this.insertBefore(listItem, this.items[index]);
 | 
| +
 | 
| +      var uid = cr.getUid(listItem);
 | 
| +      this.uidToListItem_[uid] = listItem;
 | 
| +
 | 
| +      this.selectionModel.add(listItem);
 | 
| +    },
 | 
| +
 | 
| +    remove: function(listItem) {
 | 
| +      this.selectionModel.remove(listItem);
 | 
| +
 | 
| +      this.removeChild(listItem);
 | 
| +
 | 
| +      var uid = cr.getUid(listItem);
 | 
| +      delete this.uidToListItem_[uid];
 | 
| +    },
 | 
| +
 | 
| +    clear: function() {
 | 
| +      this.innerHTML = '';
 | 
| +      this.selectionModel.clear();
 | 
| +    },
 | 
| +
 | 
| +    /**
 | 
| +     * Initializes the element.
 | 
| +     */
 | 
| +    decorate: function() {
 | 
| +      this.uidToListItem_ = {};
 | 
| +
 | 
| +      this.selectionModel = new ListSelectionModel(this);
 | 
| +
 | 
| +      this.addEventListener('mousedown', this.handleMouseDownUp_);
 | 
| +      this.addEventListener('mouseup', this.handleMouseDownUp_);
 | 
| +      this.addEventListener('keydown', this.handleKeyDown);
 | 
| +      this.addEventListener('dblclick', this.handleDoubleClick_);
 | 
| +
 | 
| +      // Make list focusable
 | 
| +      if (!this.hasAttribute('tabindex'))
 | 
| +        this.tabIndex = 0;
 | 
| +    },
 | 
| +
 | 
| +    /**
 | 
| +     * Callback for mousedown and mouseup events.
 | 
| +     * @param {Event} e The mouse event object.
 | 
| +     * @private
 | 
| +     */
 | 
| +    handleMouseDownUp_: function(e) {
 | 
| +      var target = e.target;
 | 
| +      while (target && target.parentNode != this) {
 | 
| +        target = target.parentNode;
 | 
| +      }
 | 
| +      this.selectionModel.handleMouseDownUp(e, target);
 | 
| +    },
 | 
| +
 | 
| +    /**
 | 
| +     * Callback for mousedown events.
 | 
| +     * @param {Event} e The mouse event object.
 | 
| +     * @private
 | 
| +     */
 | 
| +    handleMouseUp_: function(e) {
 | 
| +      var target = e.target;
 | 
| +      while (target && target.parentNode != this) {
 | 
| +        target = target.parentNode;
 | 
| +      }
 | 
| +      if (target) {
 | 
| +        this.selectionModel.handleMouseDown(e, target);
 | 
| +      } else {
 | 
| +        this.selectionModel.clear();
 | 
| +      }
 | 
| +    },
 | 
| +
 | 
| +
 | 
| +    /**
 | 
| +     * Handle a keydown event.
 | 
| +     * @param {Event} e The keydown event.
 | 
| +     * @return {boolean} Whether the key event was handled.
 | 
| +     */
 | 
| +    handleKeyDown: function(e) {
 | 
| +      if (this.selectionModel.handleKeyDown(e))
 | 
| +        return true;
 | 
| +      if (e.keyIdentifier == 'Enter' && this.selectionModel.selectedItem) {
 | 
| +        cr.dispatchSimpleEvent(this, 'activate');
 | 
| +        return true;
 | 
| +      }
 | 
| +      return false;
 | 
| +    },
 | 
| +
 | 
| +    /**
 | 
| +     * Handler for double clicking. When the user double clicks on a selected
 | 
| +     * item we dispatch an {@code activate} event.
 | 
| +     * @param {Event} e The mouse event object.
 | 
| +     * @private
 | 
| +     */
 | 
| +    handleDoubleClick_: function(e) {
 | 
| +      if (e.button == 0 && this.selectionModel.selectedItem) {
 | 
| +        cr.dispatchSimpleEvent(this, 'activate');
 | 
| +      }
 | 
| +    },
 | 
| +
 | 
| +    /**
 | 
| +     * Callback from the selection model. We dispatch {@code change} events
 | 
| +     * when the selection changes.
 | 
| +     * @param {!cr.Event} e Event with change info.
 | 
| +     * @private
 | 
| +     */
 | 
| +    handleOnChange_: function(ce) {
 | 
| +      ce.changes.forEach(function(change) {
 | 
| +        var listItem = this.uidToListItem_[change.uid];
 | 
| +        listItem.selected = change.selected;
 | 
| +      }, this);
 | 
| +
 | 
| +      cr.dispatchSimpleEvent(this, 'change');
 | 
| +    },
 | 
| +
 | 
| +    /**
 | 
| +     * Handles a change of the lead item from the selection model.
 | 
| +     * @property {Event} pe The property change event.
 | 
| +     * @private
 | 
| +     */
 | 
| +    handleLeadChange_: function(pe) {
 | 
| +      if (pe.oldValue) {
 | 
| +        pe.oldValue.lead = false;
 | 
| +      }
 | 
| +      if (pe.newValue) {
 | 
| +        pe.newValue.lead = true;
 | 
| +      }
 | 
| +    },
 | 
| +
 | 
| +    /**
 | 
| +     * Gets a unique ID for an item. This needs to be unique to the list but
 | 
| +     * does not have to be gloabally unique. This uses {@code cr.getUid} by
 | 
| +     * default. Override to provide a more efficient way to get the unique ID.
 | 
| +     * @param {cr.ui.ListItem} item The item to get the unique ID for.
 | 
| +     * @return
 | 
| +     */
 | 
| +    itemToUid: function(item) {
 | 
| +      return cr.getUid(item);
 | 
| +    }
 | 
| +  };
 | 
| +
 | 
| +  return {
 | 
| +    List: List
 | 
| +  }
 | 
| +});
 | 
| 
 |