Index: chrome/tools/test/reference_build/chrome_linux/resources/bookmark_manager/js/bmm/bookmarklist.js |
=================================================================== |
--- chrome/tools/test/reference_build/chrome_linux/resources/bookmark_manager/js/bmm/bookmarklist.js (revision 0) |
+++ chrome/tools/test/reference_build/chrome_linux/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 |
+ }; |
+}); |
Property changes on: chrome/tools/test/reference_build/chrome_linux/resources/bookmark_manager/js/bmm/bookmarklist.js |
___________________________________________________________________ |
Name: svn:eol-style |
+ LF |