Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@
"jquery-form": "4.3.0",
"jquery.browser": "0.1.0",
"js-cookie": "^3.0.5",
"select2": "git+https://github.com/ivaynberg/select2.git#3.5.4",
"select2": "4.0.13",
"sortablejs": "^1.15.6",
"tinymce": "7.9.1",
"tinymce-i18n": "25.6.2",
Expand Down Expand Up @@ -97,7 +97,6 @@
"build": "run-s clean build:webpack build:docs",
"watch:webpack": "NODE_ENV=development webpack --config webpack.config.js --watch",
"watch:webpack:plone": "NODE_ENV=development DEPLOYMENT=plone webpack --config webpack.config.js --watch",
"postinstall": "patch --forward node_modules/select2/select2.js < patches/select2.patch || true",
"collect:externaldocs": "copyup -V node_modules/@patternslib/patternslib/src/pat/**/documentation.md node_modules/@patternslib/pat-*/README.md node_modules/pat-*/README.md docs/external/",
"start:webpack": "NODE_ENV=development webpack serve --config webpack.config.js",
"start:docs": "ELEVENTY_ENV=development npx @11ty/eleventy --serve --port 8001 ",
Expand Down
220 changes: 97 additions & 123 deletions src/pat/select2/select2.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import $ from "jquery";
import Base from "@patternslib/patternslib/src/core/base";
import I18n from "../../core/i18n";
import utils from "../../core/utils";
import _t from "../../core/i18n-wrapper";

