原生html+js输入框下拉多选带关闭模块完整案例

 

<!DOCTYPE html>
<html>
<head>
<title>多选下拉框</title>
<style>
* {
box-sizing: border-box;
margin: 0;
padding: 0;
}
.multi-select-container {
position: relative;
width: 300px;
margin: 20px;
font-family: Arial, sans-serif;
}
.multi-select-input {
width: 100%;
min-height: 40px;
padding: 5px;
border: 1px solid #ddd;
border-radius: 4px;
cursor: pointer;
display: flex;
flex-wrap: wrap;
gap: 5px;
align-items: center;
}
.multi-select-input:focus {
outline: none;
border-color: #4CAF50;
box-shadow: 0 0 5px rgba(76, 175, 80, 0.2);
}
.selected-item {
display: inline-flex;
align-items: center;
background: #e8f5e9;
border: 1px solid #4CAF50;
border-radius: 3px;
padding: 2px 8px;
margin: 2px;
font-size: 14px;
}
.remove-btn {
margin-left: 5px;
color: #666;
cursor: pointer;
font-size: 14px;
padding: 0 3px;
}
.remove-btn:hover {
color: #f44336;
}
.dropdown-list {
position: absolute;
top: 100%;
left: 0;
right: 0;
background: white;
border: 1px solid #ddd;
border-radius: 4px;
margin-top: 5px;
max-height: 200px;
overflow-y: auto;
z-index: 1000;
display: none;
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
}
.dropdown-item {
padding: 8px 12px;
cursor: pointer;
display: flex;
align-items: center;
}
.dropdown-item:hover {
background-color: #f5f5f5;
}
.dropdown-item.selected {
background-color: #e8f5e9;
color: #4CAF50;
}
.dropdown-item input[type="checkbox"] {
margin-right: 8px;
}
.limit-message {
color: #f44336;
font-size: 12px;
margin-top: 5px;
display: none;
}
/* 自定义滚动条 */
.dropdown-list::-webkit-scrollbar {
width: 6px;
}
.dropdown-list::-webkit-scrollbar-track {
background: #f1f1f1;
}
.dropdown-list::-webkit-scrollbar-thumb {
background: #888;
border-radius: 3px;
}
.dropdown-list::-webkit-scrollbar-thumb:hover {
background: #555;
}
</style>
</head>
<body>
<div class="multi-select-container">
<div class="multi-select-input" id="selectInput" tabindex="0">
<span class="placeholder">请选择分类...</span>
</div>
<div class="dropdown-list" id="dropdownList"></div>
<div class="limit-message">最多只能选择3个选项</div>
</div>
<script>
class MultiSelect {
constructor(options = {}) {
this.maxSelect = options.maxSelect || 3;
this.container = document.querySelector('.multi-select-container');
this.input = document.getElementById('selectInput');
this.dropdown = document.getElementById('dropdownList');
this.limitMessage = document.querySelector('.limit-message');
this.placeholder = this.input.querySelector('.placeholder');
this.selectedItems = new Set();
// 示例数据
this.items = options.items || [
{ id: 1, name: '技术' },
{ id: 2, name: '设计' },
{ id: 3, name: '产品' },
{ id: 4, name: '运营' },
{ id: 5, name: '市场' },
{ id: 6, name: '销售' },
{ id: 7, name: '客服' },
{ id: 8, name: '人力资源' }
];
this.init();
}
init() {
this.renderDropdown();
this.bindEvents();
}
renderDropdown() {
this.dropdown.innerHTML = this.items.map(item => `
<div class="dropdown-item" data-id="${item.id}">
<input type="checkbox" id="item${item.id}" ${this.selectedItems.has(item.id) ? 'checked' : ''}>
<label for="item${item.id}">${item.name}</label>
</div>
`).join('');
}
updateSelectedDisplay() {
const selectedHtml = Array.from(this.selectedItems).map(id => {
const item = this.items.find(i => i.id === id);
return `
<span class="selected-item" data-id="${id}">
${item.name}
<span class="remove-btn" data-id="${id}">×</span>
</span>
`;
}).join('');
this.input.innerHTML = selectedHtml || '<span class="placeholder">请选择分类...</span>';
}
toggleDropdown(show) {
this.dropdown.style.display = show ? 'block' : 'none';
if (show) {
this.renderDropdown();
}
}
bindEvents() {
// 点击输入框显示下拉列表
this.input.addEventListener('click', () => {
this.toggleDropdown(true);
});
// 点击其他地方关闭下拉列表
document.addEventListener('click', (e) => {
if (!this.container.contains(e.target)) {
this.toggleDropdown(false);
}
});
// 选择项目
this.dropdown.addEventListener('click', (e) => {
const item = e.target.closest('.dropdown-item');
if (!item) return;
const id = parseInt(item.dataset.id);
const checkbox = item.querySelector('input[type="checkbox"]');
if (this.selectedItems.has(id)) {
this.selectedItems.delete(id);
checkbox.checked = false;
} else {
if (this.selectedItems.size >= this.maxSelect) {
this.showLimitMessage();
return;
}
this.selectedItems.add(id);
checkbox.checked = true;
}
this.updateSelectedDisplay();
e.stopPropagation();
});
// 删除已选项
this.input.addEventListener('click', (e) => {
if (e.target.classList.contains('remove-btn')) {
const id = parseInt(e.target.dataset.id);
this.selectedItems.delete(id);
this.updateSelectedDisplay();
this.renderDropdown();
e.stopPropagation();
}
});
}
showLimitMessage() {
this.limitMessage.style.display = 'block';
setTimeout(() => {
this.limitMessage.style.display = 'none';
}, 2000);
}
// 获取选中的值
getSelected() {
return Array.from(this.selectedItems).map(id =>
this.items.find(item => item.id === id)
);
}
}
// 初始化
const multiSelect = new MultiSelect({
maxSelect: 3,
items: [
{ id: 1, name: '技术' },
{ id: 2, name: '设计' },
{ id: 3, name: '产品' },
{ id: 4, name: '运营' },
{ id: 5, name: '市场' },
{ id: 6, name: '销售' },
{ id: 7, name: '客服' },
{ id: 8, name: '人力资源' }
]
});
</script>
</body>
</html>

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/912441.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

