NOTICE: By continued use of this site you understand and agree to the binding Terms of Service and Privacy Policy.
// ==UserScript==
// @name p4u-activity-dialog
// @description Keyboard shortcuts for P4U Activity dialogs
// @version 1.3.1
// @namespace https://plus4u.net/
// @author bubblefoil
// @license MIT
// @match https://plus4u.net/*
// @run-at document-idle
// @grant GM_addStyle
// ==/UserScript==
(function () {
'use strict';
GM_addStyle(`
.p4u-ext-clickable:hover{
cursor: pointer;
}
`);
/**
* Activates various Task list enhancments.
*/
function enhanceTable() {
//Table header sorting pop-up menu originally displays only on right click, which is counter-intuitive in a browser.
leftClickContextMenu();
//Activate keyboard shorcuts for the highlighted table row.
registerShortcuts();
//Artifact state dialog opens when double-clicking a table row.
registerDoubleClickStateChange();
}
/**
* Activate Artifact Page enhancements, like buttons for flipping pages within an Artifact
*/
function enhanceArtifactPage() {
addListButtons();
}
function leftClickContextMenu() {
const th1 = document.getElementById('listID_headcell_0');
if (!th1) {
return;
}
Array
.from(th1.parentElement.cells)
.slice(1, 5)//drop first and last cols
.forEach(c => {
c.classList.add('p4u-ext-clickable');
c.onclick = function (e) {
c.oncontextmenu(e);
};
});
}
function registerShortcuts() {
window.addEventListener("keydown", ev => {
if (ev.code === 'KeyS') {
console.debug('Trigger Artifact state change');
const row = getHighlightedTableRow();
if (row) {
changeArtifactState(row);
} else {
console.debug('No Artifact is highlighted.')
}
}
});
}
function registerDoubleClickStateChange() {
if (getTableEnvelope()) {
const dbl = (ev) => {
console.log(ev);
changeArtifactState(ev.currentTarget);
}
Array.from(getTableEnvelope().querySelectorAll('tbody > tr'))
.forEach(tr => {
tr.addEventListener("dblclick", dbl);
})
}
}
function addListButtons() {
let selectedPageLi = document.querySelector('#ues-ctrlbar-artMenubar-artObjects-ul li.menuSelected');
let artifactHorizontalMenuUl = document.getElementById('ues-ctrlbar-artMenubar-artObjects-ul');
if (selectedPageLi && artifactHorizontalMenuUl) {
if (selectedPageLi.nextSibling) {
let newChild = listMenuItemToPageLink(selectedPageLi.nextSibling, '>');
artifactHorizontalMenuUl.insertBefore(
newChild,
artifactHorizontalMenuUl.firstChild.nextSibling)
}
if (selectedPageLi.previousSibling) {
artifactHorizontalMenuUl.insertBefore(
listMenuItemToPageLink(selectedPageLi.previousSibling, '<'),
artifactHorizontalMenuUl.firstChild)
}
}
}
function listMenuItemToPageLink(liNode, linkText) {
let linkNode = liNode.cloneNode(true);
let menuTextDiv = linkNode.querySelector('div.menuText');
let pageName = menuTextDiv.innerText;
menuTextDiv.innerText = linkText;
linkNode.title = pageName;
return linkNode;
}
function getTableEnvelope() {
return document.getElementById('listID');
}
/**
* @returns (HTMLTableRowElement) row
*/
function getHighlightedTableRow() {
let listElement = getTableEnvelope();
return listElement && listElement.querySelector('tbody > tr.Actual');
}
/**
* @param row (HTMLTableRowElement) - Table row
*/
function changeArtifactState(row) {
if (row && !!(row.cells)) {
const a = row.cells[5].querySelector('a');
if (a) {
a.click();
} else {
console.error('Cannot trigger Artifact state change. Wrong element: ', row);
}
}
}
const onFrameLoaded = function (iframe) {
if (iframe.id !== 'modal-iframe1') {
console.debug('p4u-activity-dialog:', `No iframe with id "modal-iframe1"`);
return;
}
const btnOk = iframe.contentDocument.getElementById('form-btn-ok');
if (btnOk) {
btnOk.parentElement.title = "Ctrl + Enter";
}
const btnCancel = iframe.contentDocument.getElementById('form-btn-cancel');
if (btnCancel) {
btnCancel.parentElement.title = "Escape";
}
iframe.contentDocument.onkeydown = function (e) {
if (btnOk && e.key === 'Enter' && e.ctrlKey) {
btnOk.parentElement.click();
} else if (btnCancel && e.key === 'Escape') {
btnCancel.parentElement.click();
}
};
const optionsBlock = iframe.contentDocument.getElementById('listbox_FIRST_ListContentTag');
if (optionsBlock) {
setTimeout(function () {
optionsBlock.focus();
}, 10);
}
};
const observer = new MutationObserver(function (mutations) {
mutations.forEach(function (mutation) {
[].filter.call(mutation.addedNodes, function (node) {
return node.nodeName === 'IFRAME' && node.id === 'modal-iframe1';
}).forEach(function (node) {
node.addEventListener('load', function (e) {
console.debug('p4u-activity-dialog:', 'enhancing loaded iframe', node.id);
onFrameLoaded(node);
});
});
});
});
observer.observe(document.body, { childList: true, subtree: true });
enhanceTable();
enhanceArtifactPage();
})();