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