Adding functionality for using the up and down arrow keys to select a table row

后端 未结 4 2203
甜味超标
甜味超标 2021-02-10 15:17

I need the help of an expert on my question below as it exceed and goes well beyond the level of knowledge that I have for programming in JavaScript.

Given the existing

相关标签:
4条回答
  • 2021-02-10 16:00

    I don't think this actually needs to be that long--you just need to keep the index of the currently highlighted row.

    This has only been tested on Chrome (I don't have IE), but it should work.

    (function() {
    
    
    /**
     * Gets the tr at the specified row or column
     */
    var tbody = document.getElementsByTagName('tbody')[0];
    function getRow(row) {
        return tbody.getElementsByTagName('tr')[row];
    }
    
    // store these so we won't have to keep recalculating
    var numRows = tbody.getElementsByTagName('tr').length;
    
    // index of the currently highlighted row
    var curRow = 0;
    
    // highlight the initially highlighted cell
    getRow(curRow).className = 'highlighted';
    
    
    
    
    // listen for keydown event
    if (addEventListener) {
      window.addEventListener('keydown',keydownHandler, false);
    } else if (window.attachEvent) {
      window.attachEvent('onkeydown', keydownHandler);
    }
    
    
    
    // handle keydown event
    function keydownHandler (evt) {
        // return the old cell to normal
        getRow(curRow).className = 'normal';
    
        // increment/decrement the position of the current cell
        // depending on the key pressed
        if (evt.keyCode == 38 && curRow > 0) // up
            curRow--;
        else if (evt.keyCode == 40 && curRow < numRows-1) // down
            curRow++;
    
        // update the new cell
        getRow(curRow).className = 'highlighted';  
    }
    
    
    })();//end script
    
    0 讨论(0)
  • 2021-02-10 16:02

    I have create a demo using JQuery here on JSBin

    In general, we have 2 task:

    • highlight selected row
    • choose next/prev row

    To highlight the "clicked" row, I use this code

    $("#mstrTable tr").click(function(evt){
       var element = $(evt.target);
       var tableElement = element.parents('table');
       tableElement.find('tr').removeClass('highlighted');
       element.parents('tr').addClass('highlighted');
    });
    

    To choose next/prev row, I use jQuery tree traversal function with some exception when there is no tr inside your tbody. Note that keyCode of left, right, up, down arrow are 37, 39, 38, 40 respectively.

    $(document).keypress(function(evt){
              var highlightedRow = $("#mstrTable .highlighted");
              if (highlightedRow.length > 0) // table cell is selected
              {
                var tbodyElement = highlightedRow.parents('tbody');
                var trElements = tbodyElement.find('tr');
                var nextElement =  highlightedRow.next('tr');
                var prevElement = highlightedRow.prev('tr');
                trElements.removeClass("highlighted");
                switch(evt.keyCode)
                {
                  case 40:
                    if(nextElement.length)
                    {
                      nextElement.addClass('highlighted');
                    }
                    else if (trElements.length)
                    {
                      $(trElements[0]).addClass('highlighted'); 
                    }
                    break;
                  case 38:
                    if(prevElement.length)
                    {
                      prevElement.addClass('highlighted');
                    }
                    else if (trElements.length)
                    {
                      $(trElements[trElements.length - 1]).addClass('highlighted'); 
                    }
                    break;
                }
              }
            });
    
    0 讨论(0)
  • 2021-02-10 16:03

    Here is the complete solution which selects rows in table just like a windows file selection works.

    add class multiSelect to you table and then place this code in a JS file

    $(document).ready(function() {  
    var selectionPivot; 
    // code for selected rows. 
    $('.multiSelect tbody').on( 'click', 'tr', function (e) {
    var tbodyElement = $(this).parents('tbody');
    var trElements = tbodyElement.find('tr');
    if(!e.ctrlKey && (!e.shiftKey) ){   
      trElements.removeClass("row_selected");
      selectionPivot=$(this);
     } 
    
    if(e.shiftKey){ 
    var bot = Math.min(selectionPivot[0].rowIndex, $(this)[0].rowIndex);
    var top = Math.max(selectionPivot[0].rowIndex, $(this)[0].rowIndex);
    trElements.removeClass("row_selected");
    for(var i=bot; i<=top; i++){    
    trElements[i-1].className+=" row_selected";
    }     
    }  
    else  { 
       selectionPivot=$(this);
       trElements.removeClass("focus"); 
       $(this).addClass('focus');
        if ( $(this).hasClass('row_selected') ) {
        $(this).removeClass('row_selected');
        }
        else {      
            $(this).addClass('row_selected');
        }
    }
    });
    
    $(document).keypress(function(evt){
    if(evt.shiftKey){
          var highlightedRow = $(".multiSelect .focus");        
          if (highlightedRow.length > 0) // table cell is selected
          {
            var tbodyElement = highlightedRow.parents('tbody');
            var trElements = tbodyElement.find('tr');
            var nextElement =  highlightedRow.next('tr');
            var prevElement = highlightedRow.prev('tr');
            trElements.removeClass("focus");
            switch(evt.keyCode)
            {
              case 40:
                if(nextElement.length)
                {
                  nextElement.addClass('row_selected');
                  nextElement.addClass('focus');
                }
                else if (trElements.length)
                {
                  $(trElements[0]).addClass('row_selected'); 
                   $(trElements[0]).addClass('focus');
                }
                break;
              case 38:
                if(prevElement.length)
                {
                  prevElement.addClass('row_selected');
                  prevElement.addClass('focus');
                }
                else if (trElements.length)
                {
                  $(trElements[trElements.length - 1]).addClass('row_selected'); 
                    $(trElements[trElements.length - 1]).addClass('focus');
                }
                break;
            }
          }
          }
        });
        });
    
    0 讨论(0)
  • 2021-02-10 16:04

    This is certainly not optimal, but as you're not using jQuery (or a similar library) you've incurred a lot of cross browser overhead. This should be backwards compatible up to IE8.

    Live Demo

    HTML

    Only change here is the addition of the tabindex

    <table tabindex='0' id="mstrTable" cellspacing="0" border="1">
    

    JS

    //From: http://forrst.com/posts/JavaScript_Cross_Browser_Event_Binding-yMd
    var addEvent = (function( window, document ) {
        if ( document.addEventListener ) {
            return function( elem, type, cb ) {
                if ( (elem && !elem.length) || elem === window ) {
                    elem.addEventListener(type, cb, false );
                }
                else if ( elem && elem.length ) {
                    var len = elem.length;
                    for ( var i = 0; i < len; i++ ) {
                        addEvent( elem[i], type, cb );
                    }
                }
            };
        }
        else if ( document.attachEvent ) {
            return function ( elem, type, cb ) {
                if ( (elem && !elem.length) || elem === window ) {
                    elem.attachEvent( 'on' + type, function() { return cb.call(elem, window.event) } );
                }
                else if ( elem.length ) {
                    var len = elem.length;
                    for ( var i = 0; i < len; i++ ) {
                        addEvent( elem[i], type, cb );
                    }
                }
            };
        }
    })( this, document );
    
    //derived from: http://stackoverflow.com/a/10924150/402706
    function getpreviousSibling(element) {
        var p = element;
        do p = p.previousSibling;
        while (p && p.nodeType != 1);
        return p;
    }
    
    //derived from: http://stackoverflow.com/a/10924150/402706
    function getnextSibling(element) {
        var p = element;
        do p = p.nextSibling;
        while (p && p.nodeType != 1);
        return p;
    }
    
    ;(function() {
        var trows = document.getElementById("mstrTable").rows;
    
        for (var t = 1; t < trows.length; ++t) {
            trow = trows[t];
            trow.className = "normal";
            trow.onclick = highlightRow;
        }//end for
    
        function highlightRow() {
            for ( var t = 1; t < trows.length; ++t ) {
                trow = trows[t];
                if (trow != this) { trow.className = "normal" }
            }//end for
    
            this.className = (this.className == "highlighted")?"normal":"highlighted";
        }//end function
    
        addEvent(document.getElementById('mstrTable'), 'keydown', function(e){
            var key = e.keyCode || e.which;
    
            if((key === 38 || key === 40) && !e.shiftKey && !e.metaKey && !e.ctrlKey && !e.altKey){
    
                var highlightedRows = document.querySelectorAll('.highlighted'); 
    
                if(highlightedRows.length > 0){
    
                    var highlightedRow = highlightedRows[0];
    
                    var prev = getpreviousSibling(highlightedRow); 
                    var next = getnextSibling(highlightedRow); 
    
                    if(key === 38 && prev && prev.nodeName === highlightedRow.nodeName){//up
                        highlightedRow.className = 'normal';
                        prev.className = 'highlighted';
                    } else if(key === 40 && next && next.nodeName === highlightedRow.nodeName){ //down
                        highlightedRow.className = 'normal';
                        next.className = 'highlighted';
                    }
    
                }
            }
    
        });
    
    
    })();//end script
    
    0 讨论(0)
提交回复
热议问题