Наведение курсора на ячейку таблицы JS

113
21 января 2020, 07:30

Как при наведении на ячейку таблицы с числами в JS подсветить еще например 3 ячейки, близких по значению к основной? Меня интересует не готовое решение, а подход как сделать.

  function matrix(m, n, x) {
  const table = document.createElement('table');
  const arr = [];
  const colAvg = [];
  const sumArr = [];
  const changeValues = (i, j) => {
    console.log(i, j)
    sumArr[i] += 1;
    arr[i][j] += 1;
    const columns = arr[i][j];
      for (let j = 0; j < columns; j++) {
        var columnTotal = 0
        for (let i = 0; i < arr.length; i++) {
          columnTotal += arr[i][j]
        }
        colAvg[j] = columnTotal / arr.length
      }
    console.log(sumArr)
    console.log(arr[i][j])
    console.log(colAvg)
    document.getElementById(i + "-" + j).textContent = arr[i][j];
    document.getElementsByClassName('sumChange')[i].textContent = sumArr[i];
    document.getElementsByClassName('Avg')[j].textContent = colAvg[j];
  }
  for (var j = 0; j < n; j++) {
    colAvg[j] = 0;
    var sumCol = 0;
  }
  for (let i = 0; i < m; i++) {
    var tr = document.createElement('tr');
    arr[i] = [];
    var summM = 0;
    for (let j = 0; j < n; j++) {
      var td = document.createElement('td');
      td.id = + i + "-" + j;
      td.className = "plusOne";
      td.textContent = arr[i][j] = getRandom();
      td.onclick = function () {
        changeValues(i, j);
      } 
      td.onmouseover = function () {
        var target = event.target;
        target.style.background = '#8888FF';
      };
      td.onmouseout = function () {
        var target = event.target;
        target.style.background = '';
      };
      tr.appendChild(td);
      summM += arr[i][j];
      colAvg[j] += arr[i][j] / colAvg.length;
    }
      for (var j = 0; j < 1 ; j++) {
        td = document.createElement('td');
        td.className = "sumChange";
        td.textContent = summM;
        tr.appendChild(td);
        sumArr.push(summM);
  }
    table.appendChild(tr);
    console.log(tr)
    console.log(sumArr)
  }
  tr = document.createElement('tr');
  for (var j = 0; j < n ; j++) {
    td = document.createElement('td');
    td.className = "Avg";
    td.textContent = colAvg[j];
    tr.appendChild(td);
    colAvg;
    }
  table.appendChild(tr);
  console.log(colAvg)
  console.log(tr)
  console.log(arr)

  document.getElementById('myTable').appendChild(table);
  function getRandom() {
    return Math.round(Math.random() * 900 + 99);
  }
}
matrix(4, 4, 4);
Answer 1
  • Определяете критерий "близкие по значению".
  • При наведении на ячейку берете её значение и сравниваете со значениями в остальных ячейках. Если используете jQuery, то jQuery.filter() то, что нужно.
  • Всем найденным ячейкам присваиваете класс, по котому они подсвечиваются.
  • При уходе с ячейки - удаляете класс подсветки со всех элементов

Добавлено

Задачка усложняется возможностью наличия одинаковых чисел в таблице. В этом случае следует ещё считать расстояние от ячейки.

Ниже и на codepen - полный рабочий код. Я постарался добавить комментариев по-максимуму