在 Ubuntu 操作系统上:改变 App 任务栏菜单的背景色

Ubuntu 官方默认的终端&#xff0c;与操作系统的主题 theme 无关。

【优选算法 — 滑动窗口】滑动窗口小专题(一)

长度最小的子数组 长度最小的子数组 题目解析&#xff1a; 对于示例一 对于剩下两种示例&#xff1a; 解法一&#xff1a;暴力枚举 把所有的子数组全部枚举出来&#xff0c;并且枚举出的每一个子数组求和判断&#xff0c;返回长度最小的子数组&#xff1b; 时间复杂度 &…

半波整流器原理

一、二极管不控整流 1.阻性负载 1.1.电路拓扑结构 电路只由交流源、二极管和电阻组成。最基本的带阻性负载的半波整流器如图所示。输入源为交流源&#xff0c;目标是使输出电压含有非零直流分量&#xff0c;负载为R。功率二极管只允许电流往一个方向流动。 1.2.工作模态分析…

yolov8涨点系列之引入CBAM注意力机制

文章目录 YOLOv8 中添加注意力机制 CBAM 具有多方面的好处特征增强与选择通道注意力方面空间注意力方面 提高模型性能计算效率优化&#xff1a; yolov8增加CBAM具体步骤CBAM代码(1)在__init.pyconv.py文件的__all__内添加‘CBAM’(2)conv.py文件复制粘贴CBAM代码(3)修改task.py…

Rust-AOP编程实战

文章本天成&#xff0c;妙手偶得之。粹然无疵瑕&#xff0c;岂复须人为&#xff1f;君看古彝器&#xff0c;巧拙两无施。汉最近先秦&#xff0c;固已殊淳漓。胡部何为者&#xff0c;豪竹杂哀丝。后夔不复作&#xff0c;千载谁与期&#xff1f; ——《文章》宋陆游 【哲理】文章…

基于 SSM(Spring + Spring MVC + MyBatis)框架构建电器网上订购系统

基于 SSM&#xff08;Spring Spring MVC MyBatis&#xff09;框架构建电器网上订购系统可以为用户提供一个方便快捷的购物平台。以下将详细介绍该系统的开发流程&#xff0c;包括需求分析、技术选型、数据库设计、项目结构搭建、主要功能实现以及前端页面设计。 需求分析 …

Docker部署Oracle 11g

1&#xff0c;拉取镜像&#xff1a; sudo docker pull registry.cn-hangzhou.aliyuncs.com/helowin/oracle_11gsudo docker images 2&#xff0c;启动一个临时容器&#xff0c;用于拷贝数据库文件&#xff0c;挂载到宿主主机&#xff0c;使数据持久化&#xff1a; sudo docke…

Linux操作系统:学习进程_了解并掌握进程的状态

对进程状态之间转换感到头疼&#xff0c;只听书本概念根本无法理解&#xff0c;死记硬背不是什么好的解决方法。只有进行底层操作去了解每一个进程状态&#xff0c;才能彻底弄清楚进程状态是如何转换的。 一、进程的各个状态 我们先从Linux内核数据结构来看&#xff1a; 每一个…

分布式环境下宕机的处理方案有哪些?

