File "SpipSelect2.js"
Full path: /home/argothem/www/organecyberpresse/plugins/auto/select2/v2.1.0/javascript/SpipSelect2.js
File size: 6.74 KB
MIME-type: text/x-c++
Charset: utf-8
class SpipSelect2 {
// Helpers
static helpers = {
markMatch: function(text, term) {
const match = text.toUpperCase().indexOf(term.toUpperCase());
const result = document.createElement('span');
if (match < 0) {
result.textContent = text;
return result;
}
const mark = document.createElement('span');
mark.classList.add('select2-rendered__match');
mark.textContent = text.substring(match, match + term.length);
result.insertAdjacentText('afterbegin', text.substring(0, match));
result.appendChild(mark)
result.insertAdjacentText('beforeend', text.substring(match + term.length));
return result;
},
transport: function (params, success, failure) {
// utiliser l’ajax natif de jquery pour pas déclencher onAjaxLoad
// à chaque appel à l’autocomplete ...
const request = (typeof jQuery.spip.intercepted.ajax === "function")
? jQuery.spip.intercepted.ajax(params)
: jQuery.ajax(params);
request.then(success);
request.fail(failure);
return request;
}
};
/**
* Retourne true uniquement au premier chargement de ce node
* @param {node} node
* @returns bool
*/
static started(node) {
if (node.dataset.select2On === "on") {
return true;
}
node.dataset.select2On = "on";
return false;
}
// Appel de Select2, en prenant en compte quelques options en plus
// SpipSelect2.on_select(document.querySelector('select'), {...});
static on_select = function(select, options = {}) {
if (SpipSelect2.started(select)) {
return;
}
// Éviter des onAjaxLoad() sur les hits autocomplete
if (options.ajax?.url || select.dataset['ajax-Url'] || select.dataset['ajaxUrl']) {
options = jQuery.extend(true, {
ajax: {
delay: 250, // can be overriden with data-ajax-delay="..."
transport: SpipSelect2.helpers.transport
}
}, options);
}
// autoriser le html sur les textes retournés
if (!options.templateResult) {
options.templateResult = i => jQuery('<span>' + (i.long_text || i.text) + '</span>');
}
if (!options.templateSelection) {
options.templateSelection = i => jQuery('<span>' + i.text + '</span>');
}
// indiquer qu’on crée un tag, pour différencier sur les événements ces actions
if (!options.createTag) {
options.createTag = params => {
return {
id: params.term,
text: params.term,
tag: true,
};
}
};
// sortAlpha : trier les <option> par ordre alphabétique
if (options.sortAlpha || select.dataset['sortAlpha']) {
options = jQuery.extend(true, {
sorter: data => data.sort((a, b) => a.text.localeCompare(b.text))
}, options);
}
// highlightSearchTerm : souligner les lettres recherchées dans les textes des <option>
// Note: incompatible avec du HTML dans les textes de réponses
if (options.highlightSearchTerm || select.dataset['highlightSearchTerm']) {
options = jQuery.extend(true, options, {
templateResult: item => {
if (item.loading) {
return item.text;
}
const term = document.querySelector('.select2-container--open .select2-search__field[aria-controls]').value;
if (!term || !term.length) {
return item.text;
}
return SpipSelect2.helpers.markMatch(item.text, term);
}
});
}
// déclarer des événements options.events = {'select2:open': function...; }
// notamment utile depuis un la création via un input (où on ne connait pas le select)
if (options.events !== undefined) {
Object.entries(options.events).forEach(([eventKey, callback]) => {
jQuery(select).on(eventKey, callback);
});
}
jQuery(select).select2(options);
};
// Préparation de Select2, sur un input
// On crée un <select> spécifique relié à l’input
// SpipSelect2.on_input(document.querySelector('input.select2'), {...});
static on_input = function (input, options = {}) {
if (SpipSelect2.started(input)) {
return;
}
const reword = input.outerHTML.replace('<input', '<select');
const template = document.createElement('template');
template.innerHTML = reword.trim();
const select = template.content.firstChild;
select.classList.remove('select2'); // ne pas être relancé sur le select sur un ajax
select.removeAttribute('name'); // ne pas le poster
delete select.dataset.select2On;
select.setAttribute('multiple', true);
if (select.hasAttribute('id')) {
select.setAttribute('id', select.getAttribute('id').trim() + ':select2');
}
if (select.hasAttribute('placeholder')) {
select.dataset.placeholder = select.getAttribute('placeholder');
select.removeAttribute('placeholder');
}
if (!select.dataset.separator) {
select.dataset.maximumSelectionLength = 1;
}
select.dataset.tags = true;
select.dataset.onEnterSubmit = true;
if (input.getAttribute('list')) {
const datalist = document.querySelector('#' + input.getAttribute('list'));
if (datalist) {
select.innerHTML = datalist.innerHTML;
}
}
if (input.value) {
let values = [input.value];
if (select.dataset.separator) {
values = input.value.split(select.dataset.separator);
}
values.forEach(value => {
const exists = select.querySelector("option[value='" + CSS.escape(value) + "']");
if (exists) {
exists.setAttribute('selected', true);
} else {
const option = document.createElement('option');
let label = value;
if (input.dataset.optionLabel) {
try {
const labels = JSON.parse(input.dataset.optionLabel);
label = labels[value] || value;
} catch (e) {
console && console.error("Failed to parse data-option-label: " + e);
}
}
option.textContent = label;
option.setAttribute('value', value);
option.setAttribute('selected', true);
select.appendChild(option);
}
});
}
// Pour mettre à jour un input après une modification du select2 correspondant
const update_input = function () {
const data = Array.from(select.selectedOptions).map(option => option.value);
input.value = data.join(select.dataset.separator || "");
input.dispatchEvent(new Event('change'));
};
// on évite de gérer une délégation d’événement sur un node hors DOM
options.events = {
...{'change': update_input},
...(options.events || {})
};
// select.setAttribute('onChange', 'this.spip_select2_update_input();')
input.setAttribute('type', 'hidden');
input.after(select);
SpipSelect2.on_select(select, options);
};
}
// document.querySelector('select').spip_select2()
HTMLElement.prototype.spip_select2 = function (options) {
SpipSelect2.on_select(this, options);
}
;(() => {
// @deprecated 2.0
jQuery.spip.select2 = SpipSelect2.helpers;
// Appel de .spip_select2(), via jQuery
jQuery.fn.spip_select2 = function(options) {
SpipSelect2.on_select(this.get(), options);
};
})();