primo commit
This commit is contained in:
194
media/plg_system_shortcut/js/shortcut.js
Normal file
194
media/plg_system_shortcut/js/shortcut.js
Normal file
@ -0,0 +1,194 @@
|
||||
import JoomlaDialog from 'joomla.dialog';
|
||||
|
||||
/**
|
||||
* @copyright (C) 2022 Open Source Matters, Inc. <https://www.joomla.org>
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*/
|
||||
if (!window.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;
|
||||
}
|
||||
|
||||
// Ignore TinyMCE joomlaHighlighter plugin,
|
||||
// @TODO: remove this when the joomlaHighlighter plugin will use JoomlaDialog
|
||||
if (target.classList.contains('tox-textarea-wrap') && target.closest('.joomla-highlighter-dialog')) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// 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);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Helper to create an element
|
||||
* @param {String} nodeName
|
||||
* @param {String} text
|
||||
* @param {Array} classList
|
||||
* @returns {HTMLElement}
|
||||
*/
|
||||
const createEl = (nodeName, text = '', classList = []) => {
|
||||
const el = document.createElement(nodeName);
|
||||
el.textContent = text;
|
||||
if (classList && classList.length) {
|
||||
el.classList.add(...classList);
|
||||
}
|
||||
return el;
|
||||
};
|
||||
let overviewDialog;
|
||||
const initOverviewModal = options => {
|
||||
if (overviewDialog) {
|
||||
return overviewDialog;
|
||||
}
|
||||
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);
|
||||
});
|
||||
|
||||
// Render:
|
||||
// <dl>
|
||||
// <div><dt><kbd>J</kbd><span>then</span><kbd>...</kbd><dd>....</dd></div>
|
||||
// <div><dt><kbd>J</kbd><span>then</span><kbd>...</kbd><dd>....</dd></div>
|
||||
// ...
|
||||
// </dl>
|
||||
const dl = createEl('dl');
|
||||
dlItems.forEach((titles, shortcut) => {
|
||||
const row = createEl('div');
|
||||
const dt = createEl('dt', '', ['d-inline-block']);
|
||||
row.appendChild(dt);
|
||||
dt.appendChild(createEl('kbd', 'J'));
|
||||
shortcut.split('+').forEach(key => {
|
||||
dt.appendChild(createEl('span', Joomla.Text._('PLG_SYSTEM_SHORTCUT_THEN'), ['px-1']));
|
||||
dt.appendChild(createEl('kbd', key));
|
||||
});
|
||||
titles.forEach(title => {
|
||||
const dd = createEl('dd', '', ['d-inline-block', 'ps-1']);
|
||||
dd.innerHTML = Joomla.sanitizeHtml(title);
|
||||
row.appendChild(dd);
|
||||
});
|
||||
dl.appendChild(row);
|
||||
});
|
||||
|
||||
// Create the content for the dialog
|
||||
const intro = createEl('p');
|
||||
intro.innerHTML = Joomla.sanitizeHtml(Joomla.Text._('PLG_SYSTEM_SHORTCUT_OVERVIEW_DESC'), {
|
||||
kbd: '*'
|
||||
});
|
||||
const info = createEl('div');
|
||||
info.appendChild(dl);
|
||||
const content = createEl('div', '', ['p-3']);
|
||||
content.appendChild(intro);
|
||||
content.appendChild(info);
|
||||
overviewDialog = new JoomlaDialog({
|
||||
textHeader: Joomla.Text._('PLG_SYSTEM_SHORTCUT_OVERVIEW_TITLE'),
|
||||
textClose: Joomla.Text._('JCLOSE'),
|
||||
popupContent: content,
|
||||
width: '600px',
|
||||
height: 'fit-content'
|
||||
});
|
||||
return overviewDialog;
|
||||
};
|
||||
const showOverviewModal = options => {
|
||||
initOverviewModal(options).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')) {
|
||||
hotkeys('X', 'joomla', () => {
|
||||
showOverviewModal(options);
|
||||
});
|
||||
addOverviewHint();
|
||||
}
|
||||
setShortcutFilter();
|
||||
startupShortcuts();
|
||||
});
|
||||
Reference in New Issue
Block a user