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('options', function() { | 5 cr.define('options', function() { |
6 /** @const */ var FocusOutlineManager = cr.ui.FocusOutlineManager; | 6 /** @const */ var FocusOutlineManager = cr.ui.FocusOutlineManager; |
7 | 7 |
8 ///////////////////////////////////////////////////////////////////////////// | 8 ///////////////////////////////////////////////////////////////////////////// |
9 // OptionsPage class: | 9 // OptionsPage class: |
10 | 10 |
(...skipping 338 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
349 | 349 |
350 this.restoreLastFocusedElement_(); | 350 this.restoreLastFocusedElement_(); |
351 if (!this.isOverlayVisible_()) | 351 if (!this.isOverlayVisible_()) |
352 $('searchBox').removeAttribute('aria-hidden'); | 352 $('searchBox').removeAttribute('aria-hidden'); |
353 }; | 353 }; |
354 | 354 |
355 /** | 355 /** |
356 * Cancels (closes) the overlay, due to the user pressing <Esc>. | 356 * Cancels (closes) the overlay, due to the user pressing <Esc>. |
357 */ | 357 */ |
358 OptionsPage.cancelOverlay = function() { | 358 OptionsPage.cancelOverlay = function() { |
| 359 var overlay = this.getVisibleOverlay_(); |
| 360 if (!overlay) |
| 361 return; |
| 362 |
359 // Blur the active element to ensure any changed pref value is saved. | 363 // Blur the active element to ensure any changed pref value is saved. |
360 document.activeElement.blur(); | 364 document.activeElement.blur(); |
361 var overlay = this.getVisibleOverlay_(); | 365 |
362 // Let the overlay handle the <Esc> if it wants to. | 366 // Let the overlay handle the <Esc> if it wants to. |
363 if (overlay.handleCancel) { | 367 if (overlay.handleCancel) { |
364 overlay.handleCancel(); | 368 overlay.handleCancel(); |
365 this.restoreLastFocusedElement_(); | 369 this.restoreLastFocusedElement_(); |
366 } else { | 370 } else { |
367 this.closeOverlay(); | 371 this.closeOverlay(); |
368 } | 372 } |
369 }; | 373 }; |
370 | 374 |
371 /** | 375 /** |
(...skipping 276 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
648 */ | 652 */ |
649 OptionsPage.initialize = function() { | 653 OptionsPage.initialize = function() { |
650 chrome.send('coreOptionsInitialize'); | 654 chrome.send('coreOptionsInitialize'); |
651 uber.onContentFrameLoaded(); | 655 uber.onContentFrameLoaded(); |
652 FocusOutlineManager.forDocument(document); | 656 FocusOutlineManager.forDocument(document); |
653 document.addEventListener('scroll', this.handleScroll_.bind(this)); | 657 document.addEventListener('scroll', this.handleScroll_.bind(this)); |
654 | 658 |
655 // Trigger the scroll handler manually to set the initial state. | 659 // Trigger the scroll handler manually to set the initial state. |
656 this.handleScroll_(); | 660 this.handleScroll_(); |
657 | 661 |
658 // Shake the dialog if the user clicks outside the dialog bounds. | 662 var dialogs = document.querySelectorAll('.overlay-container .page'); |
659 var containers = [$('overlay-container-1'), $('overlay-container-2')]; | 663 for (var i = 0; i < dialogs.length; i++) { |
660 for (var i = 0; i < containers.length; i++) { | 664 var dialog = dialogs[i]; |
661 var overlay = containers[i]; | 665 cr.ui.overlay.setupOverlay(dialog); |
662 cr.ui.overlay.setupOverlay(overlay); | 666 dialog.addEventListener('cancelOverlay', |
663 overlay.addEventListener('cancelOverlay', | 667 OptionsPage.cancelOverlay.bind(OptionsPage)); |
664 OptionsPage.cancelOverlay.bind(OptionsPage)); | 668 dialog.addEventListener('webkitAnimationEnd', |
| 669 OptionsPage.handleDialogAnimationEnd_); |
665 } | 670 } |
666 | 671 |
667 cr.ui.overlay.globalInitialization(); | 672 cr.ui.overlay.globalInitialization(); |
668 }; | 673 }; |
669 | 674 |
670 /** | 675 /** |
| 676 * Called when a webkitAnimationEnd event occurs on a dialog. If it was a |
| 677 * fading away animation that completed, closes the dialog. |
| 678 */ |
| 679 OptionsPage.handleDialogAnimationEnd_ = function(e) { |
| 680 if (e.target != e.currentTarget) |
| 681 return; |
| 682 var dialog = e.target; |
| 683 dialog.classList.remove('opening'); |
| 684 dialog.classList.remove('pulse'); |
| 685 if (dialog.classList.contains('closing')) { |
| 686 dialog.close(); |
| 687 // TODO(falken): It's probably better move these to a close event handler, |
| 688 // once <dialog> implements it. |
| 689 dialog.classList.remove('closing'); |
| 690 dialog.page.fadeCompleted_(); |
| 691 } |
| 692 } |
| 693 |
| 694 /** |
671 * Does a bounds check for the element on the given x, y client coordinates. | 695 * Does a bounds check for the element on the given x, y client coordinates. |
672 * @param {Element} e The DOM element. | 696 * @param {Element} e The DOM element. |
673 * @param {number} x The client X to check. | 697 * @param {number} x The client X to check. |
674 * @param {number} y The client Y to check. | 698 * @param {number} y The client Y to check. |
675 * @return {boolean} True if the point falls within the element's bounds. | 699 * @return {boolean} True if the point falls within the element's bounds. |
676 * @private | 700 * @private |
677 */ | 701 */ |
678 OptionsPage.elementContainsPoint_ = function(e, x, y) { | 702 OptionsPage.elementContainsPoint_ = function(e, x, y) { |
679 var clientRect = e.getBoundingClientRect(); | 703 var clientRect = e.getBoundingClientRect(); |
680 return x >= clientRect.left && x <= clientRect.right && | 704 return x >= clientRect.left && x <= clientRect.right && |
(...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
805 get container() { | 829 get container() { |
806 assert(this.isOverlay); | 830 assert(this.isOverlay); |
807 return this.pageDiv.parentNode; | 831 return this.pageDiv.parentNode; |
808 }, | 832 }, |
809 | 833 |
810 /** | 834 /** |
811 * Gets page visibility state. | 835 * Gets page visibility state. |
812 * @type {boolean} | 836 * @type {boolean} |
813 */ | 837 */ |
814 get visible() { | 838 get visible() { |
815 // If this is an overlay dialog it is no longer considered visible while | 839 if (this.isOverlay) { |
816 // the overlay is fading out. See http://crbug.com/118629. | 840 if (!this.pageDiv.open || this.pageDiv.classList.contains('closing')) |
817 if (this.isOverlay && | 841 return false; |
818 this.container.classList.contains('transparent')) { | |
819 return false; | |
820 } | 842 } |
821 if (this.pageDiv.hidden) | 843 if (this.pageDiv.hidden) |
822 return false; | 844 return false; |
823 return this.pageDiv.page == this; | 845 return this.pageDiv.page == this; |
824 }, | 846 }, |
825 | 847 |
826 /** | 848 /** |
827 * Sets page visibility. | 849 * Sets page visibility. |
828 * @type {boolean} | 850 * @type {boolean} |
829 */ | 851 */ |
(...skipping 16 matching lines...) Expand all Loading... |
846 }, | 868 }, |
847 | 869 |
848 /** | 870 /** |
849 * Shows or hides an overlay (including any visible dialog). | 871 * Shows or hides an overlay (including any visible dialog). |
850 * @param {boolean} visible Whether the overlay should be visible or not. | 872 * @param {boolean} visible Whether the overlay should be visible or not. |
851 * @private | 873 * @private |
852 */ | 874 */ |
853 setOverlayVisible_: function(visible) { | 875 setOverlayVisible_: function(visible) { |
854 assert(this.isOverlay); | 876 assert(this.isOverlay); |
855 var pageDiv = this.pageDiv; | 877 var pageDiv = this.pageDiv; |
856 var container = this.container; | |
857 | 878 |
858 if (visible) { | 879 if (visible) { |
859 uber.invokeMethodOnParent('beginInterceptingEvents'); | 880 uber.invokeMethodOnParent('beginInterceptingEvents'); |
860 this.pageDiv.removeAttribute('aria-hidden'); | 881 this.pageDiv.removeAttribute('aria-hidden'); |
861 if (this.parentPage) | 882 if (this.parentPage) |
862 this.parentPage.pageDiv.setAttribute('aria-hidden', true); | 883 this.parentPage.pageDiv.setAttribute('aria-hidden', true); |
863 } else { | 884 } else { |
864 if (this.parentPage) | 885 if (this.parentPage) |
865 this.parentPage.pageDiv.removeAttribute('aria-hidden'); | 886 this.parentPage.pageDiv.removeAttribute('aria-hidden'); |
866 } | 887 } |
867 | 888 |
868 if (container.hidden != visible) { | 889 if (visible) { |
869 if (visible) { | 890 // If the dialog is set invisible and then immediately set visible |
870 // If the container is set hidden and then immediately set visible | 891 // again, the webkitAnimationEnd callback would cause it to be |
871 // again, the fadeCompleted_ callback would cause it to be erroneously | 892 // erroneously closed again. Removing the closing tag avoids that. |
872 // hidden again. Removing the transparent tag avoids that. | 893 pageDiv.classList.remove('closing'); |
873 container.classList.remove('transparent'); | |
874 | 894 |
875 // Hide all dialogs in this container since a different one may have | 895 // Hide all dialogs in this container since a different one may have |
876 // been previously visible before fading out. | 896 // been previously visible before fading out. |
877 var pages = container.querySelectorAll('.page'); | 897 var pages = this.container.querySelectorAll('.page'); |
878 for (var i = 0; i < pages.length; i++) | 898 for (var i = 0; i < pages.length; i++) { |
879 pages[i].hidden = true; | 899 if (pages[i].open) |
880 // Show the new dialog. | 900 pages[i].close(); |
881 pageDiv.hidden = false; | |
882 pageDiv.page = this; | |
883 } | 901 } |
884 return; | |
885 } | |
886 | 902 |
887 if (visible) { | 903 pageDiv.showModal(); |
888 container.hidden = false; | |
889 pageDiv.hidden = false; | |
890 pageDiv.page = this; | 904 pageDiv.page = this; |
891 // NOTE: This is a hacky way to force the container to layout which | |
892 // will allow us to trigger the webkit transition. | |
893 container.scrollTop; | |
894 container.classList.remove('transparent'); | |
895 this.onVisibilityChanged_(); | 905 this.onVisibilityChanged_(); |
| 906 cr.ui.overlay.center(pageDiv); |
| 907 pageDiv.classList.add('opening'); |
896 } else { | 908 } else { |
897 // Kick change events for text fields. | 909 // Kick change events for text fields. |
898 if (pageDiv.contains(document.activeElement)) | 910 if (pageDiv.contains(document.activeElement)) |
899 document.activeElement.blur(); | 911 document.activeElement.blur(); |
900 var self = this; | 912 |
901 // TODO: Use an event delegate to avoid having to subscribe and | 913 pageDiv.classList.add('closing'); |
902 // unsubscribe for webkitTransitionEnd events. | |
903 container.addEventListener('webkitTransitionEnd', function f(e) { | |
904 if (e.target != e.currentTarget || e.propertyName != 'opacity') | |
905 return; | |
906 container.removeEventListener('webkitTransitionEnd', f); | |
907 self.fadeCompleted_(); | |
908 }); | |
909 container.classList.add('transparent'); | |
910 } | 914 } |
911 }, | 915 }, |
912 | 916 |
913 /** | 917 /** |
914 * Called when a container opacity transition finishes. | 918 * Called when a dialog closing animation finishes. |
915 * @private | 919 * @private |
916 */ | 920 */ |
917 fadeCompleted_: function() { | 921 fadeCompleted_: function() { |
918 if (this.container.classList.contains('transparent')) { | 922 this.onVisibilityChanged_(); |
919 this.pageDiv.hidden = true; | 923 if (this.nestingLevel == 1) |
920 this.container.hidden = true; | 924 uber.invokeMethodOnParent('stopInterceptingEvents'); |
921 this.onVisibilityChanged_(); | |
922 if (this.nestingLevel == 1) | |
923 uber.invokeMethodOnParent('stopInterceptingEvents'); | |
924 } | |
925 }, | 925 }, |
926 | 926 |
927 /** | 927 /** |
928 * Called when a page is shown or hidden to update the root options page | 928 * Called when a page is shown or hidden to update the root options page |
929 * based on this page's visibility. | 929 * based on this page's visibility. |
930 * @private | 930 * @private |
931 */ | 931 */ |
932 onVisibilityChanged_: function() { | 932 onVisibilityChanged_: function() { |
933 OptionsPage.updateRootPageFreezeState(); | 933 OptionsPage.updateRootPageFreezeState(); |
934 | 934 |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
982 canShowPage: function() { | 982 canShowPage: function() { |
983 return true; | 983 return true; |
984 }, | 984 }, |
985 }; | 985 }; |
986 | 986 |
987 // Export | 987 // Export |
988 return { | 988 return { |
989 OptionsPage: OptionsPage | 989 OptionsPage: OptionsPage |
990 }; | 990 }; |
991 }); | 991 }); |
OLD | NEW |