/** @const */ var BookmarkList = bmm.BookmarkList;
/** @const */ var BookmarkTree = bmm.BookmarkTree;
/** @const */ var Command = cr.ui.Command;
-/** @const */ var CommandBinding = cr.ui.CommandBinding;
/** @const */ var LinkKind = cr.LinkKind;
/** @const */ var ListItem = cr.ui.ListItem;
/** @const */ var Menu = cr.ui.Menu;
/**
* An array containing the BookmarkTreeNodes that were deleted in the last
* deletion action. This is used for implementing undo.
- * @type {Array.<BookmarkTreeNode>}
+ * @type {?{nodes: Array.<Array.<BookmarkTreeNode>>, target: EventTarget}}
*/
-var lastDeletedNodes;
+var lastDeleted;
/**
*
/**
* Holds a link controller singleton. Use getLinkController() rarther than
* accessing this variabie.
- * @type {LinkController}
+ * @type {cr.LinkController}
*/
var linkController;
* Updates the location hash to reflect the current state of the application.
*/
function updateHash() {
- window.location.hash = tree.selectedItem.bookmarkId;
+ window.location.hash = bmm.tree.selectedItem.bookmarkId;
updateAllCommands();
}
'BookmarkManager_NavigateTo_' + metricsId);
if (opt_callback) {
- if (list.parentId == id)
+ if (bmm.list.parentId == id)
opt_callback();
else
- addOneShotEventListener(list, 'load', opt_callback);
+ addOneShotEventListener(bmm.list, 'load', opt_callback);
}
}
*/
function updateParentId(id) {
// Setting list.parentId fires 'load' event.
- list.parentId = id;
+ bmm.list.parentId = id;
// When tree.selectedItem changed, tree view calls navigatTo() then it
// calls updateHash() when list view displayed specified folder.
- tree.selectedItem = bmm.treeLookup[id] || tree.selectedItem;
+ bmm.tree.selectedItem = bmm.treeLookup[id] || bmm.tree.selectedItem;
}
// Process the location hash. This is called by onhashchange and when the page
var id = window.location.hash.slice(1);
if (!id) {
// If we do not have a hash, select first item in the tree.
- id = tree.items[0].bookmarkId;
+ id = bmm.tree.items[0].bookmarkId;
}
var valid = false;
var bookmarkNode = bookmarkNodes[0];
// After the list reloads, edit the desired bookmark.
- var editBookmark = function(e) {
- var index = list.dataModel.findIndexById(bookmarkNode.id);
+ var editBookmark = function() {
+ var index = bmm.list.dataModel.findIndexById(bookmarkNode.id);
if (index != -1) {
- var sm = list.selectionModel;
+ var sm = bmm.list.selectionModel;
sm.anchorIndex = sm.leadIndex = sm.selectedIndex = index;
scrollIntoViewAndMakeEditable(index);
}
};
- navigateTo(bookmarkNode.parentId, editBookmark);
+ var parentId = assert(bookmarkNode.parentId);
+ navigateTo(parentId, editBookmark);
});
// We handle the two cases of navigating to the bookmark to be edited
input.value = searchText;
if (searchText) {
- tree.add(searchTreeItem);
- tree.selectedItem = searchTreeItem;
+ bmm.tree.add(searchTreeItem);
+ bmm.tree.selectedItem = searchTreeItem;
} else {
// Go "home".
- tree.selectedItem = tree.items[0];
- id = tree.selectedItem.bookmarkId;
+ bmm.tree.selectedItem = bmm.tree.items[0];
+ id = bmm.tree.selectedItem.bookmarkId;
}
navigateTo(id);
* @return {string} The path to the the bookmark,
*/
function getFolder(parentId) {
- var parentNode = tree.getBookmarkNodeById(parentId);
+ var parentNode = bmm.tree.getBookmarkNodeById(parentId);
if (parentNode) {
var s = parentNode.title;
if (parentNode.parentId != bmm.ROOT_ID) {
// Get a future promise for the nodes.
var promises = nodes.map(function(node) {
- if (bmm.isFolder(node))
+ if (bmm.isFolder(assert(node)))
return bmm.loadSubtree(node.id);
// Not a folder so we already have all the data we need.
return Promise.resolve(node);
/**
* Returns the nodes (non recursive) to use for the open commands.
- * @param {HTMLElement} target .
- * @return {Array.<BookmarkTreeNode>} .
+ * @param {HTMLElement} target
+ * @return {!Array.<BookmarkTreeNode>}
*/
function getNodesForOpen(target) {
- if (target == tree) {
- if (tree.selectedItem != searchTreeItem)
- return tree.selectedFolders;
+ if (target == bmm.tree) {
+ if (bmm.tree.selectedItem != searchTreeItem)
+ return bmm.tree.selectedFolders;
// Fall through to use all nodes in the list.
} else {
- var items = list.selectedItems;
+ var items = bmm.list.selectedItems;
if (items.length)
return items;
}
// The list starts off with a null dataModel. We can get here during startup.
- if (!list.dataModel)
+ if (!bmm.list.dataModel)
return [];
// Return an array based on the dataModel.
- return list.dataModel.slice();
+ return bmm.list.dataModel.slice();
}
/**
return;
}
- getUrlsForOpenCommands(e.target).then(function(urls) {
+ getUrlsForOpenCommands(assertInstanceof(e.target, HTMLElement)).then(
+ function(urls) {
var disabled = !urls.length;
command.disabled = disabled;
e.canExecute = !disabled;
* @param {Function=} opt_f Function to call after the state has been updated.
*/
function updatePasteCommand(opt_f) {
- function update(canPaste) {
- var organizeMenuCommand = $('paste-from-organize-menu-command');
- var contextMenuCommand = $('paste-from-context-menu-command');
- organizeMenuCommand.disabled = !canPaste;
- contextMenuCommand.disabled = !canPaste;
- if (opt_f)
- opt_f();
+ function update(commandId, canPaste) {
+ $(commandId).disabled = !canPaste;
}
- // We cannot paste into search view.
- if (list.isSearch())
- update(false);
- else
- chrome.bookmarkManagerPrivate.canPaste(list.parentId, update);
+
+ var promises = [];
+
+ // The folders menu.
+ if (bmm.tree.selectedItem) {
+ promises.push(new Promise(function(resolve) {
+ var id = bmm.tree.selectedItem.bookmarkId;
+ chrome.bookmarkManagerPrivate.canPaste(id, function(canPaste) {
+ update('paste-from-folders-menu-command', canPaste);
+ resolve(canPaste);
+ });
+ }));
+ } else {
+ // Tree's not loaded yet.
+ update('paste-from-folders-menu-command', false);
+ }
+
+ // The organize menu.
+ var listId = bmm.list.parentId;
+ if (bmm.list.isSearch() || !listId) {
+ // We cannot paste into search view or the list isn't ready.
+ update('paste-from-organize-menu-command', false);
+ } else {
+ promises.push(new Promise(function(resolve) {
+ chrome.bookmarkManagerPrivate.canPaste(listId, function(canPaste) {
+ update('paste-from-organize-menu-command', canPaste);
+ resolve(canPaste);
+ });
+ }));
+ }
+
+ Promise.all(promises).then(function() {
+ var cmd;
+ if (document.activeElement == bmm.list)
+ cmd = 'paste-from-organize-menu-command';
+ else if (document.activeElement == bmm.tree)
+ cmd = 'paste-from-folders-menu-command';
+
+ if (cmd)
+ update('paste-from-context-menu-command', !$(cmd).disabled);
+
+ if (opt_f) opt_f();
+ });
}
function handleCanExecuteForDocument(e) {
case 'import-menu-command':
e.canExecute = canEdit;
break;
+
case 'export-menu-command':
// We can always execute the export-menu command.
e.canExecute = true;
break;
+
case 'sort-command':
- e.canExecute = !list.isSearch() &&
- list.dataModel && list.dataModel.length > 1 &&
- !isUnmodifiable(tree.getBookmarkNodeById(list.parentId));
+ e.canExecute = !bmm.list.isSearch() &&
+ bmm.list.dataModel && bmm.list.dataModel.length > 1 &&
+ !isUnmodifiable(bmm.tree.getBookmarkNodeById(bmm.list.parentId));
break;
+
case 'undo-command':
// If the search box is active, pass the undo command through
// (fixes http://crbug.com/278112). Otherwise, because
// just make it a no-op if undo is not possible.
e.canExecute = e.currentTarget.activeElement !== $('term');
break;
+
default:
canExecuteForList(e);
+ if (!e.defaultPrevented)
+ canExecuteForTree(e);
break;
}
}
/**
* Helper function for handling canExecute for the list and the tree.
- * @param {!Event} e Can execute event object.
+ * @param {!cr.ui.CanExecuteEvent} e Can execute event object.
* @param {boolean} isSearch Whether the user is trying to do a command on
* search.
*/
function canExecuteShared(e, isSearch) {
var command = e.command;
- var commandId = command.id;
- switch (commandId) {
+ switch (command.id) {
+ case 'paste-from-folders-menu-command':
case 'paste-from-organize-menu-command':
case 'paste-from-context-menu-command':
updatePasteCommand();
case 'add-new-bookmark-command':
case 'new-folder-command':
+ case 'new-folder-from-folders-menu-command':
var parentId = computeParentFolderForNewItem();
- var unmodifiable = isUnmodifiable(tree.getBookmarkNodeById(parentId));
+ var unmodifiable = isUnmodifiable(
+ bmm.tree.getBookmarkNodeById(parentId));
e.canExecute = !isSearch && canEdit && !unmodifiable;
break;
case 'open-in-new-tab-command':
updateOpenCommand(e, command, 'open_in_new_tab', 'open_all', false);
break;
+
case 'open-in-background-tab-command':
updateOpenCommand(e, command, '', '', false);
break;
+
case 'open-in-new-window-command':
updateOpenCommand(e, command,
'open_in_new_window', 'open_all_new_window',
// Disabled when incognito is forced.
incognitoModeAvailability == 'forced' || !canOpenNewWindows);
break;
+
case 'open-incognito-window-command':
updateOpenCommand(e, command,
'open_incognito', 'open_all_incognito',
break;
case 'undo-delete-command':
- e.canExecute = !!lastDeletedNodes;
+ e.canExecute = !!lastDeleted;
break;
}
}
/**
* Helper function for handling canExecute for the list and document.
- * @param {!Event} e Can execute event object.
+ * @param {!cr.ui.CanExecuteEvent} e Can execute event object.
*/
function canExecuteForList(e) {
- var command = e.command;
- var commandId = command.id;
-
function hasSelected() {
- return !!list.selectedItem;
+ return !!bmm.list.selectedItem;
}
function hasSingleSelected() {
- return list.selectedItems.length == 1;
+ return bmm.list.selectedItems.length == 1;
}
function canCopyItem(item) {
}
function canCopyItems() {
- var selectedItems = list.selectedItems;
+ var selectedItems = bmm.list.selectedItems;
return selectedItems && selectedItems.some(canCopyItem);
}
function isSearch() {
- return list.isSearch();
+ return bmm.list.isSearch();
}
- switch (commandId) {
+ var command = e.command;
+ switch (command.id) {
case 'rename-folder-command':
// Show rename if a single folder is selected.
- var items = list.selectedItems;
+ var items = bmm.list.selectedItems;
if (items.length != 1) {
e.canExecute = false;
command.hidden = true;
case 'edit-command':
// Show the edit command if not a folder.
- var items = list.selectedItems;
+ var items = bmm.list.selectedItems;
if (items.length != 1) {
e.canExecute = false;
command.hidden = false;
case 'delete-command':
case 'cut-command':
e.canExecute = canCopyItems() && canEdit &&
- !hasUnmodifiable(list.selectedItems);
+ !hasUnmodifiable(bmm.list.selectedItems);
break;
case 'copy-command':
// Update canExecute for the commands when the list is the active element.
function handleCanExecuteForList(e) {
- if (e.target != list) return;
+ if (e.target != bmm.list) return;
canExecuteForList(e);
}
// Update canExecute for the commands when the tree is the active element.
function handleCanExecuteForTree(e) {
- if (e.target != tree) return;
-
- var command = e.command;
- var commandId = command.id;
+ if (e.target != bmm.tree) return;
+ canExecuteForTree(e);
+}
+function canExecuteForTree(e) {
function hasSelected() {
- return !!e.target.selectedItem;
+ return !!bmm.tree.selectedItem;
}
function isSearch() {
- var item = e.target.selectedItem;
- return item == searchTreeItem;
+ return bmm.tree.selectedItem == searchTreeItem;
}
function isTopLevelItem() {
- return e.target.selectedItem.parentNode == tree;
+ return bmm.tree.selectedItem &&
+ bmm.tree.selectedItem.parentNode == bmm.tree;
}
- switch (commandId) {
+ var command = e.command;
+ switch (command.id) {
case 'rename-folder-command':
+ case 'rename-folder-from-folders-menu-command':
command.hidden = false;
e.canExecute = hasSelected() && !isTopLevelItem() && canEdit &&
- !hasUnmodifiable(tree.selectedFolders);
+ !hasUnmodifiable(bmm.tree.selectedFolders);
break;
case 'edit-command':
break;
case 'delete-command':
+ case 'delete-from-folders-menu-command':
case 'cut-command':
+ case 'cut-from-folders-menu-command':
e.canExecute = hasSelected() && !isTopLevelItem() && canEdit &&
- !hasUnmodifiable(tree.selectedFolders);
+ !hasUnmodifiable(bmm.tree.selectedFolders);
break;
case 'copy-command':
+ case 'copy-from-folders-menu-command':
e.canExecute = hasSelected() && !isTopLevelItem();
break;
+ case 'undo-delete-from-folders-menu-command':
+ e.canExecute = lastDeleted && lastDeleted.target == bmm.tree;
+ break;
+
default:
canExecuteShared(e, isSearch());
}
}
function updateEditingCommands() {
- var editingCommands = ['cut', 'delete', 'rename-folder', 'edit',
- 'add-new-bookmark', 'new-folder', 'sort',
- 'paste-from-context-menu', 'paste-from-organize-menu'];
+ var editingCommands = [
+ 'add-new-bookmark',
+ 'cut',
+ 'cut-from-folders-menu',
+ 'delete',
+ 'edit',
+ 'new-folder',
+ 'paste-from-context-menu',
+ 'paste-from-folders-menu',
+ 'paste-from-organize-menu',
+ 'rename-folder',
+ 'sort',
+ ];
chrome.bookmarkManagerPrivate.canEdit(function(result) {
if (result != canEdit) {
}
function handleChangeForTree(e) {
- navigateTo(tree.selectedItem.bookmarkId);
+ navigateTo(bmm.tree.selectedItem.bookmarkId);
}
-function handleOrganizeButtonClick(e) {
+function handleMenuButtonClicked(e) {
updateEditingCommands();
- $('add-new-bookmark-command').canExecuteChange();
- $('new-folder-command').canExecuteChange();
- $('sort-command').canExecuteChange();
+
+ if (e.currentTarget.id == 'folders-menu') {
+ $('copy-from-folders-menu-command').canExecuteChange();
+ $('undo-delete-from-folders-menu-command').canExecuteChange();
+ } else {
+ $('copy-command').canExecuteChange();
+ }
}
function handleRename(e) {
context.url = bookmarkNode.url;
if (bookmarkNode.id == 'new') {
- selectItemsAfterUserAction(list);
+ selectItemsAfterUserAction(/** @type {BookmarkList} */(bmm.list));
// New page
context.parentId = bookmarkNode.parentId;
chrome.bookmarks.create(context, function(node) {
// A new node was created and will get added to the list due to the
// handler.
- var dataModel = list.dataModel;
+ var dataModel = bmm.list.dataModel;
var index = dataModel.indexOf(bookmarkNode);
dataModel.splice(index, 1);
// Select new item.
var newIndex = dataModel.findIndexById(node.id);
if (newIndex != -1) {
- var sm = list.selectionModel;
- list.scrollIndexIntoView(newIndex);
+ var sm = bmm.list.selectionModel;
+ bmm.list.scrollIndexIntoView(newIndex);
sm.leadIndex = sm.anchorIndex = sm.selectedIndex = newIndex;
}
});
var item = e.target;
var bookmarkNode = item.bookmarkNode;
if (bookmarkNode.id == 'new') {
- var dataModel = list.dataModel;
+ var dataModel = bmm.list.dataModel;
var index = dataModel.findIndexById('new');
dataModel.splice(index, 1);
}
* used for the show-in-folder command.
*/
function showInFolder() {
- var bookmarkNode = list.selectedItem;
+ var bookmarkNode = bmm.list.selectedItem;
if (!bookmarkNode)
return;
var parentId = bookmarkNode.parentId;
// After the list is loaded we should select the revealed item.
function selectItem() {
- var index = list.dataModel.findIndexById(bookmarkNode.id);
+ var index = bmm.list.dataModel.findIndexById(bookmarkNode.id);
if (index == -1)
return;
- var sm = list.selectionModel;
+ var sm = bmm.list.selectionModel;
sm.anchorIndex = sm.leadIndex = sm.selectedIndex = index;
- list.scrollIndexIntoView(index);
+ bmm.list.scrollIndexIntoView(index);
}
var treeItem = bmm.treeLookup[parentId];
* Returns the selected bookmark nodes of the provided tree or list.
* If |opt_target| is not provided or null the active element is used.
* Only call this if the list or the tree is focused.
- * @param {BookmarkList|BookmarkTree} opt_target The target list or tree.
+ * @param {EventTarget=} opt_target The target list or tree.
* @return {!Array} Array of bookmark nodes.
*/
function getSelectedBookmarkNodes(opt_target) {
- return (opt_target || document.activeElement) == tree ?
- tree.selectedFolders : list.selectedItems;
+ return (opt_target || document.activeElement) == bmm.tree ?
+ bmm.tree.selectedFolders : bmm.list.selectedItems;
}
/**
+ * @param {EventTarget=} opt_target The target list or tree.
* @return {!Array.<string>} An array of the selected bookmark IDs.
*/
-function getSelectedBookmarkIds() {
- var selectedNodes = getSelectedBookmarkNodes();
+function getSelectedBookmarkIds(opt_target) {
+ var selectedNodes = getSelectedBookmarkNodes(opt_target);
selectedNodes.sort(function(a, b) { return a.index - b.index });
return selectedNodes.map(function(node) {
return node.id;
* @return {boolean} Whether the given node is unmodifiable.
*/
function isUnmodifiable(node) {
- return node && node.unmodifiable;
+ return !!(node && node.unmodifiable);
}
/**
- * @param {BookmarkList} A list of BookmarkNodes.
+ * @param {Array.<BookmarkTreeNode>} nodes A list of BookmarkTreeNodes.
* @return {boolean} Whether any of the nodes is managed.
*/
function hasUnmodifiable(nodes) {
/**
* Opens the selected bookmarks.
- * @param {LinkKind} kind The kind of link we want to open.
- * @param {HTMLElement} opt_eventTarget The target of the user initiated event.
+ * @param {cr.LinkKind} kind The kind of link we want to open.
+ * @param {HTMLElement=} opt_eventTarget The target of the user initiated event.
*/
function openBookmarks(kind, opt_eventTarget) {
// If we have selected any folders, we need to find all the bookmarks one
// level down. We use multiple async calls to getSubtree instead of getting
// the whole tree since we would like to minimize the amount of data sent.
- var urlsP = getUrlsForOpenCommands(opt_eventTarget);
+ var urlsP = getUrlsForOpenCommands(opt_eventTarget ? opt_eventTarget : null);
urlsP.then(function(urls) {
- getLinkController().openUrls(urls, kind);
+ getLinkController().openUrls(assert(urls), kind);
chrome.bookmarkManagerPrivate.recordLaunch();
});
}
* This ensures children of deleted folders do not remain in results
*/
function updateSearchResults() {
- if (list.isSearch()) {
- list.reload();
- }
+ if (bmm.list.isSearch())
+ bmm.list.reload();
}
/**
* Deletes the selected bookmarks. The bookmarks are saved in memory in case
* the user needs to undo the deletion.
+ * @param {EventTarget=} opt_target The deleter of bookmarks.
*/
-function deleteBookmarks() {
- var selectedIds = getSelectedBookmarkIds();
- var filteredIds = getFilteredSelectedBookmarkIds();
- lastDeletedNodes = [];
+function deleteBookmarks(opt_target) {
+ var selectedIds = getSelectedBookmarkIds(opt_target);
+ if (!selectedIds.length)
+ return;
+
+ var filteredIds = getFilteredSelectedBookmarkIds(opt_target);
+ lastDeleted = {nodes: [], target: opt_target || document.activeElement};
function performDelete() {
// Only remove filtered ids.
chrome.bookmarkManagerPrivate.removeTrees(filteredIds);
$('undo-delete-command').canExecuteChange();
+ $('undo-delete-from-folders-menu-command').canExecuteChange();
performGlobalUndo = undoDelete;
}
// Store all selected ids.
selectedIds.forEach(function(id) {
chrome.bookmarks.getSubTree(id, function(results) {
- lastDeletedNodes.push(results);
+ lastDeleted.nodes.push(results);
// When all nodes have been saved, perform the deletion.
- if (lastDeletedNodes.length === selectedIds.length) {
+ if (lastDeleted.nodes.length === selectedIds.length) {
performDelete();
updateSearchResults();
}
/**
* Restores a tree of bookmarks under a specified folder.
* @param {BookmarkTreeNode} node The node to restore.
- * @param {=string} parentId The ID of the folder to restore under. If not
- * specified, the original parentId of the node will be used.
+ * @param {(string|number)=} opt_parentId If a string is passed, it's the ID of
+ * the folder to restore under. If not specified or a number is passed, the
+ * original parentId of the node will be used.
*/
-function restoreTree(node, parentId) {
+function restoreTree(node, opt_parentId) {
var bookmarkInfo = {
- parentId: parentId || node.parentId,
+ parentId: typeof opt_parentId == 'string' ? opt_parentId : node.parentId,
title: node.title,
index: node.index,
url: node.url
* Restores the last set of bookmarks that was deleted.
*/
function undoDelete() {
- lastDeletedNodes.forEach(function(arr) {
+ lastDeleted.nodes.forEach(function(arr) {
arr.forEach(restoreTree);
});
- lastDeletedNodes = null;
+ lastDeleted = null;
$('undo-delete-command').canExecuteChange();
+ $('undo-delete-from-folders-menu-command').canExecuteChange();
// Only a single level of undo is supported, so disable global undo now.
performGlobalUndo = null;
* @return {string} The id of folder node where we'll create new page/folder.
*/
function computeParentFolderForNewItem() {
- if (document.activeElement == tree)
- return list.parentId;
- var selectedItem = list.selectedItem;
+ if (document.activeElement == bmm.tree)
+ return bmm.list.parentId;
+ var selectedItem = bmm.list.selectedItem;
return selectedItem && bmm.isFolder(selectedItem) ?
- selectedItem.id : list.parentId;
+ selectedItem.id : bmm.list.parentId;
}
/**
* selected item.
*/
function editSelectedItem() {
- if (document.activeElement == tree) {
- tree.selectedItem.editing = true;
+ if (document.activeElement == bmm.tree) {
+ bmm.tree.selectedItem.editing = true;
} else {
- var li = list.getListItem(list.selectedItem);
+ var li = bmm.list.getListItem(bmm.list.selectedItem);
if (li)
li.editing = true;
}
/**
* Callback for the new folder command. This creates a new folder and starts
* a rename of it.
+ * @param {EventTarget=} opt_target The target to create a new folder in.
*/
-function newFolder() {
+function newFolder(opt_target) {
performGlobalUndo = null; // This can't be undone, so disable global undo.
var parentId = computeParentFolderForNewItem();
}, callback);
}
- if (document.activeElement == tree) {
+ if ((opt_target || document.activeElement) == bmm.tree) {
createFolder(function(newNode) {
navigateTo(newNode.id, function() {
bmm.treeLookup[newNode.id].editing = true;
function editNewFolderInList() {
createFolder(function() {
- var index = list.dataModel.length - 1;
- var sm = list.selectionModel;
+ var index = bmm.list.dataModel.length - 1;
+ var sm = bmm.list.selectionModel;
sm.anchorIndex = sm.leadIndex = sm.selectedIndex = index;
scrollIntoViewAndMakeEditable(index);
});
* @param {number} index The index of the item to make editable.
*/
function scrollIntoViewAndMakeEditable(index) {
- list.scrollIndexIntoView(index);
+ bmm.list.scrollIndexIntoView(index);
// onscroll is now dispatched asynchronously so we have to postpone
// the rest.
setTimeout(function() {
- var item = list.getListItemByIndex(index);
+ var item = bmm.list.getListItemByIndex(index);
if (item)
item.editing = true;
- });
+ }, 0);
}
/**
parentId: parentId,
id: 'new'
};
- var dataModel = list.dataModel;
+ var dataModel = bmm.list.dataModel;
var length = dataModel.length;
dataModel.splice(length, 0, fakeNode);
- var sm = list.selectionModel;
+ var sm = bmm.list.selectionModel;
sm.anchorIndex = sm.leadIndex = sm.selectedIndex = length;
scrollIntoViewAndMakeEditable(length);
};
* This function is used to select items after a user action such as paste, drop
* add page etc.
* @param {BookmarkList|BookmarkTree} target The target of the user action.
- * @param {=string} opt_selectedTreeId If provided, then select that tree id.
+ * @param {string=} opt_selectedTreeId If provided, then select that tree id.
*/
function selectItemsAfterUserAction(target, opt_selectedTreeId) {
// We get one onCreated event per item so we delay the handling until we get
function handle(id, bookmarkNode) {
clearTimeout(timer);
- if (opt_selectedTreeId || list.parentId == bookmarkNode.parentId)
+ if (opt_selectedTreeId || bmm.list.parentId == bookmarkNode.parentId)
ids.push(id);
timer = setTimeout(handleTimeout, 50);
}
if (opt_selectedTreeId && ids.indexOf(opt_selectedTreeId) != -1) {
var index = ids.indexOf(opt_selectedTreeId);
if (index != -1 && opt_selectedTreeId in bmm.treeLookup) {
- tree.selectedItem = bmm.treeLookup[opt_selectedTreeId];
+ bmm.tree.selectedItem = bmm.treeLookup[opt_selectedTreeId];
}
- } else if (target == list) {
- var dataModel = list.dataModel;
+ } else if (target == bmm.list) {
+ var dataModel = bmm.list.dataModel;
var firstIndex = dataModel.findIndexById(ids[0]);
var lastIndex = dataModel.findIndexById(ids[ids.length - 1]);
if (firstIndex != -1 && lastIndex != -1) {
- var selectionModel = list.selectionModel;
+ var selectionModel = bmm.list.selectionModel;
selectionModel.selectedIndex = -1;
selectionModel.selectRange(firstIndex, lastIndex);
selectionModel.anchorIndex = selectionModel.leadIndex = lastIndex;
- list.focus();
+ bmm.list.focus();
}
}
- list.endBatchUpdates();
+ bmm.list.endBatchUpdates();
}
- list.startBatchUpdates();
+ bmm.list.startBatchUpdates();
chrome.bookmarks.onCreated.addListener(handle);
chrome.bookmarks.onMoved.addListener(handle);
* tree view or list view).
*/
function getSelectedId() {
- if (document.activeElement == tree)
- return tree.selectedItem.bookmarkId;
- var selectedItem = list.selectedItem;
+ if (document.activeElement == bmm.tree)
+ return bmm.tree.selectedItem.bookmarkId;
+ var selectedItem = bmm.list.selectedItem;
return selectedItem && bmm.isFolder(selectedItem) ?
- selectedItem.id : tree.selectedItem.bookmarkId;
+ selectedItem.id : bmm.tree.selectedItem.bookmarkId;
}
/**
*/
function pasteBookmark(id) {
recordUserAction('Paste');
- selectItemsAfterUserAction(list);
+ selectItemsAfterUserAction(/** @type {BookmarkList} */(bmm.list));
chrome.bookmarkManagerPrivate.paste(id, getSelectedBookmarkIds());
}
return true;
// Keep digging.
- return hasSelectedAncestor(tree.getBookmarkNodeById(parentNode.parentId));
+ return hasSelectedAncestor(
+ bmm.tree.getBookmarkNodeById(parentNode.parentId));
}
-function getFilteredSelectedBookmarkIds() {
+/**
+ * @param {EventTarget=} opt_target A target to get bookmark IDs from.
+ * @return {Array.<string>} An array of bookmarks IDs.
+ */
+function getFilteredSelectedBookmarkIds(opt_target) {
// Remove duplicates from filteredIds and return.
- var filteredIds = new Array();
+ var filteredIds = [];
// Selected nodes to iterate through for matches.
- var nodes = getSelectedBookmarkNodes();
+ var nodes = getSelectedBookmarkNodes(opt_target);
for (var i = 0; i < nodes.length; i++)
- if (!hasSelectedAncestor(tree.getBookmarkNodeById(nodes[i].parentId)))
+ if (!hasSelectedAncestor(bmm.tree.getBookmarkNodeById(nodes[i].parentId)))
filteredIds.splice(0, 0, nodes[i].id);
return filteredIds;
*/
function handleCommand(e) {
var command = e.command;
- var commandId = command.id;
- switch (commandId) {
+ var target;
+ switch (command.id) {
case 'import-menu-command':
recordUserAction('Import');
chrome.bookmarks.import();
break;
+
case 'export-menu-command':
recordUserAction('Export');
chrome.bookmarks.export();
break;
+
case 'undo-command':
if (performGlobalUndo) {
recordUserAction('UndoGlobal');
recordUserAction('UndoNone');
}
break;
+
case 'show-in-folder-command':
recordUserAction('ShowInFolder');
showInFolder();
break;
+
case 'open-in-new-tab-command':
case 'open-in-background-tab-command':
recordUserAction('OpenInNewTab');
- openBookmarks(LinkKind.BACKGROUND_TAB, e.target);
+ openBookmarks(LinkKind.BACKGROUND_TAB,
+ assertInstanceof(e.target, HTMLElement));
break;
+
case 'open-in-new-window-command':
recordUserAction('OpenInNewWindow');
- openBookmarks(LinkKind.WINDOW, e.target);
+ openBookmarks(LinkKind.WINDOW,
+ assertInstanceof(e.target, HTMLElement));
break;
+
case 'open-incognito-window-command':
recordUserAction('OpenIncognito');
- openBookmarks(LinkKind.INCOGNITO, e.target);
+ openBookmarks(LinkKind.INCOGNITO,
+ assertInstanceof(e.target, HTMLElement));
break;
+
+ case 'delete-from-folders-menu-command':
+ target = bmm.tree;
case 'delete-command':
recordUserAction('Delete');
- deleteBookmarks();
+ deleteBookmarks(target);
break;
+
+ case 'copy-from-folders-menu-command':
+ target = bmm.tree;
case 'copy-command':
recordUserAction('Copy');
- chrome.bookmarkManagerPrivate.copy(getSelectedBookmarkIds(),
+ chrome.bookmarkManagerPrivate.copy(getSelectedBookmarkIds(target),
updatePasteCommand);
break;
+
+ case 'cut-from-folders-menu-command':
+ target = bmm.tree;
case 'cut-command':
recordUserAction('Cut');
- chrome.bookmarkManagerPrivate.cut(getSelectedBookmarkIds(),
+ chrome.bookmarkManagerPrivate.cut(getSelectedBookmarkIds(target),
function() {
updatePasteCommand();
updateSearchResults();
});
break;
+
case 'paste-from-organize-menu-command':
- pasteBookmark(list.parentId);
+ pasteBookmark(bmm.list.parentId);
break;
+
+ case 'paste-from-folders-menu-command':
+ pasteBookmark(bmm.tree.selectedItem.bookmarkId);
+ break;
+
case 'paste-from-context-menu-command':
pasteBookmark(getSelectedId());
break;
+
case 'sort-command':
recordUserAction('Sort');
- chrome.bookmarkManagerPrivate.sortChildren(list.parentId);
+ chrome.bookmarkManagerPrivate.sortChildren(bmm.list.parentId);
break;
+
case 'rename-folder-command':
editSelectedItem();
break;
+
+ case 'rename-folder-from-folders-menu-command':
+ bmm.tree.selectedItem.editing = true;
+ break;
+
case 'edit-command':
recordUserAction('Edit');
editSelectedItem();
break;
+
+ case 'new-folder-from-folders-menu-command':
+ target = bmm.tree;
case 'new-folder-command':
recordUserAction('NewFolder');
- newFolder();
+ newFolder(target);
break;
+
case 'add-new-bookmark-command':
recordUserAction('AddPage');
addPage();
break;
+
case 'open-in-same-window-command':
recordUserAction('OpenInSame');
openItem();
break;
+
case 'undo-delete-command':
+ case 'undo-delete-from-folders-menu-command':
recordUserAction('UndoDelete');
undoDelete();
break;
// shortcuts for these commands.
function installEventHandlerForCommand(eventName, commandId) {
function handle(e) {
- if (document.activeElement != list && document.activeElement != tree)
+ if (document.activeElement != bmm.list &&
+ document.activeElement != bmm.tree)
return;
var command = $(commandId);
if (!command.disabled) {
var splitter = document.querySelector('.main > .splitter');
Splitter.decorate(splitter);
+ var splitterStyle = splitter.previousElementSibling.style;
+
// The splitter persists the size of the left component in the local store.
- if ('treeWidth' in localStorage)
- splitter.previousElementSibling.style.width = localStorage['treeWidth'];
+ if ('treeWidth' in window.localStorage)
+ splitterStyle.width = window.localStorage['treeWidth'];
splitter.addEventListener('resize', function(e) {
- localStorage['treeWidth'] = splitter.previousElementSibling.style.width;
+ window.localStorage['treeWidth'] = splitterStyle.width;
});
}
cr.ui.decorate('menu', Menu);
cr.ui.decorate('button[menu]', MenuButton);
cr.ui.decorate('command', Command);
- BookmarkList.decorate(list);
- BookmarkTree.decorate(tree);
-
- list.addEventListener('canceledit', handleCancelEdit);
- list.addEventListener('canExecute', handleCanExecuteForList);
- list.addEventListener('change', updateAllCommands);
- list.addEventListener('contextmenu', updateEditingCommands);
- list.addEventListener('dblclick', handleDoubleClickForList);
- list.addEventListener('edit', handleEdit);
- list.addEventListener('rename', handleRename);
- list.addEventListener('urlClicked', handleUrlClickedForList);
-
- tree.addEventListener('canExecute', handleCanExecuteForTree);
- tree.addEventListener('change', handleChangeForTree);
- tree.addEventListener('contextmenu', updateEditingCommands);
- tree.addEventListener('rename', handleRename);
- tree.addEventListener('load', handleLoadForTree);
-
- cr.ui.contextMenuHandler.addContextMenuProperty(tree);
- list.contextMenu = $('context-menu');
- tree.contextMenu = $('context-menu');
+ BookmarkList.decorate($('list'));
+ BookmarkTree.decorate($('tree'));
+
+ bmm.list.addEventListener('canceledit', handleCancelEdit);
+ bmm.list.addEventListener('canExecute', handleCanExecuteForList);
+ bmm.list.addEventListener('change', updateAllCommands);
+ bmm.list.addEventListener('contextmenu', updateEditingCommands);
+ bmm.list.addEventListener('dblclick', handleDoubleClickForList);
+ bmm.list.addEventListener('edit', handleEdit);
+ bmm.list.addEventListener('rename', handleRename);
+ bmm.list.addEventListener('urlClicked', handleUrlClickedForList);
+
+ bmm.tree.addEventListener('canExecute', handleCanExecuteForTree);
+ bmm.tree.addEventListener('change', handleChangeForTree);
+ bmm.tree.addEventListener('contextmenu', updateEditingCommands);
+ bmm.tree.addEventListener('rename', handleRename);
+ bmm.tree.addEventListener('load', handleLoadForTree);
+
+ cr.ui.contextMenuHandler.addContextMenuProperty(
+ /** @type {!Element} */(bmm.tree));
+ bmm.list.contextMenu = $('context-menu');
+ bmm.tree.contextMenu = $('context-menu');
// We listen to hashchange so that we can update the currently shown folder
// when // the user goes back and forward in the history.
window.addEventListener('hashchange', processHash);
- document.querySelector('header form').onsubmit = function(e) {
+ document.querySelector('header form').onsubmit =
+ /** @type {function(Event=)} */(function(e) {
setSearch($('term').value);
e.preventDefault();
- };
+ });
$('term').addEventListener('search', handleSearch);
- document.querySelector('.summary button').addEventListener(
- 'click', handleOrganizeButtonClick);
+ $('folders-button').addEventListener('click', handleMenuButtonClicked);
+ $('organize-button').addEventListener('click', handleMenuButtonClicked);
document.addEventListener('canExecute', handleCanExecuteForDocument);
document.addEventListener('command', handleCommand);
initializeSplitter();
bmm.addBookmarkModelListeners();
dnd.init(selectItemsAfterUserAction);
- tree.reload();
+ bmm.tree.reload();
}
initializeBookmarkManager();