Commit 111c030b authored by Sebastien Robin's avatar Sebastien Robin

erp5_web_renderjs_ui: enable keyboard to navigate relation field menu

Also, manually handle mouseover for highlighting relation field menu lines instead
of using css. Indeed, we have to manually handle possibility that highlight could
be done either by mouse or by keyboard.
parent 3e148c20
......@@ -1315,8 +1315,7 @@ div[data-gadget-scope='header'] .ui-header ul {
.relation-input ul li::before {
padding-right: 6pt;
}
.relation-input ul li:hover,
.relation-input ul li:active {
.relation-input ul .active {
background-color: #1F1F1F;
}
.relation-input .ui-icon-warning {
......
......@@ -3,7 +3,8 @@
SimpleQuery, ComplexQuery, Query, QueryFactory, document, XMLHttpRequest,
console*/
(function (window, rJS, RSVP, URI, document,
SimpleQuery, ComplexQuery, Query, QueryFactory, XMLHttpRequest, console) {
SimpleQuery, ComplexQuery, Query, QueryFactory, XMLHttpRequest, console,
MouseEvent) {
"use strict";
function displayNonEditableLink(gadget) {
......@@ -548,7 +549,79 @@
}
}
}, false, false)
.onEvent('keydown', function (evt) {
var gadget = this,
i,
next_event,
active_index,
ul = gadget.element.querySelector(".search_ul");
if (evt.key === "ArrowDown" || evt.key === "ArrowUp") {
if (ul.childNodes.length > 0) {
for (i = 0; i < ul.childNodes.length; i += 1) {
if (ul.childNodes[i].classList.contains('active')) {
active_index = i;
}
}
if (active_index === undefined) {
if (evt.key === "ArrowDown") {
active_index = 0;
} else if (evt.key === "ArrowUp") {
active_index = ul.childNodes.length - 1;
}
} else {
if (evt.key === "ArrowDown") {
active_index = active_index + 1;
} else if (evt.key === "ArrowUp") {
active_index = active_index - 1;
}
if (active_index >= ul.childNodes.length) {
active_index = 0;
}
else if (active_index === -1) {
active_index = ul.childNodes.length - 1;
}
}
for (i = 0; i < ul.childNodes.length; i += 1) {
if (i === active_index) {
if (!ul.childNodes[i].classList.contains('active')) {
ul.childNodes[i].classList.add('active');
}
} else {
if (ul.childNodes[i].classList.contains('active')) {
ul.childNodes[i].classList.remove('active');
}
}
}
evt.preventDefault();
}
} else if (evt.key === "Enter") {
for (i = 0; i < ul.childNodes.length; i += 1) {
if (ul.childNodes[i].classList.contains('active')) {
next_event = new MouseEvent('click', {
view: window,
bubbles: true,
cancelable: true
});
ul.childNodes[i].dispatchEvent(next_event);
evt.preventDefault();
}
}
}
}, true, false)
.onEvent('mouseover', function (evt) {
// Do not use li:hover css syntax, since we have to disable manually
// the highlightnment when keyboard is used
var gadget = this,
i,
ul = gadget.element.querySelector(".search_ul");
if (evt.target.tagName.toLowerCase() === 'li') {
for (i = 0; i < ul.childNodes.length; i += 1) {
ul.childNodes[i].classList.remove('active');
}
evt.target.classList.add('active');
}
}, true, false)
.declareAcquiredMethod("notifyBlur", "notifyBlur")
.onEvent('blur', function (evt) {
var gadget = this;
......@@ -647,4 +720,5 @@
}, true, false);
}(window, rJS, RSVP, URI, document,
SimpleQuery, ComplexQuery, Query, QueryFactory, XMLHttpRequest, console));
\ No newline at end of file
SimpleQuery, ComplexQuery, Query, QueryFactory, XMLHttpRequest, console,
MouseEvent));
\ No newline at end of file
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="ZopePageTemplate" module="Products.PageTemplates.ZopePageTemplate"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_bind_names</string> </key>
<value>
<object>
<klass>
<global name="_reconstructor" module="copy_reg"/>
</klass>
<tuple>
<global name="NameAssignments" module="Shared.DC.Scripts.Bindings"/>
<global name="object" module="__builtin__"/>
<none/>
</tuple>
<state>
<dictionary>
<item>
<key> <string>_asgns</string> </key>
<value>
<dictionary>
<item>
<key> <string>name_subpath</string> </key>
<value> <string>traverse_subpath</string> </value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</state>
</object>
</value>
</item>
<item>
<key> <string>content_type</string> </key>
<value> <string>text/html</string> </value>
</item>
<item>
<key> <string>expand</string> </key>
<value> <int>0</int> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>testRelationFieldArrowKeys</string> </value>
</item>
<item>
<key> <string>output_encoding</string> </key>
<value> <string>utf-8</string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <unicode></unicode> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<html xmlns:tal="http://xml.zope.org/namespaces/tal"
xmlns:metal="http://xml.zope.org/namespaces/metal">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Test RenderJS UI</title>
</head>
<body>
<table cellpadding="1" cellspacing="1" border="1">
<thead>
<tr><td rowspan="1" colspan="3">Test RenderJS UI</td></tr>
</thead><tbody>
<tal:block metal:use-macro="here/Zuite_CommonTemplate/macros/init" />
<!-- Clean Up -->
<tr>
<td>open</td>
<td>${base_url}/foo_module/ListBoxZuite_reset</td>
<td></td>
</tr>
<tr>
<td>assertTextPresent</td>
<td>Reset Successfully.</td>
<td></td>
</tr>
<!-- Initialize -->
<tr>
<td>open</td>
<td>${base_url}/web_site_module/renderjs_runner/#/foo_module</td>
<td></td>
</tr>
<tal:block metal:use-macro="here/Zuite_CommonTemplateForRenderjsUi/macros/wait_for_app_loaded" />
<tal:block tal:define="click_configuration python: {'text': 'Add'}">
<tal:block metal:use-macro="here/Zuite_CommonTemplateForRenderjsUi/macros/click_on_header_link" />
</tal:block>
<tal:block metal:use-macro="here/Zuite_CommonTemplateForRenderjsUi/macros/wait_for_content_loaded" />
<tal:block metal:use-macro="here/Zuite_CommonTemplateForRenderjsUi/macros/submit_dialog" />
<tal:block tal:define="notification_configuration python: {'class': 'success',
'text': 'Object created.'}">
<tal:block metal:use-macro="here/Zuite_CommonTemplateForRenderjsUi/macros/wait_for_notification" />
</tal:block>
<tal:block metal:use-macro="here/Zuite_CommonTemplateForRenderjsUi/macros/wait_for_content_loaded" />
<tr>
<td>assertTextPresent</td>
<td>Save</td>
<td></td>
</tr>
<tr>
<td>assertTextPresent</td>
<td>Quantity</td>
<td></td>
</tr>
<tal:block metal:use-macro="here/Zuite_CommonTemplateForRenderjsUi/macros/go_to_foo_relation_field_view" />
<tr>
<td>waitForElementPresent</td>
<td>//input[@name='field_my_foo_category_title']</td>
<td></td>
</tr>
<tr>
<td>click</td>
<td>//input[@name='field_my_foo_category_title']</td>
<td></td>
</tr>
<tr>
<td>assertEval</td>
<td>(function() { selenium.browserbot.getCurrentWindow().document.getElementById("field_my_foo_category_title").value = "Qua%"; return true;})()
<td>true</td>
</tr>
<tr>
<td>fireEvent</td>
<td>//input[@name='field_my_foo_category_title']</td>
<td>input</td>
</tr>
<tr>
<td>waitForElementPresent</td>
<td>//li[@data-relative-url='portal_categories/divergence_scope/quantity']</td>
<td></td>
</tr>
<!-- We have class "active" for every line that should be highlighted -->
<!-- Initially, no lines are highlighted -->
<tr>
<td>assertElementNotPresent</td>
<td>//input[@name='field_my_foo_category_title']/parent::*//li[position()=1 and contains(@class,'active')]</td>
<td></td>
</tr>
<tr>
<td>assertElementNotPresent</td>
<td>//input[@name='field_my_foo_category_title']/parent::*//li[position()=2 and contains(@class,'active')]</td>
<td></td>
</tr>
<!-- We do Arrow down key, then first line should be highlighted -->
<tr>
<td>assertEval</td>
<td>var e = new KeyboardEvent('keydown', {'key':'ArrowDown'});
selenium.browserbot.getDocument().querySelector("input[name='field_my_foo_category_title']").dispatchEvent(e)</td>
<td>true</td>
</tr>
<tr>
<td>waitForElementPresent</td>
<td>//input[@name='field_my_foo_category_title']/parent::*//li[position()=1 and contains(@class,'active')]</td>
<td></td>
</tr>
<tr>
<td>assertElementPresent</td>
<td>//input[@name='field_my_foo_category_title']/parent::*//li[position()=1 and contains(@class,'active')]</td>
<td></td>
</tr>
<tr>
<td>assertElementNotPresent</td>
<td>//input[@name='field_my_foo_category_title']/parent::*//li[position()=2 and contains(@class,'active')]</td>
<td></td>
</tr>
<!-- We do Arrow down key again, then second line should be highlighted -->
<tr>
<td>assertEval</td>
<td>var e = new KeyboardEvent('keydown', {'key':'ArrowDown'});
selenium.browserbot.getDocument().querySelector("input[name='field_my_foo_category_title']").dispatchEvent(e)</td>
<td>true</td>
</tr>
<tr>
<td>waitForElementPresent</td>
<td>//input[@name='field_my_foo_category_title']/parent::*//li[position()=2 and contains(@class,'active')]</td>
<td></td>
</tr>
<tr>
<td>assertElementNotPresent</td>
<td>//input[@name='field_my_foo_category_title']/parent::*//li[position()=1 and contains(@class,'active')]</td>
<td></td>
</tr>
<tr>
<td>assertElementPresent</td>
<td>//input[@name='field_my_foo_category_title']/parent::*//li[position()=2 and contains(@class,'active')]</td>
<td></td>
</tr>
<!-- We do Arrow up key, then first line should be highlighted -->
<tr>
<td>assertEval</td>
<td>var e = new KeyboardEvent('keydown', {'key':'ArrowUp'});
selenium.browserbot.getDocument().querySelector("input[name='field_my_foo_category_title']").dispatchEvent(e)</td>
<td>true</td>
</tr>
<tr>
<td>waitForElementPresent</td>
<td>//input[@name='field_my_foo_category_title']/parent::*//li[position()=1 and contains(@class,'active')]</td>
<td></td>
</tr>
<tr>
<td>assertElementPresent</td>
<td>//input[@name='field_my_foo_category_title']/parent::*//li[position()=1 and contains(@class,'active')]</td>
<td></td>
</tr>
<tr>
<td>assertElementNotPresent</td>
<td>//input[@name='field_my_foo_category_title']/parent::*//li[position()=2 and contains(@class,'active')]</td>
<td></td>
</tr>
<!-- Make sure Enter key allows to validate the selected line and disable the list of choice -->
<tr>
<td>assertEval</td>
<td>var e = new KeyboardEvent('keydown', {'key':'Enter'});
selenium.browserbot.getDocument().querySelector("input[name='field_my_foo_category_title']").dispatchEvent(e)</td>
<td>true</td>
</tr>
<tr>
<td>assertElementNotPresent</td>
<td>//li[@data-relative-url='portal_categories/divergence_scope/quantity']</td>
<td></td>
</tr>
<tr>
<td>assertValue</td>
<td>//input[@name='field_my_foo_category_title']</td>
<td>Quantity</td>
</tr>
<tal:block metal:use-macro="here/Zuite_CommonTemplateForRenderjsUi/macros/save" />
<tr>
<td>assertValue</td>
<td>//input[@name='field_my_foo_category_title']</td>
<td>Quantity</td>
</tr>
</tbody></table>
</body>
</html>
\ No newline at end of file
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment