157 lines
5.2 KiB
JavaScript
157 lines
5.2 KiB
JavaScript
((document, Joomla) => {
|
|
|
|
if (!Joomla) {
|
|
throw new Error('Joomla API is not properly initialised');
|
|
}
|
|
|
|
/* global hotkeys */
|
|
Joomla.addShortcut = (hotkey, callback) => {
|
|
hotkeys(hotkey, 'joomla', event => {
|
|
event.preventDefault();
|
|
event.stopPropagation();
|
|
event.stopImmediatePropagation();
|
|
callback.call();
|
|
});
|
|
};
|
|
Joomla.addClickShortcut = (hotkey, selector) => {
|
|
Joomla.addShortcut(hotkey, () => {
|
|
const element = document.querySelector(selector);
|
|
if (element) {
|
|
element.click();
|
|
}
|
|
});
|
|
};
|
|
Joomla.addFocusShortcut = (hotkey, selector) => {
|
|
Joomla.addShortcut(hotkey, () => {
|
|
const element = document.querySelector(selector);
|
|
if (element) {
|
|
element.focus();
|
|
}
|
|
});
|
|
};
|
|
Joomla.addLinkShortcut = (hotkey, selector) => {
|
|
Joomla.addShortcut(hotkey, () => {
|
|
window.location.href = selector;
|
|
});
|
|
};
|
|
const setShortcutFilter = () => {
|
|
hotkeys.filter = event => {
|
|
const target = event.target || event.srcElement;
|
|
const {
|
|
tagName
|
|
} = target;
|
|
|
|
// Checkboxes should not block a shortcut event
|
|
if (target.type === 'checkbox') {
|
|
return true;
|
|
}
|
|
// Default hotkeys filter behavior
|
|
return !(target.isContentEditable || tagName === 'INPUT' || tagName === 'SELECT' || tagName === 'TEXTAREA');
|
|
};
|
|
};
|
|
const startupShortcuts = () => {
|
|
hotkeys('J', event => {
|
|
// If we're already in the scope, it's a normal shortkey
|
|
if (hotkeys.getScope() === 'joomla') {
|
|
return;
|
|
}
|
|
event.preventDefault();
|
|
event.stopPropagation();
|
|
event.stopImmediatePropagation();
|
|
hotkeys.setScope('joomla');
|
|
|
|
// Leave the scope after x milliseconds
|
|
setTimeout(() => {
|
|
hotkeys.setScope(false);
|
|
}, Joomla.getOptions('plg_system_shortcut.timeout', 2000));
|
|
});
|
|
};
|
|
const addOverviewHint = () => {
|
|
const mainContainer = document.querySelector('.com_cpanel .container-main');
|
|
if (mainContainer) {
|
|
const containerElement = document.createElement('section');
|
|
containerElement.className = 'content pt-4';
|
|
containerElement.insertAdjacentHTML('beforeend', Joomla.Text._('PLG_SYSTEM_SHORTCUT_OVERVIEW_HINT'));
|
|
mainContainer.appendChild(containerElement);
|
|
}
|
|
};
|
|
const initOverviewModal = options => {
|
|
const dlItems = new Map();
|
|
Object.values(options).forEach(value => {
|
|
if (!value.shortcut || !value.title) {
|
|
return;
|
|
}
|
|
let titles = [];
|
|
if (dlItems.has(value.shortcut)) {
|
|
titles = dlItems.get(value.shortcut);
|
|
titles.push(value.title);
|
|
} else {
|
|
titles = [value.title];
|
|
}
|
|
dlItems.set(value.shortcut, titles);
|
|
});
|
|
let dl = '<dl>';
|
|
dlItems.forEach((titles, shortcut) => {
|
|
dl += '<div>';
|
|
dl += '<dt class="d-inline-block"><kbd>J</kbd>';
|
|
shortcut.split('+').forEach(key => {
|
|
dl += ` ${Joomla.Text._('PLG_SYSTEM_SHORTCUT_THEN')} <kbd>${key.trim()}</kbd>`;
|
|
});
|
|
dl += '</dt>';
|
|
titles.forEach(title => {
|
|
dl += `<dd class="d-inline-block ms-1">${title}</dd>`;
|
|
});
|
|
dl += '</div>';
|
|
});
|
|
dl += '</dl>';
|
|
const modal = `
|
|
<div class="modal fade" id="shortcutOverviewModal" tabindex="-1" role="dialog" data-bs-backdrop="static" aria-labelledby="shortcutOverviewModalLabel" aria-hidden="true">
|
|
<div class="modal-dialog" role="document">
|
|
<div class="modal-content">
|
|
<div class="modal-header">
|
|
<h3 id="shortcutOverviewModalLabel" class="modal-title">
|
|
${Joomla.Text._('PLG_SYSTEM_SHORTCUT_OVERVIEW_TITLE')}
|
|
</h3>
|
|
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="${Joomla.Text._('JCLOSE')}"></button>
|
|
</div>
|
|
<div class="modal-body p-3">
|
|
<p>${Joomla.Text._('PLG_SYSTEM_SHORTCUT_OVERVIEW_DESC')}</p>
|
|
<div class="mb-3">
|
|
${dl}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
`;
|
|
document.body.insertAdjacentHTML('beforeend', modal);
|
|
const bootstrapModal = new bootstrap.Modal(document.getElementById('shortcutOverviewModal'), {
|
|
keyboard: true,
|
|
backdrop: true
|
|
});
|
|
hotkeys('X', 'joomla', () => bootstrapModal.show());
|
|
};
|
|
document.addEventListener('DOMContentLoaded', () => {
|
|
const options = Joomla.getOptions('plg_system_shortcut.shortcuts');
|
|
Object.values(options).forEach(value => {
|
|
if (!value.shortcut || !value.selector) {
|
|
return;
|
|
}
|
|
if (value.selector.startsWith('/') || value.selector.startsWith('http://') || value.selector.startsWith('www.')) {
|
|
Joomla.addLinkShortcut(value.shortcut, value.selector);
|
|
} else if (value.selector.includes('input')) {
|
|
Joomla.addFocusShortcut(value.shortcut, value.selector);
|
|
} else {
|
|
Joomla.addClickShortcut(value.shortcut, value.selector);
|
|
}
|
|
});
|
|
// Show hint and overview on logged in backend only (not login page)
|
|
if (document.querySelector('nav')) {
|
|
initOverviewModal(options);
|
|
addOverviewHint();
|
|
}
|
|
setShortcutFilter();
|
|
startupShortcuts();
|
|
});
|
|
})(document, Joomla);
|