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

View File

@ -1487,6 +1487,34 @@ export class Form
src.innerHTML = jsOMS.htmlspecialchars_encode(value); src.innerHTML = jsOMS.htmlspecialchars_encode(value);
break; 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: default:
src.value = jsOMS.htmlspecialchars_decode(value); src.value = jsOMS.htmlspecialchars_decode(value);
} }
@ -1495,6 +1523,8 @@ export class Form
setTextOfElement(src, value) setTextOfElement(src, value)
{ {
switch (src.tagName.toLowerCase()) { switch (src.tagName.toLowerCase()) {
case 'select':
break;
case 'div': case 'div':
case 'span': case 'span':
case 'pre': case 'pre':
@ -1505,24 +1535,28 @@ export class Form
case 'h1': case 'h1':
src.innerHTML = jsOMS.htmlspecialchars_encode(value); src.innerHTML = jsOMS.htmlspecialchars_encode(value);
break; break;
case 'textarea':
// textarea only has value data in it's content and nothing else!
break;
default: default:
src.value = jsOMS.htmlspecialchars_decode(value); if (src.value === '') {
src.value = jsOMS.htmlspecialchars_decode(value);
}
} }
}; };
getValueFromDataSource(src) getValueFromDataSource(src)
{ {
if (src.getAttribute('data-value') !== null) {
return src.getAttribute('data-value');
}
switch (src.tagName.toLowerCase()) { switch (src.tagName.toLowerCase()) {
case 'td':
case 'div': case 'div':
case 'span': case 'span':
case 'pre': case 'pre':
case 'article': case 'article':
case 'section': case 'section':
case 'h1': case 'h1':
return src.innerHTML; return src.innerText;
default: default:
return src.value; return src.value;
} }
@ -1531,6 +1565,7 @@ export class Form
getTextFromDataSource(src) getTextFromDataSource(src)
{ {
switch (src.tagName.toLowerCase()) { switch (src.tagName.toLowerCase()) {
case 'td':
case 'div': case 'div':
case 'span': case 'span':
case 'pre': case 'pre':

View File

@ -27,6 +27,10 @@ import { ResponseType } from '../../Message/Response/ResponseType.js';
* Data download * 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. * 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. * 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 export class Table
{ {
@ -151,6 +155,9 @@ export class Table
for (let i = 0; i < length; ++i) { for (let i = 0; i < length; ++i) {
this.bindCheckbox(checkboxes[i], id); 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. * Swaps the row on click.
* *
@ -202,16 +293,14 @@ export class Table
const table = document.getElementById(id), const table = document.getElementById(id),
rows = table.getElementsByTagName('tbody')[0].rows, rows = table.getElementsByTagName('tbody')[0].rows,
rowLength = rows.length, rowLength = rows.length,
rowId = this.closest('tr').rowIndex, rowId = this.closest('tr').rowIndex - 1,
orderType = jsOMS.hasClass(this, 'order-up') ? 1 : -1; orderType = jsOMS.hasClass(this, 'order-up') ? 1 : -1;
if (orderType === 1 && rowId > 1) { if (orderType === 1 && rowId > 0) {
rows[rowId].parentNode.insertBefore(rows[rowId - 2], rows[rowId]); rows[rowId].parentNode.insertBefore(rows[rowId], rows[rowId - 1]);
} else if (orderType === -1 && rowId < rowLength) { } 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; length = !elements ? 0 : elements.length;
for (let i = 0; i < length; ++i) { for (let i = 0; i < length; ++i) {
if (typeof elements[i].getAttribute('id') !== 'undefined' && elements[i].getAttribute('id') !== null) { this.bindElement(elements[i]);
this.bindElement(elements[i].getAttribute('id'));
}
} }
} }
}; };
@ -69,10 +67,9 @@ export class DragNDrop
* *
* @since 1.0.0 * @since 1.0.0
*/ */
bindElement (id) bindElement (element)
{ {
const element = document.getElementById(id), const self = this;
self = this;
if (!element) { if (!element) {
return; return;
@ -87,10 +84,31 @@ export class DragNDrop
}, false); }, false);
element.addEventListener('dragenter', function(e) { element.addEventListener('dragenter', function(e) {
/** const rowIndex = Array.from(this.parentElement.children).indexOf(this);
* @todo Orange-Management/jsOMS#??? [t:feature] [p:low] [d:medium] const dragIndex = Array.from(self.dragging.parentElement.children).indexOf(self.dragging);
* Highlight the drop area
*/ 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); }, false);
element.addEventListener('dragover', function(e) { element.addEventListener('dragover', function(e) {
@ -101,39 +119,25 @@ export class DragNDrop
element.addEventListener('dragleave', function(e) { element.addEventListener('dragleave', function(e) {
e.preventDefault(); e.preventDefault();
/**
* @todo Orange-Management/jsOMS#??? [t:feature] [p:low] [d:medium]
* Stop highlighting the drop area
*/
}, false); }, false);
element.addEventListener('dragend', function(e) { element.addEventListener('dragend', function(e) {
e.preventDefault(); e.preventDefault();
/** const oldPlaceholder = this.parentNode.querySelector('.drag-placeholder');
* @todo Orange-Management/jsOMS#??? [t:feature] [p:low] [d:medium] if (oldPlaceholder === null) {
* Reset all UI states return;
*/ }
this.parentNode.insertBefore(self.dragging, oldPlaceholder);
this.parentNode.removeChild(oldPlaceholder);
self.dragging = null;
}, false); }, false);
element.addEventListener('drop', function(e) { element.addEventListener('drop', function(e) {
e.stopPropagation(); e.stopPropagation();
e.preventDefault(); 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); }, 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 * Get table header elements which provide filter functionality
* *