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

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

项目效果

操作方法

  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 的多选功能的更多相关文章

  1. js获取checkbox中所有选中值及input后面所跟的文本

    <html> <head> <meta http-equiv="Content-Type" content="text/html; char ...

  2. D3.js v4版本 按住shift键框选节点demo

    http://download.csdn.net/download/qq_25042329/10139649

  3. jQuery 判断多个 input checkbox 中至少有一个勾选

    html ( 使用 TP 标签 ) : <volist name="health_tag" id="htag"> <input type=&q ...

  4. js~一个列表中包含上移下移删除等功能

    最近做了一个项目,包括了一个列表页,为了用户体验,操作均使用JS实现,其中包括在列表中实现上移,下移,删除等功能,前台JS,后端数据修改使用AJAX,本文主要说一下前台JS这块 先看一下页面的截图

  5. [原创]纯JS实现网页中多选复选框checkbox和单选radio的美化效果

    图片素材: 最终效果图: <html><title> 纯JS实现网页中多选复选框checkbox和单选radio的美化效果</title><head>& ...

  6. ASP.NET js控制treeview中的checkbox实现单选功能

    ASP.NET js控制treeview中的checkbox实现单选功能 function OnTreeNodeChecked() { var element = window.event.srcEl ...

  7. 使用js获取checkbox控件在GridView中的第几行

    这次的知识点是如何使用js获取checkbox控件所在的是第几行!!! 我们可以使用 JavaScript 中自带的 rowIndex 和 cellIndex 来获取行和列的键值 (从0开始) 这两个 ...

  8. js实现reqire中的amd,cmd功能

    js实现reqire中的amd,cmd功能 ,大概实现了 路径和模块 引入等重要功能. 本帖属于原创,转载请出名出处. <!DOCTYPE html PUBLIC "-//W3C//D ...

  9. js获取URL中的参数

    js获取URL中的一些参数的意思 location对象 含有当前URL的信息. 属性 href 整个URL字符串. protocol 含有URL第一部分的字符串,如http: host 包含有URL中 ...

随机推荐

  1. html续篇及初识爬虫

    今日内容概要 form表单 requests模块 可以模拟浏览器朝服务端发送各式各样的请求 cookie与session requests模块小案例(网站的基本防爬措施) 今日内容详细 form表单 ...

  2. Django中的Session和cookie

    Session和cookie 参考文献:https://www.cnblogs.com/wupeiqi/articles/5246483.html 1.问题引入 1.1 cookie是什么? 保存在客 ...

  3. [csi]浅聊ceph-csi组件

    描述   ceph-csi扩展各种存储类型的卷的管理能力,实现第三方存储ceph的各种操作能力与k8s存储系统的结合.调用第三方存储ceph的接口或命令,从而提供ceph数据卷的创建/删除.挂载/解除 ...

  4. ASP.NET Core 6框架揭秘实例演示[19]:数据加解密与哈希

    数据保护(Data Protection)框架旨在解决数据在传输与持久化存储过程中的一致性(Integrity)和机密性(confidentiality)问题,前者用于检验接收到的数据是否经过篡改,后 ...

  5. 微服务7:通信之RPC

    ★微服务系列 微服务1:微服务及其演进史 微服务2:微服务全景架构 微服务3:微服务拆分策略 微服务4:服务注册与发现 微服务5:服务注册与发现(实践篇) 微服务6:通信之网关 微服务7:通信之RPC ...

  6. pandas连接数据库

    项目中使用pandas方法读取数据库数据可能用到的方法 使用pandas连接数据库 例如 mysql_conn = pymysql.connect(host='172.28.*.***', port= ...

  7. 25 面向对象编程 继承概念 代码 快捷键 super注意点

    继承概念 继承的本质是对某一批的抽象,从而实现对现实世界更美好的建模. extends的意思的"扩展".子类是父类的扩展. JAVA中类只有单继承,没有多继承!理解:一个儿子只能有 ...

  8. x86-7-页式管理(Paging)

    x86-7-页式管理(Paging) 页式管理是重中之重! 在段式管理下操作系统的运作出现了很多问题,因为段的长度不定,在分配内存时,可能会发生内存中的空闲区域小于要加载的段,或者空闲区域远远大于要加 ...

  9. 了解Redis持久化

    Redis是一个键值对数据库服务器,由于Redis是内存数据库,那么有很多内存的特点,例如掉电易失,或者进程退出,服务器中的数据也将消失不见,所以需要一种方法将数据从内存中写到磁盘,这一过程称之为数据 ...

  10. c# winform 窗体 对话框绑定的值如何填到主窗体问题

    这段代码放在主窗体中 private void txt_KeJiaAModel_DoubleClick(object sender, EventArgs e) { TimerEvent(); } // ...