You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@myfaces.apache.org by lo...@apache.org on 2019/06/13 13:55:54 UTC
[myfaces-tobago] branch master updated: TOBAGO-1633: TS
refactoring: focus
This is an automated email from the ASF dual-hosted git repository.
lofwyr pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/myfaces-tobago.git
The following commit(s) were added to refs/heads/master by this push:
new 4342daa TOBAGO-1633: TS refactoring: focus
4342daa is described below
commit 4342daa04d8042ac880403b3412e918558011e79
Author: Udo Schnurpfeil <lo...@apache.org>
AuthorDate: Thu Jun 13 15:55:46 2019 +0200
TOBAGO-1633: TS refactoring: focus
---
.../src/main/npm/package.json | 2 +-
.../src/main/npm/ts/tobago-all.ts | 1 +
.../src/main/npm/ts/tobago-core.ts | 70 -------------
.../src/main/npm/ts/tobago-focus.ts | 109 +++++++++++++++++++++
.../src/main/npm/ts/tobago-in.ts | 3 +-
.../src/main/resources/META-INF/tobago-config.xml | 1 +
6 files changed, 113 insertions(+), 73 deletions(-)
diff --git a/tobago-theme/tobago-theme-standard/src/main/npm/package.json b/tobago-theme/tobago-theme-standard/src/main/npm/package.json
index 8376704..2c8f1ba 100644
--- a/tobago-theme/tobago-theme-standard/src/main/npm/package.json
+++ b/tobago-theme/tobago-theme-standard/src/main/npm/package.json
@@ -24,7 +24,7 @@
"css-prefix": "postcss --config postcss.config.js --replace \"css/*.css\" \"!css/*.min.css\"",
"css-minify": "cleancss --level 1 --source-map --source-map-inline-sources --output css/tobago.min.css css/tobago.css",
"ts-compile": "tsc",
- "js-minify": "uglifyjs --compress typeofs=false,drop_console=true --mangle --source-map includeSources --output js/tobago.min.js js/tobago-myfaces.js js/tobago-deltaspike.js js/tobago-polyfill.js js/tobago-listener.js js/tobago-core.js js/tobago-dropdown.js js/tobago-calendar.js js/tobago-command.js js/tobago-file.js js/tobago-header-footer.js js/tobago-in.js js/tobago-jsf.js js/tobago-overlay.js js/tobago-panel.js js/tobago-popover.js js/tobago-popup.js js/tobago-reload.js js/tobago [...]
+ "js-minify": "uglifyjs --compress typeofs=false,drop_console=true --mangle --source-map includeSources --output js/tobago.min.js js/tobago-myfaces.js js/tobago-deltaspike.js js/tobago-polyfill.js js/tobago-listener.js js/tobago-core.js js/tobago-dropdown.js js/tobago-calendar.js js/tobago-command.js js/tobago-file.js js/tobago-focus.js js/tobago-header-footer.js js/tobago-in.js js/tobago-jsf.js js/tobago-overlay.js js/tobago-panel.js js/tobago-popover.js js/tobago-popup.js js/tobago- [...]
"test": "jest"
},
"devDependencies": {
diff --git a/tobago-theme/tobago-theme-standard/src/main/npm/ts/tobago-all.ts b/tobago-theme/tobago-theme-standard/src/main/npm/ts/tobago-all.ts
index 9b231be..f8fda21 100644
--- a/tobago-theme/tobago-theme-standard/src/main/npm/ts/tobago-all.ts
+++ b/tobago-theme/tobago-theme-standard/src/main/npm/ts/tobago-all.ts
@@ -21,6 +21,7 @@ import "./tobago-dropdown";
import "./tobago-calendar";
import "./tobago-command";
import "./tobago-file";
+import "./tobago-focus";
import "./tobago-header-footer";
import "./tobago-in";
import "./tobago-jsf";
diff --git a/tobago-theme/tobago-theme-standard/src/main/npm/ts/tobago-core.ts b/tobago-theme/tobago-theme-standard/src/main/npm/ts/tobago-core.ts
index eabca9f..3e0428c 100644
--- a/tobago-theme/tobago-theme-standard/src/main/npm/ts/tobago-core.ts
+++ b/tobago-theme/tobago-theme-standard/src/main/npm/ts/tobago-core.ts
@@ -226,9 +226,6 @@ export class Tobago4 {
static initDom = function (elements) {
elements = elements.jQuery ? elements : jQuery(elements); // fixme jQuery -> ES5
- // focus
- Tobago4.initFocus(elements);
-
Tobago4.initScrollPosition(elements ? elements : jQuery(".tobago-page"));
};
@@ -259,73 +256,6 @@ export class Tobago4 {
});
};
-// -------- Util functions ----------------------------------------------------
-
- /**
- * Sets the focus to the requested element or to the first possible if
- * no element is explicitly requested.
- *
- * The priority order is:
- * - error (the first error element gets the focus)
- * - auto (the element with the tobago tag attribute focus="true" gets the focus)
- * - last (the element from the last request with same id gets the focus, not AJAX)
- * - first (the first input element (without tabindex=-1) gets the focus, not AJAX)
- */
- static initFocus = function (elements) {
-
- var $focusable = jQuery(":input:enabled:visible:not(button):not([tabindex='-1'])");
- $focusable.focus(function () {
- // remember the last focused element, for later
- Tobago4.findSubElementOfPage("lastFocusId").val(jQuery(this).attr("id"));
- });
-
- var $hasDanger = Tobago4Utils.selectWithJQuery(elements, '.has-danger');
- var $dangerInput = $hasDanger.find("*").filter(":input:enabled:visible:first");
- if ($dangerInput.length > 0) {
- Tobago4.setFocus($dangerInput);
- return;
- }
-
- var $autoFocus = Tobago4Utils.selectWithJQuery(elements, '[autofocus]');
- var hasAutoFocus = $autoFocus.length > 0;
- if (hasAutoFocus) {
- // nothing to do, because the browser make the work.
-
- // autofocus in popups doesn't work automatically... so we fix that here
- jQuery('.modal').on('shown.bs.modal', function () {
- Tobago4.setFocus(jQuery(this).find('[autofocus]'));
- });
-
- return;
- }
-
- if (elements) {
- // seems to be AJAX, so end here
- return;
- }
-
- var lastFocusId = Tobago4.findSubElementOfPage("lastFocusId").get(0).getAttribute("value");
- if (lastFocusId) {
- Tobago4.setFocus(jQuery(DomUtils.escapeClientId(lastFocusId)));
- return;
- }
-
- var $firstInput = jQuery(":input:enabled:visible:not(button):not([tabindex='-1']):first");
- if ($firstInput.length > 0) {
- Tobago4.setFocus($firstInput);
- return;
- }
- };
-
- static setFocus = function ($element) {
- try {
- // focus() on not visible elements breaks some IE
- $element.focus();
- } catch (e) {
- console.error("element-id=" + $element.attr("id") + " exception=" + e);
- }
- };
-
static toString = function (element) {
var result = '';
for (var property in element) {
diff --git a/tobago-theme/tobago-theme-standard/src/main/npm/ts/tobago-focus.ts b/tobago-theme/tobago-theme-standard/src/main/npm/ts/tobago-focus.ts
new file mode 100644
index 0000000..0fb3f87
--- /dev/null
+++ b/tobago-theme/tobago-theme-standard/src/main/npm/ts/tobago-focus.ts
@@ -0,0 +1,109 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import {Tobago4} from "./tobago-core";
+import {DomUtils} from "./tobago-utils";
+import {Listener, Phase} from "./tobago-listener";
+
+export class Focus {
+
+ private static getHidden(): HTMLInputElement {
+ return <HTMLInputElement>document.getElementById(DomUtils.page().id + Tobago4.SUB_COMPONENT_SEP + "lastFocusId");
+ }
+
+ static setLastFocusId(id: string): void {
+ this.getHidden().value = id;
+ }
+
+ static getLastFocusId(): string {
+ return this.getHidden().value;
+ }
+
+ /**
+ * Sets the focus to the requested element or to the first possible if
+ * no element is explicitly requested.
+ *
+ * The priority order is:
+ * - error (the first error element gets the focus)
+ * - auto (the element with the tobago tag attribute focus="true" gets the focus)
+ * - last (the element from the last request with same id gets the focus, not AJAX)
+ * - first (the first input element (without tabindex=-1) gets the focus, not AJAX)
+ */
+ static init = function (element: HTMLElement) {
+
+ const activeInputs = Focus.activeInputs(element);
+
+ for (const focusable of activeInputs) {
+ focusable.addEventListener("focus", function (event: FocusEvent) {
+ const target = <HTMLElement>event.target;
+ if (target.style.visibility !== "hidden" && target.style.display != "none") {
+ // remember the last focused element, for later
+ Focus.setLastFocusId(target.id);
+ }
+ });
+ }
+
+ for (const hasDanger of DomUtils.selfOrElementsByClassName(element, ".has-danger")) {
+ const activeInputsInsideDanger = Focus.activeInputs(hasDanger);
+ if (activeInputsInsideDanger.length > 0) {
+ activeInputsInsideDanger[0].focus();
+ return;
+ }
+ }
+
+ const autoFocus = element.querySelector("[autofocus]");
+ if (autoFocus) {
+ // nothing to do, because the browser make the work.
+
+ // autofocus in popups doesn't work automatically... so we fix that here
+ jQuery('.modal').on('shown.bs.modal', function () {
+ jQuery(this).find('[autofocus]').get(0).focus();
+ });
+
+ return;
+ }
+
+ if (element.parentElement) {
+ // seems to be AJAX, so end here
+ return;
+ }
+
+ const lastFocusId = Focus.getLastFocusId();
+ if (lastFocusId) {
+ document.getElementById(lastFocusId).focus();
+ return;
+ }
+
+ if (activeInputs.length > 0) {
+ activeInputs[0].focus();
+ return;
+ }
+ };
+
+ private static activeInputs(element: HTMLElement) {
+ return DomUtils.selfOrQuerySelectorAll(element,
+ "input:not([type='hidden']):not([disabled]):not([tabindex='-1'])," +
+ "select:not([disabled]):not([tabindex='-1'])," +
+ "textarea:not([disabled]):not([tabindex='-1'])")
+ .filter((element) =>
+ element.style.visibility !== "hidden"
+ && element.style.display != "none");
+ }
+}
+
+Listener.register(Focus.init, Phase.DOCUMENT_READY);
+Listener.register(Focus.init, Phase.AFTER_UPDATE);
diff --git a/tobago-theme/tobago-theme-standard/src/main/npm/ts/tobago-in.ts b/tobago-theme/tobago-theme-standard/src/main/npm/ts/tobago-in.ts
index 75f75ff..bade8dc 100644
--- a/tobago-theme/tobago-theme-standard/src/main/npm/ts/tobago-in.ts
+++ b/tobago-theme/tobago-theme-standard/src/main/npm/ts/tobago-in.ts
@@ -15,11 +15,10 @@
* limitations under the License.
*/
-// XXX regexp example only - blueprint
-
import {Listener, Phase} from "./tobago-listener";
import {DomUtils} from "./tobago-utils";
+// XXX regexp example only - blueprint
class RegExpTest {
private readonly element: HTMLInputElement;
diff --git a/tobago-theme/tobago-theme-standard/src/main/resources/META-INF/tobago-config.xml b/tobago-theme/tobago-theme-standard/src/main/resources/META-INF/tobago-config.xml
index 2cb11e7..313ee3f 100644
--- a/tobago-theme/tobago-theme-standard/src/main/resources/META-INF/tobago-config.xml
+++ b/tobago-theme/tobago-theme-standard/src/main/resources/META-INF/tobago-config.xml
@@ -73,6 +73,7 @@
<script name="/tobago/standard/tobago-bootstrap/${project.version}/js/tobago-calendar.js"/>
<script name="/tobago/standard/tobago-bootstrap/${project.version}/js/tobago-command.js"/>
<script name="/tobago/standard/tobago-bootstrap/${project.version}/js/tobago-file.js"/>
+ <script name="/tobago/standard/tobago-bootstrap/${project.version}/js/tobago-focus.js"/>
<script name="/tobago/standard/tobago-bootstrap/${project.version}/js/tobago-header-footer.js"/>
<script name="/tobago/standard/tobago-bootstrap/${project.version}/js/tobago-in.js"/>
<script name="/tobago/standard/tobago-bootstrap/${project.version}/js/tobago-jsf.js"/>