first commit
This commit is contained in:
166
media/system/js/fields/modal-content-select-field.js
Normal file
166
media/system/js/fields/modal-content-select-field.js
Normal file
@ -0,0 +1,166 @@
|
||||
import JoomlaDialog from 'joomla.dialog';
|
||||
|
||||
/**
|
||||
* @copyright (C) 2023 Open Source Matters, Inc. <https://www.joomla.org>
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*/
|
||||
|
||||
/**
|
||||
* Helper method to set values on the fields, and trigger "change" event
|
||||
*
|
||||
* @param {object} data
|
||||
* @param {HTMLInputElement} inputValue
|
||||
* @param {HTMLInputElement} inputTitle
|
||||
*/
|
||||
const setValues = (data, inputValue, inputTitle) => {
|
||||
const value = `${data.id || data.value || ''}`;
|
||||
const isChanged = inputValue.value !== value;
|
||||
inputValue.value = value;
|
||||
if (inputTitle) {
|
||||
inputTitle.value = data.title || inputValue.value;
|
||||
}
|
||||
if (isChanged) {
|
||||
inputValue.dispatchEvent(new CustomEvent('change', {
|
||||
bubbles: true,
|
||||
cancelable: true
|
||||
}));
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Show Select dialog
|
||||
*
|
||||
* @param {HTMLInputElement} inputValue
|
||||
* @param {HTMLInputElement} inputTitle
|
||||
* @param {Object} dialogConfig
|
||||
* @returns {Promise}
|
||||
*/
|
||||
const doSelect = (inputValue, inputTitle, dialogConfig) => {
|
||||
// Use a JoomlaExpectingPostMessage flag to be able to distinct legacy methods
|
||||
// @TODO: This should be removed after full transition to postMessage()
|
||||
window.JoomlaExpectingPostMessage = true;
|
||||
// Create and show the dialog
|
||||
const dialog = new JoomlaDialog(dialogConfig);
|
||||
dialog.classList.add('joomla-dialog-content-select-field');
|
||||
dialog.show();
|
||||
return new Promise(resolve => {
|
||||
const msgListener = event => {
|
||||
// Avoid cross origins
|
||||
if (event.origin !== window.location.origin) return;
|
||||
// Check message type
|
||||
if (event.data.messageType === 'joomla:content-select') {
|
||||
setValues(event.data, inputValue, inputTitle);
|
||||
dialog.close();
|
||||
} else if (event.data.messageType === 'joomla:cancel') {
|
||||
dialog.close();
|
||||
}
|
||||
};
|
||||
|
||||
// Clear all when dialog is closed
|
||||
dialog.addEventListener('joomla-dialog:close', () => {
|
||||
delete window.JoomlaExpectingPostMessage;
|
||||
window.removeEventListener('message', msgListener);
|
||||
dialog.destroy();
|
||||
resolve();
|
||||
});
|
||||
|
||||
// Wait for message
|
||||
window.addEventListener('message', msgListener);
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Update view, depending if value is selected or not
|
||||
*
|
||||
* @param {HTMLInputElement} inputValue
|
||||
* @param {HTMLElement} container
|
||||
*/
|
||||
const updateView = (inputValue, container) => {
|
||||
const hasValue = !!inputValue.value;
|
||||
container.querySelectorAll('[data-show-when-value]').forEach(el => {
|
||||
if (el.dataset.showWhenValue) {
|
||||
// eslint-disable-next-line no-unused-expressions
|
||||
hasValue ? el.removeAttribute('hidden') : el.setAttribute('hidden', '');
|
||||
} else {
|
||||
// eslint-disable-next-line no-unused-expressions
|
||||
hasValue ? el.setAttribute('hidden', '') : el.removeAttribute('hidden');
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Initialise the field
|
||||
* @param {HTMLElement} container
|
||||
*/
|
||||
const setupField = container => {
|
||||
const inputValue = container ? container.querySelector('.js-input-value') : null;
|
||||
const inputTitle = container ? container.querySelector('.js-input-title') : null;
|
||||
if (!container || !inputValue) {
|
||||
throw new Error('Incomplete markup of Content dialog field');
|
||||
}
|
||||
container.addEventListener('change', () => {
|
||||
updateView(inputValue, container);
|
||||
});
|
||||
|
||||
// Bind the buttons
|
||||
container.addEventListener('click', event => {
|
||||
const button = event.target.closest('[data-button-action]');
|
||||
if (!button) return;
|
||||
event.preventDefault();
|
||||
|
||||
// Extract the data
|
||||
const action = button.dataset.buttonAction;
|
||||
const dialogConfig = button.dataset.modalConfig ? JSON.parse(button.dataset.modalConfig) : {};
|
||||
|
||||
// Handle requested action
|
||||
let handle;
|
||||
switch (action) {
|
||||
case 'select':
|
||||
case 'create':
|
||||
handle = doSelect(inputValue, inputTitle, dialogConfig);
|
||||
break;
|
||||
case 'edit':
|
||||
{
|
||||
// Update current value in the URL
|
||||
const url = dialogConfig.src.indexOf('http') === 0 ? new URL(dialogConfig.src) : new URL(dialogConfig.src, window.location.origin);
|
||||
url.searchParams.set('id', inputValue.value);
|
||||
dialogConfig.src = url.toString();
|
||||
handle = doSelect(inputValue, inputTitle, dialogConfig);
|
||||
break;
|
||||
}
|
||||
case 'clear':
|
||||
handle = (async () => setValues({
|
||||
id: '',
|
||||
title: ''
|
||||
}, inputValue, inputTitle))();
|
||||
break;
|
||||
default:
|
||||
throw new Error(`Unknown action ${action} for Modal select field`);
|
||||
}
|
||||
handle.then(() => {
|
||||
// Perform checkin when needed
|
||||
if (button.dataset.checkinUrl) {
|
||||
const chckUrl = button.dataset.checkinUrl;
|
||||
const url = chckUrl.indexOf('http') === 0 ? new URL(chckUrl) : new URL(chckUrl, window.location.origin);
|
||||
// Add value to request
|
||||
url.searchParams.set('id', inputValue.value);
|
||||
url.searchParams.set('cid[]', inputValue.value);
|
||||
// Also add value to POST, because Controller may expect it from there
|
||||
const data = new FormData();
|
||||
data.append('id', inputValue.value);
|
||||
data.append('cid[]', inputValue.value);
|
||||
Joomla.request({
|
||||
url: url.toString(),
|
||||
method: 'POST',
|
||||
promise: true,
|
||||
data
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
};
|
||||
const setup = container => {
|
||||
container.querySelectorAll('.js-modal-content-select-field').forEach(el => setupField(el));
|
||||
};
|
||||
document.addEventListener('DOMContentLoaded', () => setup(document));
|
||||
document.addEventListener('joomla:updated', event => setup(event.target));
|
||||
Reference in New Issue
Block a user