| OLD | NEW |
| (Empty) |
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | |
| 2 // Use of this source code is governed by a BSD-style license that can be | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 cr.define('ntp4', function() { | |
| 6 'use strict'; | |
| 7 | |
| 8 var localStrings = new LocalStrings; | |
| 9 | |
| 10 /** | |
| 11 * A running count of bookmark tiles that we create so that each will have | |
| 12 * a unique ID. | |
| 13 */ | |
| 14 var tileId = 0; | |
| 15 | |
| 16 /** | |
| 17 * The maximum number of tiles that we will display on this page. If there | |
| 18 * are not enough spaces to show all bookmarks, we'll include a link to the | |
| 19 * Bookmarks manager. | |
| 20 * TODO(csilv): Eliminate the need for this restraint. | |
| 21 * @type {number} | |
| 22 * @const | |
| 23 */ | |
| 24 var MAX_BOOKMARK_TILES = 18; | |
| 25 | |
| 26 /** | |
| 27 * The root node's ID. We need this to determine removable items (direct | |
| 28 * children aren't removable). | |
| 29 * @type {number} | |
| 30 * @const | |
| 31 */ | |
| 32 var ROOT_NODE_ID = '0'; | |
| 33 | |
| 34 /** | |
| 35 * The bookmark bar's ID. We need this to allow combining the root and | |
| 36 * bookmarks bars at the top level of the folder hierarchy/bookmarks page. | |
| 37 * aren't removable). | |
| 38 * @type {number} | |
| 39 * @const | |
| 40 */ | |
| 41 var BOOKMARKS_BAR_ID = '1'; | |
| 42 | |
| 43 /** | |
| 44 * Creates a new bookmark object. | |
| 45 * @param {Object} data The url and title. | |
| 46 * @constructor | |
| 47 * @extends {HTMLDivElement} | |
| 48 */ | |
| 49 function Bookmark(data) { | |
| 50 var el = $('bookmark-template').cloneNode(true); | |
| 51 el.__proto__ = Bookmark.prototype; | |
| 52 el.initialize(data); | |
| 53 | |
| 54 return el; | |
| 55 } | |
| 56 | |
| 57 Bookmark.prototype = { | |
| 58 __proto__: HTMLDivElement.prototype, | |
| 59 | |
| 60 /** | |
| 61 * Initialize the bookmark object. | |
| 62 * @param {Object} data The bookmark data (url, title, etc). | |
| 63 */ | |
| 64 initialize: function(data) { | |
| 65 this.data = data; | |
| 66 this.hidden = false; | |
| 67 | |
| 68 var id = tileId++; | |
| 69 this.id = 'bookmark_tile_' + id; | |
| 70 | |
| 71 var title = this.querySelector('.title'); | |
| 72 title.textContent = this.data.title; | |
| 73 | |
| 74 // Sets the tooltip. | |
| 75 this.title = this.data.title; | |
| 76 | |
| 77 if (this.data.url) { | |
| 78 var button = this.querySelector('.button'); | |
| 79 button.href = title.href = this.data.url; | |
| 80 } | |
| 81 | |
| 82 var faviconDiv = this.querySelector('.favicon'); | |
| 83 var faviconUrl; | |
| 84 if (this.data.url) { | |
| 85 faviconUrl = 'chrome://favicon/size/16/' + this.data.url; | |
| 86 chrome.send('getFaviconDominantColor', [faviconUrl, this.id]); | |
| 87 } else { | |
| 88 faviconUrl = 'chrome://theme/IDR_BOOKMARK_BAR_FOLDER'; | |
| 89 // TODO(csilv): Should we vary this color by platform? | |
| 90 this.stripeColor = '#919191'; | |
| 91 } | |
| 92 faviconDiv.style.backgroundImage = url(faviconUrl); | |
| 93 | |
| 94 if (this.canBeRemoved()) | |
| 95 this.classList.add('removable'); | |
| 96 | |
| 97 this.addEventListener('click', this.handleClick_.bind(this)); | |
| 98 }, | |
| 99 | |
| 100 /** | |
| 101 * Sets the color of the favicon dominant color bar. | |
| 102 * @param {string} color The css-parsable value for the color. | |
| 103 */ | |
| 104 set stripeColor(color) { | |
| 105 this.querySelector('.color-stripe').style.backgroundColor = color; | |
| 106 }, | |
| 107 | |
| 108 /** | |
| 109 * Set the size and position of the bookmark tile. | |
| 110 * @param {number} size The total size of |this|. | |
| 111 * @param {number} x The x-position. | |
| 112 * @param {number} y The y-position. | |
| 113 * animate. | |
| 114 */ | |
| 115 setBounds: function(size, x, y) { | |
| 116 this.style.width = size + 'px'; | |
| 117 this.style.height = heightForWidth(size) + 'px'; | |
| 118 | |
| 119 this.style.left = x + 'px'; | |
| 120 this.style.right = x + 'px'; | |
| 121 this.style.top = y + 'px'; | |
| 122 }, | |
| 123 | |
| 124 /** | |
| 125 * Set some data on the drag when it starts. | |
| 126 * @param {DataTransfer} dataTransfer A data transfer object from the | |
| 127 * current drag. | |
| 128 */ | |
| 129 setDragData: function(dataTransfer) { | |
| 130 // OS X requires extra data drag data to consider a drag useful, so we're | |
| 131 // appending some semi-useful data at the end to force drags to work on | |
| 132 // this OS. Don't use this data for anything -- this is just a hack to | |
| 133 // ensure drag works the same as on other platforms. | |
| 134 dataTransfer.setData('Text', this.data.id); | |
| 135 }, | |
| 136 | |
| 137 /** | |
| 138 * Invoked when a bookmark is clicked | |
| 139 * @param {Event} e The click event. | |
| 140 * @private | |
| 141 */ | |
| 142 handleClick_: function(e) { | |
| 143 if (e.target.classList.contains('close-button')) { | |
| 144 e.preventDefault(); | |
| 145 this.removeFromChrome(); | |
| 146 } else if (!this.data.url) { | |
| 147 chrome.send('getBookmarksData', [this.data.id]); | |
| 148 e.preventDefault(); | |
| 149 } | |
| 150 }, | |
| 151 | |
| 152 /** @inheritDoc */ | |
| 153 removeFromChrome: function() { | |
| 154 chrome.send('removeBookmark', [this.data.id]); | |
| 155 }, | |
| 156 | |
| 157 /** | |
| 158 * All bookmarks except for children of the root node. | |
| 159 * @return {boolean} Whether or not the item can be removed. | |
| 160 */ | |
| 161 canBeRemoved: function() { | |
| 162 return this.data.parentId !== ROOT_NODE_ID; | |
| 163 }, | |
| 164 }; | |
| 165 | |
| 166 /** | |
| 167 * Creates a new bookmark title object. | |
| 168 * @param {Object} data The url and title. | |
| 169 * @constructor | |
| 170 * @extends {HTMLDivElement} | |
| 171 */ | |
| 172 function BookmarkTitle(data) { | |
| 173 var el = cr.doc.createElement('div'); | |
| 174 el.__proto__ = BookmarkTitle.prototype; | |
| 175 el.initialize(data); | |
| 176 | |
| 177 return el; | |
| 178 } | |
| 179 | |
| 180 BookmarkTitle.prototype = { | |
| 181 __proto__: HTMLDivElement.prototype, | |
| 182 | |
| 183 /** | |
| 184 * Initialize the bookmark title object. | |
| 185 */ | |
| 186 initialize: function(data) { | |
| 187 this.className = 'title-crumb'; | |
| 188 this.folderId = data.id; | |
| 189 this.textContent = data.parentId ? data.title : | |
| 190 localStrings.getString('bookmarksPage'); | |
| 191 | |
| 192 this.addEventListener('click', this.handleClick_); | |
| 193 }, | |
| 194 | |
| 195 /** | |
| 196 * Invoked when a bookmark title is clicked | |
| 197 * @param {Event} e The click event. | |
| 198 * @private | |
| 199 */ | |
| 200 handleClick_: function(e) { | |
| 201 chrome.send('getBookmarksData', [this.folderId]); | |
| 202 }, | |
| 203 }; | |
| 204 | |
| 205 var TilePage = ntp4.TilePage; | |
| 206 | |
| 207 var bookmarksPageGridValues = { | |
| 208 // The fewest tiles we will show in a row. | |
| 209 minColCount: 3, | |
| 210 // The most tiles we will show in a row. | |
| 211 maxColCount: 6, | |
| 212 | |
| 213 // The smallest a tile can be. | |
| 214 minTileWidth: 64, | |
| 215 // The biggest a tile can be. | |
| 216 maxTileWidth: 96, | |
| 217 | |
| 218 // The padding between tiles, as a fraction of the tile width. | |
| 219 tileSpacingFraction: 1 / 2, | |
| 220 }; | |
| 221 TilePage.initGridValues(bookmarksPageGridValues); | |
| 222 | |
| 223 /** | |
| 224 * Calculates the height for a bookmarks tile for a given width. The size | |
| 225 * is based on a desired size of 96x72 ratio. | |
| 226 * @return {number} The height. | |
| 227 */ | |
| 228 function heightForWidth(width) { | |
| 229 // The 2s are for borders, the 31 is for the title. | |
| 230 return (width - 2) * 72 / 96 + 2 + 31; | |
| 231 } | |
| 232 | |
| 233 /** | |
| 234 * Creates a new BookmarksPage object. | |
| 235 * @constructor | |
| 236 * @extends {TilePage} | |
| 237 */ | |
| 238 function BookmarksPage() { | |
| 239 var el = new TilePage(bookmarksPageGridValues); | |
| 240 el.__proto__ = BookmarksPage.prototype; | |
| 241 el.initialize(); | |
| 242 | |
| 243 return el; | |
| 244 } | |
| 245 | |
| 246 BookmarksPage.prototype = { | |
| 247 __proto__: TilePage.prototype, | |
| 248 | |
| 249 /** | |
| 250 * Initialize the bookmarks page object. | |
| 251 */ | |
| 252 initialize: function() { | |
| 253 this.classList.add('bookmarks-page'); | |
| 254 | |
| 255 // Insert the bookmark titles header which is unique to bookmark pages. | |
| 256 var titleWrapper = $('bookmarks-title-wrapper') | |
| 257 titleWrapper.hidden = false; | |
| 258 this.insertBefore(titleWrapper, this.firstChild); | |
| 259 | |
| 260 // Insert the top & bottom links for the Bookmarks Manager page. | |
| 261 var pageContent = this.querySelector('.tile-page-content'); | |
| 262 var topWrapper = $('bookmarks-top-link-wrapper'); | |
| 263 pageContent.insertBefore(topWrapper, pageContent.firstChild); | |
| 264 topWrapper.hidden = false; | |
| 265 pageContent.appendChild($('bookmarks-bottom-link-wrapper')); | |
| 266 }, | |
| 267 | |
| 268 /** | |
| 269 * Build the bookmark titles bar (ie, navigation hiearchy). | |
| 270 * @param {Array} items The parent hiearchy of the current folder. | |
| 271 * @private | |
| 272 */ | |
| 273 updateBookmarkTitles_: function(items) { | |
| 274 var wrapper = $('bookmarks-title-wrapper'); | |
| 275 var title = wrapper.querySelector('.section-title'); | |
| 276 title.innerHTML = ''; | |
| 277 | |
| 278 for (var i = items.length - 1; i > 0; i--) { | |
| 279 title.appendChild(new BookmarkTitle(items[i])); | |
| 280 | |
| 281 var separator = document.createElement('hr'); | |
| 282 separator.className = 'bookmark-separator'; | |
| 283 title.appendChild(separator); | |
| 284 } | |
| 285 | |
| 286 var titleCrumb = new BookmarkTitle(items[0]); | |
| 287 titleCrumb.classList.add('title-crumb-active'); | |
| 288 title.appendChild(titleCrumb); | |
| 289 }, | |
| 290 | |
| 291 /** | |
| 292 * Build the bookmark tiles. | |
| 293 * @param {Array} items The contents of the current folder. | |
| 294 * @private | |
| 295 */ | |
| 296 updateBookmarkTiles_: function(items) { | |
| 297 this.removeAllTiles(); | |
| 298 var tile_count = Math.min(items.length, MAX_BOOKMARK_TILES); | |
| 299 for (var i = 0; i < tile_count; i++) | |
| 300 this.appendTile(new Bookmark(items[i]), false); | |
| 301 | |
| 302 var folder_id = this.id == ROOT_NODE_ID ? BOOKMARKS_BAR_ID : this.id; | |
| 303 var top_link = $('bookmarks-top-link-wrapper').querySelector('a'); | |
| 304 top_link.href = 'chrome://bookmarks/#' + folder_id; | |
| 305 | |
| 306 var wrapper = $('bookmarks-bottom-link-wrapper'); | |
| 307 if (items.length > MAX_BOOKMARK_TILES) { | |
| 308 var bottom_link = wrapper.querySelector('a'); | |
| 309 bottom_link.href = 'chrome://bookmarks/#' + folder_id; | |
| 310 wrapper.hidden = false; | |
| 311 } else { | |
| 312 wrapper.hidden = true; | |
| 313 } | |
| 314 | |
| 315 if (this.id === ROOT_NODE_ID && !tile_count && !cr.isChromeOS) | |
| 316 this.showImportPromo_(); | |
| 317 }, | |
| 318 | |
| 319 /** | |
| 320 * Determine whether a bookmark ID matches a folder in the current | |
| 321 * hierarchy. | |
| 322 * @param {string} id The bookmark ID to search for. | |
| 323 * @private | |
| 324 */ | |
| 325 isBookmarkInParentHierarchy_: function(id) { | |
| 326 var titlesWrapper = $('bookmarks-title-wrapper'); | |
| 327 var titles = titlesWrapper.querySelectorAll('.title-crumb'); | |
| 328 for (var i = 0; i < titles.length; i++) { | |
| 329 var bookmarkTitle = titles[i]; | |
| 330 if (bookmarkTitle.folderId == id) | |
| 331 return true; | |
| 332 } | |
| 333 return false; | |
| 334 }, | |
| 335 | |
| 336 /** | |
| 337 * Tells if we're in currently in the given folder. | |
| 338 * @param {String} id The folder node's ID. | |
| 339 * @returns {boolean} If it's in that folder (visually). | |
| 340 */ | |
| 341 currentlyInFolder_: function(id) { | |
| 342 return id === this.id || (this.id === ROOT_NODE_ID && | |
| 343 id === BOOKMARKS_BAR_ID); | |
| 344 }, | |
| 345 | |
| 346 /** @inheritDoc */ | |
| 347 shouldAcceptDrag: function(e) { | |
| 348 var tile = ntp4.getCurrentlyDraggingTile(); | |
| 349 if (tile) | |
| 350 return !!tile.querySelector('.most-visited, .bookmark'); | |
| 351 // If there was no dragging tile, look for a URL in the drag data. | |
| 352 return e.dataTransfer && e.dataTransfer.types && | |
| 353 e.dataTransfer.types.indexOf('url') != -1; | |
| 354 }, | |
| 355 | |
| 356 /** @inheritDoc */ | |
| 357 heightForWidth: heightForWidth, | |
| 358 | |
| 359 /** | |
| 360 * Invoked before a batch import begins. We will ignore added/changed | |
| 361 * notifications while the operation is in progress. | |
| 362 */ | |
| 363 bookmarkImportBegan: function() { | |
| 364 this.importing = true; | |
| 365 }, | |
| 366 | |
| 367 /** | |
| 368 * Invoked after a batch import finishes. We will reload the bookmarks | |
| 369 * page to reflect the new state. | |
| 370 */ | |
| 371 bookmarkImportEnded: function() { | |
| 372 this.importing = false; | |
| 373 chrome.send('getBookmarksData', []); | |
| 374 }, | |
| 375 | |
| 376 /** | |
| 377 * Invoked when a node has been added. | |
| 378 * @param {string} id The id of the newly created bookmark node. | |
| 379 * @param {Object} bookmark The new bookmark node. | |
| 380 * @param {boolean} fromCurrentPage True if the action was from this page. | |
| 381 */ | |
| 382 bookmarkNodeAdded: function(id, bookmark, fromCurrentPage) { | |
| 383 if (this.importing) return; | |
| 384 if (this.currentlyInFolder_(bookmark.parentId)) { | |
| 385 // Hide the import promo if it exists. | |
| 386 this.hideImportPromo_(); | |
| 387 // Only add the item if it should be visible. | |
| 388 if (bookmark.index < MAX_BOOKMARK_TILES) { | |
| 389 // If source of the add came from this page, show an animated | |
| 390 // insertion, otherwise just quietly do it. | |
| 391 this.addTileAt(new Bookmark(bookmark), bookmark.index, | |
| 392 fromCurrentPage); | |
| 393 // Delete extra tiles if they exist. | |
| 394 while (this.tiles.length > MAX_BOOKMARK_TILES) { | |
| 395 var tile = this.tiles[this.tiles.length - 1]; | |
| 396 this.removeTile(tile, false); | |
| 397 } | |
| 398 this.repositionTiles_(); | |
| 399 } | |
| 400 } | |
| 401 }, | |
| 402 | |
| 403 /** | |
| 404 * Invoked when the title or url of a node changes. | |
| 405 * @param {string} id The id of the changed node. | |
| 406 * @param {Object} changeInfo Details of the changed node. | |
| 407 */ | |
| 408 bookmarkNodeChanged: function(id, changeInfo) { | |
| 409 if (this.importing) return; | |
| 410 | |
| 411 // If the current folder or parent is being re-named, reload the page. | |
| 412 // TODO(csilv): Optimize this to reload just the titles. | |
| 413 if (this.isBookmarkInParentHierarchy_(id)) { | |
| 414 chrome.send('getBookmarksData', [this.id]); | |
| 415 return; | |
| 416 } | |
| 417 | |
| 418 // If the target item is contained in this folder, update just that item. | |
| 419 for (var i = 0; i < this.tiles.length; i++) { | |
| 420 var tile = this.tiles[i]; | |
| 421 var data = tile.firstChild.data; | |
| 422 | |
| 423 if (data.id == id) { | |
| 424 data.title = changeInfo.title; | |
| 425 var title = tile.querySelector('.title'); | |
| 426 title.textContent = data.title; | |
| 427 | |
| 428 if (changeInfo.url) { | |
| 429 data.url = changeInfo.url; | |
| 430 var button = tile.querySelector('.button'); | |
| 431 button.href = title.href = data.url; | |
| 432 } | |
| 433 break; | |
| 434 } | |
| 435 } | |
| 436 }, | |
| 437 | |
| 438 /** | |
| 439 * Invoked when the children (just direct children, not descendants) of | |
| 440 * a folder have been reordered in some way, such as sorted. | |
| 441 * @param {string} id The id of the reordered bookmark node. | |
| 442 * @param {!Object} reorderInfo Details of the reordered bookmark node. | |
| 443 */ | |
| 444 bookmarkNodeChildrenReordered: function(id, reorderInfo) { | |
| 445 if (this.currentlyInFolder_(id)) | |
| 446 chrome.send('getBookmarksData', [this.id]); | |
| 447 }, | |
| 448 | |
| 449 /** | |
| 450 * Invoked when a node has moved. | |
| 451 * @param {string} id The id of the moved bookmark node. | |
| 452 * @param {!Object} moveInfo Details of the moved bookmark. | |
| 453 */ | |
| 454 bookmarkNodeMoved: function(id, moveInfo) { | |
| 455 // TODO(csilv): Optimize this by doing less than reloading the folder. | |
| 456 // Reload the current page if the target item is the current folder | |
| 457 // or a parent of the current folder. | |
| 458 if (this.isBookmarkInParentHierarchy_(id)) { | |
| 459 chrome.send('getBookmarksData', [this.id]); | |
| 460 return; | |
| 461 } | |
| 462 | |
| 463 // Reload the current page if the target item is being moved to/from the | |
| 464 // current folder. | |
| 465 if (this.currentlyInFolder_(moveInfo.parentId) || | |
| 466 this.currentlyInFolder_(moveInfo.oldParentId)) { | |
| 467 chrome.send('getBookmarksData', [this.id]); | |
| 468 } | |
| 469 }, | |
| 470 | |
| 471 /** | |
| 472 * Invoked when a node has been removed from a folder. | |
| 473 * @param {string} id The id of the removed bookmark node. | |
| 474 * @param {!Object} removeInfo Details of the removed bookmark node. | |
| 475 * @param {boolearn} fromCurrentPage If the event was from this page. | |
| 476 */ | |
| 477 bookmarkNodeRemoved: function(id, removeInfo, fromCurrentPage) { | |
| 478 // If the target item is the visibile folder or a parent folder, load | |
| 479 // the parent of the removed item. | |
| 480 if (this.isBookmarkInParentHierarchy_(id)) { | |
| 481 chrome.send('getBookmarksData', [removeInfo.parentId]); | |
| 482 return; | |
| 483 } | |
| 484 | |
| 485 // If the target item is contained in the visible folder, find the | |
| 486 // matching tile and delete it. | |
| 487 if (this.currentlyInFolder_(removeInfo.parentId)) { | |
| 488 for (var i = 0; i < this.tiles.length; i++) { | |
| 489 var tile = this.tiles[i]; | |
| 490 if (tile.firstChild.data.id == id) { | |
| 491 this.removeTile(tile, fromCurrentPage); | |
| 492 break; | |
| 493 } | |
| 494 } | |
| 495 } | |
| 496 }, | |
| 497 | |
| 498 /** | |
| 499 * Set the bookmark data that should be displayed, replacing any existing | |
| 500 * data. | |
| 501 * @param {Object} data Data that shoudl be displayed. Contains arrays | |
| 502 * 'items' and 'navigationItems'. | |
| 503 */ | |
| 504 set data(data) { | |
| 505 this.id = data.navigationItems[0].id; | |
| 506 this.updateBookmarkTiles_(data.items); | |
| 507 this.updateBookmarkTitles_(data.navigationItems); | |
| 508 }, | |
| 509 | |
| 510 /** @inheritDoc */ | |
| 511 get extraBottomPadding() { | |
| 512 return 40; | |
| 513 }, | |
| 514 | |
| 515 /** @inheritDoc */ | |
| 516 setDropEffect: function(dataTransfer) { | |
| 517 var tile = ntp4.getCurrentlyDraggingTile(); | |
| 518 if (tile && tile.querySelector('.bookmark')) | |
| 519 ntp4.setCurrentDropEffect(dataTransfer, 'move'); | |
| 520 else | |
| 521 ntp4.setCurrentDropEffect(dataTransfer, 'copy'); | |
| 522 }, | |
| 523 | |
| 524 /** @inheritDoc */ | |
| 525 addDragData: function(dataTransfer, index) { | |
| 526 var parentId = ROOT_NODE_ID == this.id ? BOOKMARKS_BAR_ID : this.id; | |
| 527 var currentlyDraggingTile = ntp4.getCurrentlyDraggingTile(); | |
| 528 if (currentlyDraggingTile) { | |
| 529 var tileContents = currentlyDraggingTile.firstChild; | |
| 530 if (tileContents.classList.contains('most-visited')) { | |
| 531 this.generateBookmarkForLink(parentId, index, | |
| 532 tileContents.textContent, | |
| 533 tileContents.href); | |
| 534 } | |
| 535 } else { | |
| 536 this.addOutsideData_(dataTransfer, parentId, index); | |
| 537 } | |
| 538 }, | |
| 539 | |
| 540 /** | |
| 541 * If we got an outside drag from a page or the URL bar. | |
| 542 * @param {!DataTransfer} dataTransfer The drag data transfer object. | |
| 543 * @param {number} parentId The parent ID for the current bookmark level. | |
| 544 * @param {number} index Position it will be inserted relative to siblings. | |
| 545 */ | |
| 546 addOutsideData_: function(dataTransfer, parentId, index) { | |
| 547 var url = dataTransfer.getData('url'); | |
| 548 assert(url && url !== window.location.href); | |
| 549 // Look for any text/html types first (links, etc.). | |
| 550 var title, html = dataTransfer.getData('text/html'); | |
| 551 if (html) { | |
| 552 // NOTE: Don't insert this into the DOM! It could XSS the page! | |
| 553 var node = this.ownerDocument.createElement('div'); | |
| 554 node.innerHTML = html; | |
| 555 var text = node.textContent, img = node.firstChild; | |
| 556 // OS X prepends a <meta> tag to the html for some reason... | |
| 557 if ('META' == img.nodeName) | |
| 558 img = img.nextSibling; | |
| 559 // Use the combined text (if it exists), otherwise fall back to an | |
| 560 // image's alternate text (if they dragged an image onto this page). | |
| 561 title = text || ('IMG' == img.nodeName && img.alt); | |
| 562 } | |
| 563 // If we *still* don't have a title, just use the URL. | |
| 564 if (!title) | |
| 565 title = url; | |
| 566 // Create a bookmark for the dropped data. | |
| 567 this.generateBookmarkForLink(parentId, index, title, url); | |
| 568 }, | |
| 569 | |
| 570 /** | |
| 571 * Show the 'Import bookmarks' promo. | |
| 572 * @private | |
| 573 */ | |
| 574 showImportPromo_: function() { | |
| 575 var importTemplate = $('bookmarks-import-data-link-template'); | |
| 576 var importWrapper = importTemplate.cloneNode(true); | |
| 577 importWrapper.id = ''; | |
| 578 importWrapper.hidden = false; | |
| 579 this.querySelector('.tile-page-content').appendChild(importWrapper); | |
| 580 }, | |
| 581 | |
| 582 /** | |
| 583 * Hide the 'Import bookmarks' promo. | |
| 584 * @private | |
| 585 */ | |
| 586 hideImportPromo_: function() { | |
| 587 var wrapper = this.querySelector('.bookmarks-import-data-link-wrapper'); | |
| 588 if (wrapper) | |
| 589 wrapper.parentNode.removeChild(wrapper); | |
| 590 }, | |
| 591 | |
| 592 /** | |
| 593 * Create a bookmark from a title/url. | |
| 594 * @param {!string} parentId Stringified int64 of the parent node's ID. | |
| 595 * @param {number} index Sibling relative index, i.e. 3rd on this level. | |
| 596 * @param {string} title More human readable title of the bookmark. | |
| 597 * @param {string} url URL of the bookmark to be created. | |
| 598 */ | |
| 599 generateBookmarkForLink: function(parentId, index, title, url) { | |
| 600 // Bookmark creation actually only *requires* a parent ID, as if we just | |
| 601 // pass a parent ID it's created as a folder with blank title as a child | |
| 602 // of that parent. | |
| 603 assert(parentId); | |
| 604 chrome.send('createBookmark', [parentId, index, title, url]); | |
| 605 }, | |
| 606 | |
| 607 /** @inheritDoc */ | |
| 608 tileMoved: function(tile, prevIndex) { | |
| 609 var parentId = ROOT_NODE_ID == this.id ? BOOKMARKS_BAR_ID : this.id; | |
| 610 chrome.send('moveBookmark', [tile.firstChild.data.id, parentId, | |
| 611 tile.index + (prevIndex < tile.index)]); | |
| 612 }, | |
| 613 }; | |
| 614 | |
| 615 /** | |
| 616 * Initializes and renders the bookmark chevron canvas. This needs to be | |
| 617 * performed after the page has been loaded so that we have access to the | |
| 618 * style sheet values. | |
| 619 */ | |
| 620 function initBookmarkChevron() { | |
| 621 var wrapperStyle = window.getComputedStyle($('bookmarks-title-wrapper')); | |
| 622 var width = 10; | |
| 623 var height = parseInt(wrapperStyle.height, 10); | |
| 624 var ctx = document.getCSSCanvasContext('2d', 'bookmark-chevron', | |
| 625 width, height); | |
| 626 ctx.strokeStyle = wrapperStyle.borderBottomColor; | |
| 627 ctx.beginPath(); | |
| 628 ctx.moveTo(0, 0); | |
| 629 ctx.lineTo(width, height / 2); | |
| 630 ctx.lineTo(0, height); | |
| 631 ctx.stroke(); | |
| 632 } | |
| 633 | |
| 634 /** | |
| 635 * Set the dominant color for a bookmark tile. This is the callback method | |
| 636 * from a request made when the tile was created. | |
| 637 * @param {string} id The ID of the bookmark tile. | |
| 638 * @param {string} color The color represented as a CSS string. | |
| 639 */ | |
| 640 function setBookmarksFaviconDominantColor(id, color) { | |
| 641 var tile = $(id); | |
| 642 if (tile) | |
| 643 tile.stripeColor = color; | |
| 644 } | |
| 645 | |
| 646 return { | |
| 647 BookmarksPage: BookmarksPage, | |
| 648 initBookmarkChevron: initBookmarkChevron, | |
| 649 }; | |
| 650 }); | |
| 651 | |
| 652 window.addEventListener('load', ntp4.initBookmarkChevron); | |
| OLD | NEW |