Improved sticky page header handling
authorAlexander Ebert <ebert@woltlab.com>
Mon, 15 Feb 2016 16:13:26 +0000 (17:13 +0100)
committerAlexander Ebert <ebert@woltlab.com>
Mon, 15 Feb 2016 16:13:38 +0000 (17:13 +0100)
com.woltlab.wcf/templates/pageHeader.tpl
com.woltlab.wcf/templates/pageHeaderSearch.tpl
wcfsetup/install/files/js/WoltLab/WCF/Ui/Page/Header/Fixed.js [new file with mode: 0644]
wcfsetup/install/files/style/layout/pageHeaderSticky.scss

index a54597f2fac418b40ad1d1f7285faadc2f7aa0bf..c1f0892f9d0ec33cf2445e0097db4e3f50d90425 100644 (file)
@@ -1,4 +1,4 @@
-<div class="pageHeaderContainer">
+<div id="pageHeaderContainer" class="pageHeaderContainer">
        <header id="pageHeader" class="pageHeader">
                <div>
                        <div class="layoutBoundary">
                </div>
                
                <script data-relocate="true">
-                       var header = elById('pageHeader');
-                       var pageHeaderContainer = elBySel('.pageHeaderContainer');
-                       header.style.setProperty('min-height', header.clientHeight + 'px');
-                       
-                       function stickyHeader() {
-                               header.classList[(document.body.scrollTop > 50) ? 'add' : 'remove']('sticky');
-                               pageHeaderContainer.classList[(document.body.scrollTop > 50) ? 'add' : 'remove']('stickyPageHeader');
-                       }
-                       
-                       stickyHeader();
-                       window.addEventListener('scroll', stickyHeader);
+                       require(['WoltLab/WCF/Ui/Page/Header/Fixed'], function(UiPageHeaderFixed) {
+                               UiPageHeaderFixed.init();
+                       });
                </script>
        </header>
        
index d9d212502ee1efc23c609ee8543a4abb74fbb36d..9189baf74a40d2a837f915ed91bdf09788044fd1 100644 (file)
@@ -5,9 +5,9 @@
 
 {event name='settings'}
 
-<div id="pageHeaderSearch" class="pageHeaderSearch" data-disable-auto-focus="true">
+<div id="pageHeaderSearch" class="pageHeaderSearch">
        <form method="post" action="{@$__searchFormLink}">
-               <div class="pageHeaderSearchInputContainer dropdown">
+               <div id="pageHeaderSearchInputContainer" class="pageHeaderSearchInputContainer dropdown" data-disable-auto-focus="true" data-dropdown-prevent-toggle="true">
                        <input type="search" name="q" id="pageHeaderSearchInput" class="pageHeaderSearchInput dropdownToggle" placeholder="{@$__searchInputPlaceholder}" autocomplete="off" required="required" value="{if $query|isset}{$query}{/if}" data-toggle="search" />
                        
                        <ul class="dropdownMenu">
 
 {if !OFFLINE || $__wcf->session->getPermission('admin.general.canViewPageDuringOfflineMode')}
        <script data-relocate="true">
-               //<![CDATA[
                $(function() {
-                       new WCF.Search.Message.SearchArea($('#pageHeaderSearch'));
+                       new WCF.Search.Message.SearchArea($('#pageHeaderSearchInputContainer'));
                });
-               //]]>
        </script>
 {/if}
\ No newline at end of file
diff --git a/wcfsetup/install/files/js/WoltLab/WCF/Ui/Page/Header/Fixed.js b/wcfsetup/install/files/js/WoltLab/WCF/Ui/Page/Header/Fixed.js
new file mode 100644 (file)
index 0000000..bebf4b5
--- /dev/null
@@ -0,0 +1,77 @@
+/**
+ * Manages the sticky page header.
+ * 
+ * @author     Alexander Ebert
+ * @copyright  2001-2016 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @module     WoltLab/WCF/Ui/Page/Header/Fixed
+ */
+define(['Ui/CloseOverlay', 'Ui/SimpleDropdown'], function(UiCloseOverlay, UiSimpleDropdown) {
+       "use strict";
+       
+       var _pageHeader, _pageHeaderContainer, _pageHeaderSearchInputContainer, _isFixed = false;
+       
+       /**
+        * @exports     WoltLab/WCF/Ui/Page/Header/Fixed
+        */
+       return {
+               /**
+                * Initializes the sticky page header handler.
+                */
+               init: function() {
+                       _pageHeader = elById('pageHeader');
+                       _pageHeaderContainer = elById('pageHeaderContainer');
+                       _pageHeaderSearchInputContainer = elById('pageHeaderSearchInputContainer');
+                       
+                       this._initStickyPageHeader();
+                       this._initSearchBar();
+               },
+               
+               /**
+                * Enforces a min-height for the original header's location to prevent collapsing
+                * when setting the header to `position: fixed`.
+                * 
+                * @protected
+                */
+               _initStickyPageHeader: function() {
+                       _pageHeader.style.setProperty('min-height', _pageHeader.clientHeight + 'px');
+                       
+                       this._scroll();
+                       window.addEventListener('scroll', this._scroll.bind(this));
+               },
+               
+               /**
+                * Provides the collapsible search bar.
+                * 
+                * @protected
+                */
+               _initSearchBar: function() {
+                       var searchInput = elById('pageHeaderSearchInput');
+                       
+                       UiSimpleDropdown.registerCallback('pageHeaderSearchInputContainer', function() {
+                               if (_isFixed && !_pageHeaderSearchInputContainer.classList.contains('open')) {
+                                       _pageHeaderSearchInputContainer.classList.add('open');
+                                       searchInput.focus();
+                               }
+                       });
+                       
+                       UiCloseOverlay.add('WoltLab/WCF/Ui/Page/Header/Fixed', function() {
+                               _pageHeaderSearchInputContainer.classList.remove('open');
+                       });
+               },
+               
+               /**
+                * Updates the page header state after scrolling.
+                * 
+                * @protected
+                */
+               _scroll: function() {
+                       _isFixed = (document.body.scrollTop > 50);
+                       
+                       _pageHeader.classList[_isFixed ? 'add' : 'remove']('sticky');
+                       _pageHeaderContainer.classList[_isFixed ? 'add' : 'remove']('stickyPageHeader');
+                       
+                       _pageHeaderSearchInputContainer.classList.remove('open');
+               }
+       };
+});
index f8072ea69716cf8c5f815cf95797eb00362c4ef5..06aeb8ae7c6fe36ab81cc8421342f733cf0a60ed 100644 (file)
                flex: 0 auto;
                order: 4;
        }
+       
+       .pageHeaderSearchInputContainer:not(.open) {
+               > .pageHeaderSearchInput {
+                       padding-right: 20px;
+                       width: 20px;
+               }
+               
+               > .pageHeaderSearchInputButton {
+                       pointer-events: none;
+               }
+       }
 }