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 cr.define('ntp', function() { | 5 cr.define('ntp', function() { |
6 'use strict'; | 6 'use strict'; |
7 | 7 |
8 // We can't pass the currently dragging tile via dataTransfer because of | 8 // We can't pass the currently dragging tile via dataTransfer because of |
9 // http://crbug.com/31037 | 9 // http://crbug.com/31037 |
10 var currentlyDraggingTile = null; | 10 var currentlyDraggingTile = null; |
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
113 e.dataTransfer.effectAllowed = 'copyMove'; | 113 e.dataTransfer.effectAllowed = 'copyMove'; |
114 this.firstChild.setDragData(e.dataTransfer); | 114 this.firstChild.setDragData(e.dataTransfer); |
115 | 115 |
116 // The drag clone is the node we use as a representation during the drag. | 116 // The drag clone is the node we use as a representation during the drag. |
117 // It's attached to the top level document element so that it floats above | 117 // It's attached to the top level document element so that it floats above |
118 // image masks. | 118 // image masks. |
119 this.dragClone = this.cloneNode(true); | 119 this.dragClone = this.cloneNode(true); |
120 this.dragClone.style.right = ''; | 120 this.dragClone.style.right = ''; |
121 this.dragClone.classList.add('drag-representation'); | 121 this.dragClone.classList.add('drag-representation'); |
122 $('card-slider-frame').appendChild(this.dragClone); | 122 $('card-slider-frame').appendChild(this.dragClone); |
123 this.eventTracker.add(this.dragClone, 'transitionend', | 123 this.eventTracker.add( |
124 this.onDragCloneTransitionEnd_.bind(this)); | 124 this.dragClone, 'transitionend', |
| 125 this.onDragCloneTransitionEnd_.bind(this)); |
125 | 126 |
126 this.classList.add('dragging'); | 127 this.classList.add('dragging'); |
127 // offsetLeft is mirrored in RTL. Un-mirror it. | 128 // offsetLeft is mirrored in RTL. Un-mirror it. |
128 var offsetLeft = isRTL() ? | 129 var offsetLeft = isRTL() ? this.parentNode.clientWidth - this.offsetLeft : |
129 this.parentNode.clientWidth - this.offsetLeft : | 130 this.offsetLeft; |
130 this.offsetLeft; | |
131 this.dragOffsetX = e.x - offsetLeft - this.parentNode.offsetLeft; | 131 this.dragOffsetX = e.x - offsetLeft - this.parentNode.offsetLeft; |
132 this.dragOffsetY = e.y - this.offsetTop - | 132 this.dragOffsetY = e.y - this.offsetTop - |
133 // Unlike offsetTop, this value takes scroll position into account. | 133 // Unlike offsetTop, this value takes scroll position into account. |
134 this.parentNode.getBoundingClientRect().top; | 134 this.parentNode.getBoundingClientRect().top; |
135 | 135 |
136 this.onDragMove_(e); | 136 this.onDragMove_(e); |
137 }, | 137 }, |
138 | 138 |
139 /** | 139 /** |
140 * The handler for drag events fired on |this|. | 140 * The handler for drag events fired on |this|. |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
173 this.dragClone.classList.add('deleting'); | 173 this.dragClone.classList.add('deleting'); |
174 } else if (tilePage) { | 174 } else if (tilePage) { |
175 // TODO(dbeam): Until we fix dropEffect to the correct behavior it will | 175 // TODO(dbeam): Until we fix dropEffect to the correct behavior it will |
176 // differ on windows - crbug.com/39399. That's why we use the custom | 176 // differ on windows - crbug.com/39399. That's why we use the custom |
177 // this.lastDropEffect instead of e.dataTransfer.dropEffect. | 177 // this.lastDropEffect instead of e.dataTransfer.dropEffect. |
178 if (tilePage.selected && this.lastDropEffect != 'copy') { | 178 if (tilePage.selected && this.lastDropEffect != 'copy') { |
179 // The drag clone can still be hidden from the last drag move event. | 179 // The drag clone can still be hidden from the last drag move event. |
180 this.dragClone.hidden = false; | 180 this.dragClone.hidden = false; |
181 // The tile's contents may have moved following the respositioning; | 181 // The tile's contents may have moved following the respositioning; |
182 // adjust for that. | 182 // adjust for that. |
183 var contentDiffX = this.dragClone.firstChild.offsetLeft - | 183 var contentDiffX = |
184 this.firstChild.offsetLeft; | 184 this.dragClone.firstChild.offsetLeft - this.firstChild.offsetLeft; |
185 var contentDiffY = this.dragClone.firstChild.offsetTop - | 185 var contentDiffY = |
186 this.firstChild.offsetTop; | 186 this.dragClone.firstChild.offsetTop - this.firstChild.offsetTop; |
187 this.dragClone.style.left = | 187 this.dragClone.style.left = |
188 toCssPx(this.gridX + this.parentNode.offsetLeft - | 188 toCssPx(this.gridX + this.parentNode.offsetLeft - contentDiffX); |
189 contentDiffX); | 189 this.dragClone.style.top = toCssPx( |
190 this.dragClone.style.top = | 190 this.gridY + this.parentNode.getBoundingClientRect().top - |
191 toCssPx(this.gridY + | 191 contentDiffY); |
192 this.parentNode.getBoundingClientRect().top - | |
193 contentDiffY); | |
194 } else if (this.dragClone.hidden) { | 192 } else if (this.dragClone.hidden) { |
195 this.finalizeDrag_(); | 193 this.finalizeDrag_(); |
196 } else { | 194 } else { |
197 // The CSS3 transitions spec intentionally leaves it up to individual | 195 // The CSS3 transitions spec intentionally leaves it up to individual |
198 // user agents to determine when styles should be applied. On some | 196 // user agents to determine when styles should be applied. On some |
199 // platforms (at the moment, Windows), when you apply both classes | 197 // platforms (at the moment, Windows), when you apply both classes |
200 // immediately a transition may not occur correctly. That's why we're | 198 // immediately a transition may not occur correctly. That's why we're |
201 // using a setTimeout here to queue adding the class until the | 199 // using a setTimeout here to queue adding the class until the |
202 // previous class (currently: .placing) sets up a transition. | 200 // previous class (currently: .placing) sets up a transition. |
203 // http://dev.w3.org/csswg/css3-transitions/#starting | 201 // http://dev.w3.org/csswg/css3-transitions/#starting |
(...skipping 27 matching lines...) Expand all Loading... |
231 for (var i = 0; i < clonelets.length; i++) { | 229 for (var i = 0; i < clonelets.length; i++) { |
232 clonelets[i].classList.remove('real'); | 230 clonelets[i].classList.remove('real'); |
233 } | 231 } |
234 | 232 |
235 this.appendChild(clone); | 233 this.appendChild(clone); |
236 this.doppleganger_ = clone; | 234 this.doppleganger_ = clone; |
237 | 235 |
238 if (isRTL()) | 236 if (isRTL()) |
239 x *= -1; | 237 x *= -1; |
240 | 238 |
241 this.doppleganger_.style.transform = 'translate(' + x + 'px, ' + | 239 this.doppleganger_.style.transform = |
242 y + 'px)'; | 240 'translate(' + x + 'px, ' + y + 'px)'; |
243 }, | 241 }, |
244 | 242 |
245 /** | 243 /** |
246 * Destroys the current doppleganger. | 244 * Destroys the current doppleganger. |
247 */ | 245 */ |
248 clearDoppleganger: function() { | 246 clearDoppleganger: function() { |
249 if (this.doppleganger_) { | 247 if (this.doppleganger_) { |
250 this.removeChild(this.doppleganger_); | 248 this.removeChild(this.doppleganger_); |
251 this.doppleganger_ = null; | 249 this.doppleganger_ = null; |
252 } | 250 } |
(...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
371 } | 369 } |
372 | 370 |
373 /** | 371 /** |
374 * Takes a collection of grid layout pixel values and updates them with | 372 * Takes a collection of grid layout pixel values and updates them with |
375 * additional tiling values that are calculated from TilePage constants. | 373 * additional tiling values that are calculated from TilePage constants. |
376 * @param {Object} grid The grid layout pixel values to update. | 374 * @param {Object} grid The grid layout pixel values to update. |
377 */ | 375 */ |
378 TilePage.initGridValues = function(grid) { | 376 TilePage.initGridValues = function(grid) { |
379 // The amount of space we need to display a narrow grid (all narrow grids | 377 // The amount of space we need to display a narrow grid (all narrow grids |
380 // are this size). | 378 // are this size). |
381 grid.narrowWidth = | 379 grid.narrowWidth = grid.minTileWidth * |
382 grid.minTileWidth * tileWidthFraction(grid.minColCount, | 380 tileWidthFraction(grid.minColCount, grid.tileSpacingFraction); |
383 grid.tileSpacingFraction); | |
384 // The minimum amount of space we need to display a wide grid. | 381 // The minimum amount of space we need to display a wide grid. |
385 grid.minWideWidth = | 382 grid.minWideWidth = grid.minTileWidth * |
386 grid.minTileWidth * tileWidthFraction(grid.maxColCount, | 383 tileWidthFraction(grid.maxColCount, grid.tileSpacingFraction); |
387 grid.tileSpacingFraction); | |
388 // The largest we will ever display a wide grid. | 384 // The largest we will ever display a wide grid. |
389 grid.maxWideWidth = | 385 grid.maxWideWidth = grid.maxTileWidth * |
390 grid.maxTileWidth * tileWidthFraction(grid.maxColCount, | 386 tileWidthFraction(grid.maxColCount, grid.tileSpacingFraction); |
391 grid.tileSpacingFraction); | |
392 // Tile-related pixel values for the narrow display. | 387 // Tile-related pixel values for the narrow display. |
393 grid.narrowTileValues = tileValuesForGrid(grid.narrowWidth, | 388 grid.narrowTileValues = tileValuesForGrid( |
394 grid.minColCount, | 389 grid.narrowWidth, grid.minColCount, grid.tileSpacingFraction); |
395 grid.tileSpacingFraction); | |
396 // Tile-related pixel values for the minimum narrow display. | 390 // Tile-related pixel values for the minimum narrow display. |
397 grid.wideTileValues = tileValuesForGrid(grid.minWideWidth, | 391 grid.wideTileValues = tileValuesForGrid( |
398 grid.maxColCount, | 392 grid.minWideWidth, grid.maxColCount, grid.tileSpacingFraction); |
399 grid.tileSpacingFraction); | |
400 }; | 393 }; |
401 | 394 |
402 TilePage.prototype = { | 395 TilePage.prototype = { |
403 __proto__: HTMLDivElement.prototype, | 396 __proto__: HTMLDivElement.prototype, |
404 | 397 |
405 initialize: function() { | 398 initialize: function() { |
406 this.className = 'tile-page'; | 399 this.className = 'tile-page'; |
407 | 400 |
408 // Div that acts as a custom scrollbar. The scrollbar has to live | 401 // Div that acts as a custom scrollbar. The scrollbar has to live |
409 // outside the content div so it doesn't flicker when scrolling (due to | 402 // outside the content div so it doesn't flicker when scrolling (due to |
(...skipping 14 matching lines...) Expand all Loading... |
424 // Div that sets the vertical position of the tile grid. | 417 // Div that sets the vertical position of the tile grid. |
425 this.topMargin_ = this.ownerDocument.createElement('div'); | 418 this.topMargin_ = this.ownerDocument.createElement('div'); |
426 this.topMargin_.className = 'top-margin'; | 419 this.topMargin_.className = 'top-margin'; |
427 this.content_.appendChild(this.topMargin_); | 420 this.content_.appendChild(this.topMargin_); |
428 | 421 |
429 // Div that holds the tiles. | 422 // Div that holds the tiles. |
430 this.tileGrid_ = this.ownerDocument.createElement('div'); | 423 this.tileGrid_ = this.ownerDocument.createElement('div'); |
431 this.tileGrid_.className = 'tile-grid'; | 424 this.tileGrid_.className = 'tile-grid'; |
432 this.tileGrid_.style.minWidth = this.gridValues_.narrowWidth + 'px'; | 425 this.tileGrid_.style.minWidth = this.gridValues_.narrowWidth + 'px'; |
433 this.tileGrid_.setAttribute('role', 'menu'); | 426 this.tileGrid_.setAttribute('role', 'menu'); |
434 this.tileGrid_.setAttribute('aria-label', | 427 this.tileGrid_.setAttribute( |
| 428 'aria-label', |
435 loadTimeData.getString( | 429 loadTimeData.getString( |
436 'tile_grid_screenreader_accessible_description')); | 430 'tile_grid_screenreader_accessible_description')); |
437 | 431 |
438 this.content_.appendChild(this.tileGrid_); | 432 this.content_.appendChild(this.tileGrid_); |
439 | 433 |
440 // Ordered list of our tiles. | 434 // Ordered list of our tiles. |
441 this.tileElements_ = this.tileGrid_.getElementsByClassName('tile real'); | 435 this.tileElements_ = this.tileGrid_.getElementsByClassName('tile real'); |
442 // Ordered list of the elements which want to accept keyboard focus. These | 436 // Ordered list of the elements which want to accept keyboard focus. These |
443 // elements will not be a part of the normal tab order; the tile grid | 437 // elements will not be a part of the normal tab order; the tile grid |
444 // initially gets focused and then these elements can be focused via the | 438 // initially gets focused and then these elements can be focused via the |
445 // arrow keys. | 439 // arrow keys. |
446 this.focusableElements_ = | 440 this.focusableElements_ = |
447 this.tileGrid_.getElementsByClassName('focusable'); | 441 this.tileGrid_.getElementsByClassName('focusable'); |
448 | 442 |
449 // These are properties used in updateTopMargin. | 443 // These are properties used in updateTopMargin. |
450 this.animatedTopMarginPx_ = 0; | 444 this.animatedTopMarginPx_ = 0; |
451 this.topMarginPx_ = 0; | 445 this.topMarginPx_ = 0; |
452 | 446 |
453 this.eventTracker = new EventTracker(); | 447 this.eventTracker = new EventTracker(); |
454 this.eventTracker.add(window, 'resize', this.onResize_.bind(this)); | 448 this.eventTracker.add(window, 'resize', this.onResize_.bind(this)); |
455 | 449 |
456 this.addEventListener('DOMNodeInsertedIntoDocument', | 450 this.addEventListener( |
457 this.onNodeInsertedIntoDocument_); | 451 'DOMNodeInsertedIntoDocument', this.onNodeInsertedIntoDocument_); |
458 | 452 |
459 this.content_.addEventListener('scroll', this.onScroll_.bind(this)); | 453 this.content_.addEventListener('scroll', this.onScroll_.bind(this)); |
460 | 454 |
461 this.dragWrapper_ = new cr.ui.DragWrapper(this.tileGrid_, this); | 455 this.dragWrapper_ = new cr.ui.DragWrapper(this.tileGrid_, this); |
462 | 456 |
463 this.addEventListener('cardselected', this.handleCardSelection_); | 457 this.addEventListener('cardselected', this.handleCardSelection_); |
464 this.addEventListener('carddeselected', this.handleCardDeselection_); | 458 this.addEventListener('carddeselected', this.handleCardDeselection_); |
465 this.addEventListener('focus', this.handleFocus_); | 459 this.addEventListener('focus', this.handleFocus_); |
466 this.addEventListener('keydown', this.handleKeyDown_); | 460 this.addEventListener('keydown', this.handleKeyDown_); |
467 this.addEventListener('mousedown', this.handleMouseDown_); | 461 this.addEventListener('mousedown', this.handleMouseDown_); |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
515 /** | 509 /** |
516 * Removes the tilePage from the DOM and cleans up event handlers. | 510 * Removes the tilePage from the DOM and cleans up event handlers. |
517 * | 511 * |
518 * TODO(dbeam): this method now conflicts with HTMLElement#remove(). Rename. | 512 * TODO(dbeam): this method now conflicts with HTMLElement#remove(). Rename. |
519 */ | 513 */ |
520 remove: function() { | 514 remove: function() { |
521 // This checks arguments.length as most remove functions have a boolean | 515 // This checks arguments.length as most remove functions have a boolean |
522 // |opt_animate| argument, but that's not necesarilly applicable to | 516 // |opt_animate| argument, but that's not necesarilly applicable to |
523 // removing a tilePage. Selecting a different card in an animated way and | 517 // removing a tilePage. Selecting a different card in an animated way and |
524 // deleting the card afterward is probably a better choice. | 518 // deleting the card afterward is probably a better choice. |
525 assert(typeof arguments[0] != 'boolean', | 519 assert( |
526 'This function takes no |opt_animate| argument.'); | 520 typeof arguments[0] != 'boolean', |
| 521 'This function takes no |opt_animate| argument.'); |
527 this.tearDown_(); | 522 this.tearDown_(); |
528 this.parentNode.removeChild(this); | 523 this.parentNode.removeChild(this); |
529 }, | 524 }, |
530 | 525 |
531 /** | 526 /** |
532 * Cleans up resources that are no longer needed after this TilePage | 527 * Cleans up resources that are no longer needed after this TilePage |
533 * instance is removed from the DOM. | 528 * instance is removed from the DOM. |
534 * @private | 529 * @private |
535 */ | 530 */ |
536 tearDown_: function() { | 531 tearDown_: function() { |
(...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
673 this.updateFocusElement_(); | 668 this.updateFocusElement_(); |
674 }, | 669 }, |
675 | 670 |
676 /** | 671 /** |
677 * Since we are doing custom focus handling, we have to manually | 672 * Since we are doing custom focus handling, we have to manually |
678 * set focusability on click (as well as keyboard nav above). | 673 * set focusability on click (as well as keyboard nav above). |
679 * @param {Event} e The focus event. | 674 * @param {Event} e The focus event. |
680 * @private | 675 * @private |
681 */ | 676 */ |
682 handleMouseDown_: function(e) { | 677 handleMouseDown_: function(e) { |
683 var focusable = findAncestorByClass(/** @type {Element} */(e.target), | 678 var focusable = |
684 'focusable'); | 679 findAncestorByClass(/** @type {Element} */ (e.target), 'focusable'); |
685 if (focusable) { | 680 if (focusable) { |
686 this.focusElementIndex_ = | 681 this.focusElementIndex_ = |
687 Array.prototype.indexOf.call(this.focusableElements_, | 682 Array.prototype.indexOf.call(this.focusableElements_, focusable); |
688 focusable); | |
689 this.updateFocusElement_(); | 683 this.updateFocusElement_(); |
690 } | 684 } |
691 }, | 685 }, |
692 | 686 |
693 /** | 687 /** |
694 * Handle arrow key focus nav. | 688 * Handle arrow key focus nav. |
695 * @param {Event} e The focus event. | 689 * @param {Event} e The focus event. |
696 * @private | 690 * @private |
697 */ | 691 */ |
698 handleKeyDown_: function(e) { | 692 handleKeyDown_: function(e) { |
699 // We only handle up, down, left, right without control keys. | 693 // We only handle up, down, left, right without control keys. |
700 if (e.metaKey || e.shiftKey || e.altKey || e.ctrlKey) | 694 if (e.metaKey || e.shiftKey || e.altKey || e.ctrlKey) |
701 return; | 695 return; |
702 | 696 |
703 // Wrap the given index to |this.focusableElements_|. | 697 // Wrap the given index to |this.focusableElements_|. |
704 var wrap = function(idx) { | 698 var wrap = function(idx) { |
705 return (idx + this.focusableElements_.length) % | 699 return (idx + this.focusableElements_.length) % |
706 this.focusableElements_.length; | 700 this.focusableElements_.length; |
707 }.bind(this); | 701 }.bind(this); |
708 | 702 |
709 switch (e.key) { | 703 switch (e.key) { |
710 case 'ArrowRight': | 704 case 'ArrowRight': |
711 case 'ArrowLeft': | 705 case 'ArrowLeft': |
712 var direction = e.key == 'ArrowRight' ? 1 : -1; | 706 var direction = e.key == 'ArrowRight' ? 1 : -1; |
713 this.focusElementIndex_ = wrap(this.focusElementIndex_ + direction); | 707 this.focusElementIndex_ = wrap(this.focusElementIndex_ + direction); |
714 break; | 708 break; |
715 case 'ArrowUp': | 709 case 'ArrowUp': |
716 case 'ArrowDown': | 710 case 'ArrowDown': |
717 // Look through all focusable elements. Find the first one that is | 711 // Look through all focusable elements. Find the first one that is |
718 // in the same column. | 712 // in the same column. |
719 var direction = e.key == 'ArrowUp' ? -1 : 1; | 713 var direction = e.key == 'ArrowUp' ? -1 : 1; |
720 var currentIndex = | 714 var currentIndex = Array.prototype.indexOf.call( |
721 Array.prototype.indexOf.call(this.focusableElements_, | 715 this.focusableElements_, this.currentFocusElement_); |
722 this.currentFocusElement_); | |
723 var newFocusIdx = wrap(currentIndex + direction); | 716 var newFocusIdx = wrap(currentIndex + direction); |
724 var tile = this.currentFocusElement_.parentNode; | 717 var tile = this.currentFocusElement_.parentNode; |
725 for (;; newFocusIdx = wrap(newFocusIdx + direction)) { | 718 for (;; newFocusIdx = wrap(newFocusIdx + direction)) { |
726 var newTile = this.focusableElements_[newFocusIdx].parentNode; | 719 var newTile = this.focusableElements_[newFocusIdx].parentNode; |
727 var rowTiles = this.layoutValues_.numRowTiles; | 720 var rowTiles = this.layoutValues_.numRowTiles; |
728 if ((newTile.index - tile.index) % rowTiles == 0) | 721 if ((newTile.index - tile.index) % rowTiles == 0) |
729 break; | 722 break; |
730 } | 723 } |
731 | 724 |
732 this.focusElementIndex_ = newFocusIdx; | 725 this.focusElementIndex_ = newFocusIdx; |
(...skipping 14 matching lines...) Expand all Loading... |
747 * make the focusable element at this.focusElementIndex_ (if any) eligible | 740 * make the focusable element at this.focusElementIndex_ (if any) eligible |
748 * for tab focus, and the previously-focused element not eligible. | 741 * for tab focus, and the previously-focused element not eligible. |
749 * @protected | 742 * @protected |
750 */ | 743 */ |
751 updateFocusableElement: function() { | 744 updateFocusableElement: function() { |
752 if (this.focusableElements_.length == 0 || !this.selected) { | 745 if (this.focusableElements_.length == 0 || !this.selected) { |
753 this.focusElementIndex_ = -1; | 746 this.focusElementIndex_ = -1; |
754 return; | 747 return; |
755 } | 748 } |
756 | 749 |
757 this.focusElementIndex_ = Math.min(this.focusableElements_.length - 1, | 750 this.focusElementIndex_ = |
758 this.focusElementIndex_); | 751 Math.min(this.focusableElements_.length - 1, this.focusElementIndex_); |
759 this.focusElementIndex_ = Math.max(0, this.focusElementIndex_); | 752 this.focusElementIndex_ = Math.max(0, this.focusElementIndex_); |
760 | 753 |
761 var newFocusElement = this.focusableElements_[this.focusElementIndex_]; | 754 var newFocusElement = this.focusableElements_[this.focusElementIndex_]; |
762 var lastFocusElement = this.currentFocusElement_; | 755 var lastFocusElement = this.currentFocusElement_; |
763 if (lastFocusElement && lastFocusElement != newFocusElement) | 756 if (lastFocusElement && lastFocusElement != newFocusElement) |
764 lastFocusElement.tabIndex = -1; | 757 lastFocusElement.tabIndex = -1; |
765 | 758 |
766 newFocusElement.tabIndex = 1; | 759 newFocusElement.tabIndex = 1; |
767 }, | 760 }, |
768 | 761 |
(...skipping 24 matching lines...) Expand all Loading... |
793 * hidden, but call before being shown. | 786 * hidden, but call before being shown. |
794 * @private | 787 * @private |
795 */ | 788 */ |
796 calculateLayoutValues_: function() { | 789 calculateLayoutValues_: function() { |
797 var grid = this.gridValues_; | 790 var grid = this.gridValues_; |
798 var availableSpace = this.tileGrid_.clientWidth - 2 * MIN_WIDE_MARGIN; | 791 var availableSpace = this.tileGrid_.clientWidth - 2 * MIN_WIDE_MARGIN; |
799 var wide = availableSpace >= grid.minWideWidth; | 792 var wide = availableSpace >= grid.minWideWidth; |
800 var numRowTiles = wide ? grid.maxColCount : grid.minColCount; | 793 var numRowTiles = wide ? grid.maxColCount : grid.minColCount; |
801 | 794 |
802 var effectiveGridWidth = wide ? | 795 var effectiveGridWidth = wide ? |
803 Math.min(Math.max(availableSpace, grid.minWideWidth), | 796 Math.min( |
804 grid.maxWideWidth) : | 797 Math.max(availableSpace, grid.minWideWidth), grid.maxWideWidth) : |
805 grid.narrowWidth; | 798 grid.narrowWidth; |
806 var realTileValues = tileValuesForGrid(effectiveGridWidth, numRowTiles, | 799 var realTileValues = tileValuesForGrid( |
807 grid.tileSpacingFraction); | 800 effectiveGridWidth, numRowTiles, grid.tileSpacingFraction); |
808 | 801 |
809 // leftMargin centers the grid within the avaiable space. | 802 // leftMargin centers the grid within the avaiable space. |
810 var minMargin = wide ? MIN_WIDE_MARGIN : 0; | 803 var minMargin = wide ? MIN_WIDE_MARGIN : 0; |
811 var leftMargin = | 804 var leftMargin = Math.max( |
812 Math.max(minMargin, | 805 minMargin, (this.tileGrid_.clientWidth - effectiveGridWidth) / 2); |
813 (this.tileGrid_.clientWidth - effectiveGridWidth) / 2); | |
814 | 806 |
815 var rowHeight = this.heightForWidth(realTileValues.tileWidth) + | 807 var rowHeight = this.heightForWidth(realTileValues.tileWidth) + |
816 realTileValues.interTileSpacing; | 808 realTileValues.interTileSpacing; |
817 | 809 |
818 this.layoutValues_ = { | 810 this.layoutValues_ = { |
819 colWidth: realTileValues.offsetX, | 811 colWidth: realTileValues.offsetX, |
820 gridWidth: effectiveGridWidth, | 812 gridWidth: effectiveGridWidth, |
821 leftMargin: leftMargin, | 813 leftMargin: leftMargin, |
822 numRowTiles: numRowTiles, | 814 numRowTiles: numRowTiles, |
823 rowHeight: rowHeight, | 815 rowHeight: rowHeight, |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
866 var indexOffset = opt_indexOffset || 0; | 858 var indexOffset = opt_indexOffset || 0; |
867 // Add the offset _after_ the modulus division. We might want to show the | 859 // Add the offset _after_ the modulus division. We might want to show the |
868 // tile off the side of the grid. | 860 // tile off the side of the grid. |
869 var col = index % layout.numRowTiles + indexOffset; | 861 var col = index % layout.numRowTiles + indexOffset; |
870 var row = Math.floor(index / layout.numRowTiles); | 862 var row = Math.floor(index / layout.numRowTiles); |
871 // Calculate the final on-screen position for the tile. | 863 // Calculate the final on-screen position for the tile. |
872 var realX = col * layout.colWidth + layout.leftMargin; | 864 var realX = col * layout.colWidth + layout.leftMargin; |
873 var realY = row * layout.rowHeight; | 865 var realY = row * layout.rowHeight; |
874 | 866 |
875 // Calculate the portion of the tile's position that should be animated. | 867 // Calculate the portion of the tile's position that should be animated. |
876 var animatedTileValues = layout.wide ? | 868 var animatedTileValues = |
877 grid.wideTileValues : grid.narrowTileValues; | 869 layout.wide ? grid.wideTileValues : grid.narrowTileValues; |
878 // Animate the difference between three-wide and six-wide. | 870 // Animate the difference between three-wide and six-wide. |
879 var animatedLeftMargin = this.getAnimatedLeftMargin_(); | 871 var animatedLeftMargin = this.getAnimatedLeftMargin_(); |
880 var animatedX = col * animatedTileValues.offsetX + animatedLeftMargin; | 872 var animatedX = col * animatedTileValues.offsetX + animatedLeftMargin; |
881 var animatedY = row * (this.heightForWidth(animatedTileValues.tileWidth) + | 873 var animatedY = row * |
882 animatedTileValues.interTileSpacing); | 874 (this.heightForWidth(animatedTileValues.tileWidth) + |
| 875 animatedTileValues.interTileSpacing); |
883 | 876 |
884 var tile = this.tileElements_[index]; | 877 var tile = this.tileElements_[index]; |
885 tile.setGridPosition(animatedX, animatedY); | 878 tile.setGridPosition(animatedX, animatedY); |
886 tile.firstChild.setBounds(layout.tileWidth, | 879 tile.firstChild.setBounds( |
887 realX - animatedX, | 880 layout.tileWidth, realX - animatedX, realY - animatedY); |
888 realY - animatedY); | |
889 | 881 |
890 // This code calculates whether the tile needs to show a clone of itself | 882 // This code calculates whether the tile needs to show a clone of itself |
891 // wrapped around the other side of the tile grid. | 883 // wrapped around the other side of the tile grid. |
892 var offTheRight = col == layout.numRowTiles || | 884 var offTheRight = col == layout.numRowTiles || |
893 (col == layout.numRowTiles - 1 && tile.hasDoppleganger()); | 885 (col == layout.numRowTiles - 1 && tile.hasDoppleganger()); |
894 var offTheLeft = col == -1 || (col == 0 && tile.hasDoppleganger()); | 886 var offTheLeft = col == -1 || (col == 0 && tile.hasDoppleganger()); |
895 if (this.isCurrentDragTarget && (offTheRight || offTheLeft)) { | 887 if (this.isCurrentDragTarget && (offTheRight || offTheLeft)) { |
896 var sign = offTheRight ? 1 : -1; | 888 var sign = offTheRight ? 1 : -1; |
897 tile.showDoppleganger(-layout.numRowTiles * layout.colWidth * sign, | 889 tile.showDoppleganger( |
898 layout.rowHeight * sign); | 890 -layout.numRowTiles * layout.colWidth * sign, |
| 891 layout.rowHeight * sign); |
899 } else { | 892 } else { |
900 tile.clearDoppleganger(); | 893 tile.clearDoppleganger(); |
901 } | 894 } |
902 | 895 |
903 if (index == this.tileElements_.length - 1) { | 896 if (index == this.tileElements_.length - 1) { |
904 this.tileGrid_.style.height = (realY + layout.rowHeight) + 'px'; | 897 this.tileGrid_.style.height = (realY + layout.rowHeight) + 'px'; |
905 this.queueUpdateScrollbars_(); | 898 this.queueUpdateScrollbars_(); |
906 } | 899 } |
907 }, | 900 }, |
908 | 901 |
909 /** | 902 /** |
910 * Gets the index of the tile that should occupy coordinate (x, y). Note | 903 * Gets the index of the tile that should occupy coordinate (x, y). Note |
911 * that this function doesn't care where the tiles actually are, and will | 904 * that this function doesn't care where the tiles actually are, and will |
912 * return an index even for the space between two tiles. This function is | 905 * return an index even for the space between two tiles. This function is |
913 * effectively the inverse of |positionTile_|. | 906 * effectively the inverse of |positionTile_|. |
914 * @param {number} x The x coordinate, in pixels, relative to the left of | 907 * @param {number} x The x coordinate, in pixels, relative to the left of |
915 * |this|. | 908 * |this|. |
916 * @param {number} y The y coordinate, in pixels, relative to the top of | 909 * @param {number} y The y coordinate, in pixels, relative to the top of |
917 * |this|. | 910 * |this|. |
918 * @return {number} | 911 * @return {number} |
919 * @private | 912 * @private |
920 */ | 913 */ |
921 getWouldBeIndexForPoint_: function(x, y) { | 914 getWouldBeIndexForPoint_: function(x, y) { |
922 var grid = this.gridValues_; | 915 var grid = this.gridValues_; |
923 var layout = this.layoutValues_; | 916 var layout = this.layoutValues_; |
924 | 917 |
925 var gridClientRect = this.tileGrid_.getBoundingClientRect(); | 918 var gridClientRect = this.tileGrid_.getBoundingClientRect(); |
926 var col = Math.floor((x - gridClientRect.left - layout.leftMargin) / | 919 var col = Math.floor( |
927 layout.colWidth); | 920 (x - gridClientRect.left - layout.leftMargin) / layout.colWidth); |
928 if (col < 0 || col >= layout.numRowTiles) | 921 if (col < 0 || col >= layout.numRowTiles) |
929 return -1; | 922 return -1; |
930 | 923 |
931 if (isRTL()) | 924 if (isRTL()) |
932 col = layout.numRowTiles - 1 - col; | 925 col = layout.numRowTiles - 1 - col; |
933 | 926 |
934 var row = Math.floor((y - gridClientRect.top) / layout.rowHeight); | 927 var row = Math.floor((y - gridClientRect.top) / layout.rowHeight); |
935 return row * layout.numRowTiles + col; | 928 return row * layout.numRowTiles + col; |
936 }, | 929 }, |
937 | 930 |
(...skipping 24 matching lines...) Expand all Loading... |
962 * @private | 955 * @private |
963 */ | 956 */ |
964 updateMask_: function() { | 957 updateMask_: function() { |
965 if (!this.isCurrentDragTarget) { | 958 if (!this.isCurrentDragTarget) { |
966 this.tileGrid_.style.WebkitMaskBoxImage = ''; | 959 this.tileGrid_.style.WebkitMaskBoxImage = ''; |
967 return; | 960 return; |
968 } | 961 } |
969 | 962 |
970 var leftMargin = this.layoutValues_.leftMargin; | 963 var leftMargin = this.layoutValues_.leftMargin; |
971 // The fade distance is the space between tiles. | 964 // The fade distance is the space between tiles. |
972 var fadeDistance = (this.gridValues_.tileSpacingFraction * | 965 var fadeDistance = |
973 this.layoutValues_.tileWidth); | 966 (this.gridValues_.tileSpacingFraction * this.layoutValues_.tileWidth); |
974 fadeDistance = Math.min(leftMargin, fadeDistance); | 967 fadeDistance = Math.min(leftMargin, fadeDistance); |
975 // On Skia we don't use any fade because it works very poorly. See | 968 // On Skia we don't use any fade because it works very poorly. See |
976 // http://crbug.com/99373 | 969 // http://crbug.com/99373 |
977 if (!cr.isMac) | 970 if (!cr.isMac) |
978 fadeDistance = 1; | 971 fadeDistance = 1; |
979 var gradient = | 972 var gradient = '-webkit-linear-gradient(left,' + |
980 '-webkit-linear-gradient(left,' + | 973 'transparent, ' + |
981 'transparent, ' + | 974 'transparent ' + (leftMargin - fadeDistance) + 'px, ' + |
982 'transparent ' + (leftMargin - fadeDistance) + 'px, ' + | 975 'black ' + leftMargin + 'px, ' + |
983 'black ' + leftMargin + 'px, ' + | 976 'black ' + (this.tileGrid_.clientWidth - leftMargin) + 'px, ' + |
984 'black ' + (this.tileGrid_.clientWidth - leftMargin) + 'px, ' + | 977 'transparent ' + |
985 'transparent ' + (this.tileGrid_.clientWidth - leftMargin + | 978 (this.tileGrid_.clientWidth - leftMargin + fadeDistance) + 'px, ' + |
986 fadeDistance) + 'px, ' + | 979 'transparent)'; |
987 'transparent)'; | |
988 this.tileGrid_.style.WebkitMaskBoxImage = gradient; | 980 this.tileGrid_.style.WebkitMaskBoxImage = gradient; |
989 }, | 981 }, |
990 | 982 |
991 updateTopMargin_: function() { | 983 updateTopMargin_: function() { |
992 var layout = this.layoutValues_; | 984 var layout = this.layoutValues_; |
993 | 985 |
994 // The top margin is set so that the vertical midpoint of the grid will | 986 // The top margin is set so that the vertical midpoint of the grid will |
995 // be 1/3 down the page. | 987 // be 1/3 down the page. |
996 var numTiles = this.tileCount + | 988 var numTiles = this.tileCount + |
997 (this.isCurrentDragTarget && !this.withinPageDrag_ ? 1 : 0); | 989 (this.isCurrentDragTarget && !this.withinPageDrag_ ? 1 : 0); |
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1089 * Queues an update on the custom scrollbar. Used for two reasons: first, | 1081 * Queues an update on the custom scrollbar. Used for two reasons: first, |
1090 * coalescing of multiple updates, and second, because action like | 1082 * coalescing of multiple updates, and second, because action like |
1091 * repositioning a tile can require a delay before they affect values | 1083 * repositioning a tile can require a delay before they affect values |
1092 * like clientHeight. | 1084 * like clientHeight. |
1093 * @private | 1085 * @private |
1094 */ | 1086 */ |
1095 queueUpdateScrollbars_: function() { | 1087 queueUpdateScrollbars_: function() { |
1096 if (this.scrollbarUpdate_) | 1088 if (this.scrollbarUpdate_) |
1097 return; | 1089 return; |
1098 | 1090 |
1099 this.scrollbarUpdate_ = window.setTimeout( | 1091 this.scrollbarUpdate_ = |
1100 this.doUpdateScrollbars_.bind(this), 0); | 1092 window.setTimeout(this.doUpdateScrollbars_.bind(this), 0); |
1101 }, | 1093 }, |
1102 | 1094 |
1103 /** | 1095 /** |
1104 * Does the work of calculating the visibility, height and position of the | 1096 * Does the work of calculating the visibility, height and position of the |
1105 * scrollbar thumb (there is no track or buttons). | 1097 * scrollbar thumb (there is no track or buttons). |
1106 * @private | 1098 * @private |
1107 */ | 1099 */ |
1108 doUpdateScrollbars_: function() { | 1100 doUpdateScrollbars_: function() { |
1109 this.scrollbarUpdate_ = 0; | 1101 this.scrollbarUpdate_ = 0; |
1110 | 1102 |
1111 var content = this.content_; | 1103 var content = this.content_; |
1112 | 1104 |
1113 // Adjust scroll-height to account for possible header-bar. | 1105 // Adjust scroll-height to account for possible header-bar. |
1114 var adjustedScrollHeight = content.scrollHeight - content.offsetTop; | 1106 var adjustedScrollHeight = content.scrollHeight - content.offsetTop; |
1115 | 1107 |
1116 if (adjustedScrollHeight <= content.clientHeight) { | 1108 if (adjustedScrollHeight <= content.clientHeight) { |
1117 this.scrollbar_.hidden = true; | 1109 this.scrollbar_.hidden = true; |
1118 return; | 1110 return; |
1119 } else { | 1111 } else { |
1120 this.scrollbar_.hidden = false; | 1112 this.scrollbar_.hidden = false; |
1121 } | 1113 } |
1122 | 1114 |
1123 var thumbTop = content.offsetTop + | 1115 var thumbTop = content.offsetTop + |
1124 content.scrollTop / adjustedScrollHeight * content.clientHeight; | 1116 content.scrollTop / adjustedScrollHeight * content.clientHeight; |
1125 var thumbHeight = content.clientHeight / adjustedScrollHeight * | 1117 var thumbHeight = |
1126 this.clientHeight; | 1118 content.clientHeight / adjustedScrollHeight * this.clientHeight; |
1127 | 1119 |
1128 this.scrollbar_.style.top = thumbTop + 'px'; | 1120 this.scrollbar_.style.top = thumbTop + 'px'; |
1129 this.scrollbar_.style.height = thumbHeight + 'px'; | 1121 this.scrollbar_.style.height = thumbHeight + 'px'; |
1130 this.firePageLayoutEvent_(); | 1122 this.firePageLayoutEvent_(); |
1131 }, | 1123 }, |
1132 | 1124 |
1133 /** | 1125 /** |
1134 * Get the height for a tile of a certain width. Override this function to | 1126 * Get the height for a tile of a certain width. Override this function to |
1135 * get non-square tiles. | 1127 * get non-square tiles. |
1136 * @param {number} width The pixel width of a tile. | 1128 * @param {number} width The pixel width of a tile. |
(...skipping 14 matching lines...) Expand all Loading... |
1151 this.cleanupDrag(); | 1143 this.cleanupDrag(); |
1152 }, | 1144 }, |
1153 | 1145 |
1154 /** @override */ | 1146 /** @override */ |
1155 doDragEnter: function(e) { | 1147 doDragEnter: function(e) { |
1156 // Applies the mask so doppleganger tiles disappear into the fog. | 1148 // Applies the mask so doppleganger tiles disappear into the fog. |
1157 this.updateMask_(); | 1149 this.updateMask_(); |
1158 | 1150 |
1159 this.classList.add('animating-tile-page'); | 1151 this.classList.add('animating-tile-page'); |
1160 this.withinPageDrag_ = this.contains(currentlyDraggingTile); | 1152 this.withinPageDrag_ = this.contains(currentlyDraggingTile); |
1161 this.dragItemIndex_ = this.withinPageDrag_ ? | 1153 this.dragItemIndex_ = this.withinPageDrag_ ? currentlyDraggingTile.index : |
1162 currentlyDraggingTile.index : this.tileElements_.length; | 1154 this.tileElements_.length; |
1163 this.currentDropIndex_ = this.dragItemIndex_; | 1155 this.currentDropIndex_ = this.dragItemIndex_; |
1164 | 1156 |
1165 // The new tile may change the number of rows, hence the top margin | 1157 // The new tile may change the number of rows, hence the top margin |
1166 // will change. | 1158 // will change. |
1167 if (!this.withinPageDrag_) | 1159 if (!this.withinPageDrag_) |
1168 this.updateTopMargin_(); | 1160 this.updateTopMargin_(); |
1169 | 1161 |
1170 this.doDragOver(e); | 1162 this.doDragOver(e); |
1171 }, | 1163 }, |
1172 | 1164 |
1173 /** @override */ | 1165 /** @override */ |
1174 doDragOver: function(e) { | 1166 doDragOver: function(e) { |
1175 e.preventDefault(); | 1167 e.preventDefault(); |
1176 | 1168 |
1177 this.setDropEffect(e.dataTransfer); | 1169 this.setDropEffect(e.dataTransfer); |
1178 var newDragIndex = this.getWouldBeIndexForPoint_(e.pageX, e.pageY); | 1170 var newDragIndex = this.getWouldBeIndexForPoint_(e.pageX, e.pageY); |
1179 if (newDragIndex < 0 || newDragIndex >= this.tileElements_.length) | 1171 if (newDragIndex < 0 || newDragIndex >= this.tileElements_.length) |
1180 newDragIndex = this.dragItemIndex_; | 1172 newDragIndex = this.dragItemIndex_; |
1181 this.updateDropIndicator_(newDragIndex); | 1173 this.updateDropIndicator_(newDragIndex); |
1182 }, | 1174 }, |
1183 | 1175 |
1184 /** @override */ | 1176 /** @override */ |
1185 doDrop: function(e) { | 1177 doDrop: function(e) { |
1186 e.stopPropagation(); | 1178 e.stopPropagation(); |
1187 e.preventDefault(); | 1179 e.preventDefault(); |
1188 | 1180 |
1189 var index = this.currentDropIndex_; | 1181 var index = this.currentDropIndex_; |
1190 // Only change data if this was not a 'null drag'. | 1182 // Only change data if this was not a 'null drag'. |
1191 if (!((index == this.dragItemIndex_) && this.withinPageDrag_)) { | 1183 if (!((index == this.dragItemIndex_) && this.withinPageDrag_)) { |
1192 var adjustedIndex = this.currentDropIndex_ + | 1184 var adjustedIndex = |
1193 (index > this.dragItemIndex_ ? 1 : 0); | 1185 this.currentDropIndex_ + (index > this.dragItemIndex_ ? 1 : 0); |
1194 if (this.withinPageDrag_) { | 1186 if (this.withinPageDrag_) { |
1195 this.tileGrid_.insertBefore( | 1187 this.tileGrid_.insertBefore( |
1196 currentlyDraggingTile, | 1188 currentlyDraggingTile, this.tileElements_[adjustedIndex]); |
1197 this.tileElements_[adjustedIndex]); | |
1198 this.tileMoved(currentlyDraggingTile, this.dragItemIndex_); | 1189 this.tileMoved(currentlyDraggingTile, this.dragItemIndex_); |
1199 } else { | 1190 } else { |
1200 var originalPage = currentlyDraggingTile ? | 1191 var originalPage = |
1201 currentlyDraggingTile.tilePage : null; | 1192 currentlyDraggingTile ? currentlyDraggingTile.tilePage : null; |
1202 this.addDragData(e.dataTransfer, adjustedIndex); | 1193 this.addDragData(e.dataTransfer, adjustedIndex); |
1203 if (originalPage) | 1194 if (originalPage) |
1204 originalPage.cleanupDrag(); | 1195 originalPage.cleanupDrag(); |
1205 } | 1196 } |
1206 | 1197 |
1207 // Dropping the icon may cause topMargin to change, but changing it | 1198 // Dropping the icon may cause topMargin to change, but changing it |
1208 // now would cause everything to move (annoying), so we leave it | 1199 // now would cause everything to move (annoying), so we leave it |
1209 // alone. The top margin will be re-calculated next time the window is | 1200 // alone. The top margin will be re-calculated next time the window is |
1210 // resized or the page is selected. | 1201 // resized or the page is selected. |
1211 } | 1202 } |
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1294 addDragData: function(dataTransfer, index) { | 1285 addDragData: function(dataTransfer, index) { |
1295 assertNotReached(); | 1286 assertNotReached(); |
1296 }, | 1287 }, |
1297 | 1288 |
1298 /** | 1289 /** |
1299 * Called when a tile has been moved (via dragging). Override this to make | 1290 * Called when a tile has been moved (via dragging). Override this to make |
1300 * backend updates. | 1291 * backend updates. |
1301 * @param {Node} draggedTile The tile that was dropped. | 1292 * @param {Node} draggedTile The tile that was dropped. |
1302 * @param {number} prevIndex The previous index of the tile. | 1293 * @param {number} prevIndex The previous index of the tile. |
1303 */ | 1294 */ |
1304 tileMoved: function(draggedTile, prevIndex) { | 1295 tileMoved: function(draggedTile, prevIndex) {}, |
1305 }, | |
1306 | 1296 |
1307 /** | 1297 /** |
1308 * Sets the drop effect on |dataTransfer| to the desired value (e.g. | 1298 * Sets the drop effect on |dataTransfer| to the desired value (e.g. |
1309 * 'copy'). | 1299 * 'copy'). |
1310 * @param {Object} dataTransfer The drag event dataTransfer object. | 1300 * @param {Object} dataTransfer The drag event dataTransfer object. |
1311 */ | 1301 */ |
1312 setDropEffect: function(dataTransfer) { | 1302 setDropEffect: function(dataTransfer) { |
1313 assertNotReached(); | 1303 assertNotReached(); |
1314 }, | 1304 }, |
1315 }; | 1305 }; |
1316 | 1306 |
1317 return { | 1307 return { |
1318 getCurrentlyDraggingTile: getCurrentlyDraggingTile, | 1308 getCurrentlyDraggingTile: getCurrentlyDraggingTile, |
1319 setCurrentDropEffect: setCurrentDropEffect, | 1309 setCurrentDropEffect: setCurrentDropEffect, |
1320 // Not used outside, just for usage in JSDoc inside this file. | 1310 // Not used outside, just for usage in JSDoc inside this file. |
1321 Tile: Tile, | 1311 Tile: Tile, |
1322 TilePage: TilePage, | 1312 TilePage: TilePage, |
1323 }; | 1313 }; |
1324 }); | 1314 }); |
OLD | NEW |