Skip to content

Commit 8f4e353

Browse files
authored
Merge pull request #1003 from Patternslib/fix-auto-suggest
Fix auto suggest
2 parents 2d10732 + 4c39332 commit 8f4e353

File tree

6 files changed

+124
-12
lines changed

6 files changed

+124
-12
lines changed

src/core/events.js

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,20 @@ const input_event = () => {
118118
});
119119
};
120120

121+
const mousedown_event = () => {
122+
return new Event("mousedown", {
123+
bubbles: true,
124+
cancelable: true,
125+
});
126+
};
127+
128+
const mouseup_event = () => {
129+
return new Event("mouseup", {
130+
bubbles: true,
131+
cancelable: true,
132+
});
133+
};
134+
121135
const scroll_event = () => {
122136
return new Event("scroll", {
123137
bubbles: true,
@@ -140,6 +154,8 @@ export default {
140154
click_event: click_event,
141155
change_event: change_event,
142156
input_event: input_event,
157+
mousedown_event: mousedown_event,
158+
mouseup_event: mouseup_event,
143159
scroll_event: scroll_event,
144160
submit_event: submit_event,
145161
};

src/core/events.test.js

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,24 @@ describe("core.events tests", () => {
123123
expect(catched).toBe("outer");
124124
});
125125

126+
it("mousedown event", async () => {
127+
outer.addEventListener("mousedown", () => {
128+
catched = "outer";
129+
});
130+
inner.dispatchEvent(events.mousedown_event());
131+
await utils.timeout(1);
132+
expect(catched).toBe("outer");
133+
});
134+
135+
it("mouseup event", async () => {
136+
outer.addEventListener("mouseup", () => {
137+
catched = "outer";
138+
});
139+
inner.dispatchEvent(events.mouseup_event());
140+
await utils.timeout(1);
141+
expect(catched).toBe("outer");
142+
});
143+
126144
it("scroll event", async () => {
127145
outer.addEventListener("scroll", () => {
128146
catched = "outer";

src/core/parser.js

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ class ArgumentParser {
1616

1717
this.group_pattern = /([a-z][a-z0-9]*)-([A-Z][a-z0-0\-]*)/i;
1818
this.json_param_pattern = /^\s*\[?\s*{/i;
19-
this.named_param_pattern = /^\s*([a-z][a-z0-9\-]*)\s*:(.*)/i;
19+
this.named_param_pattern = /^\s*([a-z][a-z0-9\-]*)\s*:(.*)/is;
2020
this.token_pattern = /((["']).*?(?!\\)\2)|\s*(\S+)\s*/g;
2121
}
2222

@@ -442,7 +442,6 @@ class ArgumentParser {
442442
continue;
443443
}
444444
const _parse = this._parse.bind(this);
445-
446445
if (data.match(/&&/)) {
447446
frame = data.split(/\s*&&\s*/).map(_parse);
448447
} else {

src/core/parser.test.js

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,32 @@ describe("The Patterns parser", function () {
124124
done();
125125
});
126126

127+
it("allows values to span multiple lines", function (done) {
128+
const parser = new ArgumentParser("mypattern");
129+
parser.addArgument("jayson");
130+
parser.addArgument("ob-ject");
131+
const content = document.createElement("div");
132+
content.innerHTML = `
133+
<div data-pat-mypattern='
134+
jayson: [
135+
{"key1": "value 1"},
136+
{"key2": "value 2"}
137+
];
138+
ob-ject: {"key3": "value 3"}
139+
'>
140+
</div>
141+
`;
142+
const opts = parser.parse(content.querySelector("[data-pat-mypattern]"));
143+
const jayson = JSON.parse(opts.jayson);
144+
const ob_ject = JSON.parse(opts.obJect);
145+
expect(jayson.length).toBe(2);
146+
expect(jayson[0].key1).toBe("value 1");
147+
expect(jayson[1].key2).toBe("value 2");
148+
expect(ob_ject.key3).toBe("value 3");
149+
150+
done();
151+
});
152+
127153
it("does a type casting to the default value's type", function (done) {
128154
const parser = new ArgumentParser("mypattern");
129155
parser.addArgument("selector");

src/pat/auto-suggest/auto-suggest.js

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -102,15 +102,11 @@ export default Base.extend({
102102
}
103103
});
104104

105-
this.$el.on("click", () => {
106-
// Work around the situation that a jQuery "change" event,
107-
// submitted by select2, isn't caught by pat-validation.
108-
// Select2 also triggers a click event, which we will use here to
109-
// trigger a standard JS change event.
110-
this.el.dispatchEvent(events.change_event());
111-
// Also dispatch a ``input`` event for ``input-change-events``
112-
// and pat-auto-suggest to pick this up.
113-
// TODO: Revisit after ``input-change-events`` is removed.
105+
this.$el.on("change", () => {
106+
// The jQuery "change" event isn't caught by normal JavaScript
107+
// event listeners, e.g. in pat-validation.
108+
// Let's re-trigger as input-event, so that pat-validation but also
109+
// ``input-change-events`` can pick it up.
114110
this.el.dispatchEvent(events.input_event());
115111
});
116112

src/pat/auto-suggest/auto-suggest.test.js

Lines changed: 58 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import $ from "jquery";
2+
import events from "../../core/events";
23
import pattern from "./auto-suggest";
34
import utils from "../../core/utils";
45
import registry from "../../core/registry";
@@ -95,7 +96,7 @@ describe("pat-autosuggest", function () {
9596
});
9697

9798
describe("2.1 - Selected items", function () {
98-
it("4.1 - can be given custom CSS classes", async function () {
99+
it("2.1 - can be given custom CSS classes", async function () {
99100
testutils.createInputElement({
100101
data: 'words: apple,orange,pear; pre-fill: orange; selection-classes: {"orange": ["fruit", "orange"]}',
101102
});
@@ -180,6 +181,62 @@ describe("pat-autosuggest", function () {
180181
expect(selected[1].textContent.trim()).toBe("orange");
181182
expect(input.value).toBe("apple,orange");
182183
});
184+
185+
it("2.5 - items can be pre-filled with json.", async function () {
186+
// Check if json pre-filled fields do work as expected.
187+
// Version 7.0 introduced a problem where at json pre-filled fields
188+
// no items could be deleted or added.
189+
// Version 7.11 fixes that problem.
190+
191+
document.body.innerHTML = `
192+
<input
193+
type="text"
194+
class="pat-autosuggest"
195+
data-pat-autosuggest='
196+
words-json: [
197+
{"id": "id-apple", "text":"Apple"},
198+
{"id": "id-orange", "text": "Orange"},
199+
{"id": "id-lemon", "text":"Lemon"}
200+
];
201+
prefill-json: {
202+
"id-orange": "Orange"
203+
};
204+
' />
205+
`;
206+
207+
const input = document.querySelector("input");
208+
new pattern(input);
209+
await utils.timeout(1); // wait a tick for async to settle.
210+
211+
let selected = document.querySelectorAll(".select2-search-choice");
212+
expect(selected.length).toBe(1);
213+
expect(selected[0].textContent.trim()).toBe("Orange");
214+
expect(input.value).toBe("id-orange");
215+
216+
// NOTE: the keyboard event init key ``which`` is deprecated,
217+
// but that's what select2 3.5.1 is expecting.
218+
document
219+
.querySelector(".select2-input")
220+
.dispatchEvent(new KeyboardEvent("keydown", { which: 8 }));
221+
// Need to send two times.
222+
document
223+
.querySelector(".select2-input")
224+
.dispatchEvent(new KeyboardEvent("keydown", { which: 8 }));
225+
226+
selected = document.querySelectorAll(".select2-search-choice");
227+
expect(selected.length).toBe(0);
228+
229+
document.querySelector(".select2-input").click();
230+
document.querySelector(".select2-result").dispatchEvent(events.mouseup_event()); // prettier-ignore
231+
document.querySelector(".select2-input").click();
232+
document.querySelector(".select2-result").dispatchEvent(events.mouseup_event()); // prettier-ignore
233+
234+
selected = document.querySelectorAll(".select2-search-choice");
235+
expect(selected.length).toBe(2);
236+
expect(selected[0].textContent.trim()).toBe("Apple");
237+
expect(selected[1].textContent.trim()).toBe("Orange");
238+
expect(input.value).toBe("id-apple,id-orange");
239+
});
183240
});
184241

185242
describe("3 - Placeholder tests", function () {

0 commit comments

Comments
 (0)