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

Side by Side Diff: chrome/browser/resources/bookmark_manager/js/main.js

Issue 543863002: Typecheck chrome://bookmarks using Closure Compiler (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@true_master
Patch Set: revert checker.py Created 6 years, 3 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 unified diff | Download patch
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 (function() { 5 (function() {
6 /** @const */ var BookmarkList = bmm.BookmarkList; 6 /** @const */ var BookmarkList = bmm.BookmarkList;
7 /** @const */ var BookmarkTree = bmm.BookmarkTree; 7 /** @const */ var BookmarkTree = bmm.BookmarkTree;
8 /** @const */ var Command = cr.ui.Command; 8 /** @const */ var Command = cr.ui.Command;
9 /** @const */ var CommandBinding = cr.ui.CommandBinding;
10 /** @const */ var LinkKind = cr.LinkKind; 9 /** @const */ var LinkKind = cr.LinkKind;
11 /** @const */ var ListItem = cr.ui.ListItem; 10 /** @const */ var ListItem = cr.ui.ListItem;
12 /** @const */ var Menu = cr.ui.Menu; 11 /** @const */ var Menu = cr.ui.Menu;
13 /** @const */ var MenuButton = cr.ui.MenuButton; 12 /** @const */ var MenuButton = cr.ui.MenuButton;
14 /** @const */ var Splitter = cr.ui.Splitter; 13 /** @const */ var Splitter = cr.ui.Splitter;
15 /** @const */ var TreeItem = cr.ui.TreeItem; 14 /** @const */ var TreeItem = cr.ui.TreeItem;
16 15
17 /** 16 /**
18 * An array containing the BookmarkTreeNodes that were deleted in the last 17 * An array containing the BookmarkTreeNodes that were deleted in the last
19 * deletion action. This is used for implementing undo. 18 * deletion action. This is used for implementing undo.
20 * @type {Array.<BookmarkTreeNode>} 19 * @type {Array.<Array.<BookmarkTreeNode>>}
21 */ 20 */
22 var lastDeletedNodes; 21 var lastDeletedNodes;
23 22
24 /** 23 /**
25 * 24 *
26 * Holds the last DOMTimeStamp when mouse pointer hovers on folder in tree 25 * Holds the last DOMTimeStamp when mouse pointer hovers on folder in tree
27 * view. Zero means pointer doesn't hover on folder. 26 * view. Zero means pointer doesn't hover on folder.
28 * @type {number} 27 * @type {number}
29 */ 28 */
30 var lastHoverOnFolderTimeStamp = 0; 29 var lastHoverOnFolderTimeStamp = 0;
31 30
32 /** 31 /**
33 * Holds a function that will undo that last action, if global undo is enabled. 32 * Holds a function that will undo that last action, if global undo is enabled.
34 * @type {Function} 33 * @type {Function}
35 */ 34 */
36 var performGlobalUndo; 35 var performGlobalUndo;
37 36
38 /** 37 /**
39 * Holds a link controller singleton. Use getLinkController() rarther than 38 * Holds a link controller singleton. Use getLinkController() rarther than
40 * accessing this variabie. 39 * accessing this variabie.
41 * @type {LinkController} 40 * @type {cr.LinkController}
42 */ 41 */
43 var linkController; 42 var linkController;
44 43
45 /** 44 /**
46 * New Windows are not allowed in Windows 8 metro mode. 45 * New Windows are not allowed in Windows 8 metro mode.
47 */ 46 */
48 var canOpenNewWindows = true; 47 var canOpenNewWindows = true;
49 48
50 /** 49 /**
51 * Incognito mode availability can take the following values: , 50 * Incognito mode availability can take the following values: ,
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after
135 134
136 searchTreeItem.label = loadTimeData.getString('search'); 135 searchTreeItem.label = loadTimeData.getString('search');
137 searchTreeItem.icon = isRTL() ? 'images/bookmark_manager_search_rtl.png' : 136 searchTreeItem.icon = isRTL() ? 'images/bookmark_manager_search_rtl.png' :
138 'images/bookmark_manager_search.png'; 137 'images/bookmark_manager_search.png';
139 } 138 }
140 139
141 /** 140 /**
142 * Updates the location hash to reflect the current state of the application. 141 * Updates the location hash to reflect the current state of the application.
143 */ 142 */
144 function updateHash() { 143 function updateHash() {
145 window.location.hash = tree.selectedItem.bookmarkId; 144 window.location.hash = $('tree').selectedItem.bookmarkId;
146 updateAllCommands(); 145 updateAllCommands();
147 } 146 }
148 147
149 /** 148 /**
150 * Navigates to a bookmark ID. 149 * Navigates to a bookmark ID.
151 * @param {string} id The ID to navigate to. 150 * @param {string} id The ID to navigate to.
152 * @param {function()=} opt_callback Function called when list view loaded or 151 * @param {function()=} opt_callback Function called when list view loaded or
153 * displayed specified folder. 152 * displayed specified folder.
154 */ 153 */
155 function navigateTo(id, opt_callback) { 154 function navigateTo(id, opt_callback) {
156 window.location.hash = id; 155 window.location.hash = id;
157 updateAllCommands(); 156 updateAllCommands();
158 157
159 var metricsId = folderMetricsNameMap[id.replace(/^q=.*/, 'q=')] || 158 var metricsId = folderMetricsNameMap[id.replace(/^q=.*/, 'q=')] ||
160 folderMetricsNameMap['subfolder']; 159 folderMetricsNameMap['subfolder'];
161 chrome.metricsPrivate.recordUserAction( 160 chrome.metricsPrivate.recordUserAction(
162 'BookmarkManager_NavigateTo_' + metricsId); 161 'BookmarkManager_NavigateTo_' + metricsId);
163 162
164 if (opt_callback) { 163 if (opt_callback) {
165 if (list.parentId == id) 164 if ($('list').parentId == id)
Dan Beam 2014/09/23 02:46:56 cast to !Element here as you're already doing mayb
Vitaly Pavlenko 2014/09/23 22:20:55 Done.
166 opt_callback(); 165 opt_callback();
167 else 166 else
168 addOneShotEventListener(list, 'load', opt_callback); 167 addOneShotEventListener(/** @type {!Element} */($('list')), 'load',
168 opt_callback);
Dan Beam 2014/09/23 02:46:56 if () needs curlies
Vitaly Pavlenko 2014/09/23 22:20:55 Done.
169 } 169 }
170 } 170 }
171 171
172 /** 172 /**
173 * Updates the parent ID of the bookmark list and selects the correct tree item. 173 * Updates the parent ID of the bookmark list and selects the correct tree item.
174 * @param {string} id The id. 174 * @param {string} id The id.
175 */ 175 */
176 function updateParentId(id) { 176 function updateParentId(id) {
177 // Setting list.parentId fires 'load' event. 177 // Setting list.parentId fires 'load' event.
178 list.parentId = id; 178 $('list').parentId = id;
179 179
180 // When tree.selectedItem changed, tree view calls navigatTo() then it 180 // When tree.selectedItem changed, tree view calls navigatTo() then it
181 // calls updateHash() when list view displayed specified folder. 181 // calls updateHash() when list view displayed specified folder.
182 tree.selectedItem = bmm.treeLookup[id] || tree.selectedItem; 182 $('tree').selectedItem = bmm.treeLookup[id] || $('tree').selectedItem;
183 } 183 }
184 184
185 // Process the location hash. This is called by onhashchange and when the page 185 // Process the location hash. This is called by onhashchange and when the page
186 // is first loaded. 186 // is first loaded.
187 function processHash() { 187 function processHash() {
188 var id = window.location.hash.slice(1); 188 var id = window.location.hash.slice(1);
189 if (!id) { 189 if (!id) {
190 // If we do not have a hash, select first item in the tree. 190 // If we do not have a hash, select first item in the tree.
191 id = tree.items[0].bookmarkId; 191 id = $('tree').items[0].bookmarkId;
192 } 192 }
193 193
194 var valid = false; 194 var valid = false;
195 if (/^e=/.test(id)) { 195 if (/^e=/.test(id)) {
196 id = id.slice(2); 196 id = id.slice(2);
197 197
198 // If hash contains e=, edit the item specified. 198 // If hash contains e=, edit the item specified.
199 chrome.bookmarks.get(id, function(bookmarkNodes) { 199 chrome.bookmarks.get(id, function(bookmarkNodes) {
200 // Verify the node to edit is a valid node. 200 // Verify the node to edit is a valid node.
201 if (!bookmarkNodes || bookmarkNodes.length != 1) 201 if (!bookmarkNodes || bookmarkNodes.length != 1)
202 return; 202 return;
203 var bookmarkNode = bookmarkNodes[0]; 203 var bookmarkNode = bookmarkNodes[0];
204 204
205 // After the list reloads, edit the desired bookmark. 205 // After the list reloads, edit the desired bookmark.
206 var editBookmark = function(e) { 206 var editBookmark = function() {
207 var index = list.dataModel.findIndexById(bookmarkNode.id); 207 var index = $('list').dataModel.findIndexById(bookmarkNode.id);
208 if (index != -1) { 208 if (index != -1) {
209 var sm = list.selectionModel; 209 var sm = $('list').selectionModel;
210 sm.anchorIndex = sm.leadIndex = sm.selectedIndex = index; 210 sm.anchorIndex = sm.leadIndex = sm.selectedIndex = index;
211 scrollIntoViewAndMakeEditable(index); 211 scrollIntoViewAndMakeEditable(index);
212 } 212 }
213 }; 213 };
214 214
215 navigateTo(bookmarkNode.parentId, editBookmark); 215 navigateTo(bookmarkNode.parentId, editBookmark);
216 }); 216 });
217 217
218 // We handle the two cases of navigating to the bookmark to be edited 218 // We handle the two cases of navigating to the bookmark to be edited
219 // above. Don't run the standard navigation code below. 219 // above. Don't run the standard navigation code below.
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
266 var id = searchTreeItem.bookmarkId = 'q=' + searchText; 266 var id = searchTreeItem.bookmarkId = 'q=' + searchText;
267 bmm.treeLookup[searchTreeItem.bookmarkId] = searchTreeItem; 267 bmm.treeLookup[searchTreeItem.bookmarkId] = searchTreeItem;
268 } 268 }
269 269
270 var input = $('term'); 270 var input = $('term');
271 // Do not update the input if the user is actively using the text input. 271 // Do not update the input if the user is actively using the text input.
272 if (document.activeElement != input) 272 if (document.activeElement != input)
273 input.value = searchText; 273 input.value = searchText;
274 274
275 if (searchText) { 275 if (searchText) {
276 tree.add(searchTreeItem); 276 $('tree').add(searchTreeItem);
277 tree.selectedItem = searchTreeItem; 277 $('tree').selectedItem = searchTreeItem;
278 } else { 278 } else {
279 // Go "home". 279 // Go "home".
280 tree.selectedItem = tree.items[0]; 280 $('tree').selectedItem = $('tree').items[0];
281 id = tree.selectedItem.bookmarkId; 281 id = $('tree').selectedItem.bookmarkId;
282 } 282 }
283 283
284 navigateTo(id); 284 navigateTo(id);
285 } 285 }
286 286
287 /** 287 /**
288 * This returns the user visible path to the folder where the bookmark is 288 * This returns the user visible path to the folder where the bookmark is
289 * located. 289 * located.
290 * @param {number} parentId The ID of the parent folder. 290 * @param {number} parentId The ID of the parent folder.
291 * @return {string} The path to the the bookmark, 291 * @return {string} The path to the the bookmark,
292 */ 292 */
293 function getFolder(parentId) { 293 function getFolder(parentId) {
294 var parentNode = tree.getBookmarkNodeById(parentId); 294 var parentNode = $('tree').getBookmarkNodeById(parentId);
295 if (parentNode) { 295 if (parentNode) {
296 var s = parentNode.title; 296 var s = parentNode.title;
297 if (parentNode.parentId != bmm.ROOT_ID) { 297 if (parentNode.parentId != bmm.ROOT_ID) {
298 return getFolder(parentNode.parentId) + '/' + s; 298 return getFolder(parentNode.parentId) + '/' + s;
299 } 299 }
300 return s; 300 return s;
301 } 301 }
302 } 302 }
303 303
304 function handleLoadForTree(e) { 304 function handleLoadForTree(e) {
(...skipping 19 matching lines...) Expand all
324 if (!bmm.isFolder(child)) 324 if (!bmm.isFolder(child))
325 urls.push(child.url); 325 urls.push(child.url);
326 }); 326 });
327 } else { 327 } else {
328 urls.push(node.url); 328 urls.push(node.url);
329 } 329 }
330 } 330 }
331 331
332 // Get a future promise for the nodes. 332 // Get a future promise for the nodes.
333 var promises = nodes.map(function(node) { 333 var promises = nodes.map(function(node) {
334 if (bmm.isFolder(node)) 334 if (bmm.isFolder(assert(node)))
335 return bmm.loadSubtree(node.id); 335 return bmm.loadSubtree(node.id);
336 // Not a folder so we already have all the data we need. 336 // Not a folder so we already have all the data we need.
337 return Promise.resolve(node); 337 return Promise.resolve(node);
338 }); 338 });
339 339
340 return Promise.all(promises).then(function(nodes) { 340 return Promise.all(promises).then(function(nodes) {
341 nodes.forEach(addNodes); 341 nodes.forEach(addNodes);
342 return urls; 342 return urls;
343 }); 343 });
344 } 344 }
345 345
346 /** 346 /**
347 * Returns the nodes (non recursive) to use for the open commands. 347 * Returns the nodes (non recursive) to use for the open commands.
348 * @param {HTMLElement} target . 348 * @param {HTMLElement} target
349 * @return {Array.<BookmarkTreeNode>} . 349 * @return {!Array.<BookmarkTreeNode>}
350 */ 350 */
351 function getNodesForOpen(target) { 351 function getNodesForOpen(target) {
352 if (target == tree) { 352 if (target == $('tree')) {
353 if (tree.selectedItem != searchTreeItem) 353 if ($('tree').selectedItem != searchTreeItem)
354 return tree.selectedFolders; 354 return $('tree').selectedFolders;
355 // Fall through to use all nodes in the list. 355 // Fall through to use all nodes in the list.
356 } else { 356 } else {
357 var items = list.selectedItems; 357 var items = $('list').selectedItems;
358 if (items.length) 358 if (items.length)
359 return items; 359 return items;
360 } 360 }
361 361
362 // The list starts off with a null dataModel. We can get here during startup. 362 // The list starts off with a null dataModel. We can get here during startup.
363 if (!list.dataModel) 363 if (!$('list').dataModel)
364 return []; 364 return [];
365 365
366 // Return an array based on the dataModel. 366 // Return an array based on the dataModel.
367 return list.dataModel.slice(); 367 return $('list').dataModel.slice();
368 } 368 }
369 369
370 /** 370 /**
371 * Returns a promise that will contain all URLs of all the selected bookmarks 371 * Returns a promise that will contain all URLs of all the selected bookmarks
372 * and the nested bookmarks for use with the open commands. 372 * and the nested bookmarks for use with the open commands.
373 * @param {HTMLElement} target The target list or tree. 373 * @param {HTMLElement} target The target list or tree.
374 * @return {Promise.<Array.<string>>} . 374 * @return {Promise.<Array.<string>>} .
375 */ 375 */
376 function getUrlsForOpenCommands(target) { 376 function getUrlsForOpenCommands(target) {
377 return getAllUrls(getNodesForOpen(target)); 377 return getAllUrls(getNodesForOpen(target));
(...skipping 12 matching lines...) Expand all
390 * @param {string} pluralId The string id of menu label if the singular form is 390 * @param {string} pluralId The string id of menu label if the singular form is
391 not used. 391 not used.
392 * @param {boolean} commandDisabled Whether the menu item should be disabled 392 * @param {boolean} commandDisabled Whether the menu item should be disabled
393 no matter what bookmarks are selected. 393 no matter what bookmarks are selected.
394 */ 394 */
395 function updateOpenCommand(e, command, singularId, pluralId, commandDisabled) { 395 function updateOpenCommand(e, command, singularId, pluralId, commandDisabled) {
396 if (singularId) { 396 if (singularId) {
397 // The command label reflects the selection which might not reflect 397 // The command label reflects the selection which might not reflect
398 // how many bookmarks will be opened. For example if you right click an 398 // how many bookmarks will be opened. For example if you right click an
399 // empty area in a folder with 1 bookmark the text should still say "all". 399 // empty area in a folder with 1 bookmark the text should still say "all".
400 assert(!e.target || e.target instanceof BookmarkList ||
401 e.target instanceof BookmarkTree);
400 var selectedNodes = getSelectedBookmarkNodes(e.target).filter(notNewNode); 402 var selectedNodes = getSelectedBookmarkNodes(e.target).filter(notNewNode);
401 var singular = selectedNodes.length == 1 && !bmm.isFolder(selectedNodes[0]); 403 var singular = selectedNodes.length == 1 && !bmm.isFolder(selectedNodes[0]);
402 command.label = loadTimeData.getString(singular ? singularId : pluralId); 404 command.label = loadTimeData.getString(singular ? singularId : pluralId);
403 } 405 }
404 406
405 if (commandDisabled) { 407 if (commandDisabled) {
406 command.disabled = true; 408 command.disabled = true;
407 e.canExecute = false; 409 e.canExecute = false;
408 return; 410 return;
409 } 411 }
410 412
411 getUrlsForOpenCommands(e.target).then(function(urls) { 413 getUrlsForOpenCommands(assertInstanceof(e.target, HTMLElement)).then(
414 function(urls) {
412 var disabled = !urls.length; 415 var disabled = !urls.length;
413 command.disabled = disabled; 416 command.disabled = disabled;
414 e.canExecute = !disabled; 417 e.canExecute = !disabled;
415 }); 418 });
416 } 419 }
417 420
418 /** 421 /**
419 * Calls the backend to figure out if we can paste the clipboard into the active 422 * Calls the backend to figure out if we can paste the clipboard into the active
420 * folder. 423 * folder.
421 * @param {Function=} opt_f Function to call after the state has been updated. 424 * @param {Function=} opt_f Function to call after the state has been updated.
422 */ 425 */
423 function updatePasteCommand(opt_f) { 426 function updatePasteCommand(opt_f) {
424 function update(canPaste) { 427 function update(canPaste) {
425 var organizeMenuCommand = $('paste-from-organize-menu-command'); 428 var organizeMenuCommand = $('paste-from-organize-menu-command');
426 var contextMenuCommand = $('paste-from-context-menu-command'); 429 var contextMenuCommand = $('paste-from-context-menu-command');
427 organizeMenuCommand.disabled = !canPaste; 430 organizeMenuCommand.disabled = !canPaste;
428 contextMenuCommand.disabled = !canPaste; 431 contextMenuCommand.disabled = !canPaste;
429 if (opt_f) 432 if (opt_f)
430 opt_f(); 433 opt_f();
431 } 434 }
432 // We cannot paste into search view. 435 // We cannot paste into search view.
433 if (list.isSearch()) 436 if ($('list').isSearch())
434 update(false); 437 update(false);
435 else 438 else
436 chrome.bookmarkManagerPrivate.canPaste(list.parentId, update); 439 chrome.bookmarkManagerPrivate.canPaste($('list').parentId, update);
437 } 440 }
438 441
439 function handleCanExecuteForDocument(e) { 442 function handleCanExecuteForDocument(e) {
440 var command = e.command; 443 var command = e.command;
441 switch (command.id) { 444 switch (command.id) {
442 case 'import-menu-command': 445 case 'import-menu-command':
443 e.canExecute = canEdit; 446 e.canExecute = canEdit;
444 break; 447 break;
445 case 'export-menu-command': 448 case 'export-menu-command':
446 // We can always execute the export-menu command. 449 // We can always execute the export-menu command.
447 e.canExecute = true; 450 e.canExecute = true;
448 break; 451 break;
449 case 'sort-command': 452 case 'sort-command':
450 e.canExecute = !list.isSearch() && 453 e.canExecute = !$('list').isSearch() &&
451 list.dataModel && list.dataModel.length > 1 && 454 $('list').dataModel && $('list').dataModel.length > 1 &&
452 !isUnmodifiable(tree.getBookmarkNodeById(list.parentId)); 455 !isUnmodifiable($('tree').getBookmarkNodeById($('list').parentId));
453 break; 456 break;
454 case 'undo-command': 457 case 'undo-command':
455 // If the search box is active, pass the undo command through 458 // If the search box is active, pass the undo command through
456 // (fixes http://crbug.com/278112). Otherwise, because 459 // (fixes http://crbug.com/278112). Otherwise, because
457 // the global undo command has no visible UI, always enable it, and 460 // the global undo command has no visible UI, always enable it, and
458 // just make it a no-op if undo is not possible. 461 // just make it a no-op if undo is not possible.
459 e.canExecute = e.currentTarget.activeElement !== $('term'); 462 e.canExecute = e.currentTarget.activeElement !== $('term');
460 break; 463 break;
461 default: 464 default:
462 canExecuteForList(e); 465 canExecuteForList(e);
463 break; 466 break;
464 } 467 }
465 } 468 }
466 469
467 /** 470 /**
468 * Helper function for handling canExecute for the list and the tree. 471 * Helper function for handling canExecute for the list and the tree.
469 * @param {!Event} e Can execute event object. 472 * @param {!cr.ui.CanExecuteEvent} e Can execute event object.
470 * @param {boolean} isSearch Whether the user is trying to do a command on 473 * @param {boolean} isSearch Whether the user is trying to do a command on
471 * search. 474 * search.
472 */ 475 */
473 function canExecuteShared(e, isSearch) { 476 function canExecuteShared(e, isSearch) {
474 var command = e.command; 477 var command = e.command;
475 var commandId = command.id; 478 var commandId = command.id;
476 switch (commandId) { 479 switch (commandId) {
477 case 'paste-from-organize-menu-command': 480 case 'paste-from-organize-menu-command':
478 case 'paste-from-context-menu-command': 481 case 'paste-from-context-menu-command':
479 updatePasteCommand(); 482 updatePasteCommand();
480 break; 483 break;
481 484
482 case 'add-new-bookmark-command': 485 case 'add-new-bookmark-command':
483 case 'new-folder-command': 486 case 'new-folder-command':
484 var parentId = computeParentFolderForNewItem(); 487 var parentId = computeParentFolderForNewItem();
485 var unmodifiable = isUnmodifiable(tree.getBookmarkNodeById(parentId)); 488 var unmodifiable = isUnmodifiable(
489 $('tree').getBookmarkNodeById(parentId));
486 e.canExecute = !isSearch && canEdit && !unmodifiable; 490 e.canExecute = !isSearch && canEdit && !unmodifiable;
487 break; 491 break;
488 492
489 case 'open-in-new-tab-command': 493 case 'open-in-new-tab-command':
490 updateOpenCommand(e, command, 'open_in_new_tab', 'open_all', false); 494 updateOpenCommand(e, command, 'open_in_new_tab', 'open_all', false);
491 break; 495 break;
492 case 'open-in-background-tab-command': 496 case 'open-in-background-tab-command':
493 updateOpenCommand(e, command, '', '', false); 497 updateOpenCommand(e, command, '', '', false);
494 break; 498 break;
495 case 'open-in-new-window-command': 499 case 'open-in-new-window-command':
(...skipping 10 matching lines...) Expand all
506 break; 510 break;
507 511
508 case 'undo-delete-command': 512 case 'undo-delete-command':
509 e.canExecute = !!lastDeletedNodes; 513 e.canExecute = !!lastDeletedNodes;
510 break; 514 break;
511 } 515 }
512 } 516 }
513 517
514 /** 518 /**
515 * Helper function for handling canExecute for the list and document. 519 * Helper function for handling canExecute for the list and document.
516 * @param {!Event} e Can execute event object. 520 * @param {!cr.ui.CanExecuteEvent} e Can execute event object.
517 */ 521 */
518 function canExecuteForList(e) { 522 function canExecuteForList(e) {
519 var command = e.command; 523 var command = e.command;
520 var commandId = command.id; 524 var commandId = command.id;
521 525
522 function hasSelected() { 526 function hasSelected() {
523 return !!list.selectedItem; 527 return !!$('list').selectedItem;
524 } 528 }
525 529
526 function hasSingleSelected() { 530 function hasSingleSelected() {
527 return list.selectedItems.length == 1; 531 return $('list').selectedItems.length == 1;
528 } 532 }
529 533
530 function canCopyItem(item) { 534 function canCopyItem(item) {
531 return item.id != 'new'; 535 return item.id != 'new';
532 } 536 }
533 537
534 function canCopyItems() { 538 function canCopyItems() {
535 var selectedItems = list.selectedItems; 539 var selectedItems = $('list').selectedItems;
536 return selectedItems && selectedItems.some(canCopyItem); 540 return selectedItems && selectedItems.some(canCopyItem);
537 } 541 }
538 542
539 function isSearch() { 543 function isSearch() {
540 return list.isSearch(); 544 return $('list').isSearch();
541 } 545 }
542 546
543 switch (commandId) { 547 switch (commandId) {
544 case 'rename-folder-command': 548 case 'rename-folder-command':
545 // Show rename if a single folder is selected. 549 // Show rename if a single folder is selected.
546 var items = list.selectedItems; 550 var items = $('list').selectedItems;
547 if (items.length != 1) { 551 if (items.length != 1) {
548 e.canExecute = false; 552 e.canExecute = false;
549 command.hidden = true; 553 command.hidden = true;
550 } else { 554 } else {
551 var isFolder = bmm.isFolder(items[0]); 555 var isFolder = bmm.isFolder(items[0]);
552 e.canExecute = isFolder && canEdit && !hasUnmodifiable(items); 556 e.canExecute = isFolder && canEdit && !hasUnmodifiable(items);
553 command.hidden = !isFolder; 557 command.hidden = !isFolder;
554 } 558 }
555 break; 559 break;
556 560
557 case 'edit-command': 561 case 'edit-command':
558 // Show the edit command if not a folder. 562 // Show the edit command if not a folder.
559 var items = list.selectedItems; 563 var items = $('list').selectedItems;
560 if (items.length != 1) { 564 if (items.length != 1) {
561 e.canExecute = false; 565 e.canExecute = false;
562 command.hidden = false; 566 command.hidden = false;
563 } else { 567 } else {
564 var isFolder = bmm.isFolder(items[0]); 568 var isFolder = bmm.isFolder(items[0]);
565 e.canExecute = !isFolder && canEdit && !hasUnmodifiable(items); 569 e.canExecute = !isFolder && canEdit && !hasUnmodifiable(items);
566 command.hidden = isFolder; 570 command.hidden = isFolder;
567 } 571 }
568 break; 572 break;
569 573
570 case 'show-in-folder-command': 574 case 'show-in-folder-command':
571 e.canExecute = isSearch() && hasSingleSelected(); 575 e.canExecute = isSearch() && hasSingleSelected();
572 break; 576 break;
573 577
574 case 'delete-command': 578 case 'delete-command':
575 case 'cut-command': 579 case 'cut-command':
576 e.canExecute = canCopyItems() && canEdit && 580 e.canExecute = canCopyItems() && canEdit &&
577 !hasUnmodifiable(list.selectedItems); 581 !hasUnmodifiable($('list').selectedItems);
578 break; 582 break;
579 583
580 case 'copy-command': 584 case 'copy-command':
581 e.canExecute = canCopyItems(); 585 e.canExecute = canCopyItems();
582 break; 586 break;
583 587
584 case 'open-in-same-window-command': 588 case 'open-in-same-window-command':
585 e.canExecute = hasSelected(); 589 e.canExecute = hasSelected();
586 break; 590 break;
587 591
588 default: 592 default:
589 canExecuteShared(e, isSearch()); 593 canExecuteShared(e, isSearch());
590 } 594 }
591 } 595 }
592 596
593 // Update canExecute for the commands when the list is the active element. 597 // Update canExecute for the commands when the list is the active element.
594 function handleCanExecuteForList(e) { 598 function handleCanExecuteForList(e) {
595 if (e.target != list) return; 599 if (e.target != $('list')) return;
596 canExecuteForList(e); 600 canExecuteForList(e);
597 } 601 }
598 602
599 // Update canExecute for the commands when the tree is the active element. 603 // Update canExecute for the commands when the tree is the active element.
600 function handleCanExecuteForTree(e) { 604 function handleCanExecuteForTree(e) {
601 if (e.target != tree) return; 605 if (e.target != $('tree')) return;
602 606
603 var command = e.command; 607 var command = e.command;
604 var commandId = command.id; 608 var commandId = command.id;
605 609
606 function hasSelected() { 610 function hasSelected() {
607 return !!e.target.selectedItem; 611 return !!e.target.selectedItem;
608 } 612 }
609 613
610 function isSearch() { 614 function isSearch() {
611 var item = e.target.selectedItem; 615 var item = e.target.selectedItem;
612 return item == searchTreeItem; 616 return item == searchTreeItem;
613 } 617 }
614 618
615 function isTopLevelItem() { 619 function isTopLevelItem() {
616 return e.target.selectedItem.parentNode == tree; 620 return e.target.selectedItem.parentNode == $('tree');
617 } 621 }
618 622
619 switch (commandId) { 623 switch (commandId) {
620 case 'rename-folder-command': 624 case 'rename-folder-command':
621 command.hidden = false; 625 command.hidden = false;
622 e.canExecute = hasSelected() && !isTopLevelItem() && canEdit && 626 e.canExecute = hasSelected() && !isTopLevelItem() && canEdit &&
623 !hasUnmodifiable(tree.selectedFolders); 627 !hasUnmodifiable($('tree').selectedFolders);
624 break; 628 break;
625 629
626 case 'edit-command': 630 case 'edit-command':
627 command.hidden = true; 631 command.hidden = true;
628 e.canExecute = false; 632 e.canExecute = false;
629 break; 633 break;
630 634
631 case 'delete-command': 635 case 'delete-command':
632 case 'cut-command': 636 case 'cut-command':
633 e.canExecute = hasSelected() && !isTopLevelItem() && canEdit && 637 e.canExecute = hasSelected() && !isTopLevelItem() && canEdit &&
634 !hasUnmodifiable(tree.selectedFolders); 638 !hasUnmodifiable($('tree').selectedFolders);
635 break; 639 break;
636 640
637 case 'copy-command': 641 case 'copy-command':
638 e.canExecute = hasSelected() && !isTopLevelItem(); 642 e.canExecute = hasSelected() && !isTopLevelItem();
639 break; 643 break;
640 644
641 default: 645 default:
642 canExecuteShared(e, isSearch()); 646 canExecuteShared(e, isSearch());
643 } 647 }
644 } 648 }
(...skipping 17 matching lines...) Expand all
662 if (result != canEdit) { 666 if (result != canEdit) {
663 canEdit = result; 667 canEdit = result;
664 editingCommands.forEach(function(baseId) { 668 editingCommands.forEach(function(baseId) {
665 $(baseId + '-command').canExecuteChange(); 669 $(baseId + '-command').canExecuteChange();
666 }); 670 });
667 } 671 }
668 }); 672 });
669 } 673 }
670 674
671 function handleChangeForTree(e) { 675 function handleChangeForTree(e) {
672 navigateTo(tree.selectedItem.bookmarkId); 676 navigateTo($('tree').selectedItem.bookmarkId);
673 } 677 }
674 678
675 function handleOrganizeButtonClick(e) { 679 function handleOrganizeButtonClick(e) {
676 updateEditingCommands(); 680 updateEditingCommands();
677 $('add-new-bookmark-command').canExecuteChange(); 681 $('add-new-bookmark-command').canExecuteChange();
678 $('new-folder-command').canExecuteChange(); 682 $('new-folder-command').canExecuteChange();
679 $('sort-command').canExecuteChange(); 683 $('sort-command').canExecuteChange();
680 } 684 }
681 685
682 function handleRename(e) { 686 function handleRename(e) {
683 var item = e.target; 687 var item = e.target;
684 var bookmarkNode = item.bookmarkNode; 688 var bookmarkNode = item.bookmarkNode;
685 chrome.bookmarks.update(bookmarkNode.id, {title: item.label}); 689 chrome.bookmarks.update(bookmarkNode.id, {title: item.label});
686 performGlobalUndo = null; // This can't be undone, so disable global undo. 690 performGlobalUndo = null; // This can't be undone, so disable global undo.
687 } 691 }
688 692
689 function handleEdit(e) { 693 function handleEdit(e) {
690 var item = e.target; 694 var item = e.target;
691 var bookmarkNode = item.bookmarkNode; 695 var bookmarkNode = item.bookmarkNode;
692 var context = { 696 var context = {
693 title: bookmarkNode.title 697 title: bookmarkNode.title
694 }; 698 };
695 if (!bmm.isFolder(bookmarkNode)) 699 if (!bmm.isFolder(bookmarkNode))
696 context.url = bookmarkNode.url; 700 context.url = bookmarkNode.url;
697 701
698 if (bookmarkNode.id == 'new') { 702 if (bookmarkNode.id == 'new') {
699 selectItemsAfterUserAction(list); 703 selectItemsAfterUserAction(/** @type {BookmarkList} */($('list')));
700 704
701 // New page 705 // New page
702 context.parentId = bookmarkNode.parentId; 706 context.parentId = bookmarkNode.parentId;
703 chrome.bookmarks.create(context, function(node) { 707 chrome.bookmarks.create(context, function(node) {
704 // A new node was created and will get added to the list due to the 708 // A new node was created and will get added to the list due to the
705 // handler. 709 // handler.
706 var dataModel = list.dataModel; 710 var dataModel = $('list').dataModel;
707 var index = dataModel.indexOf(bookmarkNode); 711 var index = dataModel.indexOf(bookmarkNode);
708 dataModel.splice(index, 1); 712 dataModel.splice(index, 1);
709 713
710 // Select new item. 714 // Select new item.
711 var newIndex = dataModel.findIndexById(node.id); 715 var newIndex = dataModel.findIndexById(node.id);
712 if (newIndex != -1) { 716 if (newIndex != -1) {
713 var sm = list.selectionModel; 717 var sm = $('list').selectionModel;
714 list.scrollIndexIntoView(newIndex); 718 $('list').scrollIndexIntoView(newIndex);
715 sm.leadIndex = sm.anchorIndex = sm.selectedIndex = newIndex; 719 sm.leadIndex = sm.anchorIndex = sm.selectedIndex = newIndex;
716 } 720 }
717 }); 721 });
718 } else { 722 } else {
719 // Edit 723 // Edit
720 chrome.bookmarks.update(bookmarkNode.id, context); 724 chrome.bookmarks.update(bookmarkNode.id, context);
721 } 725 }
722 performGlobalUndo = null; // This can't be undone, so disable global undo. 726 performGlobalUndo = null; // This can't be undone, so disable global undo.
723 } 727 }
724 728
725 function handleCancelEdit(e) { 729 function handleCancelEdit(e) {
726 var item = e.target; 730 var item = e.target;
727 var bookmarkNode = item.bookmarkNode; 731 var bookmarkNode = item.bookmarkNode;
728 if (bookmarkNode.id == 'new') { 732 if (bookmarkNode.id == 'new') {
729 var dataModel = list.dataModel; 733 var dataModel = $('list').dataModel;
730 var index = dataModel.findIndexById('new'); 734 var index = dataModel.findIndexById('new');
731 dataModel.splice(index, 1); 735 dataModel.splice(index, 1);
732 } 736 }
733 } 737 }
734 738
735 /** 739 /**
736 * Navigates to the folder that the selected item is in and selects it. This is 740 * Navigates to the folder that the selected item is in and selects it. This is
737 * used for the show-in-folder command. 741 * used for the show-in-folder command.
738 */ 742 */
739 function showInFolder() { 743 function showInFolder() {
740 var bookmarkNode = list.selectedItem; 744 var bookmarkNode = $('list').selectedItem;
741 if (!bookmarkNode) 745 if (!bookmarkNode)
742 return; 746 return;
743 var parentId = bookmarkNode.parentId; 747 var parentId = bookmarkNode.parentId;
744 748
745 // After the list is loaded we should select the revealed item. 749 // After the list is loaded we should select the revealed item.
746 function selectItem() { 750 function selectItem() {
747 var index = list.dataModel.findIndexById(bookmarkNode.id); 751 var index = $('list').dataModel.findIndexById(bookmarkNode.id);
748 if (index == -1) 752 if (index == -1)
749 return; 753 return;
750 var sm = list.selectionModel; 754 var sm = $('list').selectionModel;
751 sm.anchorIndex = sm.leadIndex = sm.selectedIndex = index; 755 sm.anchorIndex = sm.leadIndex = sm.selectedIndex = index;
752 list.scrollIndexIntoView(index); 756 $('list').scrollIndexIntoView(index);
753 } 757 }
754 758
755 var treeItem = bmm.treeLookup[parentId]; 759 var treeItem = bmm.treeLookup[parentId];
756 treeItem.reveal(); 760 treeItem.reveal();
757 761
758 navigateTo(parentId, selectItem); 762 navigateTo(parentId, selectItem);
759 } 763 }
760 764
761 /** 765 /**
762 * @return {!cr.LinkController} The link controller used to open links based on 766 * @return {!cr.LinkController} The link controller used to open links based on
763 * user clicks and keyboard actions. 767 * user clicks and keyboard actions.
764 */ 768 */
765 function getLinkController() { 769 function getLinkController() {
766 return linkController || 770 return linkController ||
767 (linkController = new cr.LinkController(loadTimeData)); 771 (linkController = new cr.LinkController(loadTimeData));
768 } 772 }
769 773
770 /** 774 /**
771 * Returns the selected bookmark nodes of the provided tree or list. 775 * Returns the selected bookmark nodes of the provided tree or list.
772 * If |opt_target| is not provided or null the active element is used. 776 * If |opt_target| is not provided or null the active element is used.
773 * Only call this if the list or the tree is focused. 777 * Only call this if the list or the tree is focused.
774 * @param {BookmarkList|BookmarkTree} opt_target The target list or tree. 778 * @param {(BookmarkList|BookmarkTree)=} opt_target The target list or tree.
775 * @return {!Array} Array of bookmark nodes. 779 * @return {!Array} Array of bookmark nodes.
776 */ 780 */
777 function getSelectedBookmarkNodes(opt_target) { 781 function getSelectedBookmarkNodes(opt_target) {
778 return (opt_target || document.activeElement) == tree ? 782 return (opt_target || document.activeElement) == $('tree') ?
779 tree.selectedFolders : list.selectedItems; 783 $('tree').selectedFolders : $('list').selectedItems;
780 } 784 }
781 785
782 /** 786 /**
783 * @return {!Array.<string>} An array of the selected bookmark IDs. 787 * @return {!Array.<string>} An array of the selected bookmark IDs.
784 */ 788 */
785 function getSelectedBookmarkIds() { 789 function getSelectedBookmarkIds() {
786 var selectedNodes = getSelectedBookmarkNodes(); 790 var selectedNodes = getSelectedBookmarkNodes();
787 selectedNodes.sort(function(a, b) { return a.index - b.index }); 791 selectedNodes.sort(function(a, b) { return a.index - b.index });
788 return selectedNodes.map(function(node) { 792 return selectedNodes.map(function(node) {
789 return node.id; 793 return node.id;
790 }); 794 });
791 } 795 }
792 796
793 /** 797 /**
794 * @param {BookmarkTreeNode} node The node to test. 798 * @param {BookmarkTreeNode} node The node to test.
795 * @return {boolean} Whether the given node is unmodifiable. 799 * @return {boolean} Whether the given node is unmodifiable.
796 */ 800 */
797 function isUnmodifiable(node) { 801 function isUnmodifiable(node) {
798 return node && node.unmodifiable; 802 return node && node.unmodifiable;
799 } 803 }
800 804
801 /** 805 /**
802 * @param {BookmarkList} A list of BookmarkNodes. 806 * @param {Array.<BookmarkTreeNode>} nodes A list of BookmarkTreeNodes.
803 * @return {boolean} Whether any of the nodes is managed. 807 * @return {boolean} Whether any of the nodes is managed.
804 */ 808 */
805 function hasUnmodifiable(nodes) { 809 function hasUnmodifiable(nodes) {
806 return nodes.some(isUnmodifiable); 810 return nodes.some(isUnmodifiable);
807 } 811 }
808 812
809 /** 813 /**
810 * Opens the selected bookmarks. 814 * Opens the selected bookmarks.
811 * @param {LinkKind} kind The kind of link we want to open. 815 * @param {cr.LinkKind} kind The kind of link we want to open.
812 * @param {HTMLElement} opt_eventTarget The target of the user initiated event. 816 * @param {HTMLElement=} opt_eventTarget The target of the user initiated event.
813 */ 817 */
814 function openBookmarks(kind, opt_eventTarget) { 818 function openBookmarks(kind, opt_eventTarget) {
815 // If we have selected any folders, we need to find all the bookmarks one 819 // If we have selected any folders, we need to find all the bookmarks one
816 // level down. We use multiple async calls to getSubtree instead of getting 820 // level down. We use multiple async calls to getSubtree instead of getting
817 // the whole tree since we would like to minimize the amount of data sent. 821 // the whole tree since we would like to minimize the amount of data sent.
818 822
819 var urlsP = getUrlsForOpenCommands(opt_eventTarget); 823 var urlsP = getUrlsForOpenCommands(opt_eventTarget ? opt_eventTarget : null);
820 urlsP.then(function(urls) { 824 urlsP.then(function(urls) {
821 getLinkController().openUrls(urls, kind); 825 getLinkController().openUrls(assert(urls), kind);
822 chrome.bookmarkManagerPrivate.recordLaunch(); 826 chrome.bookmarkManagerPrivate.recordLaunch();
823 }); 827 });
824 } 828 }
825 829
826 /** 830 /**
827 * Opens an item in the list. 831 * Opens an item in the list.
828 */ 832 */
829 function openItem() { 833 function openItem() {
830 var bookmarkNodes = getSelectedBookmarkNodes(); 834 var bookmarkNodes = getSelectedBookmarkNodes();
831 // If we double clicked or pressed enter on a single folder, navigate to it. 835 // If we double clicked or pressed enter on a single folder, navigate to it.
832 if (bookmarkNodes.length == 1 && bmm.isFolder(bookmarkNodes[0])) 836 if (bookmarkNodes.length == 1 && bmm.isFolder(bookmarkNodes[0]))
833 navigateTo(bookmarkNodes[0].id); 837 navigateTo(bookmarkNodes[0].id);
834 else 838 else
835 openBookmarks(LinkKind.FOREGROUND_TAB); 839 openBookmarks(LinkKind.FOREGROUND_TAB);
836 } 840 }
837 841
838 /** 842 /**
839 * Refreshes search results after delete or undo-delete. 843 * Refreshes search results after delete or undo-delete.
840 * This ensures children of deleted folders do not remain in results 844 * This ensures children of deleted folders do not remain in results
841 */ 845 */
842 function updateSearchResults() { 846 function updateSearchResults() {
843 if (list.isSearch()) { 847 if ($('list').isSearch()) {
844 list.reload(); 848 $('list').reload();
845 } 849 }
846 } 850 }
847 851
848 /** 852 /**
849 * Deletes the selected bookmarks. The bookmarks are saved in memory in case 853 * Deletes the selected bookmarks. The bookmarks are saved in memory in case
850 * the user needs to undo the deletion. 854 * the user needs to undo the deletion.
851 */ 855 */
852 function deleteBookmarks() { 856 function deleteBookmarks() {
853 var selectedIds = getSelectedBookmarkIds(); 857 var selectedIds = getSelectedBookmarkIds();
854 var filteredIds = getFilteredSelectedBookmarkIds(); 858 var filteredIds = getFilteredSelectedBookmarkIds();
(...skipping 17 matching lines...) Expand all
872 performDelete(); 876 performDelete();
873 updateSearchResults(); 877 updateSearchResults();
874 } 878 }
875 }); 879 });
876 }); 880 });
877 } 881 }
878 882
879 /** 883 /**
880 * Restores a tree of bookmarks under a specified folder. 884 * Restores a tree of bookmarks under a specified folder.
881 * @param {BookmarkTreeNode} node The node to restore. 885 * @param {BookmarkTreeNode} node The node to restore.
882 * @param {=string} parentId The ID of the folder to restore under. If not 886 * @param {(string|number)=} opt_parentId If a string is passed, it's the ID of
883 * specified, the original parentId of the node will be used. 887 * the folder to restore under. If not specified or a number is passed (when
888 * called by forEach), the original parentId of the node will be used.
884 */ 889 */
885 function restoreTree(node, parentId) { 890 function restoreTree(node, opt_parentId) {
886 var bookmarkInfo = { 891 var bookmarkInfo = {
887 parentId: parentId || node.parentId, 892 parentId: typeof opt_parentId == 'string' ? opt_parentId : node.parentId,
888 title: node.title, 893 title: node.title,
889 index: node.index, 894 index: node.index,
890 url: node.url 895 url: node.url
891 }; 896 };
892 897
893 chrome.bookmarks.create(bookmarkInfo, function(result) { 898 chrome.bookmarks.create(bookmarkInfo, function(result) {
894 if (!result) { 899 if (!result) {
895 console.error('Failed to restore bookmark.'); 900 console.error('Failed to restore bookmark.');
896 return; 901 return;
897 } 902 }
(...skipping 21 matching lines...) Expand all
919 924
920 // Only a single level of undo is supported, so disable global undo now. 925 // Only a single level of undo is supported, so disable global undo now.
921 performGlobalUndo = null; 926 performGlobalUndo = null;
922 } 927 }
923 928
924 /** 929 /**
925 * Computes folder for "Add Page" and "Add Folder". 930 * Computes folder for "Add Page" and "Add Folder".
926 * @return {string} The id of folder node where we'll create new page/folder. 931 * @return {string} The id of folder node where we'll create new page/folder.
927 */ 932 */
928 function computeParentFolderForNewItem() { 933 function computeParentFolderForNewItem() {
929 if (document.activeElement == tree) 934 if (document.activeElement == $('tree'))
930 return list.parentId; 935 return $('list').parentId;
931 var selectedItem = list.selectedItem; 936 var selectedItem = $('list').selectedItem;
932 return selectedItem && bmm.isFolder(selectedItem) ? 937 return selectedItem && bmm.isFolder(selectedItem) ?
933 selectedItem.id : list.parentId; 938 selectedItem.id : $('list').parentId;
934 } 939 }
935 940
936 /** 941 /**
937 * Callback for rename folder and edit command. This starts editing for 942 * Callback for rename folder and edit command. This starts editing for
938 * selected item. 943 * selected item.
939 */ 944 */
940 function editSelectedItem() { 945 function editSelectedItem() {
941 if (document.activeElement == tree) { 946 if (document.activeElement == $('tree')) {
942 tree.selectedItem.editing = true; 947 $('tree').selectedItem.editing = true;
943 } else { 948 } else {
944 var li = list.getListItem(list.selectedItem); 949 var li = $('list').getListItem($('list').selectedItem);
945 if (li) 950 if (li)
946 li.editing = true; 951 li.editing = true;
947 } 952 }
948 } 953 }
949 954
950 /** 955 /**
951 * Callback for the new folder command. This creates a new folder and starts 956 * Callback for the new folder command. This creates a new folder and starts
952 * a rename of it. 957 * a rename of it.
953 */ 958 */
954 function newFolder() { 959 function newFolder() {
955 performGlobalUndo = null; // This can't be undone, so disable global undo. 960 performGlobalUndo = null; // This can't be undone, so disable global undo.
956 961
957 var parentId = computeParentFolderForNewItem(); 962 var parentId = computeParentFolderForNewItem();
958 963
959 // Callback is called after tree and list data model updated. 964 // Callback is called after tree and list data model updated.
960 function createFolder(callback) { 965 function createFolder(callback) {
961 chrome.bookmarks.create({ 966 chrome.bookmarks.create({
962 title: loadTimeData.getString('new_folder_name'), 967 title: loadTimeData.getString('new_folder_name'),
963 parentId: parentId 968 parentId: parentId
964 }, callback); 969 }, callback);
965 } 970 }
966 971
967 if (document.activeElement == tree) { 972 if (document.activeElement == $('tree')) {
968 createFolder(function(newNode) { 973 createFolder(function(newNode) {
969 navigateTo(newNode.id, function() { 974 navigateTo(newNode.id, function() {
970 bmm.treeLookup[newNode.id].editing = true; 975 bmm.treeLookup[newNode.id].editing = true;
971 }); 976 });
972 }); 977 });
973 return; 978 return;
974 } 979 }
975 980
976 function editNewFolderInList() { 981 function editNewFolderInList() {
977 createFolder(function() { 982 createFolder(function() {
978 var index = list.dataModel.length - 1; 983 var index = $('list').dataModel.length - 1;
979 var sm = list.selectionModel; 984 var sm = $('list').selectionModel;
980 sm.anchorIndex = sm.leadIndex = sm.selectedIndex = index; 985 sm.anchorIndex = sm.leadIndex = sm.selectedIndex = index;
981 scrollIntoViewAndMakeEditable(index); 986 scrollIntoViewAndMakeEditable(index);
982 }); 987 });
983 } 988 }
984 989
985 navigateTo(parentId, editNewFolderInList); 990 navigateTo(parentId, editNewFolderInList);
986 } 991 }
987 992
988 /** 993 /**
989 * Scrolls the list item into view and makes it editable. 994 * Scrolls the list item into view and makes it editable.
990 * @param {number} index The index of the item to make editable. 995 * @param {number} index The index of the item to make editable.
991 */ 996 */
992 function scrollIntoViewAndMakeEditable(index) { 997 function scrollIntoViewAndMakeEditable(index) {
993 list.scrollIndexIntoView(index); 998 $('list').scrollIndexIntoView(index);
994 // onscroll is now dispatched asynchronously so we have to postpone 999 // onscroll is now dispatched asynchronously so we have to postpone
995 // the rest. 1000 // the rest.
996 setTimeout(function() { 1001 setTimeout(function() {
997 var item = list.getListItemByIndex(index); 1002 var item = $('list').getListItemByIndex(index);
998 if (item) 1003 if (item)
999 item.editing = true; 1004 item.editing = true;
1000 }); 1005 }, 0);
1001 } 1006 }
1002 1007
1003 /** 1008 /**
1004 * Adds a page to the current folder. This is called by the 1009 * Adds a page to the current folder. This is called by the
1005 * add-new-bookmark-command handler. 1010 * add-new-bookmark-command handler.
1006 */ 1011 */
1007 function addPage() { 1012 function addPage() {
1008 var parentId = computeParentFolderForNewItem(); 1013 var parentId = computeParentFolderForNewItem();
1009 1014
1010 function editNewBookmark() { 1015 function editNewBookmark() {
1011 var fakeNode = { 1016 var fakeNode = {
1012 title: '', 1017 title: '',
1013 url: '', 1018 url: '',
1014 parentId: parentId, 1019 parentId: parentId,
1015 id: 'new' 1020 id: 'new'
1016 }; 1021 };
1017 var dataModel = list.dataModel; 1022 var dataModel = $('list').dataModel;
1018 var length = dataModel.length; 1023 var length = dataModel.length;
1019 dataModel.splice(length, 0, fakeNode); 1024 dataModel.splice(length, 0, fakeNode);
1020 var sm = list.selectionModel; 1025 var sm = $('list').selectionModel;
1021 sm.anchorIndex = sm.leadIndex = sm.selectedIndex = length; 1026 sm.anchorIndex = sm.leadIndex = sm.selectedIndex = length;
1022 scrollIntoViewAndMakeEditable(length); 1027 scrollIntoViewAndMakeEditable(length);
1023 }; 1028 };
1024 1029
1025 navigateTo(parentId, editNewBookmark); 1030 navigateTo(parentId, editNewBookmark);
1026 } 1031 }
1027 1032
1028 /** 1033 /**
1029 * This function is used to select items after a user action such as paste, drop 1034 * This function is used to select items after a user action such as paste, drop
1030 * add page etc. 1035 * add page etc.
1031 * @param {BookmarkList|BookmarkTree} target The target of the user action. 1036 * @param {BookmarkList|BookmarkTree} target The target of the user action.
1032 * @param {=string} opt_selectedTreeId If provided, then select that tree id. 1037 * @param {string=} opt_selectedTreeId If provided, then select that tree id.
1033 */ 1038 */
1034 function selectItemsAfterUserAction(target, opt_selectedTreeId) { 1039 function selectItemsAfterUserAction(target, opt_selectedTreeId) {
1035 // We get one onCreated event per item so we delay the handling until we get 1040 // We get one onCreated event per item so we delay the handling until we get
1036 // no more events coming. 1041 // no more events coming.
1037 1042
1038 var ids = []; 1043 var ids = [];
1039 var timer; 1044 var timer;
1040 1045
1041 function handle(id, bookmarkNode) { 1046 function handle(id, bookmarkNode) {
1042 clearTimeout(timer); 1047 clearTimeout(timer);
1043 if (opt_selectedTreeId || list.parentId == bookmarkNode.parentId) 1048 if (opt_selectedTreeId || $('list').parentId == bookmarkNode.parentId)
1044 ids.push(id); 1049 ids.push(id);
1045 timer = setTimeout(handleTimeout, 50); 1050 timer = setTimeout(handleTimeout, 50);
1046 } 1051 }
1047 1052
1048 function handleTimeout() { 1053 function handleTimeout() {
1049 chrome.bookmarks.onCreated.removeListener(handle); 1054 chrome.bookmarks.onCreated.removeListener(handle);
1050 chrome.bookmarks.onMoved.removeListener(handle); 1055 chrome.bookmarks.onMoved.removeListener(handle);
1051 1056
1052 if (opt_selectedTreeId && ids.indexOf(opt_selectedTreeId) != -1) { 1057 if (opt_selectedTreeId && ids.indexOf(opt_selectedTreeId) != -1) {
1053 var index = ids.indexOf(opt_selectedTreeId); 1058 var index = ids.indexOf(opt_selectedTreeId);
1054 if (index != -1 && opt_selectedTreeId in bmm.treeLookup) { 1059 if (index != -1 && opt_selectedTreeId in bmm.treeLookup) {
1055 tree.selectedItem = bmm.treeLookup[opt_selectedTreeId]; 1060 $('tree').selectedItem = bmm.treeLookup[opt_selectedTreeId];
1056 } 1061 }
1057 } else if (target == list) { 1062 } else if (target == $('list')) {
1058 var dataModel = list.dataModel; 1063 var dataModel = $('list').dataModel;
1059 var firstIndex = dataModel.findIndexById(ids[0]); 1064 var firstIndex = dataModel.findIndexById(ids[0]);
1060 var lastIndex = dataModel.findIndexById(ids[ids.length - 1]); 1065 var lastIndex = dataModel.findIndexById(ids[ids.length - 1]);
1061 if (firstIndex != -1 && lastIndex != -1) { 1066 if (firstIndex != -1 && lastIndex != -1) {
1062 var selectionModel = list.selectionModel; 1067 var selectionModel = $('list').selectionModel;
1063 selectionModel.selectedIndex = -1; 1068 selectionModel.selectedIndex = -1;
1064 selectionModel.selectRange(firstIndex, lastIndex); 1069 selectionModel.selectRange(firstIndex, lastIndex);
1065 selectionModel.anchorIndex = selectionModel.leadIndex = lastIndex; 1070 selectionModel.anchorIndex = selectionModel.leadIndex = lastIndex;
1066 list.focus(); 1071 $('list').focus();
1067 } 1072 }
1068 } 1073 }
1069 1074
1070 list.endBatchUpdates(); 1075 $('list').endBatchUpdates();
1071 } 1076 }
1072 1077
1073 list.startBatchUpdates(); 1078 $('list').startBatchUpdates();
1074 1079
1075 chrome.bookmarks.onCreated.addListener(handle); 1080 chrome.bookmarks.onCreated.addListener(handle);
1076 chrome.bookmarks.onMoved.addListener(handle); 1081 chrome.bookmarks.onMoved.addListener(handle);
1077 timer = setTimeout(handleTimeout, 300); 1082 timer = setTimeout(handleTimeout, 300);
1078 } 1083 }
1079 1084
1080 /** 1085 /**
1081 * Record user action. 1086 * Record user action.
1082 * @param {string} name An user action name. 1087 * @param {string} name An user action name.
1083 */ 1088 */
1084 function recordUserAction(name) { 1089 function recordUserAction(name) {
1085 chrome.metricsPrivate.recordUserAction('BookmarkManager_Command_' + name); 1090 chrome.metricsPrivate.recordUserAction('BookmarkManager_Command_' + name);
1086 } 1091 }
1087 1092
1088 /** 1093 /**
1089 * The currently selected bookmark, based on where the user is clicking. 1094 * The currently selected bookmark, based on where the user is clicking.
1090 * @return {string} The ID of the currently selected bookmark (could be from 1095 * @return {string} The ID of the currently selected bookmark (could be from
1091 * tree view or list view). 1096 * tree view or list view).
1092 */ 1097 */
1093 function getSelectedId() { 1098 function getSelectedId() {
1094 if (document.activeElement == tree) 1099 if (document.activeElement == $('tree'))
1095 return tree.selectedItem.bookmarkId; 1100 return $('tree').selectedItem.bookmarkId;
1096 var selectedItem = list.selectedItem; 1101 var selectedItem = $('list').selectedItem;
1097 return selectedItem && bmm.isFolder(selectedItem) ? 1102 return selectedItem && bmm.isFolder(selectedItem) ?
1098 selectedItem.id : tree.selectedItem.bookmarkId; 1103 selectedItem.id : $('tree').selectedItem.bookmarkId;
1099 } 1104 }
1100 1105
1101 /** 1106 /**
1102 * Pastes the copied/cutted bookmark into the right location depending whether 1107 * Pastes the copied/cutted bookmark into the right location depending whether
1103 * if it was called from Organize Menu or from Context Menu. 1108 * if it was called from Organize Menu or from Context Menu.
1104 * @param {string} id The id of the element being pasted from. 1109 * @param {string} id The id of the element being pasted from.
1105 */ 1110 */
1106 function pasteBookmark(id) { 1111 function pasteBookmark(id) {
1107 recordUserAction('Paste'); 1112 recordUserAction('Paste');
1108 selectItemsAfterUserAction(list); 1113 selectItemsAfterUserAction(/** @type {BookmarkList} */($('list')));
1109 chrome.bookmarkManagerPrivate.paste(id, getSelectedBookmarkIds()); 1114 chrome.bookmarkManagerPrivate.paste(id, getSelectedBookmarkIds());
1110 } 1115 }
1111 1116
1112 /** 1117 /**
1113 * Returns true if child is contained in another selected folder. 1118 * Returns true if child is contained in another selected folder.
1114 * Traces parent nodes up the tree until a selected ancestor or root is found. 1119 * Traces parent nodes up the tree until a selected ancestor or root is found.
1115 */ 1120 */
1116 function hasSelectedAncestor(parentNode) { 1121 function hasSelectedAncestor(parentNode) {
1117 function contains(arr, item) { 1122 function contains(arr, item) {
1118 for (var i = 0; i < arr.length; i++) 1123 for (var i = 0; i < arr.length; i++)
1119 if (arr[i] === item) 1124 if (arr[i] === item)
1120 return true; 1125 return true;
1121 return false; 1126 return false;
1122 } 1127 }
1123 1128
1124 // Don't search top level, cannot select permanent nodes in search. 1129 // Don't search top level, cannot select permanent nodes in search.
1125 if (parentNode == null || parentNode.id <= 2) 1130 if (parentNode == null || parentNode.id <= 2)
1126 return false; 1131 return false;
1127 1132
1128 // Found selected ancestor. 1133 // Found selected ancestor.
1129 if (contains(getSelectedBookmarkNodes(), parentNode)) 1134 if (contains(getSelectedBookmarkNodes(), parentNode))
1130 return true; 1135 return true;
1131 1136
1132 // Keep digging. 1137 // Keep digging.
1133 return hasSelectedAncestor(tree.getBookmarkNodeById(parentNode.parentId)); 1138 return hasSelectedAncestor(
1139 $('tree').getBookmarkNodeById(parentNode.parentId));
1134 } 1140 }
1135 1141
1136 function getFilteredSelectedBookmarkIds() { 1142 function getFilteredSelectedBookmarkIds() {
1137 // Remove duplicates from filteredIds and return. 1143 // Remove duplicates from filteredIds and return.
1138 var filteredIds = new Array(); 1144 var filteredIds = new Array();
1139 // Selected nodes to iterate through for matches. 1145 // Selected nodes to iterate through for matches.
1140 var nodes = getSelectedBookmarkNodes(); 1146 var nodes = getSelectedBookmarkNodes();
1141 1147
1142 for (var i = 0; i < nodes.length; i++) 1148 for (var i = 0; i < nodes.length; i++)
1143 if (!hasSelectedAncestor(tree.getBookmarkNodeById(nodes[i].parentId))) 1149 if (!hasSelectedAncestor($('tree').getBookmarkNodeById(nodes[i].parentId)))
1144 filteredIds.splice(0, 0, nodes[i].id); 1150 filteredIds.splice(0, 0, nodes[i].id);
1145 1151
1146 return filteredIds; 1152 return filteredIds;
1147 } 1153 }
1148 1154
1149 /** 1155 /**
1150 * Handler for the command event. This is used for context menu of list/tree 1156 * Handler for the command event. This is used for context menu of list/tree
1151 * and organized menu. 1157 * and organized menu.
1152 * @param {!Event} e The event object. 1158 * @param {!Event} e The event object.
1153 */ 1159 */
(...skipping 17 matching lines...) Expand all
1171 recordUserAction('UndoNone'); 1177 recordUserAction('UndoNone');
1172 } 1178 }
1173 break; 1179 break;
1174 case 'show-in-folder-command': 1180 case 'show-in-folder-command':
1175 recordUserAction('ShowInFolder'); 1181 recordUserAction('ShowInFolder');
1176 showInFolder(); 1182 showInFolder();
1177 break; 1183 break;
1178 case 'open-in-new-tab-command': 1184 case 'open-in-new-tab-command':
1179 case 'open-in-background-tab-command': 1185 case 'open-in-background-tab-command':
1180 recordUserAction('OpenInNewTab'); 1186 recordUserAction('OpenInNewTab');
1181 openBookmarks(LinkKind.BACKGROUND_TAB, e.target); 1187 openBookmarks(LinkKind.BACKGROUND_TAB,
1188 assertInstanceof(e.target, HTMLElement));
1182 break; 1189 break;
1183 case 'open-in-new-window-command': 1190 case 'open-in-new-window-command':
1184 recordUserAction('OpenInNewWindow'); 1191 recordUserAction('OpenInNewWindow');
1185 openBookmarks(LinkKind.WINDOW, e.target); 1192 openBookmarks(LinkKind.WINDOW,
1193 assertInstanceof(e.target, HTMLElement));
1186 break; 1194 break;
1187 case 'open-incognito-window-command': 1195 case 'open-incognito-window-command':
1188 recordUserAction('OpenIncognito'); 1196 recordUserAction('OpenIncognito');
1189 openBookmarks(LinkKind.INCOGNITO, e.target); 1197 openBookmarks(LinkKind.INCOGNITO,
1198 assertInstanceof(e.target, HTMLElement));
1190 break; 1199 break;
1191 case 'delete-command': 1200 case 'delete-command':
1192 recordUserAction('Delete'); 1201 recordUserAction('Delete');
1193 deleteBookmarks(); 1202 deleteBookmarks();
1194 break; 1203 break;
1195 case 'copy-command': 1204 case 'copy-command':
1196 recordUserAction('Copy'); 1205 recordUserAction('Copy');
1197 chrome.bookmarkManagerPrivate.copy(getSelectedBookmarkIds(), 1206 chrome.bookmarkManagerPrivate.copy(getSelectedBookmarkIds(),
1198 updatePasteCommand); 1207 updatePasteCommand);
1199 break; 1208 break;
1200 case 'cut-command': 1209 case 'cut-command':
1201 recordUserAction('Cut'); 1210 recordUserAction('Cut');
1202 chrome.bookmarkManagerPrivate.cut(getSelectedBookmarkIds(), 1211 chrome.bookmarkManagerPrivate.cut(getSelectedBookmarkIds(),
1203 function() { 1212 function() {
1204 updatePasteCommand(); 1213 updatePasteCommand();
1205 updateSearchResults(); 1214 updateSearchResults();
1206 }); 1215 });
1207 break; 1216 break;
1208 case 'paste-from-organize-menu-command': 1217 case 'paste-from-organize-menu-command':
1209 pasteBookmark(list.parentId); 1218 pasteBookmark($('list').parentId);
1210 break; 1219 break;
1211 case 'paste-from-context-menu-command': 1220 case 'paste-from-context-menu-command':
1212 pasteBookmark(getSelectedId()); 1221 pasteBookmark(getSelectedId());
1213 break; 1222 break;
1214 case 'sort-command': 1223 case 'sort-command':
1215 recordUserAction('Sort'); 1224 recordUserAction('Sort');
1216 chrome.bookmarkManagerPrivate.sortChildren(list.parentId); 1225 chrome.bookmarkManagerPrivate.sortChildren($('list').parentId);
1217 break; 1226 break;
1218 case 'rename-folder-command': 1227 case 'rename-folder-command':
1219 editSelectedItem(); 1228 editSelectedItem();
1220 break; 1229 break;
1221 case 'edit-command': 1230 case 'edit-command':
1222 recordUserAction('Edit'); 1231 recordUserAction('Edit');
1223 editSelectedItem(); 1232 editSelectedItem();
1224 break; 1233 break;
1225 case 'new-folder-command': 1234 case 'new-folder-command':
1226 recordUserAction('NewFolder'); 1235 recordUserAction('NewFolder');
(...skipping 12 matching lines...) Expand all
1239 undoDelete(); 1248 undoDelete();
1240 break; 1249 break;
1241 } 1250 }
1242 } 1251 }
1243 1252
1244 // Execute the copy, cut and paste commands when those events are dispatched by 1253 // Execute the copy, cut and paste commands when those events are dispatched by
1245 // the browser. This allows us to rely on the browser to handle the keyboard 1254 // the browser. This allows us to rely on the browser to handle the keyboard
1246 // shortcuts for these commands. 1255 // shortcuts for these commands.
1247 function installEventHandlerForCommand(eventName, commandId) { 1256 function installEventHandlerForCommand(eventName, commandId) {
1248 function handle(e) { 1257 function handle(e) {
1249 if (document.activeElement != list && document.activeElement != tree) 1258 if (document.activeElement != $('list') &&
1259 document.activeElement != $('tree'))
1250 return; 1260 return;
1251 var command = $(commandId); 1261 var command = $(commandId);
1252 if (!command.disabled) { 1262 if (!command.disabled) {
1253 command.execute(); 1263 command.execute();
1254 if (e) 1264 if (e)
1255 e.preventDefault(); // Prevent the system beep. 1265 e.preventDefault(); // Prevent the system beep.
1256 } 1266 }
1257 } 1267 }
1258 if (eventName == 'paste') { 1268 if (eventName == 'paste') {
1259 // Paste is a bit special since we need to do an async call to see if we 1269 // Paste is a bit special since we need to do an async call to see if we
1260 // can paste because the paste command might not be up to date. 1270 // can paste because the paste command might not be up to date.
1261 document.addEventListener(eventName, function(e) { 1271 document.addEventListener(eventName, function(e) {
1262 updatePasteCommand(handle); 1272 updatePasteCommand(handle);
1263 }); 1273 });
1264 } else { 1274 } else {
1265 document.addEventListener(eventName, handle); 1275 document.addEventListener(eventName, handle);
1266 } 1276 }
1267 } 1277 }
1268 1278
1269 function initializeSplitter() { 1279 function initializeSplitter() {
1270 var splitter = document.querySelector('.main > .splitter'); 1280 var splitter = document.querySelector('.main > .splitter');
1271 Splitter.decorate(splitter); 1281 Splitter.decorate(splitter);
1272 1282
1273 // The splitter persists the size of the left component in the local store. 1283 // The splitter persists the size of the left component in the local store.
1274 if ('treeWidth' in localStorage) 1284 if ('treeWidth' in window.localStorage)
1275 splitter.previousElementSibling.style.width = localStorage['treeWidth']; 1285 splitter.previousElementSibling.style.width =
1286 window.localStorage['treeWidth'];
1276 1287
1277 splitter.addEventListener('resize', function(e) { 1288 splitter.addEventListener('resize', function(e) {
1278 localStorage['treeWidth'] = splitter.previousElementSibling.style.width; 1289 window.localStorage['treeWidth'] =
1290 splitter.previousElementSibling.style.width;
1279 }); 1291 });
1280 } 1292 }
1281 1293
1282 function initializeBookmarkManager() { 1294 function initializeBookmarkManager() {
1283 // Sometimes the extension API is not initialized. 1295 // Sometimes the extension API is not initialized.
1284 if (!chrome.bookmarks) 1296 if (!chrome.bookmarks)
1285 console.error('Bookmarks extension API is not available'); 1297 console.error('Bookmarks extension API is not available');
1286 1298
1287 chrome.bookmarkManagerPrivate.getStrings(continueInitializeBookmarkManager); 1299 chrome.bookmarkManagerPrivate.getStrings(continueInitializeBookmarkManager);
1288 } 1300 }
1289 1301
1290 function continueInitializeBookmarkManager(localizedStrings) { 1302 function continueInitializeBookmarkManager(localizedStrings) {
1291 loadLocalizedStrings(localizedStrings); 1303 loadLocalizedStrings(localizedStrings);
1292 1304
1293 bmm.treeLookup[searchTreeItem.bookmarkId] = searchTreeItem; 1305 bmm.treeLookup[searchTreeItem.bookmarkId] = searchTreeItem;
1294 1306
1295 cr.ui.decorate('menu', Menu); 1307 cr.ui.decorate('menu', Menu);
1296 cr.ui.decorate('button[menu]', MenuButton); 1308 cr.ui.decorate('button[menu]', MenuButton);
1297 cr.ui.decorate('command', Command); 1309 cr.ui.decorate('command', Command);
1298 BookmarkList.decorate(list); 1310 BookmarkList.decorate($('list'));
1299 BookmarkTree.decorate(tree); 1311 BookmarkTree.decorate($('tree'));
1300 1312
1301 list.addEventListener('canceledit', handleCancelEdit); 1313 $('list').addEventListener('canceledit', handleCancelEdit);
1302 list.addEventListener('canExecute', handleCanExecuteForList); 1314 $('list').addEventListener('canExecute', handleCanExecuteForList);
1303 list.addEventListener('change', updateAllCommands); 1315 $('list').addEventListener('change', updateAllCommands);
1304 list.addEventListener('contextmenu', updateEditingCommands); 1316 $('list').addEventListener('contextmenu', updateEditingCommands);
1305 list.addEventListener('dblclick', handleDoubleClickForList); 1317 $('list').addEventListener('dblclick', handleDoubleClickForList);
1306 list.addEventListener('edit', handleEdit); 1318 $('list').addEventListener('edit', handleEdit);
1307 list.addEventListener('rename', handleRename); 1319 $('list').addEventListener('rename', handleRename);
1308 list.addEventListener('urlClicked', handleUrlClickedForList); 1320 $('list').addEventListener('urlClicked', handleUrlClickedForList);
1309 1321
1310 tree.addEventListener('canExecute', handleCanExecuteForTree); 1322 $('tree').addEventListener('canExecute', handleCanExecuteForTree);
1311 tree.addEventListener('change', handleChangeForTree); 1323 $('tree').addEventListener('change', handleChangeForTree);
1312 tree.addEventListener('contextmenu', updateEditingCommands); 1324 $('tree').addEventListener('contextmenu', updateEditingCommands);
1313 tree.addEventListener('rename', handleRename); 1325 $('tree').addEventListener('rename', handleRename);
1314 tree.addEventListener('load', handleLoadForTree); 1326 $('tree').addEventListener('load', handleLoadForTree);
1315 1327
1316 cr.ui.contextMenuHandler.addContextMenuProperty(tree); 1328 cr.ui.contextMenuHandler.addContextMenuProperty(
1317 list.contextMenu = $('context-menu'); 1329 /** @type {!Element} */($('tree')));
1318 tree.contextMenu = $('context-menu'); 1330 $('list').contextMenu = $('context-menu');
1331 $('tree').contextMenu = $('context-menu');
1319 1332
1320 // We listen to hashchange so that we can update the currently shown folder 1333 // We listen to hashchange so that we can update the currently shown folder
1321 // when // the user goes back and forward in the history. 1334 // when // the user goes back and forward in the history.
1322 window.addEventListener('hashchange', processHash); 1335 window.addEventListener('hashchange', processHash);
1323 1336
1324 document.querySelector('header form').onsubmit = function(e) { 1337 document.querySelector('header form').onsubmit =
1338 /** @type {function(Event=)} */(function(e) {
1325 setSearch($('term').value); 1339 setSearch($('term').value);
1326 e.preventDefault(); 1340 e.preventDefault();
1327 }; 1341 });
1328 1342
1329 $('term').addEventListener('search', handleSearch); 1343 $('term').addEventListener('search', handleSearch);
1330 1344
1331 document.querySelector('.summary button').addEventListener( 1345 document.querySelector('.summary button').addEventListener(
1332 'click', handleOrganizeButtonClick); 1346 'click', handleOrganizeButtonClick);
1333 1347
1334 document.addEventListener('canExecute', handleCanExecuteForDocument); 1348 document.addEventListener('canExecute', handleCanExecuteForDocument);
1335 document.addEventListener('command', handleCommand); 1349 document.addEventListener('command', handleCommand);
1336 1350
1337 // Listen to copy, cut and paste events and execute the associated commands. 1351 // Listen to copy, cut and paste events and execute the associated commands.
(...skipping 26 matching lines...) Expand all
1364 }); 1378 });
1365 1379
1366 chrome.bookmarkManagerPrivate.canOpenNewWindows(function(result) { 1380 chrome.bookmarkManagerPrivate.canOpenNewWindows(function(result) {
1367 canOpenNewWindows = result; 1381 canOpenNewWindows = result;
1368 }); 1382 });
1369 1383
1370 cr.ui.FocusOutlineManager.forDocument(document); 1384 cr.ui.FocusOutlineManager.forDocument(document);
1371 initializeSplitter(); 1385 initializeSplitter();
1372 bmm.addBookmarkModelListeners(); 1386 bmm.addBookmarkModelListeners();
1373 dnd.init(selectItemsAfterUserAction); 1387 dnd.init(selectItemsAfterUserAction);
1374 tree.reload(); 1388 $('tree').reload();
1375 } 1389 }
1376 1390
1377 initializeBookmarkManager(); 1391 initializeBookmarkManager();
1378 })(); 1392 })();
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698