使用控制键和Shift键选择多行 [英] select multiple rows using control and shift key

查看:90
本文介绍了使用控制键和Shift键选择多行的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

演示

<table id="tableStudent" border="1">
  <thead>
    <tr><th>ID</th><th>Name</th>                            <th>Class</th></tr>
  </thead>
  <tbody>
    <tr><td>1</td><td>John</td><td>4th</td></tr>
   <tr><td>2</td><td>Jack</td><td>5th</td></tr>
   <tr><td>3</td><td>Michel</td><td>6th</td></tr>
   <tr><td>4</td><td>Mike</td><td>7th</td></tr>
       <tr><td>5</td><td>Yke</td><td>8th</td></tr>
       <tr><td>6</td><td>4ke</td><td>9th</td></tr>
       <tr><td>7</td><td>7ke</td><td>10th</td></tr>
  </tbody>
</table>

$('tr').on('click',function(e)
{
   var objTR=$(this); 

});

我必须使用控制键选择多行. 然后将学生ID存储在数组中. 我应该如何使用jquery Click事件.

解决方案

如果只希望在按下控制键时点亮单元格,则此代码可以解决问题:

var studendIds = [];
$(window).on('keydown',(function()
{
    var target = $('tr'),
    root = $(window),
    clickCb = function(e)
    {
        if (!$(this).hasClass('ui-selected'))
        {
            $(this).addClass('ui-selected');
            //add id to array
            studentIds.push(+(this.cells[0].innerHTML))
        }
        else
        {
            $(this).removeClass('ui-selected');
            for(var i=0;i<studentIds.length;i++)
            {
                if (studentIds[i] === +(this.cells[0].innerHTML))
                {//remove id from array
                    delete studentIds[i];
                    break;
                }
            }
        }
    },
    upCb = function(e)
    {
        target.off('click',clickCb);
        root.on('keydown',downCb);
        root.off('keyup',upCb);
    },
    downCb = function(e)
    {
        if (e.which === 17 || e.which === 16)
        {//17 is ctrl, 16 is shift
            root.off('keydown',downCb);
            root.on('keyup',upCb);
            target.on('click',clickCb);
        }
    };
    return downCb;
}()));

小提琴演示.

从本质上讲,这段代码所做的是侦听keydown事件.如果该键是ctrl键(代码17),则附加一个单击侦听器,如果单击特定的行,它将设置/取消ui-selected类.处理程序还会分离keydown侦听器本身,并附加一个keyup侦听器,一旦释放ctrl键,该侦听器会将事件侦听器设置回其原始状态. 同时,附加了另一个侦听器,该侦听器在keyup事件中接听.如果释放键(ctrl),则会删除单击侦听器,并还原keydown事件侦听器.

正如我在评论中所说,尽管上面的代码确实跟踪选择了哪些ID,但我个人会这样做.
每当您需要这些ID(可能是在表单提交或执行Ajax请求)时,看到您已将这些行标记为使用类时,我就会这样做:

function assumingAjaxFunction()
{
    var data = {some: 'boring', stuff: 'you might send', ids: []};
    $('.ui-selected > td:first').each(function()
    {
        data.ids.push($(this).text());
    });
    console.log(data.ids);//array of ids
}

支持班次选择功能的VanillaJS提琴

及其附带的代码:

