维护老项目,临时写个jquery的select联动组件

组件特点

  • jq环境
  • 封装可复用
  • 使用简单

代码

赶任务,bug后面慢慢修复,没做联动数量限制。
更新: 修复了大部分可见的bug,已在项目中使用。
在这里插入图片描述

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
		<style>
						 
			.jq-cascader {
				display: inline-block;
				border: 1px solid #ccc;
				cursor: pointer;
				position: relative;
				width: 200px;
				height: 26px;
				line-height: 26px;
				padding: 0 5px;
				box-sizing: border-box;
				font-size: 12px;
				background-color: #fff;
			}

			.jq-cascader * {
				box-sizing: border-box;
			}

			.jq-cascader .body .value {
				color: #666;
			}

			.jq-cascader .body .arrow {
				border-top: 2px solid #333;
				border-right: 2px solid #333;
				width: 6px;
				height: 6px;
				display: inline-block;
				position: absolute;
				right: 10px;
				top: 9px;
				transform: rotate(135deg);
				transform-origin: center;
				transition: 0.2s;
			}

			.jq-cascader .dropdown-content {
				position: absolute;
				left: -1px;
				top: 26px;
				display: flex;
				z-index: 100;
				height: 0px;
				overflow: hidden;
			}

			.jq-cascader .dropdown-content.show {
				height: 150px;
			}

			.jq-cascader .dropdown-content>.box {
				width: 100px;
				height: 150px;
				border: 1px solid #ccc;
				border-left: 0;
				overflow: auto;
				padding: 1px;
				background-color: #fff;
			}

			.jq-cascader .dropdown-content>.box:first-child {
				width: 100px;
				height: 150px;
				border-left: 1px solid #ccc;
			}


			.jq-cascader .dropdown-content>.box.no-data {
				width: 200px;
				height: 100px;
				background-color: #fff;
				text-align: center;
				color: #999;
				font-size: 12px;
			}

			.jq-cascader .dropdown-content>.box>.item {
				height: 26px;
				line-height: 26px;
				padding: 0 5px;
				display: flex;
				justify-dropdown-content: space-between;
				position: relative;
				background-color: #fff;
			}

			.jq-cascader .dropdown-content>.box>.item:hover,
			.jq-cascader .dropdown-content>.box>.item.active {
				background-color: #ccc;
				color: #fff;
			}

			.jq-cascader .dropdown-content>.box>.item>.arrow {
				border-top: 1px solid #333;
				border-right: 1px solid #333;
				width: 5px;
				height: 5px;
				display: inline-block;
				position: absolute;
				right: 10px;
				top: 10px;
				transform: rotate(45deg);
			}

			.jq-cascader .dropdown-content>.box>.item>span {
				width: 80%;
				overflow: hidden;
				text-overflow: ellipsis;
				white-space: nowrap;
			}		
 	</style>
	</head>
	<body>
		<div>
			
			<div class="jq-cascader" id="myCascader"></div>
			<div class="jq-cascader" id="myCascader2"></div>

		</div>
		<script src="jquery-1.12.4.min.js"></script>
		<script>
			
			/**
			 * 联动选择器
			 * @param {string} id
			 * @param {[{label: string; value: string; children: []}]}  sourceData
			 * @param {boolean} selectRoot - 是否必需选择根节点, 默认 false
			 */
			var JQCascader = function (id, sourceData, selectRoot) {
			  this.id = id;
			  this.cascader = $('#' + this.id);
			  this.body = null;
			  this.content = null;
			  this.html = '';
			  this.uid = '';
			  this.label = '';
			  this.label = '';
			  this.selectRoot = selectRoot || false;
			  console.log(this.selectRoot);
			  this.sourceData = sourceData || [];
			  this.init();
			};
			
			// 原型方法
			JQCascader.prototype = {
			  init: function () {
			    var that = this;
			
			    this.initContainer();
			
			    this.initData(this.sourceData);
			
			    this.setChecked();
			
			    this.body.click(function (e) {
			      that.show();
			    });
			
			    this.body.find('.clear').click(function (e) {
			      that.clear();
			    });
			
			    this.content.on('click', '.item', function () {
			      that.uid = $(this).attr('data-uid');
			      that.setChecked();
			    });
			
			    $(document).on('click', function (event) {
			      if ($(event.target).attr('data-tag') !== that.id) {
			        that.hide();
			      }
			    });
			  },
			  // 渲染下拉部分
			  renderHTML: function () {
			    var that = this;
			    this.html = '';
			    if (this.sourceData.length === 0) {
			      return;
			    }
			
			    if (this.uid !== '') {
			      var uids = this.uid.split('-');
			      var source = this.sourceData;
			      addHtml(this.sourceData);
			      uids.forEach(function (idx, index) {
			        source = source[idx].children;
			        if (source && source.length > 0) {
			          addHtml(source);
			        }
			      });
			    } else {
			      addHtml(this.sourceData);
			    }
			
			    this.content.html($(this.html));
			
			    function addHtml(data) {
			      that.html += '<div class="box" data-tag="' + that.id + '">';
			      data.forEach(function (item) {
			        that.html += `<div class="item ${item.checked ? 'active' : ''}" data-uid="${item.uid}" data-value="${
			          item.value
			        }" data-tag="${that.id}">
			          <span class="value" data-tag="${that.id}">${item.label}</span>
			          <i class="${item.children && item.children.length > 0 ? 'arrow' : ''}" data-tag="${that.id}">
			          </i>
			        </div>`;
			      });
			      that.html += '</div>';
			    }
			  },
			  // 初始化数据
			  initData: function (data, uid) {
			    var that = this;
			    data.forEach(function (item, index) {
			      item.checked = false;
			      item.uid = uid ? uid + '-' + index : index + '';
			      if (item.children && item.children.length > 0) {
			        that.initData(item.children, item.uid);
			      }
			    });
			  },
			  // 计算嵌套深度
			  getDeep: function () {
			    var deepArr = [];
			    deep(this.sourceData, 0, deepArr);
			
			    function deep(data, i, deepArr) {
			      i += 1;
			      for (let j = 0; j < data.length; j++) {
			        if (data[j].children) {
			          deep(data[j].children, i, deepArr);
			        } else {
			          return deepArr.push(i);
			        }
			      }
			    }
			    return deepArr;
			  },
			  // 重置数据的checked状态
			  resetChecked: function (data) {
			    var that = this;
			    data.forEach(function (item, index) {
			      item.checked = false;
			      if (item.children && item.children.length > 0) {
			        that.resetChecked(item.children);
			      }
			    });
			  },
			  // 设置checked状态
			  setChecked: function () {
			    var that = this;
			    var uids = this.uid.split('-');
			    this.resetChecked(this.sourceData);
			    var source = this.sourceData;
			    var label = '';
			    var value = [];
			    uids.forEach(function (idx, index) {
			      if (idx === '') {
			        return;
			      }
			      source[idx].checked = true;
			      label += index === 0 ? source[idx].label : '/' + source[idx].label;
			      value.push(source[idx].value);
			      source = source[idx].children;
			
			      // 未到根节点也执行选中
			      if (!that.selectRoot) {
			        that.value = value;
			        that.body.find('.value').text(label);
			      }
			
			      // 当当前选项到底时,结束分层点击
			      if (!source) {
			        that.hide();
			        that.value = value;
			        that.body.find('.value').text(label);
			      }
			    });
			
			    this.renderHTML();
			  },
			  hide: function () {
			    this.content.removeClass('show');
			  },
			  show: function () {
			    this.content.addClass('show');
			  },
			  getValue: function () {
			    return this.value;
			  },
			  // 回显数据
			  setUid: function (uid) {
			    this.uid = uid;
			    this.setChecked();
			  },
			  // 设置数据
			  setData: function (data) {
			    this.sourceData = data;
			    this.initData(this.sourceData);
			    this.setChecked();
			  },
			  // 清空
			  clear: function () {
			    this.uid = '';
			    this.value = [];
			    this.setChecked();
			    this.body.find('.value').text('please select');
			  },
			  // 初始化容器
			  initContainer: function () {
			    var html = `
			    <div class="body" data-tag="${this.id}">
			      <div class="value" data-tag="${this.id}">please select</div>
			      <span class="clear" >x</span>
			      <span class="arrow" data-tag="${this.id}"></span>
			    </div>
			    <div class="dropdown-content" data-tag="${this.id}">
			      <div class="box no-data" data-tag="' + that.id + '">
			        No Data !
			      </div>
			    </div>
			  `;
			    this.cascader.html(html);
			    this.body = this.cascader.find('.body');
			    this.content = this.cascader.find('.dropdown-content');
			  },
			};

			
			var data = [
				{
					label: "0",
					value: "0",
					children: [
						{
							label: "0-0",
							value: "0-0",
							children: [
								{
									label: "0-0-0",
									value: "0-0-0",
									children: [
										{
											label: "0-0-0-0",
											value: "0-0-0-0",
										},
										{
											label: "0-0-0-1",
											value: "0-0-0-1",
										},
									]
								},
								{
									label: "0-0-0",
									value: "0-0-0",
								},
							]
						},
					]
				},
				{
					label: "0",
					value: "0",
					children: [
						{
							label: "0-0",
							value: "0-0",
							children: [
								{
									label: "0-0-0",
									value: "0-0-0",
									children: [
										{
											label: "0-0-0-0",
											value: "0-0-0-0",
										},
										{
											label: "0-0-0-1",
											value: "0-0-0-1",
										},
									]
								},
							]
						},
					]
				},
			];
			var myCascader = new JQCascader("myCascader", data);
			new JQCascader("myCascader2", data);
			myCascader.setUid("0-0-0-1");
			
		</script>
	</body>
</html>


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值