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

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

Issue 11280208: Re-factor navigateTo() in bookmark_manager/js/main.js (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: 2012-11-28T17:45 Created 8 years 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 | Annotate | Revision Log
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 /** @const */ var BookmarkList = bmm.BookmarkList; 5 /** @const */ var BookmarkList = bmm.BookmarkList;
6 /** @const */ var BookmarkTree = bmm.BookmarkTree; 6 /** @const */ var BookmarkTree = bmm.BookmarkTree;
7 /** @const */ var Command = cr.ui.Command; 7 /** @const */ var Command = cr.ui.Command;
8 /** @const */ var CommandBinding = cr.ui.CommandBinding; 8 /** @const */ var CommandBinding = cr.ui.CommandBinding;
9 /** @const */ var LinkKind = cr.LinkKind; 9 /** @const */ var LinkKind = cr.LinkKind;
10 /** @const */ var ListItem = cr.ui.ListItem; 10 /** @const */ var ListItem = cr.ui.ListItem;
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after
93 93
94 var recentTreeItem = new TreeItem({ 94 var recentTreeItem = new TreeItem({
95 icon: 'images/bookmark_manager_recent.png', 95 icon: 'images/bookmark_manager_recent.png',
96 bookmarkId: 'recent' 96 bookmarkId: 'recent'
97 }); 97 });
98 bmm.treeLookup[recentTreeItem.bookmarkId] = recentTreeItem; 98 bmm.treeLookup[recentTreeItem.bookmarkId] = recentTreeItem;
99 99
100 BookmarkTree.decorate(tree); 100 BookmarkTree.decorate(tree);
101 101
102 tree.addEventListener('change', function() { 102 tree.addEventListener('change', function() {
103 navigateTo(tree.selectedItem.bookmarkId); 103 navigateTo(tree.selectedItem.bookmarkId, updateHash);
104 }); 104 });
105 105
106 /** 106 /**
107 * Adds an event listener to a node that will remove itself after firing once. 107 * Adds an event listener to a node that will remove itself after firing once.
108 * @param {!Element} node The DOM node to add the listener to. 108 * @param {!Element} node The DOM node to add the listener to.
109 * @param {string} name The name of the event listener to add to. 109 * @param {string} name The name of the event listener to add to.
110 * @param {function(Event)} handler Function called when the event fires. 110 * @param {function(Event)} handler Function called when the event fires.
111 */ 111 */
112 function addOneShotEventListener(node, name, handler) { 112 function addOneShotEventListener(node, name, handler) {
113 var f = function(e) { 113 var f = function(e) {
114 handler(e); 114 handler(e);
115 node.removeEventListener(name, f); 115 node.removeEventListener(name, f);
116 }; 116 };
117 node.addEventListener(name, f); 117 node.addEventListener(name, f);
118 } 118 }
119 119
120 /** 120 /**
121 * Updates the location hash to reflect the current state of the application. 121 * Updates the location hash to reflect the current state of the application.
122 */ 122 */
123 function updateHash() { 123 function updateHash() {
124 window.location.hash = tree.selectedItem.bookmarkId; 124 window.location.hash = tree.selectedItem.bookmarkId;
125 } 125 }
126 126
127 /** 127 /**
128 * Navigates to a bookmark ID. 128 * Navigates to a bookmark ID.
129 * @param {string} id The ID to navigate to. 129 * @param {string} id The ID to navigate to.
130 * @param {boolean=} opt_updateHashNow Whether to immediately update the 130 * @param {function()} callback Function called when list view loaded or
131 * location.hash. If false, then it is updated in a timeout. 131 * displayed specified folder.
132 */ 132 */
133 function navigateTo(id, opt_updateHashNow) { 133 function navigateTo(id, callback) {
134 // console.info('navigateTo', 'from', window.location.hash, 'to', id); 134 if (list.parentId == id) {
135 // Update the location hash using a timer to prevent reentrancy. This is how 135 callback();
136 // often we add history entries and the time here is a bit arbitrary but was 136 return;
137 // picked as the smallest time a human perceives as instant. 137 }
138 138
139 clearTimeout(navigateTo.timer_); 139 addOneShotEventListener(list, 'load', callback);
140 if (opt_updateHashNow)
141 updateHash();
142 else
143 navigateTo.timer_ = setTimeout(updateHash, 250);
144
145 updateParentId(id); 140 updateParentId(id);
146 } 141 }
147 142
148 /** 143 /**
149 * Updates the parent ID of the bookmark list and selects the correct tree item. 144 * Updates the parent ID of the bookmark list and selects the correct tree item.
150 * @param {string} id The id. 145 * @param {string} id The id.
151 */ 146 */
152 function updateParentId(id) { 147 function updateParentId(id) {
148 // Setting list.parentId fires 'load' event.
153 list.parentId = id; 149 list.parentId = id;
154 if (id in bmm.treeLookup) 150
155 tree.selectedItem = bmm.treeLookup[id]; 151 // When tree.selectedItem changed, tree view calls navigatTo() then it
152 // calls updateHash() when list view displayed specified folder.
153 tree.selectedItem = bmm.treeLookup[id] || tree.selectedItem;
156 } 154 }
157 155
158 // Process the location hash. This is called by onhashchange and when the page 156 // Process the location hash. This is called by onhashchange and when the page
159 // is first loaded. 157 // is first loaded.
160 function processHash() { 158 function processHash() {
161 var id = window.location.hash.slice(1); 159 var id = window.location.hash.slice(1);
162 if (!id) { 160 if (!id) {
163 // If we do not have a hash, select first item in the tree. 161 // If we do not have a hash, select first item in the tree.
164 id = tree.items[0].bookmarkId; 162 id = tree.items[0].bookmarkId;
165 } 163 }
(...skipping 12 matching lines...) Expand all
178 // After the list reloads, edit the desired bookmark. 176 // After the list reloads, edit the desired bookmark.
179 var editBookmark = function(e) { 177 var editBookmark = function(e) {
180 var index = list.dataModel.findIndexById(bookmarkNode.id); 178 var index = list.dataModel.findIndexById(bookmarkNode.id);
181 if (index != -1) { 179 if (index != -1) {
182 var sm = list.selectionModel; 180 var sm = list.selectionModel;
183 sm.anchorIndex = sm.leadIndex = sm.selectedIndex = index; 181 sm.anchorIndex = sm.leadIndex = sm.selectedIndex = index;
184 scrollIntoViewAndMakeEditable(index); 182 scrollIntoViewAndMakeEditable(index);
185 } 183 }
186 }; 184 };
187 185
188 if (list.parentId == bookmarkNode.parentId) { 186 navigateTo(bookmarkNode.parentId, editBookmark);
189 // Clear the e= from the hash so that future attemps to edit the same
190 // entry will show up as a hash change.
191 updateHash();
192 editBookmark();
193 } else {
194 // Navigate to the parent folder (which will update the hash). Once
195 // it's loaded, edit the bookmark.
196 addOneShotEventListener(list, 'load', editBookmark);
197 updateParentId(bookmarkNode.parentId);
198 }
199 }); 187 });
200 188
201 // We handle the two cases of navigating to the bookmark to be edited 189 // We handle the two cases of navigating to the bookmark to be edited
202 // above. Don't run the standard navigation code below. 190 // above. Don't run the standard navigation code below.
203 return; 191 return;
204 } else if (/^q=/.test(id)) { 192 } else if (/^q=/.test(id)) {
205 // In case we got a search hash, update the text input and the 193 // In case we got a search hash, update the text input and the
206 // bmm.treeLookup to use the new id. 194 // bmm.treeLookup to use the new id.
207 setSearch(id.slice(2)); 195 setSearch(id.slice(2));
208 valid = true; 196 valid = true;
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
264 if (searchText) { 252 if (searchText) {
265 tree.add(searchTreeItem); 253 tree.add(searchTreeItem);
266 tree.selectedItem = searchTreeItem; 254 tree.selectedItem = searchTreeItem;
267 } else { 255 } else {
268 // Go "home". 256 // Go "home".
269 tree.selectedItem = tree.items[0]; 257 tree.selectedItem = tree.items[0];
270 id = tree.selectedItem.bookmarkId; 258 id = tree.selectedItem.bookmarkId;
271 } 259 }
272 260
273 // Navigate now and update hash immediately. 261 // Navigate now and update hash immediately.
274 navigateTo(id, true); 262 navigateTo(id, updateHash);
275 } 263 }
276 264
277 // Handle the logo button UI. 265 // Handle the logo button UI.
278 // When the user clicks the button we should navigate "home" and focus the list. 266 // When the user clicks the button we should navigate "home" and focus the list.
279 document.querySelector('button.logo').onclick = function(e) { 267 document.querySelector('button.logo').onclick = function(e) {
280 setSearch(''); 268 setSearch('');
281 $('list').focus(); 269 $('list').focus();
282 }; 270 };
283 271
284 /** 272 /**
(...skipping 1009 matching lines...) Expand 10 before | Expand all | Expand 10 after
1294 dataModel.splice(index, 1); 1282 dataModel.splice(index, 1);
1295 } 1283 }
1296 }); 1284 });
1297 1285
1298 /** 1286 /**
1299 * Navigates to the folder that the selected item is in and selects it. This is 1287 * Navigates to the folder that the selected item is in and selects it. This is
1300 * used for the show-in-folder command. 1288 * used for the show-in-folder command.
1301 */ 1289 */
1302 function showInFolder() { 1290 function showInFolder() {
1303 var bookmarkNode = list.selectedItem; 1291 var bookmarkNode = list.selectedItem;
1292 if (!bookmarkNode)
1293 return;
1304 var parentId = bookmarkNode.parentId; 1294 var parentId = bookmarkNode.parentId;
1305 1295
1306 // After the list is loaded we should select the revealed item. 1296 // After the list is loaded we should select the revealed item.
1307 function f(e) { 1297 function selectItem() {
1308 var index; 1298 var index = list.dataModel.findIndexById(bookmarkNode.id);
1309 if (bookmarkNode && 1299 if (index == -1)
1310 (index = list.dataModel.findIndexById(bookmarkNode.id)) != -1) { 1300 return;
1311 var sm = list.selectionModel; 1301 var sm = list.selectionModel;
1312 sm.anchorIndex = sm.leadIndex = sm.selectedIndex = index; 1302 sm.anchorIndex = sm.leadIndex = sm.selectedIndex = index;
1313 list.scrollIndexIntoView(index); 1303 list.scrollIndexIntoView(index);
1314 }
1315 list.removeEventListener('load', f);
1316 } 1304 }
1317 list.addEventListener('load', f); 1305
1318 var treeItem = bmm.treeLookup[parentId]; 1306 var treeItem = bmm.treeLookup[parentId];
1319 treeItem.reveal(); 1307 treeItem.reveal();
1320 1308
1321 navigateTo(parentId); 1309 navigateTo(parentId, selectItem);
1322 } 1310 }
1323 1311
1324 var linkController; 1312 var linkController;
1325 1313
1326 /** 1314 /**
1327 * @return {!cr.LinkController} The link controller used to open links based on 1315 * @return {!cr.LinkController} The link controller used to open links based on
1328 * user clicks and keyboard actions. 1316 * user clicks and keyboard actions.
1329 */ 1317 */
1330 function getLinkController() { 1318 function getLinkController() {
1331 return linkController || 1319 return linkController ||
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after
1402 }); 1390 });
1403 } 1391 }
1404 1392
1405 /** 1393 /**
1406 * Opens an item in the list. 1394 * Opens an item in the list.
1407 */ 1395 */
1408 function openItem() { 1396 function openItem() {
1409 var bookmarkNodes = getSelectedBookmarkNodes(); 1397 var bookmarkNodes = getSelectedBookmarkNodes();
1410 // If we double clicked or pressed enter on a single folder, navigate to it. 1398 // If we double clicked or pressed enter on a single folder, navigate to it.
1411 if (bookmarkNodes.length == 1 && bmm.isFolder(bookmarkNodes[0])) { 1399 if (bookmarkNodes.length == 1 && bmm.isFolder(bookmarkNodes[0])) {
1412 navigateTo(bookmarkNodes[0].id); 1400 navigateTo(bookmarkNodes[0].id, updateHash);
1413 } else { 1401 } else {
1414 openBookmarks(LinkKind.FOREGROUND_TAB); 1402 openBookmarks(LinkKind.FOREGROUND_TAB);
1415 } 1403 }
1416 } 1404 }
1417 1405
1418 /** 1406 /**
1419 * Deletes the selected bookmarks. The bookmarks are saved in memory in case 1407 * Deletes the selected bookmarks. The bookmarks are saved in memory in case
1420 * the user needs to undo the deletion. 1408 * the user needs to undo the deletion.
1421 */ 1409 */
1422 function deleteBookmarks() { 1410 function deleteBookmarks() {
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after
1510 // Callback is called after tree and list data model updated. 1498 // Callback is called after tree and list data model updated.
1511 function createFolder(callback) { 1499 function createFolder(callback) {
1512 chrome.bookmarks.create({ 1500 chrome.bookmarks.create({
1513 title: loadTimeData.getString('new_folder_name'), 1501 title: loadTimeData.getString('new_folder_name'),
1514 parentId: parentId 1502 parentId: parentId
1515 }, callback); 1503 }, callback);
1516 } 1504 }
1517 1505
1518 if (document.activeElement == tree) { 1506 if (document.activeElement == tree) {
1519 createFolder(function(newNode) { 1507 createFolder(function(newNode) {
1520 newItem = bmm.treeLookup[newNode.id]; 1508 navigateTo(newNode.id, function() {
1521 tree.selectedItem = newItem; 1509 bmm.treeLookup[newNode.id].editing = true;
1522 newItem.editing = true; 1510 });
1523 }); 1511 });
1524 return; 1512 return;
1525 } 1513 }
1526 1514
1527 function editNewFolderInList() { 1515 function editNewFolderInList() {
1528 createFolder(function() { 1516 createFolder(function() {
1529 var index = list.dataModel.length - 1; 1517 var index = list.dataModel.length - 1;
1530 var sm = list.selectionModel; 1518 var sm = list.selectionModel;
1531 sm.anchorIndex = sm.leadIndex = sm.selectedIndex = index; 1519 sm.anchorIndex = sm.leadIndex = sm.selectedIndex = index;
1532 scrollIntoViewAndMakeEditable(index); 1520 scrollIntoViewAndMakeEditable(index);
1533 }); 1521 });
1534 } 1522 }
1535 1523
1536 if (parentId == list.parentId) { 1524 navigateTo(parentId, editNewFolderInList);
1537 editNewFolderInList();
1538 return;
1539 }
1540
1541 addOneShotEventListener(list, 'load', editNewFolderInList);
1542 navigateTo(parentId, true);
1543 } 1525 }
1544 1526
1545 /** 1527 /**
1546 * Scrolls the list item into view and makes it editable. 1528 * Scrolls the list item into view and makes it editable.
1547 * @param {number} index The index of the item to make editable. 1529 * @param {number} index The index of the item to make editable.
1548 */ 1530 */
1549 function scrollIntoViewAndMakeEditable(index) { 1531 function scrollIntoViewAndMakeEditable(index) {
1550 list.scrollIndexIntoView(index); 1532 list.scrollIndexIntoView(index);
1551 // onscroll is now dispatched asynchronously so we have to postpone 1533 // onscroll is now dispatched asynchronously so we have to postpone
1552 // the rest. 1534 // the rest.
(...skipping 19 matching lines...) Expand all
1572 id: 'new' 1554 id: 'new'
1573 }; 1555 };
1574 var dataModel = list.dataModel; 1556 var dataModel = list.dataModel;
1575 var length = dataModel.length; 1557 var length = dataModel.length;
1576 dataModel.splice(length, 0, fakeNode); 1558 dataModel.splice(length, 0, fakeNode);
1577 var sm = list.selectionModel; 1559 var sm = list.selectionModel;
1578 sm.anchorIndex = sm.leadIndex = sm.selectedIndex = length; 1560 sm.anchorIndex = sm.leadIndex = sm.selectedIndex = length;
1579 scrollIntoViewAndMakeEditable(length); 1561 scrollIntoViewAndMakeEditable(length);
1580 }; 1562 };
1581 1563
1582 if (parentId == list.parentId) { 1564 navigateTo(parentId, editNewBookmark);
1583 editNewBookmark();
1584 return;
1585 }
1586
1587 addOneShotEventListener(list, 'load', editNewBookmark);
1588 navigateTo(parentId, true);
1589 } 1565 }
1590 1566
1591 /** 1567 /**
1592 * This function is used to select items after a user action such as paste, drop 1568 * This function is used to select items after a user action such as paste, drop
1593 * add page etc. 1569 * add page etc.
1594 * @param {BookmarkList|BookmarkTree} target The target of the user action. 1570 * @param {BookmarkList|BookmarkTree} target The target of the user action.
1595 * @param {=string} opt_selectedTreeId If provided, then select that tree id. 1571 * @param {=string} opt_selectedTreeId If provided, then select that tree id.
1596 */ 1572 */
1597 function selectItemsAfterUserAction(target, opt_selectedTreeId) { 1573 function selectItemsAfterUserAction(target, opt_selectedTreeId) {
1598 // We get one onCreated event per item so we delay the handling until we get 1574 // We get one onCreated event per item so we delay the handling until we get
(...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after
1745 document.addEventListener('copy', handle('copy-command')); 1721 document.addEventListener('copy', handle('copy-command'));
1746 document.addEventListener('cut', handle('cut-command')); 1722 document.addEventListener('cut', handle('cut-command'));
1747 1723
1748 var pasteHandler = handle('paste-command'); 1724 var pasteHandler = handle('paste-command');
1749 document.addEventListener('paste', function(e) { 1725 document.addEventListener('paste', function(e) {
1750 // Paste is a bit special since we need to do an async call to see if we can 1726 // Paste is a bit special since we need to do an async call to see if we can
1751 // paste because the paste command might not be up to date. 1727 // paste because the paste command might not be up to date.
1752 updatePasteCommand(pasteHandler); 1728 updatePasteCommand(pasteHandler);
1753 }); 1729 });
1754 })(); 1730 })();
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698