admin管理员组

文章数量:1289348

I'm building a program in JavaScript that's supposed to allow the user to navigate between table cells using up,down,left,right buttons. The appropriate table cell is highlighted after a directional button is clicked.

My table looks like this:

I'm working on building the functions to control the directional buttons, but I'm extremely lost on how to approach this. I need to be able to pass an argument that contains the currently highlighted cell, but I can't figure out how to do that.

My JavaScript so far, which doesn't really do much:

function right() {
    document.getElementById("one").nextElementSibling.style.border = '2px solid black';
}

Any help on how to deal with this would be great, because I really have no idea how to go about it.

I'm building a program in JavaScript that's supposed to allow the user to navigate between table cells using up,down,left,right buttons. The appropriate table cell is highlighted after a directional button is clicked.

My table looks like this:

I'm working on building the functions to control the directional buttons, but I'm extremely lost on how to approach this. I need to be able to pass an argument that contains the currently highlighted cell, but I can't figure out how to do that.

My JavaScript so far, which doesn't really do much:

function right() {
    document.getElementById("one").nextElementSibling.style.border = '2px solid black';
}

Any help on how to deal with this would be great, because I really have no idea how to go about it.

Share Improve this question asked Apr 29, 2016 at 16:00 123123 8,95115 gold badges65 silver badges104 bronze badges 2
  • please create a jsfiddle with the HTML table – messerbill Commented Apr 29, 2016 at 16:01
  • You may not want to do it - but using jQuery will certainly help you structure this in a simpler and more readable way. – Matthew Lymer Commented Apr 29, 2016 at 16:07
Add a ment  | 

3 Answers 3

Reset to default 5

A DYNAMIC SOLUTION USING PURE JS

You can essentially store the table objects in a 2-d matrix. While doing this have two global coordinates X and Y that store the current grid location. You can bind click events and keyboard events that track where the current focus is.

Take a look at the fiddle: https://jsfiddle/cnkr7wqa/5/

Note that this solution is dynamic regardless of the row size or the column size if every row is the same length and every column is the same length.

Also note that this works for: mouse clicks, directional keyboard presses, and button presses

HTML

<table>
<tr>
  <td>1</td>
  <td>2</td>
  <td>3</td>
</tr>
<tr>
  <td>4</td>
  <td>5</td>
  <td>6</td>
</tr>
<tr>
  <td>7</td>
  <td>8</td>
  <td>9</td>
</tr>
</table>

<button>Left</button>
<button>Up</button>
<button>Right</button>
<button>Down</button>

Javascript

var dat = document.getElementsByTagName('td');
var numOfColumns = document.getElementsByTagName('tr').length;
var numOfRows = document.getElementsByTagName('tr').length;
var currIndex = 0;
var rowObj = document.getElementsByTagName('tr');
var oneColLength = rowObj[0].children.length;
var colObj = document.getElementsByTagName('td');
var totalData = rowObj.length * colObj.length;
var dataCounter = 0;
var matrixObj = new Array(rowObj.length);
var currentX = 0;
var currentY = 0;
var buttons = document.getElementsByTagName('button');

for(var i = 0; i < matrixObj.length; i++){
   matrixObj[i] = new Array(oneColLength);
}

for(var i = 0; i < numOfRows; i++){
  for(var j = 0; j < oneColLength; j++){
     matrixObj[i][j] = colObj[dataCounter++];
  }
}

for(var i = 0; i < buttons.length; i++){
  buttons[i].addEventListener("click",function(){
    removeAllBorders();
    pareBtnEntity(this);
  });
}

for(var i = 0; i < dat.length; i++){
  dat[i].addEventListener("click",function(){
    removeAllBorders();
    this.style.border = "1px solid red";
    pareEntity(this);
  });
}

window.addEventListener("keyup",function(e){
       switch(e.keyCode){
            case 37: 
                if(currentX > 0){
                  currentX--;
                  repaint();
                }
                break;
            case 38: 
                if(currentY > 0){
                  currentY--;
                  repaint();
                }
                break;
            case 39: 
                if(currentX < oneColLength-1){
                  currentX++;
                  repaint();
                }
                break;
            case 40: 
                if(currentY < matrixObj.length-1){
                  currentY++;
                  repaint();
                }
                break;          
        }
})