function matrix(m, n, x) { 
    const table = document.createElement('table'); 
    const arr = []; 
    const values = {}; 
    const colAvg = []; 
    const sumArr = []; 
    const changeValues = (i, j) => { 
        console.log(i, j) 
        sumArr[i] += 1; 
        arr[i][j] += 1; 
        const columns = arr[i][j]; 
        for (let j = 0; j < columns; j++) { 
            var columnTotal = 0 
            for (let i = 0; i < arr.length; i++) { 
                columnTotal += arr[i][j] 
            } 
            colAvg[j] = columnTotal / arr.length 
        } 
        console.log(sumArr) 
        console.log(arr[i][j]) 
        console.log(colAvg) 
        document.getElementById(i + "-" + j).textContent = arr[i][j]; 
        document.getElementsByClassName('sumChange')[i].textContent = sumArr[i]; 
        document.getElementsByClassName('Avg')[j].textContent = colAvg[j]; 
    } 
 
    var numRandom = 4; 
    var randomValues = []; 
    for (var i = 0; i < numRandom; i++) { 
        randomValues.push(getRandom()); 
    } 
 
 
    for (var j = 0; j < n; j++) { 
        colAvg[j] = 0; 
        var sumCol = 0; 
    } 
    for (let i = 0; i < m; i++) { 
        var tr = document.createElement('tr'); 
        arr[i] = []; 
        var summM = 0; 
 
        for (let j = 0; j < n; j++) { 
            var td = document.createElement('td'); 
            td.id = + i + "-" + j; 
            td.className = "plusOne"; 
            var value = randomValues[getRandomInt(0, numRandom-1)]; 
 
            td.textContent = arr[i][j] = value; 
            values[value] = values[value] || []; 
            values[value].push({ 'i': i, 'j': j }); 
 
            td.onclick = function () { 
                changeValues(i, j); 
            } 
            td.onmouseover = function onMoOv() { 
                var target = event.target; 
                target.style.background = '#8888FF'; 
                var targetI, targetJ; 
                [targetI, targetJ] = target.id.split('-').map(x => + x); //Get coordinates from ID 
                var value = + target.textContent; 
                var index = valuesSorted.indexOf(value); //Position of the selected value in the list of sorted values 
                var closest = [ value ]; //List of the closest values. Initialized with the selected value 
                var closestQty = values[value].length; //Quantity of cells with the closest values. Note, several cells could have the same value 
                var i = index - 1, j = index + 1; //Positions before and after index 
                var delta = 0; //Current delta between values 
                var deltaPrev = Number.MAX_SAFE_INTEGER; //delta between selected value and a value before it in the list of sorted values 
                var deltaNext = Number.MAX_SAFE_INTEGER; //delta between selected value and a value after it in the list of sorted values 
                var valuePrev, valueNext; //current values before and after selected in the list of sorted values 
                var valueToAdd; 
                while (closestQty < x+1) { 
                    //Checking values from the sorted list - before of the selected value 
                    if (i >= 0) { 
                        valuePrev = valuesSorted[i]; 
                        deltaPrev = value - valuePrev; 
                    } else { 
                        deltaPrev = Number.MAX_SAFE_INTEGER; //Reset delta value 
                    } 
 
                    //Checking values from the sorted list - after the selected value 
                    if (j < valuesSorted.length) { 
                        valueNext = valuesSorted[j]; 
                        deltaNext = valueNext - value; 
                    } 
                    else { 
                        deltaNext = Number.MAX_SAFE_INTEGER; //Reset delta value 
                    } 
 
                    //Taking one with a smaller delta 
                    if (deltaPrev < deltaNext) { 
                        valueToAdd = valuePrev; 
                        i--; 
                    } else { 
                        valueToAdd = valueNext; 
                        j++; 
                    } 
 
                    closest.push(valueToAdd); 
                    closestQty += values[valueToAdd].length; 
                } 
                var closestValueIds = []; //IDs of cells we will be selecting 
                var qty = 0; //Number of cells we found to be selected 
                var k = 0; //Index in a list of the closest values 
                while (qty < x + 1) { 
                    value = closest[k]; 
                    if (x + 1 - qty >= values[value].length) { 
                    //Number of cells with a given value less than current number of cells to select 
                        for (var n = 0; n < values[value].length; n++) { 
                            var coordinates = values[value][n]; 
                            closestValueIds.push(+ coordinates.i + "-" + coordinates.j); 
                        } 
                        qty += values[value].length; 
                        k++; 
                    } else { 
                    //Calculate minimal distance between same value cells and selected cell 
                        var distances = []; 
                        for (var n = 0; n < values[value].length; n++) { 
                            var coordinates = values[value][n]; 
                            var distance = Math.sqrt(Math.pow(coordinates.i - targetI, 2) + Math.pow(coordinates.j - targetJ, 2)); 
                            distances.push({ 'distance': distance, 'id': + coordinates.i + "-" + coordinates.j }); 
                        } 
                        distances.sort((a, b) => a.distance - b.distance); 
                        for (var n = 0; n < distances.length; n++) { 
                            closestValueIds.push(distances[n].id); 
                            if (++qty == x + 1) { break; } 
                        } 
                    } 
                } 
 
                for (var i = 0; i < closestValueIds.length; i++) { 
                    document.getElementById(closestValueIds[i]).classList.add('highlighted'); 
                } 
            }; 
            td.onmouseout = function onMoOut() { 
                var target = event.target; 
                target.style.background = ''; 
                document.querySelectorAll('td.highlighted').forEach(el => el.classList.remove('highlighted')); 
            }; 
            tr.appendChild(td); 
            summM += arr[i][j]; 
            colAvg[j] += arr[i][j] / colAvg.length; 
 
        } 
 
        for (var j = 0; j < 1; j++) { 
            td = document.createElement('td'); 
            td.className = "sumChange"; 
            td.textContent = summM; 
            tr.appendChild(td); 
            sumArr.push(summM); 
 
        } 
        table.appendChild(tr); 
        console.log(tr) 
        console.log(sumArr) 
    } 
 
    tr = document.createElement('tr'); 
    for (var j = 0; j < n; j++) { 
        td = document.createElement('td'); 
        td.className = "Avg"; 
        td.textContent = colAvg[j]; 
        tr.appendChild(td); 
        colAvg; 
    } 
 
    let valuesSorted = Object.keys(values).map(x => +x).sort(); 
 
    table.appendChild(tr); 
    console.log(colAvg) 
 
    console.log(tr) 
    console.log(arr) 
 
 
    document.getElementById('myTable').appendChild(table); 
 
    function getRandom() { 
        return Math.round(Math.random() * 900 + 99); 
    } 
 
    function getRandomInt(min, max) { 
        min = Math.ceil(min); 
        max = Math.floor(max); 
        return Math.floor(Math.random() * (max - min + 1)) + min; 
    } 
} 
 
