OLD | NEW |
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 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 | 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('ntp4', function() { | 5 cr.define('ntp4', function() { |
6 'use strict'; | 6 'use strict'; |
7 | 7 |
8 /** | 8 /** |
9 * Creates a new Tileobject. Tiles wrap content on a TilePage, providing | 9 * Creates a new Tileobject. Tiles wrap content on a TilePage, providing |
10 * some styling and drag functionality. | 10 * some styling and drag functionality. |
(...skipping 316 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
327 this.onDragLeaveDot_.bind(this)); | 327 this.onDragLeaveDot_.bind(this)); |
328 }, | 328 }, |
329 get navigationDot() { | 329 get navigationDot() { |
330 return this.navigationDot_; | 330 return this.navigationDot_; |
331 }, | 331 }, |
332 | 332 |
333 /** | 333 /** |
334 * @protected | 334 * @protected |
335 */ | 335 */ |
336 appendTile: function(tileElement) { | 336 appendTile: function(tileElement) { |
| 337 this.addTileAt(tileElement, this.tileElements_.length); |
| 338 }, |
| 339 |
| 340 /** |
| 341 * Adds the given element to the tile grid. |
| 342 * @param {Node} tileElement The tile object/node to insert. |
| 343 * @param {number} index The location in the tile grid to insert it at. |
| 344 * @protected |
| 345 */ |
| 346 addTileAt: function(tileElement, index) { |
| 347 var wrapperDiv = new Tile(tileElement); |
| 348 if (index == this.tileElements_.length) { |
| 349 this.tileGrid_.appendChild(wrapperDiv); |
| 350 } else { |
| 351 this.tileGrid_.insertBefore(wrapperDiv, |
| 352 this.tileElements_[index]); |
| 353 } |
337 this.calculateLayoutValues_(); | 354 this.calculateLayoutValues_(); |
338 | 355 |
339 var wrapperDiv = new Tile(tileElement); | 356 this.positionTile_(index); |
340 this.tileGrid_.appendChild(wrapperDiv); | |
341 | |
342 this.positionTile_(this.tileElements_.length - 1); | |
343 this.classList.remove('animating-tile-page'); | 357 this.classList.remove('animating-tile-page'); |
344 }, | 358 }, |
345 | 359 |
346 /** | 360 /** |
347 * Controls whether this page will accept drags that originate from outside | 361 * Controls whether this page will accept drags that originate from outside |
348 * the page. | 362 * the page. |
349 * @return {boolean} True if this page accepts drags from outside sources. | 363 * @return {boolean} True if this page accepts drags from outside sources. |
350 */ | 364 */ |
351 acceptOutsideDrags: function() { | 365 acceptOutsideDrags: function() { |
352 return true; | 366 return true; |
(...skipping 202 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
555 heightForWidth: function(width) { | 569 heightForWidth: function(width) { |
556 return width; | 570 return width; |
557 }, | 571 }, |
558 | 572 |
559 /** Dragging **/ | 573 /** Dragging **/ |
560 | 574 |
561 /** | 575 /** |
562 * The number of un-paired dragenter events that have fired on |this|. This | 576 * The number of un-paired dragenter events that have fired on |this|. This |
563 * is incremented by |onDragEnter_| and decremented by |onDragLeave_|. This | 577 * is incremented by |onDragEnter_| and decremented by |onDragLeave_|. This |
564 * is necessary because dragging over child widgets will fire additional | 578 * is necessary because dragging over child widgets will fire additional |
565 * enter and leave events on |this|. | 579 * enter and leave events on |this|. A non-zero value does not necessarily |
| 580 * indicate that |isCurrentDragTarget_| is true. |
566 * @type {number} | 581 * @type {number} |
567 * @private | 582 * @private |
568 */ | 583 */ |
569 dragEnters_: 0, | 584 dragEnters_: 0, |
570 | 585 |
571 /** | 586 /** |
| 587 * Whether the tile page is currently being dragged over with data it can |
| 588 * accept. |
| 589 * @type {boolean} |
| 590 * @private |
| 591 */ |
| 592 isCurrentDragTarget_: false, |
| 593 |
| 594 /** |
572 * Handler for dragenter events fired on |tileGrid_|. | 595 * Handler for dragenter events fired on |tileGrid_|. |
573 * @param {Event} e A MouseEvent for the drag. | 596 * @param {Event} e A MouseEvent for the drag. |
574 * @private | 597 * @private |
575 */ | 598 */ |
576 onDragEnter_: function(e) { | 599 onDragEnter_: function(e) { |
577 if (++this.dragEnters_ > 1) | 600 if (++this.dragEnters_ > 1) |
578 return; | 601 return; |
| 602 this.doDragEnter_(e); |
| 603 }, |
579 | 604 |
580 // TODO(estade): for now we only allow tile drags. | 605 /** |
581 if (!TilePage.currentlyDraggingTile) | 606 * Thunk for dragover events fired on |tileGrid_|. |
| 607 * @param {Event} e A MouseEvent for the drag. |
| 608 * @private |
| 609 */ |
| 610 onDragOver_: function(e) { |
| 611 if (!this.isCurrentDragTarget_) |
582 return; | 612 return; |
| 613 this.doDragOver_(e); |
| 614 }, |
| 615 |
| 616 /** |
| 617 * Thunk for drop events fired on |tileGrid_|. |
| 618 * @param {Event} e A MouseEvent for the drag. |
| 619 * @private |
| 620 */ |
| 621 onDrop_: function(e) { |
| 622 this.dragEnters_ = 0; |
| 623 if (!this.isCurrentDragTarget_) |
| 624 return; |
| 625 this.doDrop_(e); |
| 626 }, |
| 627 |
| 628 /** |
| 629 * Thunk for dragleave events fired on |tileGrid_|. |
| 630 * @param {Event} e A MouseEvent for the drag. |
| 631 * @private |
| 632 */ |
| 633 onDragLeave_: function(e) { |
| 634 if (--this.dragEnters_ > 0) |
| 635 return; |
| 636 |
| 637 this.isCurrentDragTarget_ = false; |
| 638 this.cleanUpDrag_(); |
| 639 }, |
| 640 |
| 641 /** |
| 642 * Performs all actions necessary when a drag enters the tile page. |
| 643 * @param {Event} e A mouseover event for the drag enter. |
| 644 * @private |
| 645 */ |
| 646 doDragEnter_: function(e) { |
| 647 if (!this.shouldAcceptDrag(TilePage.currentlyDraggingTile, |
| 648 e.dataTransfer)) { |
| 649 return; |
| 650 } |
| 651 |
| 652 this.isCurrentDragTarget_ = true; |
583 | 653 |
584 // Applies the mask so doppleganger tiles disappear into the fog. | 654 // Applies the mask so doppleganger tiles disappear into the fog. |
585 this.updateMask_(); | 655 this.updateMask_(); |
586 | 656 |
587 this.classList.add('animating-tile-page'); | 657 this.classList.add('animating-tile-page'); |
588 this.withinPageDrag_ = this.contains(TilePage.currentlyDraggingTile); | 658 this.withinPageDrag_ = this.contains(TilePage.currentlyDraggingTile); |
589 this.dragItemIndex_ = this.withinPageDrag_ ? | 659 this.dragItemIndex_ = this.withinPageDrag_ ? |
590 TilePage.currentlyDraggingTile.index : this.tileElements_.length; | 660 TilePage.currentlyDraggingTile.index : this.tileElements_.length; |
591 this.currentDropIndex_ = this.dragItemIndex_; | 661 this.currentDropIndex_ = this.dragItemIndex_; |
592 }, | 662 }, |
593 | 663 |
594 /** | 664 /** |
595 * Handler for dragover events fired on |tileGrid_|. | 665 * Performs all actions necessary when the user moves the cursor during |
596 * @param {Event} e A MouseEvent for the drag. | 666 * a drag over the tile page. |
| 667 * @param {Event} e A mouseover event for the drag over. |
597 * @private | 668 * @private |
598 */ | 669 */ |
599 onDragOver_: function(e) { | 670 doDragOver_: function(e) { |
600 e.dataTransfer.dropEffect = 'move'; | 671 e.preventDefault(); |
601 var draggedTile = TilePage.currentlyDraggingTile; | |
602 if (!draggedTile) | |
603 return; | |
604 | 672 |
605 e.preventDefault(); | 673 if (TilePage.currentlyDraggingTile) |
| 674 e.dataTransfer.dropEffect = 'move'; |
| 675 else |
| 676 e.dataTransfer.dropEffect = 'copy'; |
606 | 677 |
607 var newDragIndex = this.getWouldBeIndexForPoint_(e.clientX, e.clientY); | 678 var newDragIndex = this.getWouldBeIndexForPoint_(e.clientX, e.clientY); |
608 if (newDragIndex < 0 || newDragIndex >= this.tileElements_.length) | 679 if (newDragIndex < 0 || newDragIndex >= this.tileElements_.length) |
609 newDragIndex = this.dragItemIndex_; | 680 newDragIndex = this.dragItemIndex_; |
610 this.updateDropIndicator_(newDragIndex); | 681 this.updateDropIndicator_(newDragIndex); |
611 }, | 682 }, |
612 | 683 |
613 /** | 684 /** |
614 * Handler for drop events fired on |tileGrid_|. | 685 * Performs all actions necessary when the user completes a drop. |
615 * @param {Event} e A MouseEvent for the drag. | 686 * @param {Event} e A mouseover event for the drag drop. |
616 * @private | 687 * @private |
617 */ | 688 */ |
618 onDrop_: function(e) { | 689 doDrop_: function(e) { |
619 this.dragEnters_ = 0; | |
620 e.stopPropagation(); | 690 e.stopPropagation(); |
| 691 this.isCurrentDragTarget_ = false; |
621 | 692 |
622 var index = this.currentDropIndex_; | 693 var index = this.currentDropIndex_; |
623 if ((index == this.dragItemIndex_) && this.withinPageDrag_) | 694 if ((index == this.dragItemIndex_) && this.withinPageDrag_) |
624 return; | 695 return; |
625 | 696 |
626 var adjustment = index > this.dragItemIndex_ ? 1 : 0; | 697 var adjustedIndex = this.currentDropIndex_ + |
627 this.tileGrid_.insertBefore( | 698 (index > this.dragItemIndex_ ? 1 : 0); |
628 TilePage.currentlyDraggingTile, | 699 if (TilePage.currentlyDraggingTile) { |
629 this.tileElements_[this.currentDropIndex_ + adjustment]); | 700 this.tileGrid_.insertBefore( |
| 701 TilePage.currentlyDraggingTile, |
| 702 this.tileElements_[adjustedIndex]); |
| 703 } else { |
| 704 this.addOutsideData(e.dataTransfer, adjustedIndex); |
| 705 } |
| 706 |
| 707 this.classList.remove('animating-tile-page'); |
630 this.cleanUpDrag_(); | 708 this.cleanUpDrag_(); |
631 }, | 709 }, |
632 | 710 |
633 /** | |
634 * Handler for dragleave events fired on |tileGrid_|. | |
635 * @param {Event} e A MouseEvent for the drag. | |
636 * @private | |
637 */ | |
638 onDragLeave_: function(e) { | |
639 if (--this.dragEnters_ > 0) | |
640 return; | |
641 | |
642 this.cleanUpDrag_(); | |
643 }, | |
644 | |
645 /** | 711 /** |
646 * Makes sure all the tiles are in the right place after a drag is over. | 712 * Makes sure all the tiles are in the right place after a drag is over. |
647 * @private | 713 * @private |
648 */ | 714 */ |
649 cleanUpDrag_: function() { | 715 cleanUpDrag_: function() { |
650 this.classList.remove('animating-tile-page'); | |
651 for (var i = 0; i < this.tileElements_.length; i++) { | 716 for (var i = 0; i < this.tileElements_.length; i++) { |
652 // The current drag tile will be positioned in its dragend handler. | 717 // The current drag tile will be positioned in its dragend handler. |
653 if (this.tileElements_[i] == this.currentlyDraggingTile) | 718 if (this.tileElements_[i] == this.currentlyDraggingTile) |
654 continue; | 719 continue; |
655 this.positionTile_(i); | 720 this.positionTile_(i); |
656 } | 721 } |
657 | 722 |
658 // Remove the drag mask. | 723 // Remove the drag mask. |
659 this.updateMask_(); | 724 this.updateMask_(); |
660 }, | 725 }, |
(...skipping 18 matching lines...) Expand all Loading... |
679 var adjustment = i <= newDragIndex ? -1 : 0; | 744 var adjustment = i <= newDragIndex ? -1 : 0; |
680 else | 745 else |
681 var adjustment = i >= newDragIndex ? 1 : 0; | 746 var adjustment = i >= newDragIndex ? 1 : 0; |
682 | 747 |
683 this.positionTile_(i, adjustment); | 748 this.positionTile_(i, adjustment); |
684 } | 749 } |
685 this.currentDropIndex_ = newDragIndex; | 750 this.currentDropIndex_ = newDragIndex; |
686 }, | 751 }, |
687 | 752 |
688 /** | 753 /** |
689 * This is equivalent to dragEnters_, but for drags over the navigation | 754 * These are equivalent to dragEnters_ and isCurrentDragTarget_, but for |
690 * dot. | 755 * drags over the navigation dot. |
| 756 * TODO(estade): thunkify the event handlers in the same manner as the |
| 757 * tile grid drag handlers. |
691 */ | 758 */ |
692 dotDragEnters_: 0, | 759 dotDragEnters_: 0, |
| 760 dotIsCurrentDragTarget_: false, |
693 | 761 |
694 /** | 762 /** |
695 * A drag has entered the navigation dot. If the user hovers long enough, | 763 * A drag has entered the navigation dot. If the user hovers long enough, |
696 * we will navigate to the relevant page. | 764 * we will navigate to the relevant page. |
697 * @param {Event} e The MouseOver event for the drag. | 765 * @param {Event} e The MouseOver event for the drag. |
698 */ | 766 */ |
699 onDragEnterDot_: function(e) { | 767 onDragEnterDot_: function(e) { |
700 if (++this.dotDragEnters_ > 1) | 768 if (++this.dotDragEnters_ > 1) |
701 return; | 769 return; |
702 | 770 |
703 if (!TilePage.currentlyDraggingTile) | 771 if (!this.shouldAcceptDrag(TilePage.currentlyDraggingTile, |
| 772 e.dataTransfer)) { |
704 return; | 773 return; |
705 if (!this.acceptOutsideDrags()) | 774 } |
706 return; | 775 |
| 776 this.dotIsCurrentDragTarget_ = true; |
707 | 777 |
708 var self = this; | 778 var self = this; |
709 function navPageClearTimeout() { | 779 function navPageClearTimeout() { |
710 self.navigationDot.showPage(); | 780 self.navigationDot.showPage(); |
711 self.dotNavTimeout = null; | 781 self.dotNavTimeout = null; |
712 } | 782 } |
713 this.dotNavTimeout = window.setTimeout(navPageClearTimeout, 500); | 783 this.dotNavTimeout = window.setTimeout(navPageClearTimeout, 500); |
714 }, | 784 }, |
715 | 785 |
716 /** | 786 /** |
717 * The drag has left the navigation dot. | 787 * The drag has left the navigation dot. |
718 * @param {Event} e The MouseOver event for the drag. | 788 * @param {Event} e The MouseOver event for the drag. |
719 */ | 789 */ |
720 onDragLeaveDot_: function(e) { | 790 onDragLeaveDot_: function(e) { |
721 if (--this.dotDragEnters_ > 0) | 791 if (--this.dotDragEnters_ > 0) |
722 return; | 792 return; |
723 | 793 |
| 794 if (!this.dotIsCurrentDragTarget_) |
| 795 return; |
| 796 this.dotIsCurrentDragTarget_ = false; |
| 797 |
724 if (this.dotNavTimeout) { | 798 if (this.dotNavTimeout) { |
725 window.clearTimeout(this.dotNavTimeout); | 799 window.clearTimeout(this.dotNavTimeout); |
726 this.dotNavTimeout = null; | 800 this.dotNavTimeout = null; |
727 } | 801 } |
728 }, | 802 }, |
| 803 |
| 804 /** |
| 805 * Checks if a page can accept a drag with the given data. |
| 806 * @param {Object} tile The drag tile, if any. |
| 807 * @param {Object} dataTransfer The dataTransfer object, if the drag object |
| 808 * is not a tile (e.g. it is a link). |
| 809 * @return {boolean} True if this page can handle the drag. |
| 810 */ |
| 811 shouldAcceptDrag: function(tile, dataTransfer) { |
| 812 return false; |
| 813 }, |
| 814 |
| 815 /** |
| 816 * Called to accept a drag drop. |
| 817 * @param {Object} dataTransfer The data transfer object that holds the drop |
| 818 * data. |
| 819 * @param {number} index The tile index at which the drop occurred. |
| 820 */ |
| 821 addOutsideData: function(dataTransfer, index) { |
| 822 // This should not get called unless there is a non-default |
| 823 // implementation. |
| 824 assert(false); |
| 825 }, |
729 }; | 826 }; |
730 | 827 |
731 return { | 828 return { |
732 TilePage: TilePage, | 829 TilePage: TilePage, |
733 }; | 830 }; |
734 }); | 831 }); |
OLD | NEW |