大家好&#xff0c;我是锋哥。今天分享关于【分布式环境下宕机的处理方案有哪些&#xff1f;】面试题。希望对大家有帮助&#xff1b; 分布式环境下宕机的处理方案有哪些&#xff1f; 1000道 互联网大厂Java工程师 精选面试题-Java资源分享网 在现代分布式系统中&#xff0c;…

接触角测量(Contact Angle Measurement)

接触角是指液滴在固体表面上的形态&#xff0c;特别是在气、液、固三相交界点处&#xff0c;气-液界面切线与固-液交界线之间的夹角。这个角度是衡量液体对固体表面润湿性的一个重要参数。接触角的大小可以反映液体与固体之间的相互作用强度&#xff0c;从而了解液体在固体表面…

《操作系统 - 清华大学》2 -2:中断、异常和系统调用

文章目录 1. 中断和异常处理机制1.1 中断1.2 异常 2. 系统调用2.1 标志C库的例子2.2 编程接口 3.系统调用的实现4. 程序调用和系统调用的不同处5. 中断、异常和系统调用的开销 1. 中断和异常处理机制 接下来看一看中断和异常的处理过程&#xff0c;看下图就比较清楚&#xff0…

Nginx简易配置将内网网站ssh转发到外网

声明&#xff1a;本内容仅供交流学习使用&#xff0c;部署网站上线还需要根据有关规定申请域名以及备案。 背景 在内网的服务器有一个运行的网页&#xff0c;现使用ssh反向代理&#xff0c;将它转发到外网的服务器。 但是外网的访问ip会被ssh反向代理拦截 所以使用Nginx进行…

Moment.js、Day.js、Miment,日期时间库怎么选?

一直以来&#xff0c;处理时间和日期的JavaScript库&#xff0c;选用的都是Momment.js。它的API清晰简单&#xff0c;使用方便灵巧&#xff0c;功能还特别齐全。 大师兄是Moment.js的重度使用者。凡是遇到时间和日期的操作&#xff0c;就把Moment.js引用上。 直到有天我发现加…

后台管理系统窗体程序:文章管理 > 文章发表

目录 文章列表的的功能介绍&#xff1a; 1、进入页面 2、页面内的各种功能设计 &#xff08;1&#xff09;进入选择 &#xff08;2&#xff09;当获取到唯一标识符时 &#xff08;3&#xff09;当没有标识符时 &#xff08;4&#xff09;发布按钮&#xff0c;存为草稿 一、网…

Linux服务控制及系统基本加固

一. liunx操作系统的开机引导的过程 1. 开机自检 根据bios的设置&#xff0c;对cpu,内存&#xff0c;显卡&#xff0c;键盘等等设备进行初步检测如果以上检测设备工作正常&#xff0c;系统会把控制权移交到硬盘 总结:检测出包含系统启动操作系统的设备&#xff0c;硬盘&#…

通过 SSH 隧道将本地端口转发到远程主机

由于服务器防火墙,只开放了22端口,想要通过5901访问服务器上的远程桌面,可以通过下面的方式进行隧道转发。 一、示例命令 这条代码的作用是通过 SSH 创建一个 本地端口转发,将你本地的端口(5901)通过加密的 SSH 隧道连接到远程服务器上的端口(5901)。这种方式通常用于在…

WPF+MVVM案例实战与特效(二十八)- 自定义WPF ComboBox样式:打造个性化下拉菜单

文章目录 1. 引言案例效果3. ComboBox 基础4. 自定义 ComboBox 样式4.1 定义 ComboBox 样式4.2 定义 ComboBoxItem 样式4.3 定义 ToggleButton 样式4.4 定义 Popup 样式5. 示例代码6. 结论1. 引言 在WPF应用程序中,ComboBox控件是一个常用的输入控件,用于从多个选项中选择一…

C#中日期和时间的处理

目录 前言 时间对于我们的作用 一些关于时间的名词说明 格里高利历 格林尼治时间(GMT) 协调世界时(UTC) 时间戳 DateTime 初始化 获取时间 计算时间 字符串转DateTime 存储时间 TimeSpan 初始化它来代表时间间隔 用它相互计算 自带常量方便用于和ticks进行计…

pdb和gdb的双剑合璧,在python中调试c代码

左手编程&#xff0c;右手年华。大家好&#xff0c;我是一点&#xff0c;关注我&#xff0c;带你走入编程的世界。 公众号&#xff1a;一点sir&#xff0c;关注领取python编程资料 问题背景 正常情况下&#xff0c;调试python代码用pdb&#xff0c;调试c代码用gdb&#xff0c;…

【Apache ECharts】<农作物病害发生防治面积>

在vs Code里打开&#xff0c; 实现 1. 首先引入 echarts.min.js 资源 2. 在body部分设一个 div&#xff0c;设置 id 为 main 3. 设置 script 3.1 基于准备好的dom&#xff0c;初始化echarts实例 var myChart echarts.init(document.getElementById(main)); 3.2 指定图表的…