mirror of
https://github.com/nottinghamtec/PyRIGS.git
synced 2026-10-12 15:45:29 +00:00
158 lines
5.7 KiB
JavaScript
158 lines
5.7 KiB
JavaScript
// Select widgets, built on Tom Select.
|
|
// * <select class="ts-select" data-sourceurl="..."> loads its options remotely as the user types
|
|
// * <select class="ts-select"> without a source URL is a plain (optionally multiple) select
|
|
|
|
var clearSelectionLabel = '(no selection)';
|
|
|
|
function changeSelectedValue(select, pk, text, update_url) { // Pass in the <select> and the new option's parameters
|
|
var ts = select.tomselect;
|
|
if (!ts) {
|
|
return;
|
|
}
|
|
ts.clear(true);
|
|
ts.clearOptions();
|
|
ts.addOption({value: pk, text: text, update_url: update_url || ''});
|
|
ts.setValue(pk, true);
|
|
select.dispatchEvent(new Event('change', {bubbles: true})); // Trigger the change function manually
|
|
}
|
|
|
|
function selectedUpdateUrl(select) {
|
|
var ts = select.tomselect;
|
|
var value = ts.getValue();
|
|
if (!value) {
|
|
return '';
|
|
}
|
|
var option = ts.options[value];
|
|
if (option && option.update_url !== undefined) {
|
|
return option.update_url;
|
|
}
|
|
var domOption = select.querySelector('option[value="' + CSS.escape(value) + '"]');
|
|
return domOption && domOption.dataset.update_url ? domOption.dataset.update_url : null;
|
|
}
|
|
|
|
function refreshUpdateHref(select) {
|
|
var target = document.getElementById(select.id + '-update');
|
|
if (!target) {
|
|
return;
|
|
}
|
|
var update_url = selectedUpdateUrl(select);
|
|
|
|
if (update_url === '') { // Nothing is selected
|
|
target.removeAttribute('href');
|
|
target.classList.add('disabled');
|
|
} else if (update_url !== null) {
|
|
target.setAttribute('href', update_url);
|
|
target.classList.remove('disabled');
|
|
}
|
|
}
|
|
|
|
function initPicker(select) {
|
|
var noClear = 'noclear' in select.dataset;
|
|
var multiple = select.multiple;
|
|
var url = select.dataset.sourceurl;
|
|
// input_autogrow keeps the search box on the same line as the selected value (otherwise it wraps and doubles the height)
|
|
var plugins = ['input_autogrow'];
|
|
if (multiple) {
|
|
plugins.push('remove_button');
|
|
} else if (!noClear) {
|
|
plugins.push('clear_button');
|
|
}
|
|
|
|
var settings = {
|
|
plugins: plugins,
|
|
valueField: 'value',
|
|
labelField: 'text',
|
|
searchField: ['text'],
|
|
allowEmptyOption: false,
|
|
placeholder: select.dataset.noneSelectedText || '',
|
|
maxOptions: null,
|
|
hideSelected: false,
|
|
closeAfterSelect: !multiple
|
|
};
|
|
|
|
if (url) {
|
|
// The server does the searching. Tom Select keeps every option it has ever loaded, so remember which
|
|
// ones the server returned for each query and only show those (otherwise results for "a" and "al"
|
|
// linger in the dropdown when searching for "ali hassan").
|
|
var results = {};
|
|
var normalise = function (query) { return query.trim().toLowerCase(); };
|
|
|
|
Object.assign(settings, {
|
|
score: function (query) {
|
|
var ids = results[normalise(query)];
|
|
return function (option) { return ids && ids.has(String(option.value)) ? 1 : 0; };
|
|
},
|
|
shouldLoad: function (query) { return query.length > 0; },
|
|
load: function (query, callback) {
|
|
var separator = url.indexOf('?') === -1 ? '?' : '&';
|
|
fetch(url + separator + 'q=' + encodeURIComponent(query), {credentials: 'same-origin'})
|
|
.then(function (response) { return response.json(); })
|
|
.then(function (data) {
|
|
var options = data.map(function (item) {
|
|
return {value: item.pk, text: item.text, update_url: item.update};
|
|
});
|
|
results[normalise(query)] = new Set(options.map(function (option) { return String(option.value); }));
|
|
callback(options);
|
|
})
|
|
.catch(function () { callback(); });
|
|
}
|
|
});
|
|
}
|
|
|
|
var update_urls = {};
|
|
select.querySelectorAll('option[data-update_url]').forEach(function (option) {
|
|
update_urls[option.value] = option.dataset.update_url;
|
|
});
|
|
|
|
var ts = new TomSelect(select, settings);
|
|
if (url) {
|
|
// Emptying the search box shouldn't list everything loaded so far (selected options are kept)
|
|
ts.on('type', function (query) {
|
|
if (query === '') {
|
|
ts.clearOptions();
|
|
}
|
|
});
|
|
}
|
|
Object.keys(update_urls).forEach(function (value) {
|
|
if (ts.options[value]) {
|
|
ts.options[value].update_url = update_urls[value];
|
|
}
|
|
});
|
|
|
|
if (select.id && document.getElementById(select.id + '-update')) {
|
|
select.addEventListener('change', function () { // on change, update the edit button href
|
|
refreshUpdateHref(select);
|
|
});
|
|
refreshUpdateHref(select); // Ensure href is correct at the beginning
|
|
}
|
|
}
|
|
|
|
function initSelects(root) {
|
|
if (typeof TomSelect === 'undefined') {
|
|
return;
|
|
}
|
|
(root || document).querySelectorAll('select.ts-select').forEach(function (select) {
|
|
if (!select.tomselect) {
|
|
initPicker(select);
|
|
}
|
|
});
|
|
}
|
|
|
|
ready(function () {
|
|
initSelects();
|
|
|
|
//When update/edit modal box submitted
|
|
var modal = document.getElementById('modal');
|
|
if (modal) {
|
|
modal.addEventListener('hide.bs.modal', function () {
|
|
if (typeof modaltarget !== 'undefined' && modaltarget && typeof modalobject !== 'undefined' && modalobject !== "") {
|
|
//Update the selector with new values
|
|
var select = document.querySelector(modaltarget);
|
|
if (select) {
|
|
changeSelectedValue(select, modalobject[0]['pk'], modalobject[0]['fields']['name'], modalobject[0]['update_url']);
|
|
}
|
|
}
|
|
});
|
|
}
|
|
});
|