function removeAllBorders(){
  for(var i = 0; i < dat.length; i++){
    dat[i].style.border = "1px solid grey";
  }
}

function pareEntity(ele){
  for(var i = 0; i < matrixObj.length; i++){
    for(var j = 0; j < oneColLength; j++){
       if(ele == matrixObj[i][j]){
          currentX = j;
          currentY = i;
       }
    }
  }
}

function pareBtnEntity(ele){
        for(var i = 0; i < buttons.length; i++){
            if(buttons[i] == ele){
                break; 
            }
        }

    switch(i){
                case 0: 
                if(currentX > 0){
                  currentX--;
                  repaint();
                }
                break;
            case 1: 
                if(currentY > 0){
                  currentY--;
                  repaint();
                }
                break;
            case 2: 
                if(currentX < oneColLength-1){
                  currentX++;
                  repaint();
                }
                break;
            case 3: 
                if(currentY < matrixObj.length-1){
                  currentY++;
                  repaint();
                }
                break;       
      }
     repaint();
  }


function repaint(){
  removeAllBorders();
  matrixObj[currentY][currentX].style.border = "1px solid red";
}

I know you didn't include the jquery tag on this, but I made a working example here (https://jsfiddle/romellem/pg6eveht/) using jQuery to make things a bit easier.

There isn't anything overly plex where you couldn't strip out the jQuery I used, but I'll leave that as an exercise for the reader. :)

I used the prototype pattern to make a hilighter class where you pass a selector to initialize a table. It doesn't account for Headers in the table, so you'll need to add that.

Otherwise, hopefully this helps you take a step in the right direction if you're totally lost.

$(document).ready(function() {
  var TableHilighter = function(table, selected) {
    this.table = $(table);
    this.rows = this.table.find('tr').length;
    this.cols = this.table.find('tr').first().find('td').length;
    this.selected = (typeof selected === 'undefined') ? [1, 1] : selected;

    // Hilight our row on initialization
    this.hilight();
  };

  TableHilighter.prototype = {
    "hilight": function(cell) {
      if (typeof cell === 'undefined') {
        cell = this.selected;
      }
      // Clear all hilighted cells
      this.table.find('td').removeClass('hilighted');

      // First find the row, then find the col, and add the .hilighted class
      this.table.find('tr:nth-child(' + this.selected[1] + ')').find('td:nth-child(' + this.selected[0] + ')').addClass('hilighted');
    },
    "move": function(dir) {
      switch (dir) {
        case 'up':
          this._up();
          break;
        case 'down':
          this._down();
          break;
        case 'left':
          this._left();
          break;
        case 'right':
          this._right();
          break;
        default:
          break;
      }
      this.hilight();
      return this.selected;
    },
    "_left": function() {
      if (this._x() > 1) {
        this._x(this._x() - 1);
      }
      return this.selected;
    },
    "_right": function() {
      if (this._x() < this.cols) {
        this._x(this._x() + 1);
      }
      return this.selected;
    },
    "_up": function() {
      if (this._y() > 1) {
        this._y(this._y() - 1);
      }
      return this.selected;
    },
    "_down": function() {
      if (this._y() < this.rows) {
        this._y(this._y() + 1);
      }
      return this.selected;
    },
    "_x": function(x) {
      if (typeof x === 'undefined') {
        return this.selected[0];
      } else {
        this.selected[0] = x;
        return this.selected[0];
      }
    },
    "_y": function(y) {
      if (typeof y === 'undefined') {
        return this.selected[1];
      } else {
        this.selected[1] = y;
        return this.selected[1];
      }
    }
  };

  // Initialize our TableHilighter
  var my_table = new TableHilighter('table');

  // Add button event handlers
  $('.up').on('click', function(e) {
    e.preventDefault();
    my_table.move('up');
  });

  $('.down').on('click', function(e) {
    e.preventDefault();
    my_table.move('down');
  });

  $('.left').on('click', function(e) {
    e.preventDefault();
    my_table.move('left');
  });

  $('.right').on('click', function(e) {
    e.preventDefault();
    my_table.move('right');
  });
});
table tr td {
  border: 1px solid black;
  padding: 2px;
}
.hilighted {
  border: 2px solid red;
  padding: 1px;
}
button.up {
  margin-left: 2em;
}
button.down {
  margin-left: 1.5em;
}
<script src="https://ajax.googleapis./ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<table>
  <tr>
    <td>1,1</td>
    <td>2,1</td>
    <td>3,1</td>
  </tr>
  <tr>
    <td>1,2</td>
    <td>2,2</td>
    <td>3,2</td>
  </tr>
  <tr>
    <td>1,3</td>
    <td>2,2</td>
    <td>3,3</td>
  </tr>
