Skip to content

Commit

Permalink
Merge pull request #1184 from Patternslib/fix-auto-submit
Browse files Browse the repository at this point in the history
Various pat-autosubmit fixes and improvements.
  • Loading branch information
thet authored Oct 22, 2023
2 parents c56dbc2 + 90b1fbc commit 993e8d8
Show file tree
Hide file tree
Showing 5 changed files with 110 additions and 30 deletions.
15 changes: 15 additions & 0 deletions src/core/events.js
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,20 @@ const await_pattern_init = (pattern) => {
* Event factories
*/

/** Generic event factory.
*
* A event factory for a bubbling and cancelable generic event.
*
* @param {string} name - The event name.
* @returns {Event} - Returns a blur event.
*/
const generic_event = (name) => {
return new Event(name, {
bubbles: true,
cancelable: true,
});
};

const blur_event = () => {
return new Event("blur", {
bubbles: false,
Expand Down Expand Up @@ -249,6 +263,7 @@ export default {
remove_event_listener: remove_event_listener,
await_event: await_event,
await_pattern_init: await_pattern_init,
generic_event: generic_event,
blur_event: blur_event,
click_event: click_event,
change_event: change_event,
Expand Down
10 changes: 10 additions & 0 deletions src/core/events.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -457,6 +457,16 @@ describe("core.events tests", () => {
inner = el.querySelector("#inner");
});

it("generic event", async () => {
const name = "fantasy_event";
outer.addEventListener(name, () => {
catched = "outer";
});
inner.dispatchEvent(events.generic_event(name));
await utils.timeout(1);
expect(catched).toBe("outer");
});

it("blur event", async () => {
outer.addEventListener("blur", () => {
catched = "outer";
Expand Down
36 changes: 22 additions & 14 deletions src/pat/auto-submit/auto-submit.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,10 @@ export default Base.extend({
},

registerListeners() {
this.$el.on(
"input-change-delayed.pat-autosubmit",
events.add_event_listener(
this.el,
"input-change-delayed",
"pat-autosubmit--input-change-delayed",
this.onInputChange.bind(this)
);
this.registerSubformListeners();
Expand All @@ -44,7 +46,7 @@ export default Base.extend({
data?.pattern === "sortable"
) {
// Directly submit when removing a clone or changing the sorting.
this.$el.submit();
this.el.dispatchEvent(events.submit_event());
log.debug(
`triggered by pat-update, pattern: ${data.pattern}, action: ${data.action}`
);
Expand All @@ -60,15 +62,21 @@ export default Base.extend({
* that only the subform gets submitted if an element inside it
* changes.
*/
const $el = typeof ev !== "undefined" ? $(ev.target) : this.$el;
$el.find(".pat-subform")
.not(".pat-autosubmit")
.each((idx, el) => {
$(el).on(
"input-change-delayed.pat-autosubmit",
this.onInputChange.bind(this)
);
});
const el = typeof ev !== "undefined" ? ev.target : this.el;

// get all subforms whice are not yet auto submit forms.
const subforms = el.querySelectorAll(
".pat-autosubmit:not(.pat-autosubmit):not(.pat-auto-submit)"
);
for (const subform of subforms) {
// register autosubmit on subform
events.add_event_listener(
subform,
"input-change-delayed",
"pat-autosubmit--input-change-delayed",
this.onInputChange.bind(this)
);
}
},

refreshListeners(ev, cfg, el, injected) {
Expand All @@ -87,10 +95,10 @@ export default Base.extend({
}

function trigger_event(ev) {
if ($(ev.target).closest(".pat-autosubmit")[0] !== this) {
if (ev.target.closest(".pat-autosubmit") !== this) {
return;
}
$(ev.target).trigger("input-change-delayed");
ev.target.dispatchEvent(events.generic_event("input-change-delayed"));
}
if (this.options.delay === "defocus") {
this.$el.on("input-defocus.pat-autosubmit", trigger_event);
Expand Down
59 changes: 53 additions & 6 deletions src/pat/auto-submit/auto-submit.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -134,10 +134,17 @@ describe("pat-autosubmit", function () {
</form>
`;
const el = document.querySelector(".pat-autosubmit");
const instance = new Pattern(el);
const spy = jest.spyOn(instance.$el, "submit");

let submit_dispatched = false;
el.addEventListener("submit", () => {
submit_dispatched = true;
});

new Pattern(el);

$(el).trigger("pat-update", { pattern: "clone", action: "removed" });
expect(spy).toHaveBeenCalled();

expect(submit_dispatched).toBe(true);
});

it("2.4 - when pat-sortable changes the sorting", function () {
Expand All @@ -146,10 +153,50 @@ describe("pat-autosubmit", function () {
</form>
`;
const el = document.querySelector(".pat-autosubmit");
const instance = new Pattern(el);
const spy = jest.spyOn(instance.$el, "submit");

let submit_dispatched = false;
el.addEventListener("submit", () => {
submit_dispatched = true;
});

new Pattern(el);

$(el).trigger("pat-update", { pattern: "sortable" });
expect(spy).toHaveBeenCalled();

expect(submit_dispatched).toBe(true);
});

it("2.5 - when a change on a single input happens with delay option", async function () {
document.body.innerHTML = `
<form>
<input
class="pat-autosubmit"
type="text"
name="q"
data-pat-autosubmit="delay: 20"
/>
</form>
`;
const input = document.querySelector(".pat-autosubmit");
new Pattern(input);
let submit_input_dispatched = false;
let submit_form_dispatched = false;
input.addEventListener("submit", () => {
submit_input_dispatched = true;
});
document.querySelector("form").addEventListener("submit", () => {
submit_form_dispatched = true;
});
input.dispatchEvent(events.input_event());
await utils.timeout(1);
expect(submit_input_dispatched).toBe(false);
expect(submit_form_dispatched).toBe(false);
await utils.timeout(9);
expect(submit_input_dispatched).toBe(false);
expect(submit_form_dispatched).toBe(false);
await utils.timeout(10);
expect(submit_input_dispatched).toBe(true);
expect(submit_form_dispatched).toBe(true);
});
});

Expand Down
20 changes: 10 additions & 10 deletions src/pat/auto-submit/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -110,19 +110,19 @@ <h2>pat-autosubmit on form with default options</h2>
</label>
</fieldset>

<fieldset class="group">
<fieldset
class="group pat-sortable pat-clone"
data-pat-clone="template: #clone-item-template; trigger-element: #add-clone-item"
data-pat-sortable="selector: .sortable-item"
>
<legend>example with pat-clone and pat-sortable</legend>

<ul class="pat-sortable pat-clone"
data-pat-clone="template: #clone-item-template; trigger-element: #add-clone-item"
data-pat-sortable="selector: .sortable-item">

<li class="sortable-item" id="clone-item-template" hidden>
<button type="button" id="add-clone-item">Add clone item</button>
<template id="clone-item-template">
<label class="sortable-item">
<input type="text" name="pat-clone-example"/>
<button type="button" class="remove-clone">x</button>
</li>
</ul>
<button type="button" id="add-clone-item">Add clone item</button>
</label>
</template>
</fieldset>

</fieldset>
Expand Down

0 comments on commit 993e8d8

Please sign in to comment.