bug fixes found through the css tests

This commit is contained in:
Dennis Eichhorn 2021-12-19 20:19:10 +01:00
parent 05f4eef3d3
commit c8164a9715
5 changed files with 195 additions and 48 deletions

View File

@ -49,11 +49,11 @@ export class AppNotification
return;
}
let output = document.importNode(tpl.content, true);
const output = document.importNode(tpl.content, true);
output.querySelector('.log-msg').classList.add('log-msg-status-' + msg.status);
output.querySelector('.log-msg-content').innerHTML = msg.message;
output.querySelector('.close').addEventListeenr('click', function() {
this.parent.remove();
output.querySelector('.close').addEventListener('click', function() {
this.parentNode.remove();
});
if (msg.title && msg.title !== '') {
@ -63,6 +63,9 @@ export class AppNotification
}
tpl.parentNode.appendChild(output);
const logs = document.getElementsByClassName('log-msg');
const lastElementAdded = logs[logs.length - 1];
window.navigator.vibrate(msg.vibrate ? 200 : 0);
if (msg.isSticky) {
@ -71,7 +74,9 @@ export class AppNotification
setTimeout(function ()
{
document.getElementsByClassName('log-msg')[0].remove();
if (lastElementAdded !== null && lastElementAdded.parentNode !== null) {
lastElementAdded.parentNode.removeChild(lastElementAdded);
}
}, 3000);
};
};

View File

@ -1487,6 +1487,34 @@ export class Form
src.innerHTML = jsOMS.htmlspecialchars_encode(value);
break;
case 'select':
const optionLength = src.options.length;
for (let i = 0; i < optionLength; ++i) {
if (src.options[i].value === value) {
src.options[i].selected = true;
break;
}
}
break;
case 'input':
if (src.type === 'radio') {
src.checked = false;
if (src.value === value) {
src.checked = true;
}
break;
} else if (src.type === 'checkbox') {
src.checked = false;
const values = value.split(',');
if (values.includes(src.value)) {
src.checked = true;
}
break;
}
default:
src.value = jsOMS.htmlspecialchars_decode(value);
}
@ -1495,6 +1523,8 @@ export class Form
setTextOfElement(src, value)
{
switch (src.tagName.toLowerCase()) {
case 'select':
break;
case 'div':
case 'span':
case 'pre':
@ -1505,24 +1535,28 @@ export class Form
case 'h1':
src.innerHTML = jsOMS.htmlspecialchars_encode(value);
break;
case 'textarea':
// textarea only has value data in it's content and nothing else!
break;
default:
src.value = jsOMS.htmlspecialchars_decode(value);
if (src.value === '') {
src.value = jsOMS.htmlspecialchars_decode(value);
}
}
};
getValueFromDataSource(src)
{
if (src.getAttribute('data-value') !== null) {
return src.getAttribute('data-value');
}
switch (src.tagName.toLowerCase()) {
case 'td':
case 'div':
case 'span':
case 'pre':
case 'article':
case 'section':
case 'h1':
return src.innerHTML;
return src.innerText;
default:
return src.value;
}
@ -1531,6 +1565,7 @@ export class Form
getTextFromDataSource(src)
{
switch (src.tagName.toLowerCase()) {
case 'td':
case 'div':
case 'span':
case 'pre':

View File

@ -27,6 +27,10 @@ import { ResponseType } from '../../Message/Response/ResponseType.js';
* Data download
* There is a small icon in the top right corner of tables which allows (not yet to be honest) to download the data in the table.
* Whether the backend should be queried for this or only the frontend data should be collected (current situation) should depend on if the table has an api endpoint defined.
*
* @todo Allow column drag/drop ordering which is also saved in the front end
*
* @todo Save column visibility filter and apply that filter on page load
*/
export class Table
{
@ -151,6 +155,9 @@ export class Table
for (let i = 0; i < length; ++i) {
this.bindCheckbox(checkboxes[i], id);
}
const header = this.tables[id].getHeader();
this.bindColumnVisibility(header, id);
};
/**
@ -183,6 +190,90 @@ export class Table
});
};
/**
* Bind column visibility
*
* @param {Element} header Header
*
* @return {void}
*
* @since 1.0.0
*/
bindColumnVisibility(header)
{
header.addEventListener('contextmenu', function (event) {
jsOMS.preventAll(event);
if (document.getElementById('table-context-menu') !== null) {
return;
}
const tpl = document.getElementById('table-context-menu-tpl');
if (tpl === null) {
return;
}
const output = document.importNode(tpl.content, true);
tpl.parentNode.appendChild(output);
const menu = document.getElementById('table-context-menu');
const columns = header.querySelectorAll('td');
let length = columns.length;
let baseMenuLine = menu.getElementsByClassName('context-line')[0].cloneNode(true);
for (let i = 0; i < length; ++i) {
if (typeof columns[i].firstChild === 'undefined'
|| typeof columns[i].firstChild.data === 'undefined'
|| columns[i].firstChild.data.trim() === ''
) {
continue;
}
const menuLine = baseMenuLine.cloneNode(true);
const lineId = menuLine.firstElementChild.getAttribute('get') + i;
menuLine.firstElementChild.setAttribute('for', lineId);
menuLine.firstElementChild.firstElementChild.setAttribute('id', lineId);
menuLine.firstElementChild.appendChild(document.createTextNode(columns[i].firstChild.data.trim()));
menu.getElementsByTagName('ul')[0].appendChild(menuLine);
menu.querySelector('ul').lastElementChild.querySelector('input[type="checkbox"]').checked = columns[i].style.display !== 'none';
menu.querySelector('ul').lastElementChild.querySelector('input[type="checkbox"]').addEventListener('change', function () {
const rows = header.parentElement.getElementsByTagName('tr');
const rowLength = rows.length;
for (let j = 0; j < rowLength; ++j) {
const cols = rows[j].getElementsByTagName('td');
cols[i].style.display = cols[i].style.display === 'none' ? '' : 'none';
}
});
}
menu.getElementsByTagName('ul')[0].removeChild(menu.getElementsByClassName('context-line')[0]);
const rect = tpl.parentElement.getBoundingClientRect();
menu.style.top = (event.clientY - rect.top) + "px";
menu.style.left = (event.clientX - rect.left) + "px";
document.addEventListener('click', Table.hideMenuClickHandler);
});
};
static hideMenuClickHandler(event)
{
const menu = document.getElementById('table-context-menu');
const isClickedOutside = !menu.contains(event.target);
if (isClickedOutside) {
menu.parentNode.removeChild(menu);
document.removeEventListener('click', Table.hideMenuClickHandler);
}
};
/**
* Swaps the row on click.
*
@ -202,16 +293,14 @@ export class Table
const table = document.getElementById(id),
rows = table.getElementsByTagName('tbody')[0].rows,
rowLength = rows.length,
rowId = this.closest('tr').rowIndex,
rowId = this.closest('tr').rowIndex - 1,
orderType = jsOMS.hasClass(this, 'order-up') ? 1 : -1;
if (orderType === 1 && rowId > 1) {
rows[rowId].parentNode.insertBefore(rows[rowId - 2], rows[rowId]);
if (orderType === 1 && rowId > 0) {
rows[rowId].parentNode.insertBefore(rows[rowId], rows[rowId - 1]);
} else if (orderType === -1 && rowId < rowLength) {
rows[rowId - 1].parentNode.insertBefore(rows[rowId], rows[rowId - 1]);
rows[rowId].parentNode.insertBefore(rows[rowId], rows[rowId + 2]);
}
// continue implementation
});
};

View File

@ -53,9 +53,7 @@ export class DragNDrop
length = !elements ? 0 : elements.length;
for (let i = 0; i < length; ++i) {
if (typeof elements[i].getAttribute('id') !== 'undefined' && elements[i].getAttribute('id') !== null) {
this.bindElement(elements[i].getAttribute('id'));
}
this.bindElement(elements[i]);
}
}
};
@ -69,10 +67,9 @@ export class DragNDrop
*
* @since 1.0.0
*/
bindElement (id)
bindElement (element)
{
const element = document.getElementById(id),
self = this;
const self = this;
if (!element) {
return;
@ -87,10 +84,31 @@ export class DragNDrop
}, false);
element.addEventListener('dragenter', function(e) {
/**
* @todo Orange-Management/jsOMS#??? [t:feature] [p:low] [d:medium]
* Highlight the drop area
*/
const rowIndex = Array.from(this.parentElement.children).indexOf(this);
const dragIndex = Array.from(self.dragging.parentElement.children).indexOf(self.dragging);
const oldPlaceholder = this.parentNode.querySelector('.drag-placeholder');
if (oldPlaceholder !== null) {
this.parentNode.removeChild(oldPlaceholder);
}
const placeholder = document.createElement(self.dragging.tagName);
if (self.dragging.tagName.toLowerCase() === 'tr') {
const placeholderTd = document.createElement('td');
placeholderTd.setAttribute('colspan', 42);
placeholder.appendChild(placeholderTd);
}
placeholder.setAttribute('draggable', 'true');
jsOMS.addClass(placeholder, 'drag-placeholder');
if (dragIndex < rowIndex) {
this.parentNode.insertBefore(placeholder, this.nextSibling);
} else {
this.parentNode.insertBefore(placeholder, this);
}
}, false);
element.addEventListener('dragover', function(e) {
@ -101,39 +119,25 @@ export class DragNDrop
element.addEventListener('dragleave', function(e) {
e.preventDefault();
/**
* @todo Orange-Management/jsOMS#??? [t:feature] [p:low] [d:medium]
* Stop highlighting the drop area
*/
}, false);
element.addEventListener('dragend', function(e) {
e.preventDefault();
/**
* @todo Orange-Management/jsOMS#??? [t:feature] [p:low] [d:medium]
* Reset all UI states
*/
const oldPlaceholder = this.parentNode.querySelector('.drag-placeholder');
if (oldPlaceholder === null) {
return;
}
this.parentNode.insertBefore(self.dragging, oldPlaceholder);
this.parentNode.removeChild(oldPlaceholder);
self.dragging = null;
}, false);
element.addEventListener('drop', function(e) {
e.stopPropagation();
e.preventDefault();
if (self.dragging === this) {
return;
}
self.dragging.innerHTML = this.innerHTML;
this.innerHTML = e.dataTransfer.getData('text/html');
/**
* @todo Orange-Management/jsOMS#??? [t:feature] [p:low] [d:medium]
* Remove from old destination if UI element and add to new destination
*/
self.dragging = null;
}, false);
}
};

View File

@ -134,6 +134,20 @@ export class TableView
);
};
/**
* Get table header
*
* @return {Array}
*
* @since 1.0.0
*/
getHeader()
{
return document.querySelector(
'#' + this.id + ' thead'
);
};
/**
* Get table header elements which provide filter functionality
*