diff --git a/bin/Controls/FloatedNav.js b/bin/Controls/FloatedNav.js index f7f74ecb229c1c5b1f3f5cb8ec78f272b846a04b..191ec8e571ec9749eb56d8a988dab2516844c269 100644 --- a/bin/Controls/FloatedNav.js +++ b/bin/Controls/FloatedNav.js @@ -21,19 +21,22 @@ define('package/quiqqer/menu/bin/Controls/FloatedNav', [ Binds: [ '$onImport', - '$setMobileBtnStatusToOpen', - '$setMobileBtnStatusToClose', + '$setToggleBtnStatusToOpen', + '$setToggleBtnStatusToClose', '$toggleNav', '$resize' ], options: { - pos : 'right', // right, left - initanimation : false, - animationtype : 'showAll', // showAll (show entire control), showOneByOne (show each entry one by one) - animationeasing : 'easeOutExpo', // see easing names on https://easings.net/ - animationduration: 500, // number - showopenbutton : 'mobile' // always / mobile / hide + pos : 'right', // right, left + initanimation : false, + animationtype : 'showAll', // showAll (show entire control), showOneByOne (show each entry one by one) + animationeasing : 'easeOutExpo', // see easing names on https://easings.net/ + animationduration : 500, // number + showtogglebutton : 'mobile', // always / mobile / hide + forceverticalcenter: false // if true, container will be centered per JS. + // Pure css way (top: 50%; transform: translateY: (-50%);) + // causes jumping effect on mobile, when url bar disappears }, initialize: function (options) { @@ -43,16 +46,18 @@ define('package/quiqqer/menu/bin/Controls/FloatedNav', [ onImport: this.$onImport }); - this.$Control = null; - this.$Nav = null; - this.$MobileBtn = null; - this.showOpenBtn = 'mobile'; - this.isBtnOpen = false; - this.$entries = null; - this.$pos = 'right'; - this.$animationType = 'showAll'; - this.$animationEasing = 'easeOutExpo'; - this.isMobile = QUI.getWindowSize().x < 768; + this.$Control = null; + this.$Nav = null; + this.$ToggleBtn = null; + this.showToggleBtn = 'mobile'; + this.isBtnOpen = false; + this.$entries = null; + this.$pos = 'right'; + this.$animationType = 'showAll'; + this.$animationEasing = 'easeOutExpo'; + this.isMobile = QUI.getWindowSize().x < 768; + this.forceVerticalCenter = false; + this.winHeight = window.innerHeight; QUI.addEvent('resize', this.$resize); }, @@ -64,13 +69,13 @@ define('package/quiqqer/menu/bin/Controls/FloatedNav', [ this.$Control = this.getElm(); this.$Nav = this.getElm().querySelector('nav'); this.$entries = this.$Nav.querySelectorAll('.quiqqer-floatedNav-entry'); - this.showOpenBtn = this.getAttribute('showopenbutton'); + this.showToggleBtn = this.getAttribute('showtogglebutton'); this.$initAnimation = this.getAttribute('initanimation'); this.$animationType = this.getAttribute('animationtype'); this.$animationEasing = this.getAttribute('animationeasing'); - if (this.$Control.get('data-qui-options-showopenbutton')) { - this.showOpenBtn = this.$Control.get('data-qui-options-showopenbutton'); + if (this.$Control.get('data-qui-options-showtogglebutton')) { + this.showToggleBtn = this.$Control.get('data-qui-options-showtogglebutton'); } if (this.$Control.get('data-qui-options-initanimation')) { @@ -85,7 +90,12 @@ define('package/quiqqer/menu/bin/Controls/FloatedNav', [ this.$animationEasing = this.$getEasingName(this.$Control.get('data-qui-options-animationeasing')); } - this.$initMobileBtn(); + if (this.$Control.get('data-qui-options-forceverticalcenter')) { + this.forceVerticalCenter = true; + this.$centerVertical(); + } + + this.$initToggleBtn(); if (this.$initAnimation) { this.$initStartAnimation(); @@ -94,11 +104,12 @@ define('package/quiqqer/menu/bin/Controls/FloatedNav', [ } }, - $initMobileBtn: function () { - this.$MobileBtn = this.$Control.querySelector('.quiqqer-floatedNav-showMobileBtn'); + $initToggleBtn: function () { + this.$ToggleBtn = this.$Control.querySelector('.quiqqer-floatedNav-toggleBtn'); - if (this.$MobileBtn) { - this.$MobileBtn.addEventListener('click', this.$toggleNav) + if (this.$ToggleBtn) { + this.$Nav.set('data-qui-open', 0); + this.$ToggleBtn.addEventListener('click', this.$toggleNav) } }, @@ -122,8 +133,8 @@ define('package/quiqqer/menu/bin/Controls/FloatedNav', [ }); }) - if (this.$MobileBtn) { - this.$MobileBtn.setStyles({ + if (this.$ToggleBtn) { + this.$ToggleBtn.setStyles({ visibility: 'visible', transform : 'translateX(60px)' }); @@ -132,8 +143,8 @@ define('package/quiqqer/menu/bin/Controls/FloatedNav', [ } if (this.isMobile) { - if (this.$MobileBtn) { - this.$showOneByOne(this.$MobileBtn, 750); + if (this.$ToggleBtn) { + this.$showOneByOne(this.$ToggleBtn, 750); this.$Nav.set('data-qui-open', 0); } else { this.$showOneByOne(this.$entries, 750); @@ -149,9 +160,9 @@ define('package/quiqqer/menu/bin/Controls/FloatedNav', [ case 'showOneByOne': let entries = Array.from(this.$entries); - if (this.$MobileBtn && this.showOpenBtn === 'always') { - this.$setMobileBtnStatusToClose(); - entries.unshift(this.$MobileBtn); + if (this.$ToggleBtn && this.showOpenBtn === 'always') { + this.$setToggleBtnStatusToClose(); + entries.unshift(this.$ToggleBtn); } this.$showOneByOne(entries, 750); @@ -162,17 +173,20 @@ define('package/quiqqer/menu/bin/Controls/FloatedNav', [ }, $initWithoutStartAnimation: function () { - if (!this.$MobileBtn) { + return; + + if (!this.$ToggleBtn) { return; } if (this.isMobile) { switch (this.$animationType) { case 'showAll': - this.$Nav.setStyles({ + /*this.$Nav.setStyles({ visibility: 'visible', right : -this.$Nav.getSize().x - 50 - }) + })*/ + break; case 'showOneByOne': @@ -184,24 +198,26 @@ define('package/quiqqer/menu/bin/Controls/FloatedNav', [ }) this.$Nav.set('data-qui-open', 0); - this.$setMobileBtnStatusToOpen(); + this.$setToggleBtnStatusToOpen(); break; } } else { this.$Nav.set('data-qui-open', 1); - this.$setMobileBtnStatusToClose(); + this.$setToggleBtnStatusToClose(); } }, $toggleNav: function () { - if (!this.$MobileBtn) { + if (!this.$ToggleBtn) { return; } + if (this.$Nav.get('data-qui-open') === '1') { + this.$Nav.set('data-qui-open', 0); - this.$animateMobileBtnToClose(); + this.$animateToggleBtnToClose(); switch (this.$animationType) { case 'showAll': @@ -216,8 +232,9 @@ define('package/quiqqer/menu/bin/Controls/FloatedNav', [ return; } + this.$Nav.set('data-qui-open', 1); - this.$animateMobileBtnToOpen(); + this.$animateToggleBtnToOpen(); switch (this.$animationType) { case 'showAll': @@ -272,12 +289,13 @@ define('package/quiqqer/menu/bin/Controls/FloatedNav', [ * @param delay {number} */ $show: function (Elm, delay = 0) { + Elm.style.transform = 'translateX(100px)'; anime({ - targets : Elm, + targets : Elm, translateX: 0, - delay : delay, - duration: 500, - easing : this.$animationEasing + delay : delay, + duration : 500, + easing : this.$animationEasing }); }, @@ -289,55 +307,55 @@ define('package/quiqqer/menu/bin/Controls/FloatedNav', [ */ $hide: function (Elm, delay = 0) { anime({ - targets : Elm, + targets : Elm, translateX: 100, - delay : delay, - duration: 500, - easing : this.$animationEasing + delay : delay, + duration : 500, + easing : this.$animationEasing }); }, - $setMobileBtnStatusToOpen: function () { - if (!this.$MobileBtn) { + $setToggleBtnStatusToOpen: function () { + if (!this.$ToggleBtn) { return; } - this.$MobileBtn.querySelector('.fa').setStyle('transform', 'rotate(0)'); + this.$ToggleBtn.querySelector('.fa').setStyle('transform', 'rotate(0)'); }, - $setMobileBtnStatusToClose: function () { - if (!this.$MobileBtn) { + $setToggleBtnStatusToClose: function () { + if (!this.$ToggleBtn) { return; } - this.$MobileBtn.querySelector('.fa').setStyle('transform', 'rotate(180deg)'); + this.$ToggleBtn.querySelector('.fa').setStyle('transform', 'rotate(180deg)'); }, - $animateMobileBtnToOpen: function () { - if (!this.$MobileBtn) { + $animateToggleBtnToOpen: function () { + if (!this.$ToggleBtn) { return; } this.isBtnOpen = true; anime({ - targets: this.$MobileBtn.querySelector('.fa'), + targets: this.$ToggleBtn.querySelector('.fa'), rotate : 180, }) }, - $animateMobileBtnToClose: function () { - if (!this.$MobileBtn) { + $animateToggleBtnToClose: function () { + if (!this.$ToggleBtn) { return; } this.isBtnOpen = false; anime({ - targets : this.$MobileBtn.querySelector('.fa'), + targets : this.$ToggleBtn.querySelector('.fa'), rotate : 360, complete: () => { - this.$MobileBtn.querySelector('.fa').setStyle('transform', 'rotate(0)'); + this.$ToggleBtn.querySelector('.fa').setStyle('transform', 'rotate(0)'); } }) }, @@ -350,7 +368,7 @@ define('package/quiqqer/menu/bin/Controls/FloatedNav', [ } if (!this.isBtnOpen && this.showOpenBtn === 'mobile') { - this.$showOneByOne(this.$MobileBtn); + this.$showOneByOne(this.$ToggleBtn); } return; @@ -362,9 +380,23 @@ define('package/quiqqer/menu/bin/Controls/FloatedNav', [ } if (this.isBtnOpen && this.showOpenBtn === 'mobile') { - this.$hideOneByOne(this.$MobileBtn); + this.$hideOneByOne(this.$ToggleBtn); } } + + // recalculate vertical position + if (this.forceVerticalCenter && this.winHeight !== window.innerHeight) { + this.winHeight = window.innerHeight; + this.$centerVertical(); + } + }, + + /** + * Calculate vertical position of the control + */ + $centerVertical: function () { + this.$Control.style.top = (window.innerHeight / 2) - (this.$Control.offsetHeight / 2) + 'px'; + this.$Control.style.transform = 'initial'; }, /** diff --git a/src/QUI/Menu/Controls/FloatedNav.css b/src/QUI/Menu/Controls/FloatedNav.css index 9399bbe7f2d8f21698a5c8142a9323a2cf38eb6e..4a95cc87c36f2aa2de7465ea23438fc74514234f 100644 --- a/src/QUI/Menu/Controls/FloatedNav.css +++ b/src/QUI/Menu/Controls/FloatedNav.css @@ -2,21 +2,21 @@ /* variables */ /*************/ .quiqqer-floatedNavControl__size-medium { - --quiqqer-floatedNav-spacing: 0.75rem; --quiqqer-floatedNav-fontSize: 1.75rem; --quiqqer-floatedNav-size: 3rem; + --quiqqer-floatedNav-spacing: 0.75rem; } .quiqqer-floatedNavControl__size-small { - --quiqqer-floatedNav-spacing: 0.5rem; --quiqqer-floatedNav-fontSize: 1.25rem; --quiqqer-floatedNav-size: 2rem; + --quiqqer-floatedNav-spacing: 0.5rem; } .quiqqer-floatedNavControl__size-large { - --quiqqer-floatedNav-spacing: 1rem; --quiqqer-floatedNav-fontSize: 2rem; --quiqqer-floatedNav-size: 3.5rem; + --quiqqer-floatedNav-spacing: 1rem; } /***********/ @@ -29,10 +29,6 @@ z-index: 10; } -.quiqqer-floatedNav { - /*position: absolute;*/ -} - .quiqqer-floatedNavControl__posX-right { right: 0; } @@ -41,12 +37,18 @@ left: 0; } +@media screen and (max-width: 767px) { + .quiqqer-floatedNavControl__toggleButton-mobile.quiqqer-floatedNavControl__posX-right .quiqqer-floatedNav { + transform: translateX(100px); + } +} + .quiqqer-floatedNav-entry { /*transition: 0.2s all ease;*/ } .quiqqer-floatedNav-entry-inner, -.quiqqer-floatedNav-showMobileBtn { +.quiqqer-floatedNav-toggleBtn { background: var(--qui-color-main, #333); border: var(--qui-border-width, 2px) solid var(--qui-color-main, #333); color: var(--qui-color-main-contrast, #fff); @@ -54,28 +56,28 @@ display: block; font-size: var(--quiqqer-floatedNav-fontSize); line-height: calc(var(--quiqqer-floatedNav-size) - (2 * var(--qui-border-width, 2px))); + overflow: hidden; text-align: center; width: var(--quiqqer-floatedNav-size); - overflow: hidden; } /* lang switch */ .quiqqer-floatedNav .quiqqer-bricks-languageswitch-flag { - font-size: calc(0.75 * var(--quiqqer-floatedNav-fontSize)); - width: var(--quiqqer-floatedNav-size); display: flex; flex-direction: column; - overflow: hidden; float: none; + font-size: calc(0.75 * var(--quiqqer-floatedNav-fontSize)); + overflow: hidden; + width: var(--quiqqer-floatedNav-size); } .quiqqer-floatedNav .quiqqer-bricks-languageswitch-flag-entry { background: var(--qui-color-main, #333); + color: var(--qui-color-main-contrast, #fff); + font-weight: bold; line-height: calc(0.5 * var(--quiqqer-floatedNav-size)); padding: 0; text-align: center; - color: var(--qui-color-main-contrast, #fff); - font-weight: bold; text-transform: uppercase; } @@ -88,30 +90,31 @@ } .quiqqer-floatedNav .quiqqer-bricks-languageswitch-flag-entry-text { - line-height: inherit; display: block; + line-height: inherit; } /* hover */ .quiqqer-floatedNav-entry:hover, .quiqqer-bricks-languageswitch-flag-entry:hover, -.quiqqer-floatedNav-showMobileBtn:hover { +.quiqqer-floatedNav-toggleBtn:hover { filter: brightness(90%); } -/* mobile */ -.quiqqer-floatedNav-showMobileBtn { +/* Toggle btn */ +.quiqqer-floatedNav-toggleBtn { + display: none; text-align: center; } -.quiqqer-floatedNav-showMobileBtn .fa { - line-height: inherit; +.quiqqer-floatedNav-toggleBtn .fa { cursor: pointer; + line-height: inherit; } @media screen and (max-width: 767px) { - .quiqqer-floatedNav-showMobileBtn { + .quiqqer-floatedNav-toggleBtn { display: block; } } @@ -129,6 +132,19 @@ padding: var(--quiqqer-floatedNav-spacing); } +.quiqqer-floatedNavControl__design-iconsBar .quiqqer-floatedNav-toggleBtn { + font-size: calc(var(--quiqqer-floatedNav-fontSize) / 1.5); + line-height: calc((var(--quiqqer-floatedNav-size) - (2 * var(--qui-border-width, 2px))) / 1.5); + margin-bottom: var(--quiqqer-floatedNav-spacing); + width: calc(var(--quiqqer-floatedNav-size) / 1.5); +} + +/* nav on the right */ +.quiqqer-floatedNavControl__posX-right.quiqqer-floatedNavControl__design-iconsBar .quiqqer-floatedNav-toggleBtn { + margin-left: auto; +} + +.quiqqer-floatedNavControl__design-iconsBar .quiqqer-floatedNav-toggleBtn, .quiqqer-floatedNavControl__design-iconsBar .quiqqer-floatedNav-entry-inner, .quiqqer-floatedNavControl__design-iconsBar .quiqqer-bricks-languageswitch-flag { border-radius: var(--qui-btn-border-radius, 5px); @@ -140,7 +156,7 @@ /* Design: flat */ .quiqqer-floatedNavControl__design-flat .quiqqer-floatedNav-entry:not(:last-child), -.quiqqer-floatedNavControl__design-flat .quiqqer-floatedNav-showMobileBtn { +.quiqqer-floatedNavControl__design-flat .quiqqer-floatedNav-toggleBtn { margin-bottom: 2px; } @@ -148,7 +164,7 @@ /* Animation */ /*************/ .quiqqer-floatedNavControl__initAnimation .quiqqer-floatedNav__animation-showAll, -.quiqqer-floatedNavControl__initAnimation .quiqqer-floatedNav-showMobileBtn, +.quiqqer-floatedNavControl__initAnimation .quiqqer-floatedNav-toggleBtn, .quiqqer-floatedNavControl__initAnimation .quiqqer-floatedNav__animation-showOneByOne .quiqqer-floatedNav-entry { visibility: hidden; } @@ -161,7 +177,7 @@ } @media screen and (min-width: 798px) { - .quiqqer-floatedNavControl__noInitAnimation .quiqqer-floatedNav-showMobileBtn .fa { + .quiqqer-floatedNavControl__noInitAnimation .quiqqer-floatedNav-toggleBtn .fa { transform: rotate(180deg); } } @@ -170,11 +186,3 @@ /* nav init open status */ /************************/ -/******************/ -/* No open button */ -/******************/ -.quiqqer-floatedNavControl__noOpenBtn.quiqqer-floatedNavControl__noInitAnimation .quiqqer-floatedNav__animation-showOneByOne .quiqqer-floatedNav-entry { - visibility: initial; - transform: translateX(0); - -} \ No newline at end of file diff --git a/src/QUI/Menu/Controls/FloatedNav.html b/src/QUI/Menu/Controls/FloatedNav.html index 0638ca356305e55f149f0bcd517806383c886836..b66fdad6396ee60ddf50fd3b17983e47aa9129f2 100644 --- a/src/QUI/Menu/Controls/FloatedNav.html +++ b/src/QUI/Menu/Controls/FloatedNav.html @@ -1,5 +1,5 @@ -{if $showOpenButton} -<div class="quiqqer-floatedNav-showMobileBtn"> +{if $showToggleButton} +<div class="quiqqer-floatedNav-toggleBtn"> <span class="fa fa-angle-double-left"></span> </div> {/if} diff --git a/src/QUI/Menu/Controls/FloatedNav.php b/src/QUI/Menu/Controls/FloatedNav.php index 384eaec6e1fceb5149bdd4cde7f0b6d9e7870feb..9f9eccc395508d1750f99e98628c8a3580f025d5 100644 --- a/src/QUI/Menu/Controls/FloatedNav.php +++ b/src/QUI/Menu/Controls/FloatedNav.php @@ -25,17 +25,18 @@ public function __construct($attributes = []) { // default options $this->setAttributes([ - 'class' => 'quiqqer-floatedNavControl', - 'menuId' => false, - 'posX' => 'right', // right, left - 'size' => 'medium', // small, medium, large - 'design' => 'iconBar', // iconBar, flat - 'animationType' => false, // false, showAll (show entire control), showOneByOne (show each entry one by one) - 'initAnimation' => false, - 'animationEasing' => 'easeOutExpo', // see easing names on https://easings.net/ + 'class' => 'quiqqer-floatedNavControl', + 'menuId' => false, + 'posX' => 'right', // right, left + 'forceVerticalCenter' => true, // if true, container will be centered per JS. pure css way (top: 50%; transform: translateY: (-50%);) causes jumping effect on mobile, when url bar disappears + 'size' => 'medium', // small, medium, large + 'design' => 'iconBar', // iconBar, flat + 'animationType' => false, // false, showAll (show entire control), showOneByOne (show each entry one by one) + 'initAnimation' => false, + 'animationEasing' => 'easeOutExpo', // see easing names on https://easings.net/ // 'navInitOpen' => 'always', // always, desktop, never - 'showOpenButton' => 'mobile', // always, mobile, hide, - 'showLangSwitch' => false, + 'showToggleButton' => 'mobile', // always, mobile, hide, + 'showLangSwitch' => false, ]); parent::__construct($attributes); @@ -69,19 +70,20 @@ public function getBody() return ''; } - $showOpenButton = true; - switch ($this->getAttribute('showOpenButton')) { + $showToggleButton = true; + switch ($this->getAttribute('showToggleButton')) { case 'always': - $this->setJavaScriptControlOption('showopenbutton', 'always'); + $this->setJavaScriptControlOption('showtogglebutton', 'always'); + $this->addCSSClass('quiqqer-floatedNavControl__toggleButton-always'); break; case 'mobile': - $this->setJavaScriptControlOption('showopenbutton', 'mobile'); + $this->setJavaScriptControlOption('showtogglebutton', 'mobile'); + $this->addCSSClass('quiqqer-floatedNavControl__toggleButton-mobile'); break; case 'hide': - $this->addCSSClass('quiqqer-floatedNavControl__noOpenBtn'); - $showOpenButton = false; + $showToggleButton = false; break; } @@ -149,6 +151,10 @@ public function getBody() $initAnimation = 'quiqqer-floatedNavControl__initAnimation'; } + if ($this->getAttribute('forceVerticalCenter')) { + $this->setJavaScriptControlOption('forceverticalcenter', 1); + } + $this->addCSSClass($initAnimation); $this->addCSSClass($size); @@ -158,11 +164,11 @@ public function getBody() $children = $IndependentMenu->getChildren(); $Engine->assign([ - 'this' => $this, - 'children' => $children, - 'animation' => $animation, - 'LangSwitch' => $LangSwitch, - 'showOpenButton' => $showOpenButton + 'this' => $this, + 'children' => $children, + 'animation' => $animation, + 'LangSwitch' => $LangSwitch, + 'showToggleButton' => $showToggleButton ]); return $Engine->fetch(dirname(__FILE__).'/FloatedNav.html');