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

Side by Side Diff: chrome/browser/resources/bookmark_manager/js/bmm/bookmark_list.js

Issue 543863002: Typecheck chrome://bookmarks using Closure Compiler (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@true_master
Patch Set: newest patchset Created 6 years, 2 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 // TODO(arv): Now that this is driven by a data model, implement a data model 5 // TODO(arv): Now that this is driven by a data model, implement a data model
6 // that handles the loading and the events from the bookmark backend. 6 // that handles the loading and the events from the bookmark backend.
7 7
8 /**
9 * @typedef {{childIds: Array.<string>}}
10 *
11 * @see chrome/common/extensions/api/bookmarks.json
12 */
13 var ReorderInfo;
14
15 /**
16 * @typedef {{parentId: string, index: number, oldParentId: string,
17 * oldIndex: number}}
18 *
19 * @see chrome/common/extensions/api/bookmarks.json
20 */
21 var MoveInfo;
22
8 cr.define('bmm', function() { 23 cr.define('bmm', function() {
9 var List = cr.ui.List; 24 var List = cr.ui.List;
10 var ListItem = cr.ui.ListItem; 25 var ListItem = cr.ui.ListItem;
11 var ArrayDataModel = cr.ui.ArrayDataModel; 26 var ArrayDataModel = cr.ui.ArrayDataModel;
12 var ContextMenuButton = cr.ui.ContextMenuButton; 27 var ContextMenuButton = cr.ui.ContextMenuButton;
13 28
14 var list;
15
16 /** 29 /**
17 * Basic array data model for use with bookmarks. 30 * Basic array data model for use with bookmarks.
18 * @param {!Array.<!BookmarkTreeNode>} items The bookmark items. 31 * @param {!Array.<!BookmarkTreeNode>} items The bookmark items.
19 * @constructor 32 * @constructor
20 * @extends {ArrayDataModel} 33 * @extends {ArrayDataModel}
21 */ 34 */
22 function BookmarksArrayDataModel(items) { 35 function BookmarksArrayDataModel(items) {
23 ArrayDataModel.call(this, items); 36 ArrayDataModel.call(this, items);
24 } 37 }
25 38
(...skipping 24 matching lines...) Expand all
50 while ((n = parent.lastChild)) { 63 while ((n = parent.lastChild)) {
51 parent.removeChild(n); 64 parent.removeChild(n);
52 } 65 }
53 parent.appendChild(newChild); 66 parent.appendChild(newChild);
54 } 67 }
55 68
56 /** 69 /**
57 * Creates a new bookmark list. 70 * Creates a new bookmark list.
58 * @param {Object=} opt_propertyBag Optional properties. 71 * @param {Object=} opt_propertyBag Optional properties.
59 * @constructor 72 * @constructor
60 * @extends {HTMLButtonElement} 73 * @extends {cr.ui.List}
61 */ 74 */
62 var BookmarkList = cr.ui.define('list'); 75 var BookmarkList = cr.ui.define('list');
63 76
64 BookmarkList.prototype = { 77 BookmarkList.prototype = {
65 __proto__: List.prototype, 78 __proto__: List.prototype,
66 79
67 /** @override */ 80 /** @override */
68 decorate: function() { 81 decorate: function() {
69 List.prototype.decorate.call(this); 82 List.prototype.decorate.call(this);
70 this.addEventListener('mousedown', this.handleMouseDown_); 83 this.addEventListener('mousedown', this.handleMouseDown_);
71 84
72 // HACK(arv): http://crbug.com/40902 85 // HACK(arv): http://crbug.com/40902
73 window.addEventListener('resize', this.redraw.bind(this)); 86 window.addEventListener('resize', this.redraw.bind(this));
74 87
75 // We could add the ContextMenuButton in the BookmarkListItem but it slows 88 // We could add the ContextMenuButton in the BookmarkListItem but it slows
76 // down redraws a lot so we do this on mouseovers instead. 89 // down redraws a lot so we do this on mouseovers instead.
77 this.addEventListener('mouseover', this.handleMouseOver_.bind(this)); 90 this.addEventListener('mouseover', this.handleMouseOver_.bind(this));
78
79 bmm.list = this;
80 }, 91 },
81 92
93 /**
94 * @param {!BookmarkTreeNode} bookmarkNode
95 * @override
96 */
82 createItem: function(bookmarkNode) { 97 createItem: function(bookmarkNode) {
83 return new BookmarkListItem(bookmarkNode); 98 return new BookmarkListItem(bookmarkNode);
84 }, 99 },
85 100
86 /** @private {string} */ 101 /** @private {string} */
87 parentId_: '', 102 parentId_: '',
88 103
89 /** @private {number} */ 104 /** @private {number} */
90 loadCount_: 0, 105 loadCount_: 0,
91 106
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after
191 var event = new Event('urlClicked', {bubbles: true}); 206 var event = new Event('urlClicked', {bubbles: true});
192 event.url = url; 207 event.url = url;
193 event.originalEvent = originalEvent; 208 event.originalEvent = originalEvent;
194 this.dispatchEvent(event); 209 this.dispatchEvent(event);
195 }, 210 },
196 211
197 /** 212 /**
198 * Handles mousedown events so that we can prevent the auto scroll as 213 * Handles mousedown events so that we can prevent the auto scroll as
199 * necessary. 214 * necessary.
200 * @private 215 * @private
201 * @param {!MouseEvent} e The mousedown event object. 216 * @param {!Event} e The mousedown event object.
202 */ 217 */
203 handleMouseDown_: function(e) { 218 handleMouseDown_: function(e) {
219 e = /** @type {!MouseEvent} */(e);
204 if (e.button == 1) { 220 if (e.button == 1) {
205 // WebKit no longer fires click events for middle clicks so we manually 221 // WebKit no longer fires click events for middle clicks so we manually
206 // listen to mouse up to dispatch a click event. 222 // listen to mouse up to dispatch a click event.
207 this.addEventListener('mouseup', this.handleMiddleMouseUp_); 223 this.addEventListener('mouseup', this.handleMiddleMouseUp_);
208 224
209 // When the user does a middle click we need to prevent the auto scroll 225 // When the user does a middle click we need to prevent the auto scroll
210 // in case the user is trying to middle click to open a bookmark in a 226 // in case the user is trying to middle click to open a bookmark in a
211 // background tab. 227 // background tab.
212 // We do not do this in case the target is an input since middle click 228 // We do not do this in case the target is an input since middle click
213 // is also paste on Linux and we don't want to break that. 229 // is also paste on Linux and we don't want to break that.
214 if (e.target.tagName != 'INPUT') 230 if (e.target.tagName != 'INPUT')
215 e.preventDefault(); 231 e.preventDefault();
216 } 232 }
217 }, 233 },
218 234
219 /** 235 /**
220 * WebKit no longer dispatches click events for middle clicks so we need 236 * WebKit no longer dispatches click events for middle clicks so we need
221 * to emulate it. 237 * to emulate it.
222 * @private 238 * @private
223 * @param {!MouseEvent} e The mouse up event object. 239 * @param {!Event} e The mouse up event object.
224 */ 240 */
225 handleMiddleMouseUp_: function(e) { 241 handleMiddleMouseUp_: function(e) {
242 e = /** @type {!MouseEvent} */(e);
226 this.removeEventListener('mouseup', this.handleMiddleMouseUp_); 243 this.removeEventListener('mouseup', this.handleMiddleMouseUp_);
227 if (e.button == 1) { 244 if (e.button == 1) {
228 var el = e.target; 245 var el = e.target;
229 while (el.parentNode != this) { 246 while (el.parentNode != this) {
230 el = el.parentNode; 247 el = el.parentNode;
231 } 248 }
232 var node = el.bookmarkNode; 249 var node = el.bookmarkNode;
233 if (node && !bmm.isFolder(node)) 250 if (node && !bmm.isFolder(node))
234 this.dispatchUrlClickedEvent_(node.url, e); 251 this.dispatchUrlClickedEvent_(node.url, e);
235 } 252 }
236 e.preventDefault(); 253 e.preventDefault();
237 }, 254 },
238 255
239 // Bookmark model update callbacks 256 // Bookmark model update callbacks
240 handleBookmarkChanged: function(id, changeInfo) { 257 handleBookmarkChanged: function(id, changeInfo) {
241 var dataModel = this.dataModel; 258 var dataModel = this.dataModel;
242 var index = dataModel.findIndexById(id); 259 var index = dataModel.findIndexById(id);
243 if (index != -1) { 260 if (index != -1) {
244 var bookmarkNode = this.dataModel.item(index); 261 var bookmarkNode = this.dataModel.item(index);
245 bookmarkNode.title = changeInfo.title; 262 bookmarkNode.title = changeInfo.title;
246 if ('url' in changeInfo) 263 if ('url' in changeInfo)
247 bookmarkNode.url = changeInfo['url']; 264 bookmarkNode.url = changeInfo['url'];
248 265
249 dataModel.updateIndex(index); 266 dataModel.updateIndex(index);
250 } 267 }
251 }, 268 },
252 269
270 /**
271 * @param {string} id
272 * @param {ReorderInfo} reorderInfo
273 */
253 handleChildrenReordered: function(id, reorderInfo) { 274 handleChildrenReordered: function(id, reorderInfo) {
254 if (this.parentId == id) { 275 if (this.parentId == id) {
255 // We create a new data model with updated items in the right order. 276 // We create a new data model with updated items in the right order.
256 var dataModel = this.dataModel; 277 var dataModel = this.dataModel;
257 var items = {}; 278 var items = {};
258 for (var i = this.dataModel.length - 1; i >= 0; i--) { 279 for (var i = this.dataModel.length - 1; i >= 0; i--) {
259 var bookmarkNode = dataModel.item(i); 280 var bookmarkNode = dataModel.item(i);
260 items[bookmarkNode.id] = bookmarkNode; 281 items[bookmarkNode.id] = bookmarkNode;
261 } 282 }
262 var newArray = []; 283 var newArray = [];
263 for (var i = 0; i < reorderInfo.childIds.length; i++) { 284 for (var i = 0; i < reorderInfo.childIds.length; i++) {
264 newArray[i] = items[reorderInfo.childIds[i]]; 285 newArray[i] = items[reorderInfo.childIds[i]];
265 newArray[i].index = i; 286 newArray[i].index = i;
266 } 287 }
267 288
268 this.dataModel = new BookmarksArrayDataModel(newArray); 289 this.dataModel = new BookmarksArrayDataModel(newArray);
269 } 290 }
270 }, 291 },
271 292
272 handleCreated: function(id, bookmarkNode) { 293 handleCreated: function(id, bookmarkNode) {
273 if (this.parentId == bookmarkNode.parentId) 294 if (this.parentId == bookmarkNode.parentId)
274 this.dataModel.splice(bookmarkNode.index, 0, bookmarkNode); 295 this.dataModel.splice(bookmarkNode.index, 0, bookmarkNode);
275 }, 296 },
276 297
298 /**
299 * @param {string} id
300 * @param {MoveInfo} moveInfo
301 */
277 handleMoved: function(id, moveInfo) { 302 handleMoved: function(id, moveInfo) {
278 if (moveInfo.parentId == this.parentId || 303 if (moveInfo.parentId == this.parentId ||
279 moveInfo.oldParentId == this.parentId) { 304 moveInfo.oldParentId == this.parentId) {
280 305
281 var dataModel = this.dataModel; 306 var dataModel = this.dataModel;
282 307
283 if (moveInfo.oldParentId == moveInfo.parentId) { 308 if (moveInfo.oldParentId == moveInfo.parentId) {
284 // Reorder within this folder 309 // Reorder within this folder
285 310
286 this.startBatchUpdates(); 311 this.startBatchUpdates();
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
337 // the size should not change since we already fixed the width. 362 // the size should not change since we already fixed the width.
338 window.setTimeout(function() { 363 window.setTimeout(function() {
339 list.style.width = ''; 364 list.style.width = '';
340 }, 0); 365 }, 0);
341 } 366 }
342 } 367 }
343 }; 368 };
344 369
345 /** 370 /**
346 * The ID of the bookmark folder we are displaying. 371 * The ID of the bookmark folder we are displaying.
347 * @type {string}
348 */ 372 */
349 cr.defineProperty(BookmarkList, 'parentId', cr.PropertyKind.JS, 373 cr.defineProperty(BookmarkList, 'parentId', cr.PropertyKind.JS,
350 function() { 374 function() {
351 this.reload(); 375 this.reload();
352 }); 376 });
353 377
354 /** 378 /**
355 * The contextMenu property. 379 * The contextMenu property.
356 * @type {cr.ui.Menu}
357 */ 380 */
358 cr.ui.contextMenuHandler.addContextMenuProperty(BookmarkList); 381 cr.ui.contextMenuHandler.addContextMenuProperty(BookmarkList);
382 /** @type {cr.ui.Menu} */
383 BookmarkList.prototype.contextMenu;
359 384
360 /** 385 /**
361 * Creates a new bookmark list item. 386 * Creates a new bookmark list item.
362 * @param {!BookmarkTreeNode} bookmarkNode The bookmark node this represents. 387 * @param {!BookmarkTreeNode} bookmarkNode The bookmark node this represents.
363 * @constructor 388 * @constructor
364 * @extends {cr.ui.ListItem} 389 * @extends {cr.ui.ListItem}
365 */ 390 */
366 function BookmarkListItem(bookmarkNode) { 391 function BookmarkListItem(bookmarkNode) {
367 var el = cr.doc.createElement('div'); 392 var el = cr.doc.createElement('div');
368 el.bookmarkNode = bookmarkNode; 393 el.bookmarkNode = bookmarkNode;
(...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after
500 listItem.editing = false; 525 listItem.editing = false;
501 } 526 }
502 }, 50); 527 }, 50);
503 } 528 }
504 529
505 var doc = this.ownerDocument; 530 var doc = this.ownerDocument;
506 if (editing) { 531 if (editing) {
507 this.setAttribute('editing', ''); 532 this.setAttribute('editing', '');
508 this.draggable = false; 533 this.draggable = false;
509 534
510 labelInput = doc.createElement('input'); 535 labelInput = /** @type {HTMLElement} */(doc.createElement('input'));
511 labelInput.placeholder = 536 labelInput.placeholder =
512 loadTimeData.getString('name_input_placeholder'); 537 loadTimeData.getString('name_input_placeholder');
513 replaceAllChildren(labelEl, labelInput); 538 replaceAllChildren(labelEl, labelInput);
514 labelInput.value = title; 539 labelInput.value = title;
515 540
516 if (!isFolder) { 541 if (!isFolder) {
517 urlInput = doc.createElement('input'); 542 urlInput = /** @type {HTMLElement} */(doc.createElement('input'));
518 urlInput.type = 'url'; 543 urlInput.type = 'url';
519 urlInput.required = true; 544 urlInput.required = true;
520 urlInput.placeholder = 545 urlInput.placeholder =
521 loadTimeData.getString('url_input_placeholder'); 546 loadTimeData.getString('url_input_placeholder');
522 547
523 // We also need a name for the input for the CSS to work. 548 // We also need a name for the input for the CSS to work.
524 urlInput.name = '-url-input-' + cr.createUid(); 549 urlInput.name = '-url-input-' + cr.createUid();
525 replaceAllChildren(urlEl, urlInput); 550 replaceAllChildren(assert(urlEl), urlInput);
526 urlInput.value = url; 551 urlInput.value = url;
527 } 552 }
528 553
529 function stopPropagation(e) { 554 var stopPropagation = function(e) {
530 e.stopPropagation(); 555 e.stopPropagation();
531 } 556 };
532 557
533 var eventsToStop = 558 var eventsToStop =
534 ['mousedown', 'mouseup', 'contextmenu', 'dblclick', 'paste']; 559 ['mousedown', 'mouseup', 'contextmenu', 'dblclick', 'paste'];
535 eventsToStop.forEach(function(type) { 560 eventsToStop.forEach(function(type) {
536 labelInput.addEventListener(type, stopPropagation); 561 labelInput.addEventListener(type, stopPropagation);
537 }); 562 });
538 labelInput.addEventListener('keydown', handleKeydown); 563 labelInput.addEventListener('keydown', handleKeydown);
539 labelInput.addEventListener('blur', handleBlur); 564 labelInput.addEventListener('blur', handleBlur);
540 cr.ui.limitInputWidth(labelInput, this, 100, 0.5); 565 cr.ui.limitInputWidth(labelInput, this, 100, 0.5);
541 labelInput.focus(); 566 labelInput.focus();
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
594 } 619 }
595 } else if (newLabel != title || newUrl != url) { 620 } else if (newLabel != title || newUrl != url) {
596 cr.dispatchSimpleEvent(this, 'edit', true); 621 cr.dispatchSimpleEvent(this, 'edit', true);
597 } 622 }
598 } 623 }
599 } 624 }
600 }; 625 };
601 626
602 return { 627 return {
603 BookmarkList: BookmarkList, 628 BookmarkList: BookmarkList,
604 list: list 629 get list() {
630 return $('list');
631 },
Dan Beam 2014/09/25 04:27:18 what about: list: /** @type {Element} */(null),
Vitaly Pavlenko 2014/09/25 15:37:15 Done.
605 }; 632 };
606 }); 633 });
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698