matrix(4, 4, 4);
table td { 
  font-family: "Lucida Sans Unicode", "Lucida Grande", Sans-Serif; 
  font-size: 14px; 
  border-spacing: 0; 
  text-align: center; 
  padding: 20px; 
  border: 1px solid black; 
} 
.sumChange { 
	background: #0a55ce; 
	color: #ffffff; 
} 
.Avg { 
	background: #0a55ce; 
	color: #ffffff; 
} 
.highlighted { 
	background: yellow; 
}
<!DOCTYPE html> 
<html> 
  <head> 
    <meta charset="UTF-8" /> 
    <title>Document</title> 
     
  </head> 
  <body> 
    <table id="myTable"></table> 
	 
     
  </body> 
</html>

READ ALSO
Удалить лишнюю переменную в цикле switch-case

Удалить лишнюю переменную в цикле switch-case

Имеется презентацияНа 2 слайде в консоли отладки для более удобной отладки отображается переменная i2 и какой "case" сработал в цикле switch-case

141
Как добавить кнопку &ldquo;показать ещё&rdquo;?

Как добавить кнопку “показать ещё”?

У меня есть массив с данными и он рендерится на странцие через метод for вот пример кода

145
Ошибка: Cannot read property &#39;classList&#39; of null

Ошибка: Cannot read property 'classList' of null

Выдается ошибка: Uncaught TypeError: Cannot read property 'classList' of null

139
Как применяются правила из различных ruleset&#39;ов в eslint

Как применяются правила из различных ruleset'ов в eslint

Пробую различные конфиг-файлыeslintrc

110