OLD | NEW |
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2010 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 // To avoid creating tons of unnecessary nodes. We assume we cannot fit more | 5 // To avoid creating tons of unnecessary nodes. We assume we cannot fit more |
6 // than this many items in the miniview. | 6 // than this many items in the miniview. |
7 var MAX_MINIVIEW_ITEMS = 15; | 7 var MAX_MINIVIEW_ITEMS = 15; |
8 | 8 |
9 // Extra spacing at the top of the layout. | 9 // Extra spacing at the top of the layout. |
10 var LAYOUT_SPACING_TOP = 25; | 10 var LAYOUT_SPACING_TOP = 25; |
(...skipping 629 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
640 } | 640 } |
641 | 641 |
642 function showFirstRunNotification() { | 642 function showFirstRunNotification() { |
643 showNotification(localStrings.getString('firstrunnotification'), | 643 showNotification(localStrings.getString('firstrunnotification'), |
644 localStrings.getString('closefirstrunnotification'), | 644 localStrings.getString('closefirstrunnotification'), |
645 null, 30000); | 645 null, 30000); |
646 var notificationElement = $('notification'); | 646 var notificationElement = $('notification'); |
647 notification.classList.add('first-run'); | 647 notification.classList.add('first-run'); |
648 } | 648 } |
649 | 649 |
650 /** | |
651 * This handles the option menu. | |
652 * @param {Element} button The button element. | |
653 * @param {Element} menu The menu element. | |
654 * @constructor | |
655 */ | |
656 function OptionMenu(button, menu) { | |
657 this.button = button; | |
658 this.menu = menu; | |
659 this.button.onclick = bind(this.handleClick, this); | |
660 this.button.onmousedown = bind(this.handleMouseDown, this); | |
661 this.button.onkeydown = bind(this.handleKeyDown, this); | |
662 this.boundHideMenu_ = bind(this.hide, this); | |
663 this.boundMaybeHide_ = bind(this.maybeHide_, this); | |
664 this.menu.onmouseover = bind(this.handleMouseOver, this); | |
665 this.menu.onmouseout = bind(this.handleMouseOut, this); | |
666 this.menu.onmouseup = bind(this.handleMouseUp, this); | |
667 } | |
668 | |
669 OptionMenu.prototype = { | |
670 show: function() { | |
671 this.positionMenu_(); | |
672 this.menu.style.display = 'block'; | |
673 this.button.classList.add('open'); | |
674 this.button.focus(); | |
675 | |
676 // Listen to document and window events so that we hide the menu when the | |
677 // user clicks outside the menu or tabs away or the whole window is blurred. | |
678 document.addEventListener('focus', this.boundMaybeHide_, true); | |
679 document.addEventListener('mousedown', this.boundMaybeHide_, true); | |
680 }, | |
681 | |
682 positionMenu_: function() { | |
683 var rect = this.button.getBoundingClientRect(); | |
684 this.menu.style.top = rect.bottom + 'px'; | |
685 if (document.documentElement.dir == 'rtl') | |
686 this.menu.style.left = rect.left + 'px'; | |
687 else | |
688 this.menu.style.right = (document.body.clientWidth - rect.right) + 'px' | |
689 }, | |
690 | |
691 hide: function() { | |
692 this.menu.style.display = 'none'; | |
693 this.button.classList.remove('open'); | |
694 this.setSelectedIndex(-1); | |
695 | |
696 document.removeEventListener('focus', this.boundMaybeHide_, true); | |
697 document.removeEventListener('mousedown', this.boundMaybeHide_, true); | |
698 }, | |
699 | |
700 isShown: function() { | |
701 return this.menu.style.display == 'block'; | |
702 }, | |
703 | |
704 /** | |
705 * Callback for document mousedown and focus. It checks if the user tried to | |
706 * navigate to a different element on the page and if so hides the menu. | |
707 * @param {Event} e The mouse or focus event. | |
708 * @private | |
709 */ | |
710 maybeHide_: function(e) { | |
711 if (!this.menu.contains(e.target) && !this.button.contains(e.target)) { | |
712 this.hide(); | |
713 } | |
714 }, | |
715 | |
716 handleMouseDown: function(e) { | |
717 if (this.isShown()) { | |
718 this.hide(); | |
719 } else { | |
720 this.show(); | |
721 } | |
722 }, | |
723 | |
724 handleClick: function(e) { | |
725 e.stopPropagation(); | |
726 }, | |
727 | |
728 handleMouseOver: function(e) { | |
729 var el = e.target; | |
730 if (!el.hasAttribute('command')) { | |
731 this.setSelectedIndex(-1); | |
732 } else { | |
733 var index = Array.prototype.indexOf.call(this.menu.children, el); | |
734 this.setSelectedIndex(index); | |
735 } | |
736 }, | |
737 | |
738 handleMouseOut: function(e) { | |
739 this.setSelectedIndex(-1); | |
740 }, | |
741 | |
742 handleMouseUp: function(e) { | |
743 var item = this.getSelectedItem(); | |
744 if (item) { | |
745 this.executeItem(item); | |
746 } | |
747 }, | |
748 | |
749 handleKeyDown: function(e) { | |
750 var item = this.getSelectedItem(); | |
751 | |
752 var self = this; | |
753 function selectNextVisible(m) { | |
754 var children = self.menu.children; | |
755 var len = children.length; | |
756 var i = self.selectedIndex_; | |
757 if (i == -1 && m == -1) { | |
758 // Edge case when we need to go the last item fisrt. | |
759 i = 0; | |
760 } | |
761 while (true) { | |
762 i = (i + m + len) % len; | |
763 item = children[i]; | |
764 if (item && item.hasAttribute('command') && | |
765 item.style.display != 'none') { | |
766 break; | |
767 } | |
768 } | |
769 if (item) { | |
770 self.setSelectedIndex(i); | |
771 } | |
772 } | |
773 | |
774 switch (e.keyIdentifier) { | |
775 case 'Down': | |
776 if (!this.isShown()) { | |
777 this.show(); | |
778 } | |
779 selectNextVisible(1); | |
780 e.preventDefault(); | |
781 break; | |
782 case 'Up': | |
783 if (!this.isShown()) { | |
784 this.show(); | |
785 } | |
786 selectNextVisible(-1); | |
787 e.preventDefault(); | |
788 break; | |
789 case 'Esc': | |
790 case 'U+001B': // Maybe this is remote desktop playing a prank? | |
791 this.hide(); | |
792 break; | |
793 case 'Enter': | |
794 case 'U+0020': // Space | |
795 if (this.isShown()) { | |
796 if (item) { | |
797 this.executeItem(item); | |
798 } else { | |
799 this.hide(); | |
800 } | |
801 } else { | |
802 this.show(); | |
803 } | |
804 e.preventDefault(); | |
805 break; | |
806 } | |
807 }, | |
808 | |
809 selectedIndex_: -1, | |
810 setSelectedIndex: function(i) { | |
811 if (i != this.selectedIndex_) { | |
812 var items = this.menu.children; | |
813 var oldItem = items[this.selectedIndex_]; | |
814 if (oldItem) { | |
815 oldItem.removeAttribute('selected'); | |
816 } | |
817 var newItem = items[i]; | |
818 if (newItem) { | |
819 newItem.setAttribute('selected', 'selected'); | |
820 } | |
821 this.selectedIndex_ = i; | |
822 } | |
823 }, | |
824 | |
825 getSelectedItem: function() { | |
826 return this.menu.children[this.selectedIndex_] || null; | |
827 }, | |
828 | |
829 executeItem: function(item) { | |
830 var command = item.getAttribute('command'); | |
831 if (command in this.commands) { | |
832 this.commands[command].call(this, item); | |
833 } | |
834 | |
835 this.hide(); | |
836 } | |
837 }; | |
838 | |
839 var optionMenu = new OptionMenu( | |
840 document.querySelector('#most-visited h2 .settings-wrapper'), | |
841 $('option-menu')); | |
842 optionMenu.commands = { | |
843 'clear-all-blacklisted' : function() { | |
844 mostVisited.clearAllBlacklisted(); | |
845 chrome.send('getMostVisited'); | |
846 } | |
847 }; | |
848 | |
849 $('main').addEventListener('click', function(e) { | 650 $('main').addEventListener('click', function(e) { |
850 var p = e.target; | 651 var p = e.target; |
851 while (p && p.tagName != 'H2') { | 652 while (p && p.tagName != 'H2') { |
| 653 // In case the user clicks on a button we do not want to expand/collapse a |
| 654 // section. |
| 655 if (p.tagName == 'BUTTON') |
| 656 return; |
852 p = p.parentNode; | 657 p = p.parentNode; |
853 } | 658 } |
854 | 659 |
855 if (!p) { | 660 if (!p) { |
856 return; | 661 return; |
857 } | 662 } |
858 | 663 |
859 p = p.parentNode; | 664 p = p.parentNode; |
860 if (!getSectionMaxiview(p)) { | 665 if (!getSectionMaxiview(p)) { |
861 return; | 666 return; |
(...skipping 197 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1059 * The sync code is not yet built by default on all platforms so we have to | 864 * The sync code is not yet built by default on all platforms so we have to |
1060 * make sure we don't send the initial sync message to the backend unless the | 865 * make sure we don't send the initial sync message to the backend unless the |
1061 * backend told us that the sync code is present. | 866 * backend told us that the sync code is present. |
1062 */ | 867 */ |
1063 function callGetSyncMessageIfSyncIsPresent() { | 868 function callGetSyncMessageIfSyncIsPresent() { |
1064 if (document.documentElement.getAttribute('syncispresent') == 'true') { | 869 if (document.documentElement.getAttribute('syncispresent') == 'true') { |
1065 chrome.send('GetSyncMessage'); | 870 chrome.send('GetSyncMessage'); |
1066 } | 871 } |
1067 } | 872 } |
1068 | 873 |
1069 function hideAllMenus() { | |
1070 optionMenu.hide(); | |
1071 } | |
1072 | |
1073 window.addEventListener('blur', hideAllMenus); | |
1074 window.addEventListener('keydown', function(e) { | |
1075 if (e.keyIdentifier == 'Alt' || e.keyIdentifier == 'Meta') { | |
1076 hideAllMenus(); | |
1077 } | |
1078 }, true); | |
1079 | |
1080 // Tooltip for elements that have text that overflows. | 874 // Tooltip for elements that have text that overflows. |
1081 document.addEventListener('mouseover', function(e) { | 875 document.addEventListener('mouseover', function(e) { |
1082 // We don't want to do this while we are dragging because it makes things very | 876 // We don't want to do this while we are dragging because it makes things very |
1083 // janky | 877 // janky |
1084 if (mostVisited.isDragging()) { | 878 if (mostVisited.isDragging()) { |
1085 return; | 879 return; |
1086 } | 880 } |
1087 | 881 |
1088 var el = findAncestor(e.target, function(el) { | 882 var el = findAncestor(e.target, function(el) { |
1089 return el.xtitle; | 883 return el.xtitle; |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1141 window.setTimeout(function() { | 935 window.setTimeout(function() { |
1142 mostVisited.ensureSmallGridCorrect(); | 936 mostVisited.ensureSmallGridCorrect(); |
1143 document.body.classList.remove('loading'); | 937 document.body.classList.remove('loading'); |
1144 }, 1); | 938 }, 1); |
1145 | 939 |
1146 // Only show the first run notification if first run. | 940 // Only show the first run notification if first run. |
1147 if (firstRun) { | 941 if (firstRun) { |
1148 showFirstRunNotification(); | 942 showFirstRunNotification(); |
1149 } | 943 } |
1150 } | 944 } |
OLD | NEW |