From 17404863e7e3971f7b4e21d62c939f3f2af62c9b Mon Sep 17 00:00:00 2001 From: David Back Date: Thu, 15 Nov 2018 17:42:51 -0800 Subject: [PATCH 1/3] entity list reordering WIP --- scripts/system/html/css/edit-style.css | 4 ++ scripts/system/html/js/entityList.js | 97 ++++++++++++++++++++------ 2 files changed, 81 insertions(+), 20 deletions(-) diff --git a/scripts/system/html/css/edit-style.css b/scripts/system/html/css/edit-style.css index 3a291bf27b..a00dc4d57c 100644 --- a/scripts/system/html/css/edit-style.css +++ b/scripts/system/html/css/edit-style.css @@ -1383,6 +1383,10 @@ input[type=button]#export { cursor: col-resize; } +#entity-table .dragging { + background-color: #b3ecff; +} + #entity-table td { box-sizing: border-box; } diff --git a/scripts/system/html/js/entityList.js b/scripts/system/html/js/entityList.js index 00c50169a6..6f12dd1e7c 100644 --- a/scripts/system/html/js/entityList.js +++ b/scripts/system/html/js/entityList.js @@ -21,6 +21,8 @@ const MAX_LENGTH_RADIUS = 9; const MINIMUM_COLUMN_WIDTH = 24; const SCROLLBAR_WIDTH = 20; const RESIZER_WIDTH = 10; +const DELTA_X_MOVE_COLUMNS_THRESHOLD = 2; +const DELTA_X_COLUMN_SWAP_POSITION = 5; const COLUMNS = { type: { @@ -177,10 +179,12 @@ let isFilterInView = false; let columns = []; let columnsByID = {}; -let currentResizeEl = null; -let startResizeEvent = null; +let lastResizeEvent = null; let resizeColumnIndex = 0; -let startThClick = null; +let elTargetTh = null; +let targetColumnIndex = 0; +let lastColumnSwapPosition = -1; +let initialThEvent = null; let elEntityTable, elEntityTableHeader, @@ -319,7 +323,7 @@ function loaded() { let thID = "entity-" + columnID; let elTh = document.createElement("th"); elTh.setAttribute("id", thID); - elTh.setAttribute("data-resizable-column-id", thID); + elTh.setAttribute("columnIndex", columnIndex); if (columnData.glyph) { let elGlyph = document.createElement("span"); elGlyph.className = "glyph"; @@ -328,14 +332,10 @@ function loaded() { } else { elTh.innerText = columnData.columnHeader; } - elTh.onmousedown = function() { - startThClick = this; - }; - elTh.onmouseup = function() { - if (startThClick === this) { - setSortColumn(columnID); - } - startThClick = null; + elTh.onmousedown = function(event) { + elTargetTh = event.target; + initialThEvent = event; + targetColumnIndex = parseInt(elTargetTh.getAttribute("columnIndex")); }; let elResizer = document.createElement("span"); @@ -1030,7 +1030,7 @@ function loaded() { } function onStartResize(event) { - startResizeEvent = event; + lastResizeEvent = event; resizeColumnIndex = parseInt(this.getAttribute("columnIndex")); event.stopPropagation(); } @@ -1074,8 +1074,33 @@ function loaded() { entityList.refresh(); } - document.onmousemove = function(ev) { - if (startResizeEvent) { + function swapColumns(columnAIndex, columnBIndex) { + let columnA = columns[columnAIndex]; + let columnB = columns[columnBIndex]; + let columnATh = columns[columnAIndex].elTh; + let columnBTh = columns[columnBIndex].elTh; + let columnThParent = columnATh.parentNode; + columnThParent.removeChild(columnBTh); + columnThParent.insertBefore(columnBTh, columnATh); + columnATh.setAttribute("columnIndex", columnBIndex); + columnBTh.setAttribute("columnIndex", columnAIndex); + columnA.elResizer.setAttribute("columnIndex", columnBIndex); + columnB.elResizer.setAttribute("columnIndex", columnAIndex); + + for (let i = 0; i < visibleEntities.length; ++i) { + let elRow = visibleEntities[i].elRow; + let columnACell = elRow.childNodes[columnAIndex]; + let columnBCell = elRow.childNodes[columnBIndex]; + elRow.removeChild(columnBCell); + elRow.insertBefore(columnBCell, columnACell); + } + + columns[columnAIndex] = columnB; + columns[columnBIndex] = columnA; + } + + document.onmousemove = function(event) { + if (lastResizeEvent) { startTh = null; let column = columns[resizeColumnIndex]; @@ -1087,7 +1112,7 @@ function loaded() { } let fullWidth = elEntityTableBody.offsetWidth; - let dx = ev.clientX - startResizeEvent.clientX; + let dx = event.clientX - lastResizeEvent.clientX; let dPct = dx / fullWidth; let newColWidth = column.width + dPct; @@ -1097,14 +1122,46 @@ function loaded() { column.width += dPct; nextColumn.width -= dPct; updateColumnWidths(); - startResizeEvent = ev; + lastResizeEvent = event; + } + } else if (elTargetTh) { + let dxFromInitial = event.clientX - initialThEvent.clientX; + if (Math.abs(dxFromInitial) >= DELTA_X_MOVE_COLUMNS_THRESHOLD) { + elTargetTh.className = "dragging"; + } + if (targetColumnIndex < columns.length - 1) { + let nextColumnIndex = targetColumnIndex + 1; + let nextColumnTh = columns[nextColumnIndex].elTh; + let nextColumnStartX = nextColumnTh.getBoundingClientRect().left; + if (event.clientX >= nextColumnStartX && event.clientX - lastColumnSwapPosition >= DELTA_X_COLUMN_SWAP_POSITION) { + swapColumns(targetColumnIndex, nextColumnIndex); + targetColumnIndex = nextColumnIndex; + lastColumnSwapPosition = event.clientX; + } + } + if (targetColumnIndex >= 1) { + let prevColumnIndex = targetColumnIndex - 1; + let prevColumnTh = columns[prevColumnIndex].elTh; + let prevColumnEndX = prevColumnTh.getBoundingClientRect().right; + if (event.clientX <= prevColumnEndX && event.clientX - lastColumnSwapPosition >= DELTA_X_COLUMN_SWAP_POSITION) { + swapColumns(prevColumnIndex, targetColumnIndex); + targetColumnIndex = prevColumnIndex; + } } } } - document.onmouseup = function(ev) { - startResizeEvent = null; - ev.stopPropagation(); + document.onmouseup = function(event) { + if (elTargetTh) { + if (elTargetTh.className !== "dragging" && elTargetTh === event.target) { + let columnID = columns[targetColumnIndex].columnID; + setSortColumn(columnID); + } + elTargetTh.className = ""; + } + lastResizeEvent = null; + elTargetTh = null; + initialThEvent = null; } function setSpaceMode(spaceMode) { From a0f79f988194a74f19e82e104241572da7ff7d30 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 16 Nov 2018 17:14:30 -0800 Subject: [PATCH 2/3] entity list reordering columns --- scripts/system/html/js/entityList.js | 68 ++++++++++++++++++---------- scripts/system/html/js/listView.js | 4 -- 2 files changed, 44 insertions(+), 28 deletions(-) diff --git a/scripts/system/html/js/entityList.js b/scripts/system/html/js/entityList.js index e1581b7877..963611f059 100644 --- a/scripts/system/html/js/entityList.js +++ b/scripts/system/html/js/entityList.js @@ -110,8 +110,8 @@ const COLUMNS = { }; const COMPARE_ASCENDING = function(a, b) { - let va = a[currentSortColumn]; - let vb = b[currentSortColumn]; + let va = a[currentSortColumnID]; + let vb = b[currentSortColumnID]; if (va < vb) { return -1; @@ -171,7 +171,7 @@ let entityList = null; // The ListView */ let entityListContextMenu = null; -let currentSortColumn = 'type'; +let currentSortColumnID = 'type'; let currentSortOrder = ASCENDING_SORT; let elSortOrders = {}; let typeFilters = []; @@ -182,6 +182,7 @@ let columnsByID = {}; let lastResizeEvent = null; let resizeColumnIndex = 0; let elTargetTh = null; +let elTargetSpan = null; let targetColumnIndex = 0; let lastColumnSwapPosition = -1; let initialThEvent = null; @@ -226,10 +227,6 @@ const PROFILE = !ENABLE_PROFILING ? PROFILE_NOOP : function(name, fn, args) { console.log("PROFILE-Web " + profileIndent + "(" + name + ") End " + delta + "ms"); }; -debugPrint = function (message) { - console.log(message); -}; - function loaded() { openEventBridge(function() { elEntityTable = document.getElementById("entity-table"); @@ -320,10 +317,11 @@ function loaded() { for (let columnID in COLUMNS) { let columnData = COLUMNS[columnID]; - let thID = "entity-" + columnID; let elTh = document.createElement("th"); + let thID = "entity-" + columnID; elTh.setAttribute("id", thID); elTh.setAttribute("columnIndex", columnIndex); + elTh.setAttribute("columnID", columnID); if (columnData.glyph) { let elGlyph = document.createElement("span"); elGlyph.className = "glyph"; @@ -333,15 +331,19 @@ function loaded() { elTh.innerText = columnData.columnHeader; } elTh.onmousedown = function(event) { - elTargetTh = event.target; + if (event.target.nodeName === 'TH') { + elTargetTh = event.target; + targetColumnIndex = parseInt(elTargetTh.getAttribute("columnIndex")); + lastColumnSwapPosition = event.clientX; + } else if (event.target.nodeName === 'SPAN') { + elTargetSpan = event.target; + } initialThEvent = event; - targetColumnIndex = parseInt(elTargetTh.getAttribute("columnIndex")); }; let elResizer = document.createElement("span"); elResizer.className = "resizer"; elResizer.innerHTML = " "; - elResizer.setAttribute("columnIndex", columnIndex); elResizer.onmousedown = onStartResize; elTh.appendChild(elResizer); @@ -699,13 +701,13 @@ function loaded() { refreshNoEntitiesMessage(); } - function setSortColumn(column) { + function setSortColumn(columnID) { PROFILE("set-sort-column", function() { - if (currentSortColumn === column) { + if (currentSortColumnID === columnID) { currentSortOrder *= -1; } else { - elSortOrders[currentSortColumn].innerHTML = ""; - currentSortColumn = column; + elSortOrders[currentSortColumnID].innerHTML = ""; + currentSortColumnID = columnID; currentSortOrder = ASCENDING_SORT; } refreshSortOrder(); @@ -714,7 +716,7 @@ function loaded() { } function refreshSortOrder() { - elSortOrders[currentSortColumn].innerHTML = currentSortOrder === ASCENDING_SORT ? ASCENDING_STRING : DESCENDING_STRING; + elSortOrders[currentSortColumnID].innerHTML = currentSortOrder === ASCENDING_SORT ? ASCENDING_STRING : DESCENDING_STRING; } function refreshEntities() { @@ -1031,7 +1033,7 @@ function loaded() { function onStartResize(event) { lastResizeEvent = event; - resizeColumnIndex = parseInt(this.getAttribute("columnIndex")); + resizeColumnIndex = parseInt(this.parentNode.getAttribute("columnIndex")); event.stopPropagation(); } @@ -1089,14 +1091,18 @@ function loaded() { for (let i = 0; i < visibleEntities.length; ++i) { let elRow = visibleEntities[i].elRow; - let columnACell = elRow.childNodes[columnAIndex]; - let columnBCell = elRow.childNodes[columnBIndex]; - elRow.removeChild(columnBCell); - elRow.insertBefore(columnBCell, columnACell); + if (elRow) { + let columnACell = elRow.childNodes[columnAIndex]; + let columnBCell = elRow.childNodes[columnBIndex]; + elRow.removeChild(columnBCell); + elRow.insertBefore(columnBCell, columnACell); + } } columns[columnAIndex] = columnB; columns[columnBIndex] = columnA; + + updateColumnWidths(); } document.onmousemove = function(event) { @@ -1143,24 +1149,38 @@ function loaded() { let prevColumnIndex = targetColumnIndex - 1; let prevColumnTh = columns[prevColumnIndex].elTh; let prevColumnEndX = prevColumnTh.getBoundingClientRect().right; - if (event.clientX <= prevColumnEndX && event.clientX - lastColumnSwapPosition >= DELTA_X_COLUMN_SWAP_POSITION) { + if (event.clientX <= prevColumnEndX && lastColumnSwapPosition - event.clientX >= DELTA_X_COLUMN_SWAP_POSITION) { swapColumns(prevColumnIndex, targetColumnIndex); - targetColumnIndex = prevColumnIndex; + targetColumnIndex = prevColumnIndex; + lastColumnSwapPosition = event.clientX; } } + } else if (elTargetSpan) { + let dxFromInitial = event.clientX - initialThEvent.clientX; + if (Math.abs(dxFromInitial) >= DELTA_X_MOVE_COLUMNS_THRESHOLD) { + elTargetTh = elTargetSpan.parentNode; + elTargetTh.className = "dragging"; + targetColumnIndex = parseInt(elTargetTh.getAttribute("columnIndex")); + lastColumnSwapPosition = event.clientX; + elTargetSpan = null; + } } } document.onmouseup = function(event) { if (elTargetTh) { if (elTargetTh.className !== "dragging" && elTargetTh === event.target) { - let columnID = columns[targetColumnIndex].columnID; + let columnID = elTargetTh.getAttribute("columnID"); setSortColumn(columnID); } elTargetTh.className = ""; + } else if (elTargetSpan) { + let columnID = elTargetSpan.parentNode.getAttribute("columnID"); + setSortColumn(columnID); } lastResizeEvent = null; elTargetTh = null; + elTargetSpan = null; initialThEvent = null; } diff --git a/scripts/system/html/js/listView.js b/scripts/system/html/js/listView.js index f775a4cb24..77e1ba99b1 100644 --- a/scripts/system/html/js/listView.js +++ b/scripts/system/html/js/listView.js @@ -9,10 +9,6 @@ const SCROLL_ROWS = 2; // number of rows used as scrolling buffer, each time we pass this number of rows we scroll const FIRST_ROW_INDEX = 2; // the first elRow element's index in the child nodes of the table body -debugPrint = function (message) { - console.log(message); -}; - function ListView(elTableBody, elTableScroll, elTableHeaderRow, createRowFunction, updateRowFunction, clearRowFunction, WINDOW_NONVARIABLE_HEIGHT) { this.elTableBody = elTableBody; From 8620a5a4c3649903a4f50c19684e95f6749f17bb Mon Sep 17 00:00:00 2001 From: David Back Date: Thu, 6 Dec 2018 13:07:59 -0800 Subject: [PATCH 3/3] CR changes --- scripts/system/html/js/listView.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/system/html/js/listView.js b/scripts/system/html/js/listView.js index b19ba7e0cb..eec3f833ad 100644 --- a/scripts/system/html/js/listView.js +++ b/scripts/system/html/js/listView.js @@ -242,7 +242,7 @@ ListView.prototype = { resize: function() { if (!this.elTableBody || !this.elTableScroll) { - debugPrint("ListView.resize - no valid table body or table scroll element"); + console.log("ListView.resize - no valid table body or table scroll element"); return; } this.preResizeFunction(); @@ -284,7 +284,7 @@ ListView.prototype = { initialize: function() { if (!this.elTableBody || !this.elTableScroll) { - debugPrint("ListView.initialize - no valid table body or table scroll element"); + console.log("ListView.initialize - no valid table body or table scroll element"); return; }