{* main menu / page options / breadcrumbs *}
<div id="pageMainMenuMobile" class="pageMainMenuMobile menuOverlayMobile" data-page-logo="{$__wcf->getPath()}images/default-logo.png"> {* TODO: use real path *}
<ol class="menuOverlayItemList" data-title="{lang}wcf.menu.page{/lang}">
- <li class="menuOverlayTitle">{lang}wcf.menu.page{/lang}</li>
- <li class="menuOverlayItem">
+ <li class="menuOverlayTitle">{lang}wcf.menu.page.navigation{/lang}</li>
+ {*<li class="menuOverlayItem">
<a href="#" class="menuOverlayItemLink box24">
<span class="icon icon24 fa-sitemap"></span>
- <span class="menuOverlayItemTitle">{lang}wcf.menu.page.navigation{/lang}</span>
+ <span class="menuOverlayItemTitle"></span>
</a>
- <ol class="menuOverlayItemList">
+ <ol class="menuOverlayItemList">*}
{foreach from=$__wcf->getBoxHandler()->getBoxes('mainMenu')[0]->getMenu()->getMenuItemNodeList() item=menuItemNode}
- <li class="menuOverlayItem">
- {assign var=__outstandingItems value=$menuItemNode->getMenuItem()->getOutstandingItems()}
- <a href="{$menuItemNode->getMenuItem()->getURL()}" class="menuOverlayItemLink{if $__outstandingItems} menuOverlayItemBadge{/if}{if $menuItemNode->isActiveNode()} active{/if}">
- <span class="menuOverlayItemTitle">{lang}{$menuItemNode->getMenuItem()->title}{/lang}</span>
- {if $__outstandingItems}
- <span class="badge badgeUpdate">{#$__outstandingItems}</span>
- {/if}
- </a>
-
- {if $menuItemNode->hasChildren()}<ol class="menuOverlayItemList">{else}</li>{/if}
+ <li class="menuOverlayItem">
+ {assign var=__outstandingItems value=$menuItemNode->getMenuItem()->getOutstandingItems()}
+ <a href="{$menuItemNode->getMenuItem()->getURL()}" class="menuOverlayItemLink{if $__outstandingItems} menuOverlayItemBadge{/if}{if $menuItemNode->isActiveNode()} active{/if}">
+ <span class="menuOverlayItemTitle">{lang}{$menuItemNode->getMenuItem()->title}{/lang}</span>
+ {if $__outstandingItems}
+ <span class="badge badgeUpdate">{#$__outstandingItems}</span>
+ {/if}
+ </a>
- {if !$menuItemNode->hasChildren() && $menuItemNode->isLastSibling()}
- {@"</ol></li>"|str_repeat:$menuItemNode->getOpenParentNodes()}
- {/if}
- {/foreach}
- </ol>
- </li>
+ {if $menuItemNode->hasChildren()}<ol class="menuOverlayItemList">{else}</li>{/if}
+
+ {if !$menuItemNode->hasChildren() && $menuItemNode->isLastSibling()}
+ {@"</ol></li>"|str_repeat:$menuItemNode->getOpenParentNodes()}
+ {/if}
+ {/foreach}
+ {*</ol>
+ </li>*}
{hascontent}
<li class="menuOverlayItem">
<a href="#" class="menuOverlayItemLink box24">
return;
}
- $trigger.click($.proxy(self._show, self)).data('elementID', $elementID);
+ $trigger.on(WCF_CLICK_EVENT, $.proxy(self._show, self)).data('elementID', $elementID);
if ($quickOption) {
// simulate click on target action
$trigger.disableSelection().data('optionName', $quickOption).dblclick($.proxy(self._click, self));
* Modal dialog handler.
*
* @author Alexander Ebert
- * @copyright 2001-2015 WoltLab GmbH
+ * @copyright 2001-2016 WoltLab GmbH
* @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
* @module WoltLab/WCF/Ui/Dialog
*/
/**
* @exports WoltLab/WCF/Ui/Dialog
*/
- var UiDialog = {
+ return {
/**
* Sets up global container and internal variables.
*/
return {};
}
};
-
- return UiDialog;
});
* @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
* @module WoltLab/WCF/Ui/Page/Menu/Abstract
*/
-define(['Environment', 'EventHandler', 'ObjectMap', 'Dom/Traverse', 'Ui/Screen'], function(Environment, EventHandler, ObjectMap, DomTraverse, UiScreen) {
+define(['Environment', 'EventHandler', 'ObjectMap', 'Dom/Traverse', 'Dom/Util', 'Ui/Screen'], function(Environment, EventHandler, ObjectMap, DomTraverse, DomUtil, UiScreen) {
"use strict";
+ var _pageContainer = elById('pageContainer');
+
/**
* @param {string} eventIdentifier event namespace
* @param {string} elementId menu element id
* @param {string} buttonSelector CSS selector for toggle button
*/
init: function(eventIdentifier, elementId, buttonSelector) {
+ this._activeList = [];
+ this._depth = 0;
this._enabled = true;
this._eventIdentifier = eventIdentifier;
this._items = new ObjectMap();
this._menu = elById(elementId);
+ this._removeActiveList = false;
var callbackOpen = this.open.bind(this);
var button = elBySel(buttonSelector);
}
}
}).bind(this));
+
+ this._menu.children[0].addEventListener('transitionend', (function() {
+ this._menu.classList.add('allowScroll');
+
+ if (this._removeActiveList) {
+ this._removeActiveList = false;
+
+ var list = this._activeList.pop();
+ if (list) {
+ list.classList.remove('activeList');
+ }
+ }
+ }).bind(this));
+
+ var backdrop = elCreate('div');
+ backdrop.className = 'menuOverlayMobileBackdrop';
+ backdrop.addEventListener(WCF_CLICK_EVENT, this.close.bind(this));
+
+ DomUtil.insertAfter(backdrop, this._menu);
},
/**
event.preventDefault();
}
- this._menu.classList.add('enableAnimation');
this._menu.classList.add('open');
+ this._menu.classList.add('allowScroll');
+ this._menu.children[0].classList.add('activeList');
UiScreen.scrollDisable();
+
+ _pageContainer.classList.add('menuOverlay-' + this._menu.id);
},
/**
if (event instanceof Event) {
event.preventDefault();
}
- else if (event === true) {
- this._menu.classList.remove('enableAnimation');
- }
if (this._menu.classList.contains('open')) {
this._menu.classList.remove('open');
UiScreen.scrollEnable();
+
+ _pageContainer.classList.remove('menuOverlay-' + this._menu.id);
}
-
},
/**
});
if (itemTitle === '') {
- itemTitle = DomTraverse.childByClass(item, 'menuOverlayItemTitle').textContent
+ itemTitle = DomTraverse.childByClass(item, 'menuOverlayItemTitle').textContent;
elData(itemList, 'title', itemTitle);
}
event.preventDefault();
}
+ this._menu.classList.remove('allowScroll');
+ this._removeActiveList = true;
+
var data = this._items.get(item);
- data.itemList.classList.remove('active');
data.parentItemList.classList.remove('hidden');
+
+ this._updateDepth(false);
},
/**
}
}
- data.itemList.classList.add('active');
+ this._menu.classList.remove('allowScroll');
+
+ data.itemList.classList.add('activeList');
data.parentItemList.classList.add('hidden');
+
+ this._activeList.push(data.itemList);
+
+ this._updateDepth(true);
+ },
+
+ _updateDepth: function(increase) {
+ this._depth += (increase) ? 1 : -1;
+
+ this._menu.children[0].style.setProperty('transform', 'translateX(' + (this._depth * -100) + '%)', '')
}
};
define(['Core', 'Dictionary'], function(Core, Dictionary) {
"use strict";
- var _bodyOverflow = '';
var _mql = new Dictionary();
var _scrollDisableCounter = 0;
*/
scrollDisable: function() {
if (_scrollDisableCounter === 0) {
- _bodyOverflow = document.body.style.getPropertyValue('overflow');
-
- document.body.style.setProperty('overflow', 'hidden', '');
+ document.documentElement.classList.add('disableScrolling');
}
_scrollDisableCounter++;
_scrollDisableCounter--;
if (_scrollDisableCounter === 0) {
- if (_bodyOverflow) {
- document.body.style.setProperty('overflow', _bodyOverflow, '');
- }
- else {
- document.body.style.removeProperty('overflow');
- }
+ document.documentElement.classList.remove('disableScrolling');
}
}
},
+html.disableScrolling {
+ overflow: hidden !important;
+
+ body {
+ overflow: hidden !important;
+
+ @include screen-md-down {
+ position: fixed !important;
+ }
+ }
+}
+
html, body {
height: 100%;
body {
font-family: $wcfFontFamily;
position: relative;
+ width: 100%;
word-wrap: break-word;
}
-@include screen-md-up {
+@include screen-lg {
.pageNavigation {
background-color: $wcfNavigationBackground;
color: $wcfNavigationText;
}
}
-@include screen-sm-down {
+@include screen-md-down {
.pageNavigation {
display: none;
}
will-change: opacity;
z-index: 399;
- @include screen-md-up {
+ @include screen-sm-up {
padding: 100px 0;
}
.dialogContainer {
z-index: 200;
- @include screen-sm-down {
+ @include screen-xs {
left: 0 !important;
position: fixed;
right: 0 !important;
top: 0 !important;
}
- @include screen-md-up {
+ @include screen-sm-up {
animation: wcfDialogOut .3s;
animation-fill-mode: forwards;
box-shadow: 0 1px 15px 0 rgba(0, 0, 0, .3);
max-height: 300px;
overflow: auto;
}
-}
-
-.boxFlag > .box24, .boxFlag.box24 {
- display: flex !important;
- min-height: 20px;
- &.dropdownToggle {
- display: inline-flex !important;
- }
-}
-
-@include screen-md-up {
- .dropdownMenu.pageHeaderSearchDropdown {
- transform: translateY(-10px);
- }
-}
-
-@include screen-sm-down {
- .dropdownMenu {
+ @include screen-xs {
left: 0 !important;
right: 0 !important;
-
+ }
+
+ @include screen-md-down {
li {
overflow: hidden;
}
}
}
+
+ @include screen-md-up {
+ .dropdownMenu.pageHeaderSearchDropdown {
+ transform: translateY(-10px);
+ }
+ }
+}
+
+.boxFlag > .box24, .boxFlag.box24 {
+ display: flex !important;
+ min-height: 20px;
+
+ &.dropdownToggle {
+ display: inline-flex !important;
+ }
}
-/* animations for overlay appearing from the left */
-@keyframes wcfMenuOverlayLeft {
- 0% { visibility: hidden; transform: translateX(-100%); }
- 100% { visibility: visible; transform: translateX(0); }
-}
-
-@keyframes wcfMenuOverlayLeftOut {
- 0% { visibility: visible; transform: translateX(0); }
- 99% { visibility: visible; transform: translateX(-100%); }
- 100% { visibility: hidden; transform: translateX(-100%); }
-}
-
-/* animations for overlay appearing from the right */
-@keyframes wcfMenuOverlayRight {
- 0% { visibility: hidden; transform: translateX(100%); }
- 100% { visibility: visible; transform: translateX(0); }
-}
-
-@keyframes wcfMenuOverlayRightOut {
- 0% { visibility: visible; transform: translateX(0); }
- 99% { visibility: visible; transform: translateX(100%); }
- 100% { visibility: hidden; transform: translateX(100%); }
+@include screen-sm-up {
+ .pageContainer {
+ &.menuOverlay-pageMainMenuMobile {
+ transform: translateX(350px);
+
+ .mainMenu {
+ visibility: hidden;
+ }
+ }
+
+ &.menuOverlay-pageUserMenuMobile {
+ transform: translateX(-350px);
+
+ .userPanel {
+ visibility: hidden;
+ }
+ }
+ }
}
/* menu container */
.menuOverlayMobile {
+ background-color: rgb(52, 73, 94);
bottom: 0;
- left: 0;
- max-width: 100vw;
+ display: none;
overflow: hidden;
- position: fixed;
- right: 0;
+ position: absolute;
top: 0;
- visibility: hidden;
z-index: 320;
- &.enableAnimation {
- animation: wcfMenuOverlayLeftOut .3s;
- animation-fill-mode: forwards;
+ &.open {
+ display: block;
- /* different animation for user menu */
- &.pageUserMenuMobile {
- animation-name: wcfMenuOverlayRightOut;
+ @include screen-sm-up {
+ + .menuOverlayMobileBackdrop {
+ display: block;
+ }
}
}
- &.open {
- animation: wcfMenuOverlayLeft .3s;
- animation-fill-mode: forwards;
+ > .menuOverlayItemList {
+ // we use `transform: translateX()` for performance reasons
+ transition: transform .24s cubic-bezier(.25, .46, .45, .94);
- /* different animation for user menu */
- &.pageUserMenuMobile {
- animation-name: wcfMenuOverlayRight;
+ /* work-around to avoid setting explicit visibility */
+ visibility: visible;
+ }
+
+ &.allowScroll {
+ .menuOverlayItemList:not(.hidden) {
+ overflow: auto;
+ }
+ }
+
+ &:not(.allowScroll) {
+ // block UI while switching between menus
+ &::before {
+ bottom: 0;
+ content: "";
+ left: 0;
+ position: absolute;
+ right: 0;
+ top: 0;
+ z-index: 500;
}
}
- /* work-around to avoid setting explicit visibility */
- > .menuOverlayItemList:not(.hidden) {
- visibility: inherit;
+ @include screen-xs {
+ left: 0;
+ max-width: 100vw;
+ right: 0;
+
+ .menuOverlayItemList {
+ right: 0;
+ }
+ }
+
+ @include screen-sm-up {
+ width: 350px;
+
+ &.pageMainMenuMobile {
+ left: 0;
+
+ & + .menuOverlayMobileBackdrop {
+ box-shadow: inset 5px 0 10px -5px rgba(0, 0, 0, .6);
+ left: 350px;
+ }
+
+ .menuOverlayItemList {
+ left: 0;
+ }
+ }
+
+ &.pageUserMenuMobile {
+ right: 0;
+
+ & + .menuOverlayMobileBackdrop {
+ box-shadow: inset -5px 0 10px -5px rgba(0, 0, 0, .6);
+ right: 350px;
+ }
+
+ .menuOverlayItemList {
+ right: 0;
+ }
+ }
}
}
+.menuOverlayMobileBackdrop {
+ background-color: rgba(0, 0, 0, .4);
+ bottom: 0;
+ display: none;
+ left: 0;
+ position: fixed;
+ right: 0;
+ top: 0;
+ z-index: 500;
+}
+
.menuOverlayItemWrapper {
display: flex;
justify-content: flex-end;
.menuOverlayItemList {
background-color: rgb(52, 73, 94);
- box-shadow: -5px 0 10px 0 rgba(0, 0, 0, .2);
+ height: 100%;
list-style-type: none;
margin: 0;
- padding: 10px 0;
- position: fixed;
+ padding: 5px 0;
+ position: absolute;
top: 0;
left: -1px;
- right: 0;
bottom: 0;
width: calc(100% + 1px);
z-index: 450;
- transition: margin-left .3s cubic-bezier(.25, .46, .45, .94);
- transition-timing-function: linear;
- will-change: margin-left;
- /* chaining `.hidden` and `.active` below is required because each active
- item list receives `.active` but it could still be `.hidden` due to
- a child list being active */
- &.hidden,
- &.hidden.active {
- margin-left: -25%;
+ @include screen-sm-up {
+ width: 350px;
+ }
+
+ &:not(.activeList) {
+ display: none;
}
}
/* nested item list */
> .menuOverlayItemList {
- margin-left: 110%;
+ margin-left: 100%;
z-index: 500;
-
- &.active {
- margin-left: 0;
- overflow: scroll;
- }
}
}