167 lines
5.4 KiB
JavaScript
167 lines
5.4 KiB
JavaScript
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));
|