[27777] Correct labels set for mobile version, focus on first menu item and collapsing on focusout working

pull/6354/head
Inga Mai 7 years ago
parent e4db31cfec
commit 5695fda45a
  1. 2
      frontend/app/components/main-menu/main-menu-toggle.component.ts
  2. 134
      frontend/app/components/main-menu/main-menu-toggle.service.ts
  3. 2
      frontend/app/components/resizer/main-menu-resizer.component.ts
  4. 86
      frontend/app/layout/controllers/main-menu-controller.js

@ -64,7 +64,7 @@ export class MainMenuToggleComponent implements OnInit {
private subscription:Subscription;
constructor(protected toggleService: MainMenuToggleService,
constructor(protected toggleService:MainMenuToggleService,
private elementRef:ElementRef) {
}

@ -41,7 +41,8 @@ export class MainMenuToggleService {
elementWidth:number;
htmlNode = document.getElementsByTagName('html')[0];
mainMenu = jQuery('#main-menu')[0]; // main menu, containing sidebar and resizer
mainMenu = jQuery('#main-menu')[0]; // main menu, containing sidebar and resizer
hideElements = jQuery('.can-hide-navigation');
private all = new BehaviorSubject<string>('');
public all$ = this.all.asObservable();
@ -50,60 +51,73 @@ export class MainMenuToggleService {
}
public initializeMenu() {
// save inital width in localStorage
if (this.mainMenu.offsetWidth < 10) { // if mainMenu is collapsed, set width 0 in localStorage
this.saveWidth("openProject-mainMenuWidth", 0);
} else if (this.mainMenu.offsetWidth < 230) { // set back to default width
this.saveWidth("openProject-mainMenuWidth", 230);
} else { // Get initial width from mainMenu and save in storage
this.saveWidth("openProject-mainMenuWidth", this.mainMenu.offsetWidth);
// mobile version default: hidden menu on initialization
if (window.innerWidth < 680) {
this.closeMenu();
}
// set correct value of boolean and label
if (this.localStorageValue < 10) {
this.showNavigation = false;
} else {
this.showNavigation = true;
// for desktop: save inital width in localStorage
else {
if (this.mainMenu.offsetWidth < 10) { // if mainMenu is collapsed, set width 0 in localStorage
this.saveWidth("openProject-mainMenuWidth", 0);
} else if (this.mainMenu.offsetWidth < 230) { // set back to default width
this.saveWidth("openProject-mainMenuWidth", 230);
} else { // Get initial width from mainMenu and save in storage
this.saveWidth("openProject-mainMenuWidth", this.mainMenu.offsetWidth);
}
// set correct value of boolean and label
if (this.localStorageValue < 10) {
this.showNavigation = false;
} else {
this.showNavigation = true;
}
}
this.addRemoveClassHidden();
this.setToggleTitle();
}
// click on arrow or hamburger icon
public toggleNavigation(event:JQueryEventObject) {
event.stopPropagation();
event.preventDefault();
if (this.mainMenu.offsetWidth < 10) { // sidebar is hidden -> show menu
this.showNavigation = true;
if (this.oldStorageValue != undefined && this.oldStorageValue > 230) { // save storage value and apply to menu width
this.saveWidth("openProject-mainMenuWidth", this.oldStorageValue);
} else { // if value of storage value < 230, set back to default size
this.saveWidth("openProject-mainMenuWidth", 230);
}
} else { // sidebar is expanded -> close menu
this.showNavigation = false;
this.oldStorageValue = this.localStorageValue;
this.saveWidth("openProject-mainMenuWidth", 0);
event.stopPropagation();
event.preventDefault();
// mobile version
if (window.innerWidth < 680) {
if(this.localStorageValue === 0) {
this.showNavigation = true; // main menu shall expand.
this.saveWidth("openProject-mainMenuWidth", window.innerWidth);
// On mobile the main menu shall close whenever you click outside the menu.
this.setupAutocloseMainMenu();
} else {
this.closeMenu();
}
}
this.setToggleTitle();
if (this.showNavigation) {
// main menu shall expand.
// Set focus on first visible main menu item.
//
// This needs to be called after AngularJS has rendered the menu, which happens some when after(!) we leave this
// method here. So we need to set the focus after a timeout.
setTimeout(function() {
jQuery('#main-menu [class*="-menu-item"]:visible').first().focus();
}, 100);
// On mobile the main menu shall close whenever you click outside the menu.
if (window.innerWidth < 680) {
this.setupAutocloseMainMenu();
// desktop version
else {
if (this.mainMenu.offsetWidth < 10) { // sidebar is hidden -> show menu
this.showNavigation = true;
if (this.oldStorageValue !== undefined && this.oldStorageValue > 230) { // save storage value and apply to menu width
this.saveWidth("openProject-mainMenuWidth", this.oldStorageValue);
} else { // if value of storage value < 230, set back to default size
this.saveWidth("openProject-mainMenuWidth", 230);
}
} else { // sidebar is expanded -> close menu
this.closeMenu();
}
}
this.addRemoveClassHidden();
this.setToggleTitle();
// Set focus on first visible main menu item.
// This needs to be called after AngularJS has rendered the menu, which happens some when after(!) we leave this
// method here. So we need to set the focus after a timeout.
setTimeout(function() {
jQuery('#main-menu [class*="-menu-item"]:visible').first().focus();
}, 500);
}
private closeMenu() {
this.showNavigation = false;
this.oldStorageValue = this.localStorageValue;
this.saveWidth("openProject-mainMenuWidth", 0);
this.hideElements.addClass('hidden-navigation');
}
private setToggleTitle() {
@ -115,6 +129,14 @@ export class MainMenuToggleService {
this.all.next(this.toggleTitle);
}
private addRemoveClassHidden() {
if (this.showNavigation) {
this.hideElements.removeClass('hidden-navigation');
} else {
this.hideElements.addClass('hidden-navigation');
}
}
public saveWidth(localStorageKey:string, width:number) {
window.OpenProject.guardedLocalStorage(localStorageKey, String(width));
this.localStorageValue = Number(window.OpenProject.guardedLocalStorage(localStorageKey));
@ -132,20 +154,22 @@ export class MainMenuToggleService {
let that = this;
jQuery('#main-menu').on('focusout.main_menu', function (event) {
jQuery('#main-menu').off('focusout.main_menu');
// Check that main menu is not closed and that the `focusout` event is not a click on an element that tries to close
// the menu anyways.
if (that.showNavigation ||
jQuery.contains(<Element>document.getElementById('main-menu-toggle'), event.relatedTarget)) {
// Check that main menu is not closed and that the `focusout` event is not a click on an element
// that tries to close the menu anyways.
if (!that.showNavigation || document.getElementById('main-menu-toggle') === event.relatedTarget) {
return;
}
});
// There might be a time gap between `focusout` and the focussing of the activeElement, thus we need a timeout.
setTimeout(function() {
if (!jQuery.contains(<Element>document.getElementById('main-menu'), document.activeElement)) {
// activeElement is outside of main menu.
that.toggleNavigation(jQuery.Event('onclick'));
else {
// There might be a time gap between `focusout` and the focussing of the activeElement, thus we need a timeout.
setTimeout(function() {
if (!jQuery.contains(<Element>document.getElementById('main-menu'), document.activeElement) &&
(document.getElementById('main-menu-toggle') !== document.activeElement)) {
// activeElement is outside of main menu.
that.closeMenu();
}
}, 0);
}
}, 0);
});
}
}

@ -128,7 +128,7 @@ export class MainMenuResizerComponent implements OnInit {
this.moving = false;
// save new width in service (if width < 230 set default value after reloading the page)
// save new width in service
this.toggleService.saveWidth(this.localStorageKey, this.elementWidth);
console.log("Saved element width: ", this.elementWidth);

@ -1,86 +0,0 @@
//-- copyright
// OpenProject is a project management system.
// Copyright (C) 2012-2018 the OpenProject Foundation (OPF)
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License version 3.
//
// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
// Copyright (C) 2006-2017 Jean-Philippe Lang
// Copyright (C) 2010-2013 the ChiliProject Team
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
//
// See docs/COPYRIGHT.rdoc for more details.
//++
module.exports = function($rootScope, $window) {
var self = this;
this.toggleNavigation = function(event) {
event.preventDefault();
event.stopPropagation();
if (!$rootScope.showNavigation) {
// main menu shall expand.
// Set focus on first visible main menu item.
//
// This needs to be called after AngularJS has rendered the menu, which happens some when after(!) we leave this
// method here. So we need to set the focus after a timeout.
setTimeout(function() {
jQuery('#main-menu [class*="-menu-item"]:visible').first().focus();
}, 100);
// On mobile the main menu shall close whenever you click outside the menu.
if ($window.innerWidth < 680) {
self.setupAutocloseMainMenu();
}
// Regain default width: Expand to default menu width if collapsed slimmer than default width.
var savedMainMenuWidth = parseInt(window.OpenProject.guardedLocalStorage("openProject-mainMenuWidth"));
if (savedMainMenuWidth < 230) {
document.documentElement.style.setProperty("--main-menu-width", '230px');
window.OpenProject.guardedLocalStorage("openProject-mainMenuWidth", '230');
}
}
$rootScope.showNavigation = !$rootScope.showNavigation;
$rootScope.$broadcast('openproject.layout.navigationToggled', $rootScope.showNavigation);
$window.sessionStorage.setItem('openproject:navigation-toggle',
!$rootScope.showNavigation ? 'collapsed' : 'expanded');
};
this.setupAutocloseMainMenu = function() {
jQuery('#main-menu').on('focusout.main_menu', function (event) {
jQuery('#main-menu').off('focusout.main_menu');
// Check that main menu is not closed and that the `focusout` event is not a click on an element that tries to close
// the menu anyways.
if (!$rootScope.showNavigation ||
jQuery.contains(document.getElementById('main-menu-toggle'), event.relatedTarget)) {
return;
}
// There might be a time gap between `focusout` and the focussing of the activeElement, thus we need a timeout.
setTimeout(function() {
if (!jQuery.contains(document.getElementById('main-menu'), document.activeElement)) {
// activeElement is outside of main menu.
self.toggleNavigation(new Event('onclick'));
}
}, 0);
});
}
};
Loading…
Cancel
Save