From af8bfa8c4bf0b43a61770021c30132d01a66b58e Mon Sep 17 00:00:00 2001 From: Johannes Raggam Date: Wed, 11 Nov 2020 18:29:03 +0100 Subject: [PATCH 1/5] pat autofocus: Modernize code. --- src/pat/autofocus/autofocus.js | 37 +++++++--------------- src/pat/autofocus/autofocus.test.js | 30 ++++++++++++++++++ src/pat/autofocus/index.html | 49 +++++++++++------------------ 3 files changed, 61 insertions(+), 55 deletions(-) create mode 100644 src/pat/autofocus/autofocus.test.js diff --git a/src/pat/autofocus/autofocus.js b/src/pat/autofocus/autofocus.js index e36582e10..86d4e8c94 100644 --- a/src/pat/autofocus/autofocus.js +++ b/src/pat/autofocus/autofocus.js @@ -1,34 +1,21 @@ -/** - * Patterns autofocus - enhanced autofocus form elements - * - * Copyright 2012-2013 Simplon B.V. - Wichert Akkerman - */ import $ from "jquery"; -import registry from "../../core/registry"; +import Base from "../../core/base"; -var autofocus = { +export default Base.extend({ name: "autofocus", trigger: ":input.pat-autofocus,:input[autofocus]", - init: function init() { + init() { this.setFocus(this.trigger); - $(document).on("patterns-injected", function (e) { - autofocus.setFocus($(e.target).find(autofocus.trigger)); - }); - $(document).on("pat-update", function (e) { - autofocus.setFocus($(e.target).find(autofocus.trigger)); + $(document).on("patterns-injected pat-update", (e) => { + this.setFocus($(e.target).find(this.trigger)); }); }, - setFocus: function (target) { - var $all = $(target); - var $visible = $all.filter(function () { - if ($(this).is(":visible")) return true; - }); - setTimeout(function () { - $visible.get(0) && $visible.get(0).focus(); - }, 10); + setFocus(target) { + const $all = $(target); + const $visible = $all.filter((idx, it) => $(it).is(":visible")); + if ($visible[0]) { + setTimeout(() => $visible[0].focus(), 10); + } }, -}; - -registry.register(autofocus); -export default autofocus; +}); diff --git a/src/pat/autofocus/autofocus.test.js b/src/pat/autofocus/autofocus.test.js new file mode 100644 index 000000000..e5567443a --- /dev/null +++ b/src/pat/autofocus/autofocus.test.js @@ -0,0 +1,30 @@ +import pattern from "./autofocus"; +import utils from "../../core/utils"; + +describe("pat-autofocus", function () { + beforeEach(function () { + const el = document.createElement("div"); + el.setAttribute("id", "lab"); + document.body.append(el); + }); + + afterEach(function () { + document.body.innerHTML = ""; + }); + + it("Focus the first element.", async (done) => { + const container = document.querySelector("#lab"); + container.innerHTML = ` + + + + `; + pattern.init(container); + await utils.timeout(20); + + const should_be_active = document.querySelector("input[name=i1]"); + expect(document.activeElement).toBe(should_be_active); + + done(); + }); +}); diff --git a/src/pat/autofocus/index.html b/src/pat/autofocus/index.html index 75c7f8834..23e768d55 100644 --- a/src/pat/autofocus/index.html +++ b/src/pat/autofocus/index.html @@ -1,33 +1,22 @@ - - - Focus demo page - - - - -
-
-
- -
-
- + + + Focus demo page + + + + +
+
+ +
+ +
+
+ From f12aeca1fe8ac960087006ee9d38e02e8e0059d3 Mon Sep 17 00:00:00 2001 From: Johannes Raggam Date: Wed, 11 Nov 2020 18:52:38 +0100 Subject: [PATCH 2/5] pat autofocus: Implement documented behavior to not focus on prefilled element, if there is another autofocus element which is empty. --- CHANGES.md | 1 + src/pat/autofocus/autofocus.js | 9 ++++++--- src/pat/autofocus/autofocus.test.js | 16 ++++++++++++++++ 3 files changed, 23 insertions(+), 3 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 5f2fa55bf..3519b91a5 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -82,6 +82,7 @@ - pat scroll: Fix scrolling offset incorrectly applied. Fixes: #763. - Core registry: Fix ``transformPattern`` to also work with patterns which extend from Base. Fixes a problem with pat-auto-suggest not auto submitting. +- pat autofocus: Implement documented behavior to not focus on prefilled element, if there is another autofocus element which is empty. ## 3.0.0-dev - unreleased diff --git a/src/pat/autofocus/autofocus.js b/src/pat/autofocus/autofocus.js index 86d4e8c94..cbd057c31 100644 --- a/src/pat/autofocus/autofocus.js +++ b/src/pat/autofocus/autofocus.js @@ -11,11 +11,14 @@ export default Base.extend({ this.setFocus($(e.target).find(this.trigger)); }); }, + setFocus(target) { const $all = $(target); - const $visible = $all.filter((idx, it) => $(it).is(":visible")); - if ($visible[0]) { - setTimeout(() => $visible[0].focus(), 10); + const visible = [...$all].filter((it) => $(it).is(":visible")); + const empty = visible.filter((it) => it.value === ""); + const el = empty[0] || visible[0]; + if (el) { + setTimeout(() => el.focus(), 10); } }, }); diff --git a/src/pat/autofocus/autofocus.test.js b/src/pat/autofocus/autofocus.test.js index e5567443a..8a510c441 100644 --- a/src/pat/autofocus/autofocus.test.js +++ b/src/pat/autofocus/autofocus.test.js @@ -27,4 +27,20 @@ describe("pat-autofocus", function () { done(); }); + + it("Focus the non-empty element, if available.", async (done) => { + const container = document.querySelector("#lab"); + container.innerHTML = ` + + + + `; + pattern.init(container); + await utils.timeout(20); + + const should_be_active = document.querySelector("input[name=i2]"); + expect(document.activeElement).toBe(should_be_active); + + done(); + }); }); From e28836af1291198db0e55e44ebbd0ce56dc9521c Mon Sep 17 00:00:00 2001 From: Johannes Raggam Date: Wed, 11 Nov 2020 19:16:01 +0100 Subject: [PATCH 3/5] pat autofocus: Do not autofocus in iframes. Fixes: #761. --- CHANGES.md | 1 + src/pat/autofocus/autofocus.js | 5 +++++ src/pat/autofocus/index-iframed.html | 21 +++++++++++++++++++++ src/pat/autofocus/index.html | 2 ++ 4 files changed, 29 insertions(+) create mode 100644 src/pat/autofocus/index-iframed.html diff --git a/CHANGES.md b/CHANGES.md index 3519b91a5..53ae2b828 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -48,6 +48,7 @@ - pat date picker: Support updating a date if it is before another dependent date. - pat tabs: Refactor based on ``ResizeObserver`` and fix problems calculating the with with transitions. - pat tabs: When clicking on the ``extra-tabs`` element, toggle between ``open`` and ``closed`` classes to allow opening/closing an extra-tabs menu via CSS. +- pat autofocus: Do not autofocus in iframes. Fixes: #761. ### Technical diff --git a/src/pat/autofocus/autofocus.js b/src/pat/autofocus/autofocus.js index cbd057c31..aa996505b 100644 --- a/src/pat/autofocus/autofocus.js +++ b/src/pat/autofocus/autofocus.js @@ -6,6 +6,11 @@ export default Base.extend({ trigger: ":input.pat-autofocus,:input[autofocus]", init() { + if (window.self !== window.top) { + // Do not autofocus in iframes. + return; + } + this.setFocus(this.trigger); $(document).on("patterns-injected pat-update", (e) => { this.setFocus($(e.target).find(this.trigger)); diff --git a/src/pat/autofocus/index-iframed.html b/src/pat/autofocus/index-iframed.html new file mode 100644 index 000000000..0ac54c538 --- /dev/null +++ b/src/pat/autofocus/index-iframed.html @@ -0,0 +1,21 @@ + + + + + Focus demo page + + + + + +
+ +
+ + diff --git a/src/pat/autofocus/index.html b/src/pat/autofocus/index.html index 23e768d55..6346fe645 100644 --- a/src/pat/autofocus/index.html +++ b/src/pat/autofocus/index.html @@ -18,5 +18,7 @@ +

Elements in the iframe below should not get the focus.

+ From 7db14ea787675f90fde9b848e967019c55a3f861 Mon Sep 17 00:00:00 2001 From: Johannes Raggam Date: Wed, 11 Nov 2020 19:34:27 +0100 Subject: [PATCH 4/5] pat autofocus: Instead of calling autofocus for each element call it only once. --- CHANGES.md | 1 + src/pat/autofocus/autofocus.js | 11 ++++++++++- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/CHANGES.md b/CHANGES.md index 53ae2b828..5631d8628 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -84,6 +84,7 @@ - Core registry: Fix ``transformPattern`` to also work with patterns which extend from Base. Fixes a problem with pat-auto-suggest not auto submitting. - pat autofocus: Implement documented behavior to not focus on prefilled element, if there is another autofocus element which is empty. +- pat autofocus: Instead of calling autofocus for each element call it only once. ## 3.0.0-dev - unreleased diff --git a/src/pat/autofocus/autofocus.js b/src/pat/autofocus/autofocus.js index aa996505b..0e4870c28 100644 --- a/src/pat/autofocus/autofocus.js +++ b/src/pat/autofocus/autofocus.js @@ -1,6 +1,8 @@ import $ from "jquery"; import Base from "../../core/base"; +let scheduled_task = null; + export default Base.extend({ name: "autofocus", trigger: ":input.pat-autofocus,:input[autofocus]", @@ -18,12 +20,19 @@ export default Base.extend({ }, setFocus(target) { + // Exit if task is scheduled. setFocus operates on whole DOM anyways. + if (scheduled_task) { + return; + } const $all = $(target); const visible = [...$all].filter((it) => $(it).is(":visible")); const empty = visible.filter((it) => it.value === ""); const el = empty[0] || visible[0]; if (el) { - setTimeout(() => el.focus(), 10); + scheduled_task = setTimeout(() => { + el.focus(); + scheduled_task = null; + }, 10); } }, }); From eb8564e619f865b31c3311a56e660d4e44d90aa8 Mon Sep 17 00:00:00 2001 From: Johannes Raggam Date: Wed, 11 Nov 2020 19:47:25 +0100 Subject: [PATCH 5/5] pat autofocus: Register event handler only once. --- CHANGES.md | 1 + src/pat/autofocus/autofocus.js | 12 +++++++++--- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 5631d8628..a96b598c0 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -85,6 +85,7 @@ Fixes a problem with pat-auto-suggest not auto submitting. - pat autofocus: Implement documented behavior to not focus on prefilled element, if there is another autofocus element which is empty. - pat autofocus: Instead of calling autofocus for each element call it only once. +- pat autofocus: Register event handler only once. ## 3.0.0-dev - unreleased diff --git a/src/pat/autofocus/autofocus.js b/src/pat/autofocus/autofocus.js index 0e4870c28..a82a6118d 100644 --- a/src/pat/autofocus/autofocus.js +++ b/src/pat/autofocus/autofocus.js @@ -2,6 +2,7 @@ import $ from "jquery"; import Base from "../../core/base"; let scheduled_task = null; +let registered_event_handler = false; export default Base.extend({ name: "autofocus", @@ -14,9 +15,14 @@ export default Base.extend({ } this.setFocus(this.trigger); - $(document).on("patterns-injected pat-update", (e) => { - this.setFocus($(e.target).find(this.trigger)); - }); + + if (!registered_event_handler) { + // Register the event handler only once. + $(document).on("patterns-injected pat-update", (e) => { + this.setFocus($(e.target).find(this.trigger)); + }); + registered_event_handler = true; + } }, setFocus(target) {