Browse Source

Merge 03bce7eaed into 154ae149f4

pull/1119/merge
George Daramouskas 5 years ago
committed by GitHub
parent
commit
091c3641f4
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 83
      web_keyboard_navigation/README.rst
  2. 2
      web_keyboard_navigation/__init__.py
  3. 22
      web_keyboard_navigation/__manifest__.py
  4. BIN
      web_keyboard_navigation/static/description/icon.png
  5. 13
      web_keyboard_navigation/static/src/css/web_keyboard_navigation.css
  6. 17
      web_keyboard_navigation/static/src/js/abstract_web_client.js
  7. 16
      web_keyboard_navigation/static/src/js/browser_detection.js
  8. 237
      web_keyboard_navigation/static/src/js/web_keyboard_navigation.js
  9. 23
      web_keyboard_navigation/views/templates.xml

83
web_keyboard_navigation/README.rst

@ -0,0 +1,83 @@
.. image:: https://img.shields.io/badge/licence-AGPL--3-blue.svg
:target: https://www.gnu.org/licenses/agpl-3.0-standalone.html
:alt: License: AGPL-3
==============================
web_keyboard_navigation
==============================
This module was written to extend the functionality of the Web Client to
support easier navigation and allow you to use the Alt key in order to get
some shortcuts shown on your client.
Installation
============
To install this module, you need to:
Follow the usual procedure for your version of Odoo.
Configuration
=============
To configure this module, you need to:
No configuration can take place at this point.
Usage
=====
To use this module, you need to:
#. go to ...
.. image:: https://odoo-community.org/website/image/ir.attachment/5784_f2813bd/datas
:alt: Try me on Runbot
:target: https://runbot.odoo-community.org/runbot/162
Known issues / Roadmap
======================
* Allow customization of the keys.
Bug Tracker
===========
Bugs are tracked on `GitHub Issues
<https://github.com/OCA/web/issues>`_. In case of trouble, please
check there if your issue has already been reported. If you spotted it first,
help us smashing it by providing a detailed and welcomed feedback.
Credits
=======
Images
------
* Odoo Community Association: `Icon <https://github.com/OCA/maintainer-tools/blob/master/template/module/static/description/icon.svg>`_.
Contributors
------------
* George Daramouskas <gdaramouskas@therp.nl>
Do not contact contributors directly about help with questions or problems concerning this addon, but use the `community mailing list <mailto:community@mail.odoo.com>`_ or the `appropriate specialized mailinglist <https://odoo-community.org/groups>`_ for help, and the bug tracker linked in `Bug Tracker`_ above for technical issues.
Maintainer
----------
.. image:: https://odoo-community.org/logo.png
:alt: Odoo Community Association
:target: https://odoo-community.org
This module is maintained by the OCA.
OCA, or the Odoo Community Association, is a nonprofit organization whose
mission is to support the collaborative development of Odoo features and
promote its widespread use.
To contribute to this module, please visit https://odoo-community.org.
**This module is a backport from Odoo SA and as such, it is not included in the
OCA CLA. That means we do not have a copy of the copyright on it like all other
OCA modules.

2
web_keyboard_navigation/__init__.py

@ -0,0 +1,2 @@
# Copyright 2018 Therp BV <https://therp.nl>
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html).

22
web_keyboard_navigation/__manifest__.py

@ -0,0 +1,22 @@
# Copyright 2018 Therp BV <https://therp.nl>
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html).
{
"name": "web_keyboard_navigation",
"version": "11.0.1.0.0",
"author": "Therp BV,Odoo Community Association (OCA)",
"license": "AGPL-3",
"category": "",
"summary": "",
"depends": [
'web',
],
"data": [
'views/templates.xml',
],
"pre_init_hook": False,
"post_init_hook": False,
"uninstall_hook": False,
"auto_install": False,
"installable": True,
"application": False,
}

BIN
web_keyboard_navigation/static/description/icon.png

After

Width: 128  |  Height: 128  |  Size: 9.2 KiB

13
web_keyboard_navigation/static/src/css/web_keyboard_navigation.css

@ -0,0 +1,13 @@
.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;
}

17
web_keyboard_navigation/static/src/js/abstract_web_client.js

