From 800bae24b701205fdfb26bdbc6198755aa73b7df Mon Sep 17 00:00:00 2001 From: Yaroslav Ovdii Date: Mon, 30 Mar 2020 08:50:54 +0300 Subject: [PATCH 1/5] changed selection feature --- js/spreadsheet.js | 303 ++++++++++++---------------------------------- 1 file changed, 80 insertions(+), 223 deletions(-) diff --git a/js/spreadsheet.js b/js/spreadsheet.js index 89383d1..aa70bed 100644 --- a/js/spreadsheet.js +++ b/js/spreadsheet.js @@ -68,247 +68,108 @@ var spreadsheet = function(options) { } /** - * We user this method to determine where is closest data is lokated from the selected cell + * The function that surfs through the table data for detecting closest cells with data from the selected cell * - * @param {Array} selectedCell - array of the coordinat of the selected cell reacived throw the hot.getSelected() method - * - * @returns {Object} - object of the directions where data is placed occording to the selected cell + * @param {array} tableData - an array of table data received from the hot.getData() + * @param {array} cellPosition - an array of the cell coordinates + * @param {array} processedCells - an array of the cells we have already checked + * @returns {array} returns array of the scaned cells example array[rowIndex][cellIndex] = hasData true/false */ - function closestData(selectedCell) { - selectedCell = selectedCell[0]; - if (!Array.isArray(selectedCell)) { - console.error('We must pass an array of the cell coordinats to the closestData function. First element is cell' + - 'row and second element is cell col. In this case script will act as if there was a value in the cell. ' + - 'Value that was passed - ', - selectedCell); - return false; - } - - var col = selectedCell[1]; - var row = selectedCell[0]; - var selectedCellData = hot.getDataAtCell(row, col) - // At this block we getting an index of the nearest cells from the selected cell - // If we selected first row it ID is 0 already and if we - 1 from it we will reacive an error in the hot.getDataAtCell() method - var top = row ? row - 1 : row; - var bottom = row + 1; - // Same as in top variable - var left = col ? col - 1 : col; - var right = col + 1; - // At this block we reacive the nearest cells value from the selected cell - var leftValue = hot.getDataAtCell(row, left); - var rightValue = hot.getDataAtCell(row, right); - var topValue = hot.getDataAtCell(top, col); - var bottomValue = hot.getDataAtCell(bottom, col); - var dataAt = { - left: false, - right: false, - top: false, - bottom: false, - all: false, - hasData: false - }; - - // If there is a data in the selected cell we should select data releated to this cell - if (selectedCellData !== null) { - dataAt.hasData = true; - return dataAt; + function getDataCoordinates(tableData, cellPosition, processedCells) { + if (!processedCells) { + processedCells = []; + processedCells[cellPosition[0]] = []; + processedCells[cellPosition[0]][cellPosition[1]] = true; } - // If no value near the selected cell we should select all table, also fires when we just load data source - // and clicked ctrl+a combination - if (leftValue === null && rightValue === null && topValue === null && bottomValue === null) { - dataAt.all = true; - return dataAt; - } + var cellsGroup = getNearestCells(cellPosition); + cellsGroup.push(cellPosition); - // Showing where is data position from the selected cell - dataAt.left = leftValue !== null; - dataAt.right = rightValue !== null; - dataAt.top = topValue !== null; - dataAt.bottom = bottomValue !== null; + cellsGroup.forEach(function(cell) { + var hasData = tableData[cell[0]][cell[1]] !== null + var processedRow = processedCells[cell[0]]; - return dataAt; - } - - /** - * Method to get a coordinats which we need to select - * - * @param {Array} startAt - array of the selected coordinats - * @param {Object} moveTo - object that returned from closestData() function - * - * @returns {Array} - coordinats that needs to be selected. Example of the returned data: [[startRow, startCol, endRow, endCol]] - */ - function coordinatsToSelect(startAt, moveTo) { - var firstCol, lastCol, firstRow, lastRow, allData; - - // Returns array of the data from the table with handsontable API - allData = hot.getData(); - startAt = startAt[0]; - - if (moveTo.left) { - // When data located on the left of the selected cell - lastCol = startAt[1]; - - // Looking for first col in the array of allData - // When we got a null value in the cell it means that we reached the range borders - for (var i = lastCol - 1; i >= 0; i--) { - if (allData[startAt[0]][i] === null) { - firstCol = i; - break; - } + if (!processedRow) { + processedCells[cell[0]] = []; } - firstCol = firstCol || 0; + var processedCell = processedCells[cell[0]][cell[1]]; - // Looking for the first row in the array of allData - // When we got a null value in the cell it means that we reached the range borders - for (var i = startAt[0]; i >= 0; i--) { - if (allData[i][firstCol] === null) { - firstRow = i; - break; - } + if (!processedCell) { + processedCells[cell[0]][cell[1]] = false; } - firstRow = firstRow || 0; - - // Looking for the last row in the array of allData - // When we got a null value in the cell it means that we reached the range borders - for (var i = firstRow; i < allData.length; i++) { - if (allData[i][firstCol] === null) { - lastRow = i; - break; - } + if (hasData && (!processedRow || !processedCell)) { + processedCells[cell[0]][cell[1]] = true; + getDataCoordinates(tableData, cell, processedCells); } + }); - lastRow = _.max([lastRow - 1, 0]); - } else if (moveTo.right) { - // When data located on the right of the selected cell - firstCol = startAt[1]; - - for (var i = firstCol + 1; i < allData.length; i++) { - if (allData[startAt[0]][i] === null) { - lastCol = i - 1; - break; - } - } - - for (var i = startAt[0]; i > 0; i--) { - if (allData[i][lastCol] === null) { - firstRow = i ? i - 1 : i; - } - } - - firstRow = firstRow || 0; - - for (var i = firstRow; i < allData.length; i++) { - if (allData[i][lastCol] === null) { - lastRow = i - 1; - break; - } - } - } else if (moveTo.top) { - // When data located on the top of the selected cell - lastRow = startAt[0]; - - for (var i = lastRow - 1; i > 0; i--) { - if (allData[i][startAt[1]] === null) { - firstRow = i; - break; - } - } - - firstRow = firstRow || 0; - - for (var i = startAt[1]; i > 0; i--) { - if (allData[firstRow][i] === null) { - firstCol = i ? i + 1 : i; - break; - } - } - - firstCol = firstCol || 0; - - for (var i = firstCol; i < allData.length; i++) { - if (allData[firstRow][i] === null) { - lastCol = i - 1; - break; - } - } - } else if (moveTo.bottom) { - // When data located on the bottom of the selected cell - firstRow = startAt[0]; - - for (var i = firstRow + 1; i < allData.length; i++) { - if (allData[i][startAt[1]] === null) { - lastRow = i - 1; - break; - } - } + return processedCells; + } - for (var i = startAt[1]; i > 0; i--) { - if (allData[lastRow][i] === null) { - firstCol = i + 1; - break; + /** + * The method that returns us a range that we should select in the table + * + * @param {array} processedCells array processed by getDataCoordinates function + */ + function getSelectionCoordinates(processedCells) { + var rowIndexes = []; + var colIndexes = []; + + processedCells.forEach(function(row, rowIndex) { + row.forEach(function(cell, colIndex) { + if (cell) { + rowIndexes.push(rowIndex); + colIndexes.push(colIndex); } - } + }); + }); - firstCol = firstCol || 0; + var firstRow = Math.min.apply(null, rowIndexes); + var firstCol = Math.min.apply(null, colIndexes); + var lastRow = Math.max.apply(null, rowIndexes); + var lastCol = Math.max.apply(null, colIndexes); - for (var i = firstCol; i < allData.length; i++) { - if (allData[lastRow][i] === null) { - lastCol = i - 1; - break; - } - } - } else if (moveTo.hasData) { - // When selected cell has data in it - if (startAt[1] === 0) { - firstCol = 0; - } else { - for (var i = startAt[1]; i > 0; i--) { - if (allData[startAt[0]][i] === null) { - firstCol = i + 1; - break; - } - } + return [[firstRow, firstCol, lastRow, lastCol]]; + } - firstCol = firstCol || 0; - } + function getNearestCells(cellPosition) { + var leftShift = cellPosition[1] - 1; + var topShift = cellPosition[0] - 1; + var left = [cellPosition[0], leftShift < 0 ? cellPosition[1] : leftShift]; + var right = [cellPosition[0], cellPosition[1] + 1]; + var top = [topShift < 0 ? cellPosition[0] : topShift, cellPosition[1]]; + var bottom = [cellPosition[0] + 1, cellPosition[1]]; - for (var i = firstCol; i < allData.length; i++) { - if (allData[startAt[0]][i] === null) { - lastCol = i - 1; - break; - } - } + return [left, right, top, bottom]; + } - if (startAt[0] === 0) { - firstRow = startAt[0]; - } else { - for (var i = startAt[0]; i > 0; i--) { - if (allData[i][firstCol] === null) { - firstRow = i + 1; - break; - } + /** + * The method that decides do we need to select a range or select all data + * + * @param {array} selectionPosition - an array of the selected cell coordinates received from hot.getSelected() + * @returns {array} range of the data that we need to select + */ + function getSelectionRange(selectionPosition) { + var dataCoordinates = getDataCoordinates(hot.getData(), selectionPosition[0]); + var selectedCells = 0; + + dataCoordinates.forEach(function(row) { + row.forEach(function(cell) { + if (cell) { + selectedCells++; } + }); + }); - firstRow = firstRow || 0; - } - - for (var i = firstRow; i < allData.length; i++) { - if (allData[i][firstCol] === null) { - lastRow = i - 1; - break; - } - } - } else if (moveTo.all) { - // When selected cell doesn't have a data in it and no data in cells around it + if (selectedCells <= 1) { return false; } - return [ - [firstRow, firstCol, lastRow, lastCol] - ]; + var selectionCoords = getSelectionCoordinates(dataCoordinates); + + return selectionCoords; } /** @@ -496,17 +357,13 @@ var spreadsheet = function(options) { if ((event.ctrlKey || event.metaKey) && event.keyCode === 65 ) { var selectedCell = hot.getSelected(); - var whereToLook = closestData(selectedCell); - var selectedRange = coordinatsToSelect(selectedCell, whereToLook); + var selectedRange = getSelectionRange(selectedCell); + if (!selectedRange) { return; } - event.stopImmediatePropagation(); - - var cols = getColumns().filter(function(column) { - return column; - }).length; + event.stopImmediatePropagation(); hot.deselectCell(); hot.selectCells(selectedRange, false, false); return false; From 94bf6697f544e15c73ac65357793662759dc40bd Mon Sep 17 00:00:00 2001 From: Yaroslav Ovdii Date: Mon, 30 Mar 2020 12:04:23 +0300 Subject: [PATCH 2/5] made changes as codacy requested --- js/spreadsheet.js | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/js/spreadsheet.js b/js/spreadsheet.js index aa70bed..c2d435b 100644 --- a/js/spreadsheet.js +++ b/js/spreadsheet.js @@ -67,6 +67,17 @@ var spreadsheet = function(options) { } } + function getNearestCells(cellPosition) { + var leftShift = cellPosition[1] - 1; + var topShift = cellPosition[0] - 1; + var left = [cellPosition[0], leftShift < 0 ? cellPosition[1] : leftShift]; + var right = [cellPosition[0], cellPosition[1] + 1]; + var top = [topShift < 0 ? cellPosition[0] : topShift, cellPosition[1]]; + var bottom = [cellPosition[0] + 1, cellPosition[1]]; + + return [left, right, top, bottom]; + } + /** * The function that surfs through the table data for detecting closest cells with data from the selected cell * @@ -86,7 +97,7 @@ var spreadsheet = function(options) { cellsGroup.push(cellPosition); cellsGroup.forEach(function(cell) { - var hasData = tableData[cell[0]][cell[1]] !== null + var hasData = tableData[cell[0]][cell[1]] !== null; var processedRow = processedCells[cell[0]]; if (!processedRow) { @@ -134,17 +145,6 @@ var spreadsheet = function(options) { return [[firstRow, firstCol, lastRow, lastCol]]; } - function getNearestCells(cellPosition) { - var leftShift = cellPosition[1] - 1; - var topShift = cellPosition[0] - 1; - var left = [cellPosition[0], leftShift < 0 ? cellPosition[1] : leftShift]; - var right = [cellPosition[0], cellPosition[1] + 1]; - var top = [topShift < 0 ? cellPosition[0] : topShift, cellPosition[1]]; - var bottom = [cellPosition[0] + 1, cellPosition[1]]; - - return [left, right, top, bottom]; - } - /** * The method that decides do we need to select a range or select all data * From 7c1f031bfdee408755a954f96e7c576776bc4215 Mon Sep 17 00:00:00 2001 From: Yaroslav Ovdii Date: Wed, 1 Apr 2020 15:20:11 +0300 Subject: [PATCH 3/5] corrected lint errors --- js/spreadsheet.js | 1 + 1 file changed, 1 insertion(+) diff --git a/js/spreadsheet.js b/js/spreadsheet.js index c2d435b..9e6afd1 100644 --- a/js/spreadsheet.js +++ b/js/spreadsheet.js @@ -94,6 +94,7 @@ var spreadsheet = function(options) { } var cellsGroup = getNearestCells(cellPosition); + cellsGroup.push(cellPosition); cellsGroup.forEach(function(cell) { From 3ad5eccd21e1ddf5d4f11793bcf677576fd0a548 Mon Sep 17 00:00:00 2001 From: Yaroslav Ovdii Date: Thu, 2 Apr 2020 12:24:10 +0300 Subject: [PATCH 4/5] made loader same as in all studio --- css/interface.css | 9 ++++----- interface.html | 8 +++++++- js/interface.js | 8 ++++---- js/spreadsheet.js | 2 +- 4 files changed, 16 insertions(+), 11 deletions(-) diff --git a/css/interface.css b/css/interface.css index 6daba24..25274eb 100644 --- a/css/interface.css +++ b/css/interface.css @@ -476,12 +476,11 @@ a[data-back] { } } -.loading-data { +.loader-holder { + display: flex; + justify-content: center; + align-items: center; position: fixed; top: 90px; left: 50%; - transform: translate(-50%, 0); - font-size: 0.9em; - padding: 0.6em 0.8em 0.7em; - box-shadow: 0 10px 25px rgba(0, 0, 0, 0.1); } \ No newline at end of file diff --git a/interface.html b/interface.html index 4042dc6..860e1fe 100644 --- a/interface.html +++ b/interface.html @@ -1,6 +1,12 @@
-
Loading data...
+
+
+
Loading...
+

Loading data...

+
+
+
diff --git a/js/interface.js b/js/interface.js index 7a16d8f..56c8c81 100644 --- a/js/interface.js +++ b/js/interface.js @@ -1,4 +1,4 @@ -var $initialSpinnerLoading = $('.loading-data'); +var $initialSpinnerLoading = $('.spinner-holder'); var $contents = $('#contents'); var $sourceContents = $('#source-contents'); var $dataSources = $('#data-sources > tbody'); @@ -34,7 +34,7 @@ var definitionEditor = CodeMirror.fromTextArea($('#definition')[0], { // Fetch all data sources function getDataSources() { - $initialSpinnerLoading.show(); + $initialSpinnerLoading.addClass('animated'); $contents.addClass('hidden'); $sourceContents.addClass('hidden'); $('[data-save]').addClass('hidden'); @@ -118,7 +118,7 @@ function renderDataSources(dataSources) { }); $dataSources.html(html.join('')); - $initialSpinnerLoading.hide(); + $initialSpinnerLoading.removeClass('animated'); $contents.removeClass('hidden'); } @@ -345,7 +345,7 @@ function browseDataSource(id) { $('[href="#entries"]').click(); $sourceContents.find('#toolbar').hide(); - $('.loading-data').show(); + $initialSpinnerLoading.addClass('animated'); $sourceContents.removeClass('hidden'); // Input file temporarily disabled diff --git a/js/spreadsheet.js b/js/spreadsheet.js index 9e6afd1..3eb1d9e 100644 --- a/js/spreadsheet.js +++ b/js/spreadsheet.js @@ -338,7 +338,7 @@ var spreadsheet = function(options) { } }); $sourceContents.find('#toolbar').show(); - $('.loading-data').hide(); + $initialSpinnerLoading.removeClass('animated'); rendered += 1; } }, From 35a168d6156cf55c859ddb158ee8535940880b5a Mon Sep 17 00:00:00 2001 From: Yaroslav Ovdii Date: Fri, 3 Apr 2020 17:06:45 +0300 Subject: [PATCH 5/5] remade solution for ctrla --- js/spreadsheet.js | 67 +++++++++++++++++++++++++++++++---------------- 1 file changed, 44 insertions(+), 23 deletions(-) diff --git a/js/spreadsheet.js b/js/spreadsheet.js index 3eb1d9e..688b0da 100644 --- a/js/spreadsheet.js +++ b/js/spreadsheet.js @@ -68,54 +68,71 @@ var spreadsheet = function(options) { } function getNearestCells(cellPosition) { - var leftShift = cellPosition[1] - 1; - var topShift = cellPosition[0] - 1; - var left = [cellPosition[0], leftShift < 0 ? cellPosition[1] : leftShift]; - var right = [cellPosition[0], cellPosition[1] + 1]; - var top = [topShift < 0 ? cellPosition[0] : topShift, cellPosition[1]]; - var bottom = [cellPosition[0] + 1, cellPosition[1]]; - - return [left, right, top, bottom]; + var leftShift = cellPosition.y - 1; + var topShift = cellPosition.x - 1; + var left = { + x: cellPosition.x, + y: leftShift < 0 ? cellPosition.y : leftShift + }; + var right = { + x: cellPosition.x, + y: cellPosition.y + 1 + }; + var top = { + x: topShift < 0 ? cellPosition.x : topShift, + y: cellPosition.y + }; + var bottom = { + x: cellPosition.x + 1, + y: cellPosition.y + }; + + return { + left: left, + right: right, + top: top, + bottom: bottom + }; } /** * The function that surfs through the table data for detecting closest cells with data from the selected cell * * @param {array} tableData - an array of table data received from the hot.getData() - * @param {array} cellPosition - an array of the cell coordinates + * @param {object} cellPosition - an object of the cell coordinates with x and y keys * @param {array} processedCells - an array of the cells we have already checked * @returns {array} returns array of the scaned cells example array[rowIndex][cellIndex] = hasData true/false */ function getDataCoordinates(tableData, cellPosition, processedCells) { if (!processedCells) { processedCells = []; - processedCells[cellPosition[0]] = []; - processedCells[cellPosition[0]][cellPosition[1]] = true; + processedCells[cellPosition.x] = []; + processedCells[cellPosition.x][cellPosition.y] = true; } var cellsGroup = getNearestCells(cellPosition); - cellsGroup.push(cellPosition); + cellsGroup['currentCell'] = cellPosition; - cellsGroup.forEach(function(cell) { - var hasData = tableData[cell[0]][cell[1]] !== null; - var processedRow = processedCells[cell[0]]; + for (var cell in cellsGroup) { + var hasData = tableData[cellsGroup[cell].x][cellsGroup[cell].y] !== null; + var processedRow = processedCells[cellsGroup[cell].x]; if (!processedRow) { - processedCells[cell[0]] = []; + processedCells[cellsGroup[cell].x] = []; } - var processedCell = processedCells[cell[0]][cell[1]]; + var processedCell = processedCells[cellsGroup[cell].x][cellsGroup[cell].y]; if (!processedCell) { - processedCells[cell[0]][cell[1]] = false; + processedCells[cellsGroup[cell].x][cellsGroup[cell].y] = false; } if (hasData && (!processedRow || !processedCell)) { - processedCells[cell[0]][cell[1]] = true; - getDataCoordinates(tableData, cell, processedCells); - } - }); + processedCells[cellsGroup[cell].x][cellsGroup[cell].y] = true; + getDataCoordinates(tableData, cellsGroup[cell], processedCells); + } + } return processedCells; } @@ -153,7 +170,11 @@ var spreadsheet = function(options) { * @returns {array} range of the data that we need to select */ function getSelectionRange(selectionPosition) { - var dataCoordinates = getDataCoordinates(hot.getData(), selectionPosition[0]); + var selectedPosition = { + x: selectionPosition[0][0], + y: selectionPosition[0][1] + }; + var dataCoordinates = getDataCoordinates(hot.getData(), selectedPosition); var selectedCells = 0; dataCoordinates.forEach(function(row) {