From 0b0690a3934cedcab0d5e34373e8d40c2ab25660 Mon Sep 17 00:00:00 2001 From: Samuel Degueldre Date: Thu, 5 Mar 2020 10:47:48 +0000 Subject: [PATCH] [IMP] website, web: add fullscreen mode and frontend keyboard shortcuts While the edit mode interface is full of useful things, it also adds a lot of clutter, and alters the page's width and thus, its layout. This commit adds keyboard shortcut for website editors to use, and allows them to enter a "fullscreen" mode that hides the editor interface while remaining in edit mode, allowing the user to have fewer distractions while editing text content, and a closer rendition of the page's final layout while editing. For this, keyboard shortcuts were required, and a few other useful shortcuts have been added, such as alt-1,2,3 for the navbar, just like in the backed. task-2126915 closes odoo/odoo#46953 Related: odoo/enterprise#9295 Signed-off-by: Quentin Smetz (qsm) --- .../js/chrome/keyboard_navigation_mixin.js | 45 ++++++++----- addons/web/static/src/scss/ui.scss | 18 +++++ addons/web/static/src/scss/webclient.scss | 10 --- addons/web_editor/views/snippets.xml | 2 +- .../static/src/js/content/website_root.js | 65 ++++++++++++++++++- .../website/static/src/js/menu/mobile_view.js | 5 +- .../website/static/src/js/menu/new_content.js | 6 ++ .../website/static/src/scss/website.ui.scss | 20 ++++++ .../website/static/src/xml/website.editor.xml | 4 +- addons/website/views/assets.xml | 3 + addons/website/views/snippets/snippets.xml | 2 +- .../views/website_navbar_templates.xml | 13 ++-- 12 files changed, 153 insertions(+), 40 deletions(-) diff --git a/addons/web/static/src/js/chrome/keyboard_navigation_mixin.js b/addons/web/static/src/js/chrome/keyboard_navigation_mixin.js index 4318bca879a..707dab1f8f9 100644 --- a/addons/web/static/src/js/chrome/keyboard_navigation_mixin.js +++ b/addons/web/static/src/js/chrome/keyboard_navigation_mixin.js @@ -30,7 +30,17 @@ odoo.define('web.KeyboardNavigationMixin', function (require) { 'keyup': '_onKeyUp', }, - init: function () { + /** + * @constructor + * @param {object} [options] + * @param {boolean} [options.autoAccessKeys=true] + * Whether accesskeys should be created automatically for buttons + * without them in the page. + */ + init: function (options) { + this.options = Object.assign({ + autoAccessKeys: true, + }, options); this._areAccessKeyVisible = false; this.BrowserDetection = new BrowserDetection(); }, @@ -130,22 +140,24 @@ odoo.define('web.KeyboardNavigationMixin', function (require) { var usedAccessKey = this._getAllUsedAccessKeys(); - var buttonsWithoutAccessKey = this.$el.find('button.btn:visible') - .not('[accesskey]') - .not('[disabled]') - .not('[tabindex="-1"]'); - _.each(buttonsWithoutAccessKey, function (elem) { - var buttonString = [elem.innerText, elem.title, "ABCDEFGHIJKLMNOPQRSTUVWXYZ"].join(''); - for (var letterIndex = 0; letterIndex < buttonString.length; letterIndex++) { - var candidateAccessKey = buttonString[letterIndex].toUpperCase(); - if (candidateAccessKey >= 'A' && candidateAccessKey <= 'Z' && - !_.includes(usedAccessKey, candidateAccessKey)) { - elem.accessKey = candidateAccessKey; - usedAccessKey.push(candidateAccessKey); - break; + if (this.options.autoAccessKeys) { + var buttonsWithoutAccessKey = this.$el.find('button.btn:visible') + .not('[accesskey]') + .not('[disabled]') + .not('[tabindex="-1"]'); + _.each(buttonsWithoutAccessKey, function (elem) { + var buttonString = [elem.innerText, elem.title, "ABCDEFGHIJKLMNOPQRSTUVWXYZ"].join(''); + for (var letterIndex = 0; letterIndex < buttonString.length; letterIndex++) { + var candidateAccessKey = buttonString[letterIndex].toUpperCase(); + if (candidateAccessKey >= 'A' && candidateAccessKey <= 'Z' && + !_.includes(usedAccessKey, candidateAccessKey)) { + elem.accessKey = candidateAccessKey; + usedAccessKey.push(candidateAccessKey); + break; + } } - } - }); + }); + } var elementsWithoutAriaKeyshortcut = this.$el.find('[accesskey]').not('[aria-keyshortcuts]'); _.each(elementsWithoutAriaKeyshortcut, function (elem) { @@ -230,4 +242,3 @@ odoo.define('web.KeyboardNavigationMixin', function (require) { return KeyboardNavigationMixin; }); - diff --git a/addons/web/static/src/scss/ui.scss b/addons/web/static/src/scss/ui.scss index 0a318c57d13..61854a8d304 100644 --- a/addons/web/static/src/scss/ui.scss +++ b/addons/web/static/src/scss/ui.scss @@ -143,3 +143,21 @@ span.o_force_ltr { .o_width_128 { width: 128px; } + +.o_web_accesskey_overlay { + @include o-position-absolute(0, 0); + display: flex; + justify-content: center; + align-items: center; + width: 100%; + height: 100%; + background-color: rgba(0, 0, 0, .6); + color: #FFFFFF; + font-size: 1rem; + + // Needed as the parent button could be using font-awesome. + // Can't be put to a BS variable here as we are in assets common (will be + // overridden for backend but left with 'sans-serif' for frontend to not + // have an useless frontend rule. + font-family: sans-serif; +} diff --git a/addons/web/static/src/scss/webclient.scss b/addons/web/static/src/scss/webclient.scss index d41d1fb0ba3..9bc77f1b29d 100644 --- a/addons/web/static/src/scss/webclient.scss +++ b/addons/web/static/src/scss/webclient.scss @@ -84,16 +84,6 @@ div.o_boolean_toggle.custom-control.custom-checkbox { .o_web_accesskey_overlay { font-family: $font-family-sans-serif; - position: absolute; - width: 100%; - height: 100%; - left: 0; - top: 0; - background-color: rgba(0,0,0,.6); - color: #FFFFFF; - justify-content: center; - display: flex; - align-items: center; } // Decorations diff --git a/addons/web_editor/views/snippets.xml b/addons/web_editor/views/snippets.xml index 3b08d7d5a52..5ba6583ecf1 100644 --- a/addons/web_editor/views/snippets.xml +++ b/addons/web_editor/views/snippets.xml @@ -2,7 +2,7 @@