</table>

<button class="up">Up</button>

<div>
  <button class="left">Left</button>
  <button class="right">Right</button>
</div>

<button class="down">Down</button>

A convenient way to deal with this problem is to give meaningful id's to your cells. Navigation bees self-explanatory then.

var dimensionX = 4;
var dimensionY = 4;
var selected = "cell-0-0";

$(document).keydown(function(event) {

  event.preventDefault();
  $("#" + selected).removeClass("selected");
  var currentX = parseInt(selected.split("-")[1]);
  var currentY = parseInt(selected.split("-")[2]);

  switch (event.which) {
    case 37:
      selected = "cell-" + (currentX == 0 ? dimensionX - 1 : currentX - 1) + "-" + currentY;
      break;

    case 38:
      selected = "cell-" + currentX + "-" + (currentY == 0 ? dimensionY - 1 : currentY - 1);
      break;

    case 39:
      selected = "cell-" + ((currentX + 1) % dimensionX) + "-" + currentY;
      break;

    case 40:
      selected = "cell-" + currentX + "-" + ((currentY + 1) % dimensionY);
      break;
  }
  $("#" + selected).addClass("selected");
});

$("#up, #down, #left, #right").click(function() {

  var currentX = parseInt(selected.split("-")[1]);
  var currentY = parseInt(selected.split("-")[2]);
  $("#" + selected).removeClass("selected");

  switch (this.id) {
    case "up":
      selected = "cell-" + currentX + "-" + (currentY == 0 ? dimensionY - 1 : currentY - 1);
      break;
    case "down":
      selected = "cell-" + currentX + "-" + ((currentY + 1) % dimensionY);
      break;
    case "left":
      selected = "cell-" + (currentX == 0 ? dimensionX - 1 : currentX - 1) + "-" + currentY;
      break;
    case "right":
      selected = "cell-" + ((currentX + 1) % dimensionX) + "-" + currentY;
      break;
  }
  $("#" + selected).addClass("selected");
});

$("#mark").click(function() {
  if ($("#" + selected).hasClass("marked")) $("#" + selected).removeClass("marked");
  else $("#" + selected).addClass("marked");
});
td {
  border: 1px solid black;
}
td.selected {
  border: 1px solid red;
}
p.buttons > span {
  border: 1px solid grey;
  border-radius: 2px;
  cursor: pointer;
  margin: 0 3px;
  display: inline-block;
  padding: 1px 3px;
}
td.marked {
  background: black;
  color: white;
}
<script src="https://ajax.googleapis./ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table id="sheet">
  <tbody>
    <tr id="row-0">
      <td id="cell-0-0" class="selected">A</td>
      <td id="cell-1-0">B</td>
      <td id="cell-2-0">C</td>
      <td id="cell-3-0">D</td>
    </tr>
    <tr id="row-1">
      <td id="cell-0-1">E</td>
      <td id="cell-1-1">F</td>
      <td id="cell-2-1">G</td>
      <td id="cell-3-1">H</td>
    </tr>
    <tr id="row-2">
      <td id="cell-0-2">I</td>
      <td id="cell-1-2">J</td>
      <td id="cell-2-2">K</td>
      <td id="cell-3-2">L</td>
    </tr>
    <tr id="row-3">
      <td id="cell-0-3">M</td>
      <td id="cell-1-3">N</td>
      <td id="cell-2-3">O</td>
      <td id="cell-3-3">P</td>
    </tr>
  </tbody>
</table>
<p class="buttons"><span id="up">Up</span> <span id="down">Down</span>  <span id="left">Left</span> <span id="right">Right</span> <span id="mark">Mark</span></p>

You need to focus the snippet in order to use arrows to move around.

本文标签: