Skip to content

Commit cfff221

Browse files
committed
feat(pat select2): Upgrade to Select2 4.0.x
1 parent 2139d1e commit cfff221

File tree

1 file changed

+97
-123
lines changed

1 file changed

+97
-123
lines changed

src/pat/select2/select2.js

Lines changed: 97 additions & 123 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import $ from "jquery";
22
import Base from "@patternslib/patternslib/src/core/base";
33
import I18n from "../../core/i18n";
44
import utils from "../../core/utils";
5+
import _t from "../../core/i18n-wrapper";
56

67
export default Base.extend({
78
name: "select2",
@@ -14,56 +15,57 @@ export default Base.extend({
1415

1516
initializeValues() {
1617
// Init Selection ---------------------------------------------
17-
if (this.options.initialValues) {
18-
this.options.id = (term) => {
19-
return term.id;
20-
};
21-
this.options.initSelection = ($el, callback) => {
22-
const data = [];
23-
const value = $el.val();
24-
let seldefaults = this.options.initialValues;
25-
26-
// Create the initSelection value that contains the default selection,
27-
// but in a javascript object
28-
if (
29-
typeof this.options.initialValues === "string" &&
30-
this.options.initialValues !== ""
31-
) {
32-
// if default selection value starts with a '{', then treat the value as
33-
// a JSON object that needs to be parsed
34-
if (this.options.initialValues[0] === "{") {
35-
seldefaults = JSON.parse(this.options.initialValues);
36-
}
37-
// otherwise, treat the value as a list, separated by the defaults.separator value of
38-
// strings in the format "id:text", and convert it to an object
39-
else {
40-
seldefaults = {};
41-
const initial_values = $(
42-
this.options.initialValues.split(this.options.separator)
43-
);
44-
for (const it of initial_values) {
45-
const selection = it.split(":");
46-
const id = selection[0].trim();
47-
const text = selection[1].trim();
48-
seldefaults[id] = text;
49-
}
18+
if (!this.options.initialValues) {
19+
return;
20+
}
21+
this.options.id = (term) => {
22+
return term.id;
23+
};
24+
this.options.initSelection = ($el, callback) => {
25+
console.log("init selection");
26+
const data = [];
27+
const value = $el.val();
28+
let seldefaults = this.options.initialValues;
29+
// Create the initSelection value that contains the default selection,
30+
// but in a javascript object
31+
if (
32+
typeof this.options.initialValues === "string" &&
33+
this.options.initialValues !== ""
34+
) {
35+
// if default selection value starts with a '{', then treat the value as
36+
// a JSON object that needs to be parsed
37+
if (this.options.initialValues[0] === "{") {
38+
seldefaults = JSON.parse(this.options.initialValues);
39+
}
40+
// otherwise, treat the value as a list, separated by the defaults.separator value of
41+
// strings in the format "id:text", and convert it to an object
42+
else {
43+
seldefaults = {};
44+
const initial_values = $(
45+
this.options.initialValues.split(this.options.separator)
46+
);
47+
for (const it of initial_values) {
48+
const selection = it.split(":");
49+
const id = selection[0].trim();
50+
const text = selection[1].trim();
51+
seldefaults[id] = text;
5052
}
5153
}
54+
}
5255

53-
const items = $(value.split(this.options.separator));
54-
for (const it of items) {
55-
let text = it;
56-
if (seldefaults[it]) {
57-
text = seldefaults[it];
58-
}
59-
data.push({
60-
id: utils.removeHTML(it),
61-
text: utils.removeHTML(text),
62-
});
56+
const items = $(value.split(this.options.separator));
57+
for (const it of items) {
58+
let text = it;
59+
if (seldefaults[it]) {
60+
text = seldefaults[it];
6361
}
64-
callback(data);
65-
};
66-
}
62+
data.push({
63+
id: utils.removeHTML(it),
64+
text: utils.removeHTML(text),
65+
});
66+
}
67+
callback(data);
68+
};
6769
},
6870

6971
initializeTags() {
@@ -99,14 +101,14 @@ export default Base.extend({
99101
onEnd: () => this.$el.select2("onSortEnd"),
100102
});
101103
};
102-
this.$el.on("change", _initializeOrdering.bind(this));
104+
this.$el.on("change.select2", _initializeOrdering.bind(this));
103105
_initializeOrdering();
104106
},
105107

106108
async initializeSelect2() {
107-
import("select2/select2.css");
109+
import("select2/dist/css/select2.min.css");
108110
import("./select2.scss");
109-
await import("select2");
111+
await import("select2/dist/js/select2.full");
110112
try {
111113
// Don't load "en" which is the default where no separate language file exists.
112114
if (this.options.language && this.options.language !== "en" && !this.options.language.startsWith("en")) {
@@ -128,6 +130,10 @@ export default Base.extend({
128130
}
129131
};
130132

133+
if (this.options.allowClear & !this.options.placeholder) {
134+
this.options.placeholder = _t("choose");
135+
}
136+
131137
function callback(action, e) {
132138
if (action) {
133139
if (this.options.debug) {
@@ -142,13 +148,14 @@ export default Base.extend({
142148
}
143149
}
144150

151+
console.log(this.options);
145152
this.$el.select2(this.options);
146-
this.$el.on("select2-selected", (e) => callback(this.options.onSelected, e));
147-
this.$el.on("select2-selecting", (e) => callback(this.options.onSelecting, e));
148-
this.$el.on("select2-deselecting", (e) =>
153+
this.$el.on("select2:select", (e) => callback(this.options.onSelected, e));
154+
this.$el.on("select2:selecting", (e) => callback(this.options.onSelecting, e));
155+
this.$el.on("select2:unselecting", (e) =>
149156
callback(this.options.onDeselecting, e)
150157
);
151-
this.$el.on("select2-deselected", (e) => callback(this.options.onDeselected, e));
158+
this.$el.on("select2:unselect", (e) => callback(this.options.onDeselected, e));
152159
this.$select2 = this.$el.parent().find(".select2-container");
153160
this.$el.parent().off("close.plone-modal.patterns");
154161
if (this.options.orderable) {
@@ -184,88 +191,55 @@ export default Base.extend({
184191
this.options.multiple === undefined ? true : this.options.multiple;
185192
this.options.ajax = this.options.ajax || {};
186193
this.options.ajax.url = this.options.vocabularyUrl;
187-
// XXX removing the following function does'nt break tests. dead code?
188-
this.options.initSelection = ($el, callback) => {
189-
const data = [];
190-
const value = $el.val();
191-
for (const val of value.split(this.options.separator)) {
192-
const _val = utils.removeHTML(val);
193-
data.push({ id: _val, text: _val });
194-
}
195-
callback(data);
196-
};
197194
}
198195

199196
let queryTerm = "";
200197

201198
const ajaxTimeout = parseInt(this.options.ajaxTimeout || 300, 10);
202199
delete this.options.ajaxTimeout;
203-
this.options.ajax = $.extend(
204-
{
205-
quietMillis: ajaxTimeout,
206-
data: (term, page) => {
207-
queryTerm = term;
208-
return {
209-
query: term,
210-
page_limit: 10,
211-
page: page,
212-
};
213-
},
214-
results: (data) => {
215-
let results = data.results;
216-
if (this.options.vocabularyUrl) {
217-
const dataIds = [];
218-
for (const it of data.results) {
219-
dataIds.push(it.id);
220-
}
221-
results = [];
222-
223-
const haveResult =
224-
queryTerm === "" || dataIds.includes(queryTerm);
225-
if (this.options.allowNewItems && !haveResult) {
226-
queryTerm = utils.removeHTML(queryTerm);
227-
results.push({
228-
id: queryTerm,
229-
text: queryTerm,
230-
});
231-
}
200+
this.options.ajax = {
201+
quietMillis: ajaxTimeout,
202+
data: (term, page) => {
203+
queryTerm = term;
204+
return {
205+
query: term,
206+
page_limit: 10,
207+
page: page,
208+
};
209+
},
210+
results: (data) => {
211+
let results = data.results;
212+
if (this.options.vocabularyUrl) {
213+
const dataIds = [];
214+
for (const it of data.results) {
215+
dataIds.push(it.id);
216+
}
217+
results = [];
218+
219+
const haveResult =
220+
queryTerm === "" || dataIds.includes(queryTerm);
221+
if (this.options.allowNewItems && !haveResult) {
222+
queryTerm = utils.removeHTML(queryTerm);
223+
results.push({
224+
id: queryTerm,
225+
text: queryTerm,
226+
});
227+
}
232228

233-
for (const it of data.results) {
234-
results.push(it);
235-
}
229+
for (const it of data.results) {
230+
results.push(it);
236231
}
237-
return { results: results };
238-
},
232+
}
233+
return { results: results };
239234
},
240-
this.options.ajax
241-
);
242-
} else if (this.options.multiple && this.$el.is("select")) {
243-
// Multiselects are converted to input[type=hidden] for Select2
244-
// TODO: This should actually not be necessary.
245-
// This is kept for backwards compatibility but should be
246-
// re-checked and removed if possible.
247-
this.$el.attr("multiple", true);
248-
const vals = this.$el.val() || [];
249-
const options = [...this.el.querySelectorAll("option")].map((it) => {
250-
return { text: it.innerHTML, id: it.value };
251-
});
252-
253-
const el = document.createElement("input");
254-
el.type = "hidden";
255-
el.value = vals.join(this.options.separator);
256-
el.className = this.el.getAttribute("class");
257-
el.name = this.el.name;
258-
el.id = this.el.id;
259-
this.el.after(el);
260-
this.el.remove();
261-
this.el = el;
262-
this.$el = $(el);
263-
264-
this.options.data = options;
235+
...this.options.ajax
236+
};
265237
}
238+
266239
this.initializeValues();
267240
this.initializeTags();
241+
268242
await this.initializeSelect2();
269-
await this.initializeOrdering();
243+
// await this.initializeOrdering();
270244
},
271245
});

0 commit comments

Comments
 (0)