window.addEventListener('load',function load()
{
    'use strict';
    var tbl = document.getElementById('tableStudent');
    window.addEventListener('keydown',(function()
    {
        var expr = /\bui\-selected\b/i,
            key, prev,
            clickCb = function(e)
            {
                e = e || window.event;
                var i, target = (function(elem)
                {//get the row element, in case user clicked on cell
                    if (elem.tagName.toLowerCase() === 'th')
                    {//head shouldn't be clickable
                        return elem;
                    }
                    while(elem !== tbl)
                    {//if elem is tbl, we can't determine which row was clicked anyway
                        if (elem.tagName.toLowerCase() === 'tr')
                        {//row found, break
                            break;
                        }
                        elem = elem.parentNode;//if td clicked, goto parent (ie tr)
                    }
                    return elem;
                }(e.target || e.srcElement));
                if (target.tagName.toLowerCase() !== 'tr')
                {//either head, table or something else was clicked
                    return e;//stop handler
                }
                if (expr.test(target.className))
                {//if row WAS selected, unselect it
                    target.className = target.className.replace(expr, '');
                }
                else
                {//target was not selected
                    target.className += ' ui-selected';//set class
                }
                if (key === 17)
                {//ctrl-key was pressed, so end handler here
                    return e;
                }
                //key === 16 here, handle shift event
                if (prev === undefined)
                {//first click, set previous and return
                    prev = target;
                    return e;
                }
                for(i=1;i<tbl.rows.length;i++)
                {//start at 1, because head is ignored
                    if (tbl.rows[i] === target)
                    {//select from bottom to top
                        break;
                    }
                    if (tbl.rows[i] === prev)
                    {//top to bottom
                        prev = target;//prev is bottom row to select
                        break;
                    }
                }
                for(i;i<tbl.rows.length;i++)
                {
                    if (!expr.test(tbl.rows[i].className))
                    {//if cel is not selected yet, select it
                        tbl.rows[i].className += 'ui-selected';
                    }
                    if (tbl.rows[i] === prev)
                    {//we've reached the previous cell, we're done
                        break;
                    }
                }
            },
            upCb = function(e)
            {
                prev = undefined;//clear prev reference, if set
                window.addEventListener('keydown',downCb,false);//restore keydown listener
                tbl.removeEventListener('click',clickCb, false);//remove click
                window.removeEventListener('keyup',upCb,false);//and keyup listeners
            },
            downCb = function(e)
            {//this is the actual event handler
                e= e || window.event;
                key = e.which || e.keyCode;//which key was pressed
                if (key === 16 || key === 17)
                {//ctrl or shift:
                    window.removeEventListener('keydown',downCb,false);//ignore other keydown events
                    tbl.addEventListener('click',clickCb,false);//listen for clicks
                    window.addEventListener('keyup', upCb, false);//register when key is released
                }
            };
        return downCb;//return handled
    }()), false);
    window.removeEventListener('load',load,false);
}, false);

此代码已接近复制粘贴准备就绪,因此,请至少给它一个机会.检查小提琴,对我来说很好.它也通过相当严格的设置(/*jslint browser: true, white: true */)传递JSlint,因此可以肯定地说这段代码还不错.是的,它看起来可能有些复杂.但是,快速阅读有关事件委派的工作方式的很快就会发现,委托事件比您想象的要容易
该代码还大量使用了闭包,闭包是一个强大的概念,本质上也不是那么难理解,该链接答案使用的图像来自本文的文章:JavaScript闭包得到了解释.读起来很容易,但是做得很好.阅读完此内容后,您将看到闭包是必不可少的,简单的,功能强大的且被低估的结构,当然,

Demo

<table id="tableStudent" border="1">
  <thead>
    <tr><th>ID</th><th>Name</th>                            <th>Class</th></tr>
  </thead>
  <tbody>
    <tr><td>1</td><td>John</td><td>4th</td></tr>
   <tr><td>2</td><td>Jack</td><td>5th</td></tr>
   <tr><td>3</td><td>Michel</td><td>6th</td></tr>
   <tr><td>4</td><td>Mike</td><td>7th</td></tr>
       <tr><td>5</td><td>Yke</td><td>8th</td></tr>
       <tr><td>6</td><td>4ke</td><td>9th</td></tr>
       <tr><td>7</td><td>7ke</td><td>10th</td></tr>
  </tbody>
</table>

$('tr').on('click',function(e)
{
   var objTR=$(this); 

});

I have to select multiple rows using control key. And then store Student ID in array. How should i do using jquery Click event.

解决方案

If you only want the cells to light up when the control key is pressed, this code does the trick:

var studendIds = [];
$(window).on('keydown',(function()
{
    var target = $('tr'),
    root = $(window),
    clickCb = function(e)
    {
        if (!$(this).hasClass('ui-selected'))
        {
            $(this).addClass('ui-selected');
            //add id to array
            studentIds.push(+(this.cells[0].innerHTML))
        }
        else
        {
            $(this).removeClass('ui-selected');
            for(var i=0;i<studentIds.length;i++)
            {
                if (studentIds[i] === +(this.cells[0].innerHTML))
                {//remove id from array
                    delete studentIds[i];
                    break;
                }
            }
        }
    },
    upCb = function(e)
    {
        target.off('click',clickCb);
        root.on('keydown',downCb);
        root.off('keyup',upCb);
    },
    downCb = function(e)
    {
        if (e.which === 17 || e.which === 16)
        {//17 is ctrl, 16 is shift
            root.off('keydown',downCb);
            root.on('keyup',upCb);
            target.on('click',clickCb);
        }
    };
    return downCb;
}()));

Fiddle demo.

