Day10 - JS 实现 Checkbox 中按住 Shift 的多选功能

冯方
• 阅读 1617

Day10 - JS 实现 Checkbox 中按住 Shift 的多选功能

作者:©liyuechun
简介:JavaScript30Wes Bos 推出的一个 30 天挑战。项目免费提供了 30 个视频教程、30 个挑战的起始文档和 30 个挑战解决方案源代码。目的是帮助人们用纯 JavaScript 来写东西,不借助框架和库,也不使用编译器和引用。现在你看到的是这系列指南的第 10 篇。完整中文版指南及视频教程在 从零到壹全栈部落

项目效果

Day10 - JS 实现 Checkbox 中按住 Shift 的多选功能

操作方法

  1. 选中 A 项
  2. 按下 Shift
  3. 再选中 B 项
  4. A-B 之间的所有项都被选中或者取消

实现方法

方法一

Wes Bos 在文档里提供了一种解决办法:用一个变量,来标记这个范围。

变量初始值为 false,当按下 Shift 键且同时选中了某个元素的时候,遍历所有项,遍历过程中,若遇到 A 或 B,则将标记值取反。同时,将所有标记为 true 的项设置为选中。

let startChecked;

//    处理方法一:用变量 inBetween 对需要选中的元素进行标记
function handleCheck0(e) {
    let inBetween = false;
    if(e.shiftKey && this.checked){
        boxs.forEach(input => {
            console.log(input);
            if(input === startChecked || input ===this) {
                inBetween = !inBetween;
            }
            if(inBetween) {
                console.log("on");
                input.checked = true;
            }
    });
    }
    startChecked = this;
}

方法二

上面会出现一个问题,初次加载页面时,按住 Shift 再点击某一项,此项之后的元素都会被选中。此外,对于取消选中,无法批量操作。下面方法三是缉熙Soyaine 的操作逻辑。方法二是我对Wes Bos实现方法逻辑的改进,方法二和方法三取消和选中均可批量操作。


let startChecked;
let onOff = false;
//    处理方法二:新增onOff变量存储复选框将要改变的状态
function handleCheck2(e) {
 let inBetween = false;
 if (e.shiftKey) {
   onOff = startChecked.checked ? true : false;
   boxs.forEach(input => {
     console.log(input);
     if (input === startChecked || input === this) {
       inBetween = !inBetween;
     }
     if (inBetween && input !== startChecked || input === this) {
       input.checked = onOff;
     }
   });
   startChecked = this;
 }
 startChecked = this;
}

onOff = startChecked.checked ? true : false; 根据startChecked设置要改变的状态。同时在if (inBetween && input !== startChecked || input === this)代码里面做了修改,新增了|| input === this,否则会出现最后一个的状态和其他复选框状态不一致的bug。

方法三

方法一中的 inBetween 仅仅表示此项是否在被选中的范围中,此处会赋给它更多的意义,用它来表示此项是选中还是未选中,而范围划定则由数组来解决。

首先将获取到的 <input> 组转化为数组,针对每次操作,获取 A 和 B,利用 indexOf() 来获得 A 和 B 在数组中的索引值,由此即可确定范围,并能通过 slice() 来直接截取 A-B 的所有 DOM 元素,并进行状态改变的操作,而变量 onOff 表示 A-B 范围内的状态,true 表示选中,false 表示取消选中。

const boxArr = Array.from(boxs);
let startChecked;
let onOff = false;

// 处理方法二:利用数组索引获取需要选中的范围
function handleCheck1(e) {
    if(!startChecked) startChecked = this;
    onOff = startChecked.checked ? true : false;
    if(e.shiftKey) {
        let start = boxArr.indexOf(this);
        let end = boxArr.indexOf(startChecked);
        boxArr.slice(Math.min(start, end), Math.max(start, end) + 1)
                   .forEach(input => input.checked = onOff);
        console.log(start + "+" + end);
    }
    startChecked = this;
}
  1. 转换 Nodelist 为数组

    const boxs = document.querySelectorAll('.inbox input[type="checkbox"]');
    const boxArr = Array.from(boxs);
  2. 针对按下了 Shift 键的情况,获取 A-B 范围

    let start = boxArr.indexOf(this);
    let end = boxArr.indexOf(startChecked);
  3. 截取该范围内的数组元素,并改变选中状态

    boxArr.slice(Math.min(start, end), Math.max(start, end) + 1)
                       .forEach(input => input.checked = onOff);
  4. 确定选中 or 取消选中

    onOff = startChecked.checked ? true : false;
  5. 标记 A 值

    if(!startChecked) startChecked = this;
    /* ... */
    startChecked = this;

源码下载

Github Source Code

社群品牌:从零到壹全栈部落

定位:寻找共好,共同学习,持续输出全栈技术社群

业界荣誉:IT界的逻辑思维

文化:输出是最好的学习方式

官方公众号:全栈部落

社群发起人:春哥(从零到壹创始人,交流微信:liyc1215)

技术交流社区:全栈部落BBS

全栈部落完整系列教程:全栈部落完整电子书学习笔记

关注全栈部落官方公众号,每晚十点接收系列原创技术推送
Day10 - JS 实现 Checkbox 中按住 Shift 的多选功能
点赞
收藏
评论区
推荐文章
blmius blmius
3年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
Karen110 Karen110
3年前
一篇文章带你了解JavaScript日期
日期对象允许您使用日期(年、月、日、小时、分钟、秒和毫秒)。一、JavaScript的日期格式一个JavaScript日期可以写为一个字符串:ThuFeb02201909:59:51GMT0800(中国标准时间)或者是一个数字:1486000791164写数字的日期,指定的毫秒数自1970年1月1日00:00:00到现在。1\.显示日期使用
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
待兔 待兔
1年前
手写Java HashMap源码
HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22
Jacquelyn38 Jacquelyn38
4年前
2020年前端实用代码段,为你的工作保驾护航
有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )
Stella981 Stella981
3年前
Jquery中prop( )和attr( )的区别和用法
 1.碰到的“坑”<label<inputtype"checkbox"class"checkbox"id"apple"苹果<inputtype"checkbox"class"checkbox"id"banana"香蕉<inputtype"checkbox"clas
Stella981 Stella981
3年前
Django中Admin中的一些参数配置
设置在列表中显示的字段,id为django模型默认的主键list_display('id','name','sex','profession','email','qq','phone','status','create_time')设置在列表可编辑字段list_editable
暗箭伤人 暗箭伤人
1年前
【www.ithunter.club】 20230922下午
不容易的2023年,我们一起努力【www.ithunter.club】(2023092208:00:00.8872062023092216:00:00.887206)1.人事招聘专员数名(可选远程或入职)2.招聘向坐标东京Yahoo、Shift、L
达里尔 达里尔
1年前
给数组添加新数据,判断数据是否重复
多选要进行数组拼接,希望判断往原数组里添的新数据是否重复,封装个简易方法languageconstdataArrayname:'aaa',id:1,name:'bbb',id:2;constnewDataname:'ccc',id:2;//要添加的新数
Python进阶者 Python进阶者
1年前
Excel中这日期老是出来00:00:00,怎么用Pandas把这个去除
大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Pandas数据筛选的问题。问题如下:这日期老是出来00:00:00,怎么把这个去除。二、实现过程后来【论草莓如何成为冻干莓】给了一个思路和代码如下:pd.toexcel之前把这
美凌格栋栋酱 美凌格栋栋酱
5个月前
Oracle 分组与拼接字符串同时使用
SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(