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

Unified Diff: resources/bookmark_manager/js/bmm/bookmarklist.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/bmm.js ('k') | resources/bookmark_manager/js/bmm/bookmarktree.js » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: resources/bookmark_manager/js/bmm/bookmarklist.js
===================================================================
--- resources/bookmark_manager/js/bmm/bookmarklist.js (revision 0)
+++ resources/bookmark_manager/js/bmm/bookmarklist.js (revision 0)
@@ -0,0 +1,420 @@
+// 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('bmm', function() {
+ // require cr.ui.define
+ // require cr.ui.limitInputWidth.
+ // require cr.ui.contextMenuHandler
+ const List = cr.ui.List;
+ const ListItem = cr.ui.ListItem;
+
+ var listLookup = {};
+
+ /**
+ * Removes all children and appends a new child.
+ * @param {!Node} parent The node to remove all children from.
+ * @param {!Node} newChild The new child to append.
+ */
+ function replaceAllChildren(parent, newChild) {
+ var n;
+ while ((n = parent.lastChild)) {
+ parent.removeChild(n);
+ }
+ parent.appendChild(newChild);
+ }
+
+ /**
+ * Creates a new bookmark list.
+ * @param {Object=} opt_propertyBag Optional properties.
+ * @constructor
+ * @extends {HTMLButtonElement}
+ */
+ var BookmarkList = cr.ui.define('list');
+
+ BookmarkList.prototype = {
+ __proto__: List.prototype,
+
+ decorate: function() {
+ List.prototype.decorate.call(this);
+ this.addEventListener('click', this.handleClick_);
+ },
+
+ parentId_: '',
+ get parentId() {
+ return this.parentId_;
+ },
+ set parentId(parentId) {
+ if (this.parentId_ == parentId)
+ return;
+
+ var oldParentId = this.parentId_;
+ this.parentId_ = parentId;
+
+ var callback = cr.bind(this.handleBookmarkCallback, this);
+
+ if (!parentId) {
+ callback([]);
+ } else if (/^q=/.test(parentId)) {
+ chrome.bookmarks.search(parentId.slice(2), callback);
+ } else if (parentId == 'recent') {
+ chrome.bookmarks.getRecent(50, callback);
+ } else {
+ chrome.bookmarks.getChildren(parentId, callback);
+ }
+
+ cr.dispatchPropertyChange(this, 'parentId', parentId, oldParentId);
+ },
+
+ handleBookmarkCallback: function(items) {
+ if (!items) {
+ // Failed to load bookmarks. Most likely due to the bookmark beeing
+ // removed.
+ cr.dispatchSimpleEvent(this, 'invalidId');
+ return;
+ }
+ // Remove all fields without recreating the object since other code
+ // references it.
+ for (var id in listLookup){
+ delete listLookup[id];
+ }
+ this.clear();
+ var showFolder = this.showFolder();
+ items.forEach(function(item) {
+ var li = createListItem(item, showFolder);
+ this.add(li);
+ }, this);
+ cr.dispatchSimpleEvent(this, 'load');
+ },
+
+ /**
+ * The bookmark node that the list is currently displaying. If we are currently
+ * displaying recent or search this returns null.
+ * @type {BookmarkTreeNode}
+ */
+ get bookmarkNode() {
+ if (this.isSearch() || this.isRecent())
+ return null;
+ var treeItem = bmm.treeLookup[this.parentId];
+ return treeItem && treeItem.bookmarkNode;
+ },
+
+ showFolder: function() {
+ return this.isSearch() || this.isRecent();
+ },
+
+ isSearch: function() {
+ return this.parentId_[0] == 'q';
+ },
+
+ isRecent: function() {
+ return this.parentId_ == 'recent';
+ },
+
+ /**
+ * Handles the clicks on the list so that we can check if the user clicked
+ * on a link or an folder.
+ * @private
+ * @param {Event} e The click event object.
+ */
+ handleClick_: function(e) {
+
+ var el = e.target;
+ if (el.href) {
+ var event = this.ownerDocument.createEvent('Event');
+ event.initEvent('urlClicked', true, false);
+ event.url = el.href;
+ event.kind = e.shiftKey ? 'window' : e.button == 1 ? 'tab' : 'self';
+ this.dispatchEvent(event);
+ }
+ },
+
+ // Bookmark model update callbacks
+ handleBookmarkChanged: function(id, changeInfo) {
+ var listItem = listLookup[id];
+ if (listItem) {
+ listItem.bookmarkNode.title = changeInfo.title;
+ if ('url' in changeInfo)
+ listItem.bookmarkNode.url = changeInfo['url'];
+ updateListItem(listItem, listItem.bookmarkNode, list.showFolder());
+ }
+ },
+
+ handleChildrenReordered: function(id, reorderInfo) {
+ if (this.parentId == id) {
+ var self = this;
+ reorderInfo.childIds.forEach(function(id, i) {
+ var li = listLookup[id]
+ self.addAt(li, i);
+ // At this point we do not read the index from the bookmark node so we
+ // do not need to update it.
+ li.bookmarkNode.index = i;
+ });
+ }
+ },
+
+ handleCreated: function(id, bookmarkNode) {
+ if (this.parentId == bookmarkNode.parentId) {
+ var li = createListItem(bookmarkNode, false);
+ this.addAt(li, bookmarkNode.index);
+ }
+ },
+
+ handleMoved: function(id, moveInfo) {
+ if (moveInfo.parentId == this.parentId ||
+ moveInfo.oldParentId == this.parentId) {
+
+ if (moveInfo.oldParentId == moveInfo.parentId) {
+ var listItem = listLookup[id];
+ if (listItem) {
+ this.remove(listItem);
+ this.addAt(listItem, moveInfo.index);
+ }
+ } else {
+ if (moveInfo.oldParentId == this.parentId) {
+ var listItem = listLookup[id];
+ if (listItem) {
+ this.remove(listItem);
+ delete listLookup[id];
+ }
+ }
+
+ if (moveInfo.parentId == list.parentId) {
+ var self = this;
+ chrome.bookmarks.get(id, function(bookmarkNodes) {
+ var bookmarkNode = bookmarkNodes[0];
+ var li = createListItem(bookmarkNode, false);
+ self.addAt(li, bookmarkNode.index);
+ });
+ }
+ }
+ }
+ },
+
+ handleRemoved: function(id, removeInfo) {
+ var listItem = listLookup[id];
+ if (listItem) {
+ this.remove(listItem);
+ delete listLookup[id];
+ }
+ }
+ };
+
+ /**
+ * The contextMenu property.
+ * @type {cr.ui.Menu}
+ */
+ cr.ui.contextMenuHandler.addContextMenuProperty(BookmarkList);
+
+ /**
+ * Creates a new bookmark list item.
+ * @param {Object=} opt_propertyBag Optional properties.
+ * @constructor
+ * @extends {cr.ui.ListItem}
+ */
+ var BookmarkListItem = cr.ui.define('li');
+
+ BookmarkListItem.prototype = {
+ __proto__: ListItem.prototype,
+ /**
+ * Whether the user is currently able to edit the list item.
+ * @type {boolean}
+ */
+ get editing() {
+ return this.hasAttribute('editing');
+ },
+ set editing(editing) {
+ var oldEditing = this.editing;
+ if (oldEditing == editing)
+ return;
+
+ var url = this.bookmarkNode.url;
+ var title = this.bookmarkNode.title;
+ var isFolder = bmm.isFolder(this.bookmarkNode);
+ var listItem = this;
+ var labelEl = this.firstChild;
+ var urlEl = this.querySelector('.url');
+ var labelInput, urlInput;
+
+ // Handles enter and escape which trigger reset and commit respectively.
+ function handleKeydown(e) {
+ // Make sure that the tree does not handle the key.
+ e.stopPropagation();
+
+ // Calling list.focus blurs the input which will stop editing the list
+ // item.
+ switch (e.keyIdentifier) {
+ case 'U+001B': // Esc
+ labelInput.value = title;
+ if (!isFolder)
+ urlInput.value = url;
+ // fall through
+ cr.dispatchSimpleEvent(listItem, 'canceledit', true);
+ case 'Enter':
+ if (listItem.parentNode)
+ listItem.parentNode.focus();
+ }
+ }
+
+ function handleBlur(e) {
+ // When the blur event happens we do not know who is getting focus so we
+ // delay this a bit since we want to know if the other input got focus
+ // before deciding if we should exit edit mode.
+ var doc = e.target.ownerDocument;
+ window.setTimeout(function() {
+ var activeElement = doc.activeElement;
+ if (activeElement != urlInput && activeElement != labelInput) {
+ listItem.editing = false;
+ }
+ }, 50);
+ }
+
+ var doc = this.ownerDocument;
+ if (editing) {
+ this.setAttribute('editing', '');
+ this.draggable = false;
+
+ labelInput = doc.createElement('input');
+ labelInput.placeholder =
+ localStrings.getString('name_input_placeholder');
+ replaceAllChildren(labelEl, labelInput);
+ labelInput.value = title;
+
+ if (!isFolder) {
+ // To use :invalid we need to put the input inside a form
+ // https://bugs.webkit.org/show_bug.cgi?id=34733
+ var form = doc.createElement('form');
+ urlInput = doc.createElement('input');
+ urlInput.type = 'url';
+ urlInput.required = true;
+ urlInput.placeholder =
+ localStrings.getString('url_input_placeholder');
+
+ // We also need a name for the input for the CSS to work.
+ urlInput.name = '-url-input-' + cr.createUid();
+ form.appendChild(urlInput);
+ replaceAllChildren(urlEl, form);
+ urlInput.value = url;
+ }
+
+ function stopPropagation(e) {
+ e.stopPropagation();
+ }
+
+ var eventsToStop = ['mousedown', 'mouseup', 'contextmenu', 'dblclick'];
+ eventsToStop.forEach(function(type) {
+ labelInput.addEventListener(type, stopPropagation);
+ });
+ labelInput.addEventListener('keydown', handleKeydown);
+ labelInput.addEventListener('blur', handleBlur);
+ cr.ui.limitInputWidth(labelInput, this, 200);
+ labelInput.focus();
+ labelInput.select();
+
+ if (!isFolder) {
+ eventsToStop.forEach(function(type) {
+ urlInput.addEventListener(type, stopPropagation);
+ });
+ urlInput.addEventListener('keydown', handleKeydown);
+ urlInput.addEventListener('blur', handleBlur);
+ cr.ui.limitInputWidth(urlInput, this, 200);
+ }
+
+ } else {
+
+ // Check that we have a valid URL and if not we do not change the
+ // editing mode.
+ if (!isFolder) {
+ var urlInput = this.querySelector('.url input');
+ var newUrl = urlInput.value;
+ if (!urlInput.validity.valid) {
+ // WebKit does not do URL fix up so we manually test if prepending
+ // 'http://' would make the URL valid.
+ // https://bugs.webkit.org/show_bug.cgi?id=29235
+ urlInput.value = 'http://' + newUrl;
+ if (!urlInput.validity.valid) {
+ // still invalid
+ urlInput.value = newUrl;
+
+ // In case the item was removed before getting here we should
+ // not alert.
+ if (listItem.parentNode) {
+ alert(localStrings.getString('invalid_url'));
+ }
+ urlInput.focus();
+ urlInput.select();
+ return;
+ }
+ newUrl = 'http://' + newUrl;
+ }
+ urlEl.textContent = this.bookmarkNode.url = newUrl;
+ }
+
+ this.removeAttribute('editing');
+ this.draggable = true;
+
+ labelInput = this.querySelector('.label input');
+ var newLabel = labelInput.value;
+ labelEl.textContent = this.bookmarkNode.title = newLabel;
+
+ if (isFolder) {
+ if (newLabel != title) {
+ cr.dispatchSimpleEvent(this, 'rename', true);
+ }
+ } else if (newLabel != title || newUrl != url) {
+ cr.dispatchSimpleEvent(this, 'edit', true);
+ }
+ }
+ }
+ };
+
+ function createListItem(bookmarkNode, showFolder) {
+ var li = listItemPromo.cloneNode(true);
+ BookmarkListItem.decorate(li);
+ updateListItem(li, bookmarkNode, showFolder);
+ li.bookmarkId = bookmarkNode.id;
+ li.bookmarkNode = bookmarkNode;
+ li.draggable = true;
+ listLookup[bookmarkNode.id] = li;
+ return li;
+ }
+
+ function updateListItem(el, bookmarkNode, showFolder) {
+ var labelEl = el.firstChild;
+ labelEl.textContent = bookmarkNode.title;
+ if (!bmm.isFolder(bookmarkNode)) {
+ labelEl.style.backgroundImage = url('chrome://favicon/' +
+ bookmarkNode.url);
+ var urlEl = el.childNodes[1].firstChild;
+ urlEl.textContent = urlEl.href = bookmarkNode.url;
+ } else {
+ el.className = 'folder';
+ }
+
+ var folderEl = el.lastChild.firstChild;
+ if (showFolder) {
+ folderEl.style.display = '';
+ folderEl.textContent = getFolder(bookmarkNode.parentId);
+ folderEl.href = '#' + bookmarkNode.parentId;
+ } else {
+ folderEl.style.display = 'none';
+ }
+ }
+
+ var listItemPromo = (function() {
+ var div = cr.doc.createElement('div');
+ div.innerHTML = '<div>' +
+ '<div class=label></div>' +
+ '<div><span class=url></span></div>' +
+ '<div><span class=folder></span></div>' +
+ '</div>';
+ return div.firstChild;
+ })();
+
+ return {
+ createListItem: createListItem,
+ BookmarkList: BookmarkList,
+ listLookup: listLookup
+ };
+});
« no previous file with comments | « resources/bookmark_manager/js/bmm.js ('k') | resources/bookmark_manager/js/bmm/bookmarktree.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698