What this code does, essentially, is listen for a keydown event. If that key is the ctrl key (code 17), a click listener is attached, that will set/unset the ui-selected class if a particular row is clicked. The handler also detaches the keydown listener itself and attaches a keyup listener that sets up the event listeners back to their original states once the ctrl key is released. Meanwhile, another listener is attached, that picks up on the keyup event. If the key (ctrl) is released, the click listener is removed, and the keydown event listener is restored.

As I said in the comments, though the code above does keep track of which ids are selected, I'd personally not do that.
Whenever you need those ids (probably on form submission, or to perform an ajax request), seeing as you have those rows marked usign a class, I'd just do this:

function assumingAjaxFunction()
{
    var data = {some: 'boring', stuff: 'you might send', ids: []};
    $('.ui-selected > td:first').each(function()
    {
        data.ids.push($(this).text());
    });
    console.log(data.ids);//array of ids
}

VanillaJS fiddle with shift-select support

and the code to go with it:

window.addEventListener('load',function load()
{
    'use strict';
    var tbl = document.getElementById('tableStudent');
    window.addEventListener('keydown',(function()
    {
        var expr = /\bui\-selected\b/i,
            key, prev,
            clickCb = function(e)
            {
                e = e || window.event;
                var i, target = (function(elem)
                {//get the row element, in case user clicked on cell
                    if (elem.tagName.toLowerCase() === 'th')
                    {//head shouldn't be clickable
                        return elem;
                    }
                    while(elem !== tbl)
                    {//if elem is tbl, we can't determine which row was clicked anyway
                        if (elem.tagName.toLowerCase() === 'tr')
                        {//row found, break
                            break;
                        }
                        elem = elem.parentNode;//if td clicked, goto parent (ie tr)
                    }
                    return elem;
                }(e.target || e.srcElement));
                if (target.tagName.toLowerCase() !== 'tr')
                {//either head, table or something else was clicked
                    return e;//stop handler
                }
                if (expr.test(target.className))
                {//if row WAS selected, unselect it
                    target.className = target.className.replace(expr, '');
                }
                else
                {//target was not selected
                    target.className += ' ui-selected';//set class
                }
                if (key === 17)
                {//ctrl-key was pressed, so end handler here
                    return e;
                }
                //key === 16 here, handle shift event
                if (prev === undefined)
                {//first click, set previous and return
                    prev = target;
                    return e;
                }
                for(i=1;i<tbl.rows.length;i++)
                {//start at 1, because head is ignored
                    if (tbl.rows[i] === target)
                    {//select from bottom to top
                        break;
                    }
                    if (tbl.rows[i] === prev)
                    {//top to bottom
                        prev = target;//prev is bottom row to select
                        break;
                    }
                }
                for(i;i<tbl.rows.length;i++)
                {
                    if (!expr.test(tbl.rows[i].className))
                    {//if cel is not selected yet, select it
                        tbl.rows[i].className += 'ui-selected';
                    }
                    if (tbl.rows[i] === prev)
                    {//we've reached the previous cell, we're done
                        break;
                    }
                }
            },
            upCb = function(e)
            {
                prev = undefined;//clear prev reference, if set
                window.addEventListener('keydown',downCb,false);//restore keydown listener
                tbl.removeEventListener('click',clickCb, false);//remove click
                window.removeEventListener('keyup',upCb,false);//and keyup listeners
            },
            downCb = function(e)
            {//this is the actual event handler
                e= e || window.event;
                key = e.which || e.keyCode;//which key was pressed
                if (key === 16 || key === 17)
                {//ctrl or shift:
                    window.removeEventListener('keydown',downCb,false);//ignore other keydown events
                    tbl.addEventListener('click',clickCb,false);//listen for clicks
                    window.addEventListener('keyup', upCb, false);//register when key is released
                }
            };
        return downCb;//return handled
    }()), false);
    window.removeEventListener('load',load,false);
}, false);

This code is close to copy-paste ready, so please, at least give it a chance. Check the fiddle, it works fine for me. It passes JSlint in with fairly strict settings, too (/*jslint browser: true, white: true */), so it's safe to say this code isn't that bad. Yes it may look somewhat complicated. But a quick read-up about how event delegation works will soon turn out that delegating an event is easier than you think
This code also heavily uses closures, a powerful concept which, in essence isn't really that hard to understand either, this linked answer uses images that came from this article: JavaScript closures explained. It's a fairly easy read, but it does a great job. After you've read this, you'll see closures as essential, easy, powerful and undervalued constructs, promise

这篇关于使用控制键和Shift键选择多行的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