export default Base.extend({
name: "select2",
Expand All @@ -14,56 +15,57 @@ export default Base.extend({

initializeValues() {
// Init Selection ---------------------------------------------
if (this.options.initialValues) {
this.options.id = (term) => {
return term.id;
};
this.options.initSelection = ($el, callback) => {
const data = [];
const value = $el.val();
let seldefaults = this.options.initialValues;

// Create the initSelection value that contains the default selection,
// but in a javascript object
if (
typeof this.options.initialValues === "string" &&
this.options.initialValues !== ""
) {
// if default selection value starts with a '{', then treat the value as
// a JSON object that needs to be parsed
if (this.options.initialValues[0] === "{") {
seldefaults = JSON.parse(this.options.initialValues);
}
// otherwise, treat the value as a list, separated by the defaults.separator value of
// strings in the format "id:text", and convert it to an object
else {
seldefaults = {};
const initial_values = $(
this.options.initialValues.split(this.options.separator)
);
for (const it of initial_values) {
const selection = it.split(":");
const id = selection[0].trim();
const text = selection[1].trim();
seldefaults[id] = text;
}
if (!this.options.initialValues) {
return;
}
this.options.id = (term) => {
return term.id;
};
this.options.initSelection = ($el, callback) => {
console.log("init selection");
const data = [];
const value = $el.val();
let seldefaults = this.options.initialValues;
// Create the initSelection value that contains the default selection,
// but in a javascript object
if (
typeof this.options.initialValues === "string" &&
this.options.initialValues !== ""
) {
// if default selection value starts with a '{', then treat the value as
// a JSON object that needs to be parsed
if (this.options.initialValues[0] === "{") {
seldefaults = JSON.parse(this.options.initialValues);
}
// otherwise, treat the value as a list, separated by the defaults.separator value of
// strings in the format "id:text", and convert it to an object
else {
seldefaults = {};
const initial_values = $(
this.options.initialValues.split(this.options.separator)
);
for (const it of initial_values) {
const selection = it.split(":");
const id = selection[0].trim();
const text = selection[1].trim();
seldefaults[id] = text;
}
}
}

const items = $(value.split(this.options.separator));
for (const it of items) {
let text = it;
if (seldefaults[it]) {
text = seldefaults[it];
}
data.push({
id: utils.removeHTML(it),
text: utils.removeHTML(text),
});
const items = $(value.split(this.options.separator));
for (const it of items) {
let text = it;
if (seldefaults[it]) {
text = seldefaults[it];
}
callback(data);
};
}
data.push({
id: utils.removeHTML(it),
text: utils.removeHTML(text),
});
}
callback(data);
};
},

initializeTags() {
Expand Down Expand Up @@ -99,14 +101,14 @@ export default Base.extend({
onEnd: () => this.$el.select2("onSortEnd"),
});
};
this.$el.on("change", _initializeOrdering.bind(this));
this.$el.on("change.select2", _initializeOrdering.bind(this));
_initializeOrdering();
},

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

if (this.options.allowClear & !this.options.placeholder) {
this.options.placeholder = _t("choose");
}

function callback(action, e) {
if (action) {
if (this.options.debug) {
Expand All @@ -142,13 +148,14 @@ export default Base.extend({
}
}

console.log(this.options);
this.$el.select2(this.options);
this.$el.on("select2-selected", (e) => callback(this.options.onSelected, e));
this.$el.on("select2-selecting", (e) => callback(this.options.onSelecting, e));
this.$el.on("select2-deselecting", (e) =>
this.$el.on("select2:select", (e) => callback(this.options.onSelected, e));
this.$el.on("select2:selecting", (e) => callback(this.options.onSelecting, e));
this.$el.on("select2:unselecting", (e) =>
callback(this.options.onDeselecting, e)
);
this.$el.on("select2-deselected", (e) => callback(this.options.onDeselected, e));
this.$el.on("select2:unselect", (e) => callback(this.options.onDeselected, e));
this.$select2 = this.$el.parent().find(".select2-container");
this.$el.parent().off("close.plone-modal.patterns");
if (this.options.orderable) {
Expand Down Expand Up @@ -184,88 +191,55 @@ export default Base.extend({
this.options.multiple === undefined ? true : this.options.multiple;
this.options.ajax = this.options.ajax || {};
this.options.ajax.url = this.options.vocabularyUrl;
// XXX removing the following function does'nt break tests. dead code?
this.options.initSelection = ($el, callback) => {
const data = [];
const value = $el.val();
for (const val of value.split(this.options.separator)) {
const _val = utils.removeHTML(val);
data.push({ id: _val, text: _val });
}
callback(data);
};
}

let queryTerm = "";

const ajaxTimeout = parseInt(this.options.ajaxTimeout || 300, 10);
delete this.options.ajaxTimeout;
this.options.ajax = $.extend(
{
quietMillis: ajaxTimeout,
data: (term, page) => {
queryTerm = term;
return {
query: term,
page_limit: 10,
page: page,
};
},
results: (data) => {
let results = data.results;
if (this.options.vocabularyUrl) {
const dataIds = [];
for (const it of data.results) {
dataIds.push(it.id);
}
results = [];

const haveResult =
queryTerm === "" || dataIds.includes(queryTerm);
if (this.options.allowNewItems && !haveResult) {
queryTerm = utils.removeHTML(queryTerm);
results.push({
id: queryTerm,
text: queryTerm,
});
}
this.options.ajax = {
quietMillis: ajaxTimeout,
data: (term, page) => {
queryTerm = term;
return {
query: term,
page_limit: 10,
page: page,
};
},
results: (data) => {
let results = data.results;
if (this.options.vocabularyUrl) {
const dataIds = [];
for (const it of data.results) {
dataIds.push(it.id);
}
results = [];

const haveResult =
queryTerm === "" || dataIds.includes(queryTerm);
if (this.options.allowNewItems && !haveResult) {
queryTerm = utils.removeHTML(queryTerm);
results.push({
id: queryTerm,
text: queryTerm,
});
}

for (const it of data.results) {
results.push(it);
}
for (const it of data.results) {
results.push(it);
}
return { results: results };
},
}
return { results: results };
},
this.options.ajax
);
} else if (this.options.multiple && this.$el.is("select")) {
// Multiselects are converted to input[type=hidden] for Select2
// TODO: This should actually not be necessary.
// This is kept for backwards compatibility but should be
// re-checked and removed if possible.
this.$el.attr("multiple", true);
const vals = this.$el.val() || [];
const options = [...this.el.querySelectorAll("option")].map((it) => {
return { text: it.innerHTML, id: it.value };
});

const el = document.createElement("input");
el.type = "hidden";
el.value = vals.join(this.options.separator);
el.className = this.el.getAttribute("class");
el.name = this.el.name;
el.id = this.el.id;
this.el.after(el);
this.el.remove();
this.el = el;
this.$el = $(el);

this.options.data = options;
...this.options.ajax
};
}

this.initializeValues();
this.initializeTags();

await this.initializeSelect2();
await this.initializeOrdering();
// await this.initializeOrdering();
},
});
Loading