@ -0,0 +1,17 @@
odoo.define('web_keyboard_navigation.WebClient', function (require) {
"use strict";
var WebClient = require('web.WebClient');
var KeyboardNavigationMixin = require(
'web_keyboard_navigation.KeyboardNavigationMixin');
return WebClient.include(KeyboardNavigationMixin, {
events: _.extend(KeyboardNavigationMixin.events, {}),
init: function (parent) {
this._super(parent);
KeyboardNavigationMixin.init.call(this);
},
});
});

16
web_keyboard_navigation/static/src/js/browser_detection.js

@ -0,0 +1,16 @@
odoo.define('web.BrowserDetection', function (require) {
"use strict";
var Class = require('web.Class');
var BrowserDetection = Class.extend({
isOsMac: function () {
return navigator.platform.toLowerCase().indexOf('mac') !== -1;
},
isBrowserChrome: function () {
return $.browser.chrome &&
navigator.userAgent.toLocaleLowerCase().indexOf('edge') === -1;
},
});
return BrowserDetection;
});

237
web_keyboard_navigation/static/src/js/web_keyboard_navigation.js

@ -0,0 +1,237 @@
odoo.define('web_keyboard_navigation.KeyboardNavigationMixin', function (
require) {
"use strict";
var BrowserDetection = require('web.BrowserDetection');
/**
* List of the key that should not be used as accesskeys.
* Either because we want to reserve them for a specific behavior in Odoo
* or because they will not work in certain browser/OS
*/
var knownUnusableAccessKeys = [' ',
'A',
'C',
'H',
'J',
'K',
'L',
'N',
'P',
'S',
'Q',
'E',
'F',
'D',
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
];
var KeyboardNavigationMixin = {
events: {
'keydown': '_onKeyDown',
'keyup': '_onKeyUp',
},
init: function () {
this._super();
this._areAccessKeyVisible = false;
this.BrowserDetection = new BrowserDetection();
},
_addAccessKeyOverlays: function () {
var accesskeyElements = $(document).find('[accesskey]').filter(
':visible');
_.each(accesskeyElements, function (elem) {
var overlay = $(_.str.sprintf(
"<div class='o_web_accesskey_overlay'>%s</div>",
$(elem).attr('accesskey').toUpperCase()));
var $overlayParent = null;
if (elem.tagName.toUpperCase() === "INPUT") {
$overlayParent = $(elem).parent();
} else {
$overlayParent = $(elem);
}
if ($overlayParent.css('position') !== 'absolute') {
$overlayParent.css('position', 'relative');
}
overlay.appendTo($overlayParent);
});
},
_getAllUsedAccessKeys: function () {
var usedAccessKeys = knownUnusableAccessKeys.slice();
this.$el.find('[accesskey]').each(function (_, elem) {
usedAccessKeys.push(elem.accessKey.toUpperCase());
});
return usedAccessKeys;
},
_hideAccessKeyOverlay: function () {
this._areAccessKeyVisible = false;
var overlays = this.$el.find('.o_web_accesskey_overlay');
if (overlays.length) {
return overlays.remove();
}
},
_setAccessKeyOnTopNavigation: function () {
this.$el.find(
'.o_menu_sections>li>a').each(function (number, item) {
item.accessKey = number + 1;
});
},
_onKeyDown: function (keyDownEvent) {
if ($('body.o_ui_blocked').length &&
(keyDownEvent.altKey || keyDownEvent.key === 'Alt') &&
!keyDownEvent.ctrlKey) {
if (keyDownEvent.preventDefault) {
keyDownEvent.preventDefault();
} else {
keyDownEvent.returnValue = false;
}
if (keyDownEvent.stopPropagation) {
keyDownEvent.stopPropagation();
}
if (keyDownEvent.cancelBubble) {
keyDownEvent.cancelBubble = true;
}
return false;
}
if (!this._areAccessKeyVisible &&
(keyDownEvent.altKey || keyDownEvent.key === 'Alt') &&
!keyDownEvent.ctrlKey) {
this._areAccessKeyVisible = true;
this._setAccessKeyOnTopNavigation();
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;
}
}
});
var elementsWithoutAriaKeyshortcut = this.$el.find(
'[accesskey]').not('[aria-keyshortcuts]');
_.each(elementsWithoutAriaKeyshortcut, function (elem) {
elem.setAttribute(
'aria-keyshortcuts', 'Alt+Shift+' + elem.accessKey);
});
this._addAccessKeyOverlays();
}
if (this.BrowserDetection.isOsMac()) {
return;
}
if (keyDownEvent.altKey &&
!keyDownEvent.ctrlKey &&
keyDownEvent.key.length === 1) {
var elementWithAccessKey = [];
if (keyDownEvent.keyCode >= 65 &&
keyDownEvent.keyCode <= 90 ||
keyDownEvent.keyCode >= 97 &&
keyDownEvent.keyCode <= 122) {
elementWithAccessKey = document.querySelectorAll(
'[accesskey="' + String.fromCharCode(
keyDownEvent.keyCode).toLowerCase() +
'"], [accesskey="' + String.fromCharCode(
keyDownEvent.keyCode).toUpperCase() + '"]');
if (elementWithAccessKey.length) {
if (this.BrowserDetection.isOsMac() ||
!this.BrowserDetection.isBrowserChrome()) {
elementWithAccessKey[0].focus();
elementWithAccessKey[0].click();
if (keyDownEvent.preventDefault) {
keyDownEvent.preventDefault();
} else {
keyDownEvent.returnValue = false;
}
if (keyDownEvent.stopPropagation) {
keyDownEvent.stopPropagation();
}
if (keyDownEvent.cancelBubble) {
keyDownEvent.cancelBubble = true;
}
return false;
}
}
}
else {
var numberKey = null;
if (keyDownEvent.originalEvent.code &&
keyDownEvent.originalEvent.code.indexOf(
'Digit') === 0) {
numberKey = keyDownEvent.originalEvent.code[
keyDownEvent.originalEvent.code.length - 1];
} else if (keyDownEvent.originalEvent.key &&
keyDownEvent.originalEvent.key.length === 1 &&
keyDownEvent.originalEvent.key >= '0' &&
keyDownEvent.originalEvent.key <= '9') {
numberKey = keyDownEvent.originalEvent.key;
} else if (
keyDownEvent.keyCode >= 48 &&
keyDownEvent.keyCode <= 57) {
numberKey = keyDownEvent.keyCode - 48;
}
if (numberKey >= '0' && numberKey <= '9') {
elementWithAccessKey = document.querySelectorAll(
'[accesskey="' + numberKey + '"]');
if (elementWithAccessKey.length) {
elementWithAccessKey[0].click();
if (keyDownEvent.preventDefault) {
keyDownEvent.preventDefault();
} else {
keyDownEvent.returnValue = false;
}
if (keyDownEvent.stopPropagation) {
keyDownEvent.stopPropagation();
}
if (keyDownEvent.cancelBubble) {
keyDownEvent.cancelBubble = true;
}
return false;
}
}
}
}
},
_onKeyUp: function (keyUpEvent) {
if ((keyUpEvent.altKey || keyUpEvent.key === 'Alt') &&
!keyUpEvent.ctrlKey) {
this._hideAccessKeyOverlay();
if (keyUpEvent.preventDefault) {
keyUpEvent.preventDefault();
}
else {
keyUpEvent.returnValue = false;
}
if (keyUpEvent.stopPropagation) {
keyUpEvent.stopPropagation();
}
if (keyUpEvent.cancelBubble) {
keyUpEvent.cancelBubble = true;
}
return false;
}
},
};
return KeyboardNavigationMixin;
});

23
web_keyboard_navigation/views/templates.xml

@ -0,0 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>
<odoo>
<data>
<template id="assets_backend" name="web_keyboard_navigation assets" inherit_id="web.assets_backend">
<xpath expr="." position="inside">
<script
type="text/javascript"
src="/web_keyboard_navigation/static/src/js/abstract_web_client.js"/>
<script
type="text/javascript"
src="/web_keyboard_navigation/static/src/js/browser_detection.js"/>
<script
type="text/javascript"
src="/web_keyboard_navigation/static/src/js/web_keyboard_navigation.js"/>
<link
rel="stylesheet"
href="/web_keyboard_navigation/static/src/css/web_keyboard_navigation.css"/>
</xpath>
</template>
</data>
</odoo>
Loading…
Cancel
Save