Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(194)

Unified Diff: resources/bookmark_manager/js/cr/ui/listselectionmodel.js

Issue 853002: Updating the Chromium reference build for Windows. The continuous... (Closed) Base URL: svn://chrome-svn/chrome/trunk/deps/reference_builds/chrome/
Patch Set: Added the symbol files back. Created 10 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « resources/bookmark_manager/js/cr/ui/listitem.js ('k') | resources/bookmark_manager/js/cr/ui/menu.js » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: resources/bookmark_manager/js/cr/ui/listselectionmodel.js
===================================================================
--- resources/bookmark_manager/js/cr/ui/listselectionmodel.js (revision 0)
+++ resources/bookmark_manager/js/cr/ui/listselectionmodel.js (revision 0)
@@ -0,0 +1,442 @@
+// 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.
+
+cr.define('cr.ui', function() {
+ const Event = cr.Event;
+ const EventTarget = cr.EventTarget;
+
+ /**
+ * Creates a new selection model that is to be used with lists. This is
+ * implemented for vertical lists but changing the behavior for horizontal
+ * lists or icon views is a matter of overriding {@code getItemBefore},
+ * {@code getItemAfter}, {@code getItemAbove} as well as {@code getItemBelow}.
+ *
+ * @constructor
+ * @extends {!cr.EventTarget}
+ */
+ function ListSelectionModel(list) {
+ this.list = list;
+ this.selectedItems_ = {};
+ }
+
+ ListSelectionModel.prototype = {
+ __proto__: EventTarget.prototype,
+
+ /**
+ * Returns the item below (y axis) the given element.
+ * @param {*} item The item to get the item below.
+ * @return {*} The item below or null if not found.
+ */
+ getItemBelow: function(item) {
+ return item.nextElementSibling;
+ },
+
+ /**
+ * Returns the item above (y axis) the given element.
+ * @param {*} item The item to get the item above.
+ * @return {*} The item below or null if not found.
+ */
+ getItemAbove: function(item) {
+ return item.previousElementSibling;
+ },
+
+ /**
+ * Returns the item before (x axis) the given element. This returns null
+ * by default but override this for icon view and horizontal selection
+ * models.
+ *
+ * @param {*} item The item to get the item before.
+ * @return {*} The item before or null if not found.
+ */
+ getItemBefore: function(item) {
+ return null;
+ },
+
+ /**
+ * Returns the item after (x axis) the given element. This returns null
+ * by default but override this for icon view and horizontal selection
+ * models.
+ *
+ * @param {*} item The item to get the item after.
+ * @return {*} The item after or null if not found.
+ */
+ getItemAfter: function(item) {
+ return null;
+ },
+
+ /**
+ * Returns the next list item. This is the next logical and should not
+ * depend on any kind of layout of the list.
+ * @param {*} item The item to get the next item for.
+ * @return {*} The next item or null if not found.
+ */
+ getNextItem: function(item) {
+ return item.nextElementSibling;
+ },
+
+ /**
+ * Returns the prevous list item. This is the previous logical and should
+ * not depend on any kind of layout of the list.
+ * @param {*} item The item to get the previous item for.
+ * @return {*} The previous item or null if not found.
+ */
+ getPreviousItem: function(item) {
+ return item.previousElementSibling;
+ },
+
+ /**
+ * @return {*} The first item.
+ */
+ getFirstItem: function() {
+ return this.list.firstElementChild;
+ },
+
+ /**
+ * @return {*} The last item.
+ */
+ getLastItem: function() {
+ return this.list.lastElementChild;
+ },
+
+ /**
+ * Called by the view when the user does a mousedown or mouseup on the list.
+ * @param {!Event} e The browser mousedown event.
+ * @param {*} item The item that was under the mouse pointer, null if none.
+ */
+ handleMouseDownUp: function(e, item) {
+ var anchorItem = this.anchorItem;
+
+ this.beginChange_();
+
+ if (!item && !e.ctrlKey && !e.shiftKey && !e.metaKey) {
+ this.clear();
+ } else {
+ var isDown = e.type == 'mousedown';
+ if (!cr.isMac && e.ctrlKey) {
+ // Handle ctrlKey on mouseup
+ if (!isDown) {
+ // toggle the current one and make it anchor item
+ this.setItemSelected(item, !this.getItemSelected(item));
+ this.leadItem = item;
+ this.anchorItem = item;
+ }
+ } else if (e.shiftKey && anchorItem && anchorItem != item) {
+ // Shift is done in mousedown
+ if (isDown) {
+ this.clearAllSelected_();
+ this.leadItem = item;
+ this.selectRange(anchorItem, item);
+ }
+ } else {
+ // Right click for a context menu need to not clear the selection.
+ var isRightClick = e.button == 2;
+
+ // If the item is selected this is handled in mouseup.
+ var itemSelected = this.getItemSelected(item);
+ if ((itemSelected && !isDown || !itemSelected && isDown) &&
+ !(itemSelected && isRightClick)) {
+ this.clearAllSelected_();
+ this.setItemSelected(item, true);
+ this.leadItem = item;
+ this.anchorItem = item;
+ }
+ }
+ }
+
+ this.endChange_();
+ },
+
+ /**
+ * Called by the view when it recieves a keydown event.
+ * @param {Event} e The keydown event.
+ */
+ handleKeyDown: function(e) {
+ var newItem = null;
+ var leadItem = this.leadItem;
+ var prevent = true;
+
+ // Ctrl/Meta+A
+ if (e.keyCode == 65 &&
+ (cr.isMac && e.metaKey || !cr.isMac && e.ctrlKey)) {
+ this.selectAll();
+ e.preventDefault();
+ return;
+ }
+
+ // Space
+ if (e.keyCode == 32) {
+ if (leadItem != null) {
+ var selected = this.getItemSelected(leadItem);
+ if (e.ctrlKey || !selected) {
+ this.beginChange_();
+ this.setItemSelected(leadItem, !selected);
+ this.endChange_();
+ return;
+ }
+ }
+ }
+
+ switch (e.keyIdentifier) {
+ case 'Home':
+ newItem = this.getFirstItem();
+ break;
+ case 'End':
+ newItem = this.getLastItem();
+ break;
+ case 'Up':
+ newItem = !leadItem ?
+ this.getLastItem() : this.getItemAbove(leadItem);
+ break;
+ case 'Down':
+ newItem = !leadItem ?
+ this.getFirstItem() : this.getItemBelow(leadItem);
+ break;
+ case 'Left':
+ newItem = !leadItem ?
+ this.getLastItem() : this.getItemBefore(leadItem);
+ break;
+ case 'Right':
+ newItem = !leadItem ?
+ this.getFirstItem() : this.getItemAfter(leadItem);
+ break;
+ default:
+ prevent = false;
+ }
+
+ if (newItem) {
+ this.beginChange_();
+
+ this.leadItem = newItem;
+ if (e.shiftKey) {
+ var anchorItem = this.anchorItem;
+ this.clearAllSelected_();
+ if (!anchorItem) {
+ this.setItemSelected(newItem, true);
+ this.anchorItem = newItem;
+ } else {
+ this.selectRange(anchorItem, newItem);
+ }
+ } else if (e.ctrlKey && !cr.isMac) {
+ // Setting the lead item is done above
+ // Mac does not allow you to change the lead.
+ } else {
+ this.clearAllSelected_();
+ this.setItemSelected(newItem, true);
+ this.anchorItem = newItem;
+ }
+
+ this.endChange_();
+
+ if (prevent)
+ e.preventDefault();
+ }
+ },
+
+ /**
+ * @type {!Array} The selected items.
+ */
+ get selectedItems() {
+ return Object.keys(this.selectedItems_).map(function(uid) {
+ return this.selectedItems_[uid];
+ }, this);
+ },
+ set selectedItems(selectedItems) {
+ this.beginChange_();
+ this.clearAllSelected_();
+ for (var i = 0; i < selectedItems.length; i++) {
+ this.setItemSelected(selectedItems[i], true);
+ }
+ this.leadItem = this.anchorItem = selectedItems[0] || null;
+ this.endChange_();
+ },
+
+ /**
+ * Convenience getter which returns the first selected item.
+ * @type {*}
+ */
+ get selectedItem() {
+ for (var uid in this.selectedItems_) {
+ return this.selectedItems_[uid];
+ }
+ return null;
+ },
+ set selectedItem(selectedItem) {
+ this.beginChange_();
+ this.clearAllSelected_();
+ if (selectedItem) {
+ this.selectedItems = [selectedItem];
+ } else {
+ this.leadItem = this.anchorItem = null;
+ }
+ this.endChange_();
+ },
+
+ /**
+ * Selects a range of items, starting with {@code start} and ends with
+ * {@code end}.
+ * @param {*} start The first item to select.
+ * @param {*} end The last item to select.
+ */
+ selectRange: function(start, end) {
+ // Swap if starts comes after end.
+ if (start.compareDocumentPosition(end) & Node.DOCUMENT_POSITION_PRECEDING) {
+ var tmp = start;
+ start = end;
+ end = tmp;
+ }
+
+ this.beginChange_();
+
+ for (var item = start; item != end; item = this.getNextItem(item)) {
+ this.setItemSelected(item, true);
+ }
+ this.setItemSelected(end, true);
+
+ this.endChange_();
+ },
+
+ /**
+ * Selects all items.
+ */
+ selectAll: function() {
+ this.selectRange(this.getFirstItem(), this.getLastItem());
+ },
+
+ /**
+ * Clears the selection
+ */
+ clear: function() {
+ this.beginChange_();
+ this.clearAllSelected_();
+ this.endChange_();
+ },
+
+ /**
+ * Clears the selection and updates the view.
+ * @private
+ */
+ clearAllSelected_: function() {
+ for (var uid in this.selectedItems_) {
+ this.setItemSelected(this.selectedItems_[uid], false);
+ }
+ },
+
+ /**
+ * Sets the selecte state for an item.
+ * @param {*} item The item to set the selected state for.
+ * @param {boolean} b Whether to select the item or not.
+ */
+ setItemSelected: function(item, b) {
+ var uid = this.list.itemToUid(item);
+ var oldSelected = uid in this.selectedItems_;
+ if (oldSelected == b)
+ return;
+
+ if (b)
+ this.selectedItems_[uid] = item;
+ else
+ delete this.selectedItems_[uid];
+
+ this.beginChange_();
+
+ // Changing back?
+ if (uid in this.changedUids_ && this.changedUids_[uid] == !b) {
+ delete this.changedUids_[uid];
+ } else {
+ this.changedUids_[uid] = b;
+ }
+
+ // End change dispatches an event which in turn may update the view.
+ this.endChange_();
+ },
+
+ /**
+ * Whether a given item is selected or not.
+ * @param {*} item The item to check.
+ * @return {boolean} Whether an item is selected.
+ */
+ getItemSelected: function(item) {
+ var uid = this.list.itemToUid(item);
+ return uid in this.selectedItems_;
+ },
+
+ /**
+ * This is used to begin batching changes. Call {@code endChange_} when you
+ * are done making changes.
+ * @private
+ */
+ beginChange_: function() {
+ if (!this.changeCount_) {
+ this.changeCount_ = 0;
+ this.changedUids_ = {};
+ }
+ this.changeCount_++;
+ },
+
+ /**
+ * Call this after changes are done and it will dispatch a change event if
+ * any changes were actually done.
+ * @private
+ */
+ endChange_: function() {
+ this.changeCount_--;
+ if (!this.changeCount_) {
+ var uids = Object.keys(this.changedUids_);
+ if (uids.length) {
+ var e = new Event('change');
+ e.changes = uids.map(function(uid) {
+ return {
+ uid: uid,
+ selected: this.changedUids_[uid]
+ };
+ }, this);
+ this.dispatchEvent(e);
+ }
+ delete this.changedUids_;
+ delete this.changeCount_;
+ }
+ },
+
+ /**
+ * Called when an item is removed from the lisst.
+ * @param {cr.ui.ListItem} item The list item that was removed.
+ */
+ remove: function(item) {
+ if (item == this.leadItem)
+ this.leadItem = this.getNextItem(item) || this.getPreviousItem(item);
+ if (item == this.anchorItem)
+ this.anchorItem = this.getNextItem(item) || this.getPreviousItem(item);
+
+ // Deselect when removing items.
+ if (this.getItemSelected(item))
+ this.setItemSelected(item, false);
+ },
+
+ /**
+ * Called when an item was added to the list.
+ * @param {cr.ui.ListItem} item The list item to add.
+ */
+ add: function(item) {
+ // We could (should?) check if the item is selected here and update the
+ // selection model.
+ }
+ };
+
+ /**
+ * The anchorItem is used with multiple selection.
+ * @type {*}
+ */
+ cr.defineProperty(ListSelectionModel, 'anchorItem', cr.PropertyKind.JS, null);
+
+ /**
+ * The leadItem is used with multiple selection and it is the item that the
+ * user is moving uysing the arrow keys.
+ * @type {*}
+ */
+ cr.defineProperty(ListSelectionModel, 'leadItem', cr.PropertyKind.JS, null);
+
+ return {
+ ListSelectionModel: ListSelectionModel
+ };
+});
« no previous file with comments | « resources/bookmark_manager/js/cr/ui/listitem.js ('k') | resources/bookmark_manager/js/cr/ui/menu.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698