JQuery仿elementui級聯控制元件
阿新 • • 發佈:2021-01-30
技術標籤:elementui級聯控制元件jqueryjquery
elementui太香了,但是基於vue.js…
沒法了,jq黨只能自己來了
以下程式碼即拿即用,別忘推薦!!!
HTML
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>級聯控制元件</title> <link rel="stylesheet" href="./ZdCascader.css" type="text/css"> </head> <body> <div> <input type="text" id="test"/> </div> <script src="http://libs.baidu.com/jquery/2.0.0/jquery.min.js"></script> <script src="./ZdCascader.js"></script> <script> var _data = [{ value: 'shanghai', label: '上海', children: [{ value: 'shanghaishi', label: '上海市', children: [{ value: 'baoshan1', label: '寶山區saa傳送飛灑傳送' }, { value: 'fengxian1', label: '奉賢區' }, { value: 'putuo1', label: '普陀區' }, { value: 'hongkou1', label: '虹口區' }] }] }, { value: 'hunan', label: '湖南省', children: [{ value: 'shaoyang', label: '邵陽市', children: [{ value: 'baoshan2', label: '寶山區' }, { value: 'fengxian2', label: '奉賢區' }, { value: 'putuo2', label: '普陀區' }, { value: 'hongkou2', label: '虹口區' }] }, { value: 'hengyang', label: '衡陽市', children: [{ value: 'baoshan3', label: '寶山區' }, { value: 'putuo3', label: '普陀區' }, { value: 'hongkou3', label: '虹口區' }] }] }, { value: 'sichuan', label: '四川省', children: [{ value: 'leshanshi', label: '樂山市', children: [{ value: 'baoshan4', label: '寶山區' }, { value: 'fengxian4', label: '奉賢區' }, { value: 'putuo4', label: '普陀區' }, { value: 'hongkou4', label: '虹口區' }] }] }, { value: 'beijing', label: '北京' }]; $(function(){ $('#test').zdCascader({ data:_data }); }) </script> </body> </html>
JavaScript外掛:
```javascript /** * @author: Zhang Dong * @version: v1.0.1 */ ; (function ($) { var _keyCodes = { ESC: 27, TAB: 9, RETURN: 13, LEFT: 37, UP: 38, RIGHT: 39, DOWN: 40, ENTER: 13, SHIFT: 16 } function ZdCascader(el, options) { this.options = options; this.CLASS = ZdCascader.CLASS; this.$el = $(el); //input this.$el_ = this.$el.clone(); this.init(); } ZdCascader.CLASS = { wrap: "zd-cascader-wrap", inputwrap: "zd-input zd-input--suffix", input: "zd-input__inner", iconWrap: "zd-input__suffix", iconInnerWrap: "zd-input__suffix-inner", icon: "icon zd-input__icon zd-icon-arrow-down", dropdownWrap: "zd-cascader__dropdown", dropdownPanel: "zd-cascader-panel", menuWrap: "zd-cascader-menu", menuList: "zd-cascader-menu__list", menuNode: "zd-cascader-node", menuNodeLabel: "zd-cascader-node__label", menuNodePostfix: "zd-cascader-node__postfix", checkClass: { wrapFocus: 'is-focus', menuNodeSelected: "in-active-path", nodeSelectedIcon: "is-selected-icon", nodeAnchor: "is-prepare" //預備選中 } } ZdCascader.DEFAULTS = { data: null, //支援格式[{value:"",label:"",children:[{value:"",label:""}]}] range: ' / ', //分割符 onChange: function (data) {} } ZdCascader.METHODS = ['reload', 'destroy']; ZdCascader.prototype.init = function () { /*構建基礎html*/ this._construct(); /*事件繫結*/ this._event(); } //構建Cascader的html ZdCascader.prototype._construct = function () { var self = this; //最外層容器 this.$container = this.$el.wrap(`<div class="${this.CLASS.wrap}"></div>`) .wrap(`<div class="${this.CLASS.inputwrap}"></div>`).addClass(this.CLASS.input).prop('readonly', true) .closest('.' + this.CLASS.wrap); //文字框右側圖示 this.$arrow = $(`<span class="zd-input__suffix"> <span class="zd-input__suffix-inner"> <svg t="1600158452164" class="icon zd-input__icon zd-icon-arrow-down" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1181" width="200" height="200"> <path d="M538.434046 617.504916c0 3.687996-1.403976 7.356548-4.211928 10.1645-5.615904 5.615904-14.713097 5.615904-20.329001 0L364.187513 476.931297c-5.615904-5.615904-5.615904-14.713097 0-20.329001 5.615904-5.615904 14.713097-5.615904 20.329001 0l149.705604 150.739143C537.03007 610.148367 538.434046 613.817943 538.434046 617.504916z" p-id="1182" fill="#515151"></path> <path d="M689.172165 466.767819c0 3.687996-1.403976 7.356548-4.211928 10.1645L534.222117 627.670439c-5.615904 5.615904-14.713097 5.615904-20.329001 0-5.615904-5.615904-5.615904-14.713097 0-20.329001L664.631236 456.603319c5.615904-5.615904 14.713097-5.615904 20.329001 0C687.768189 459.411271 689.172165 463.079824 689.172165 466.767819z" p-id="1183" fill="#515151"></path> </svg> </span> </span>`).insertAfter(this.$el); //下拉列表 this.$dropdownWrap = $(`<div class="${this.CLASS.dropdownPanel}"></div>`).appendTo(this.$container).wrap(`<div class="${this.CLASS.dropdownWrap}"></div>`); this.reload(); } /*事件繫結*/ ZdCascader.prototype._event = function () { this.$container.on('click.wrap', $.proxy(this._wrapClick, this)); this.$container.on('mousedown', $.proxy(function (event) { this.$el.focus(); event.stopPropagation(); }, this)); $(document).on('mousedown.cascader', $.proxy(function () { this.$container.removeClass(this.CLASS.checkClass.wrapFocus); }, this)); this.$container.on('blur.wrap', $.proxy(function () { this.$container.removeClass(this.CLASS.checkClass.wrapFocus); }, this)); this.$container.on('click.item', '.' + this.CLASS.menuNode, $.proxy(this._nodeClick, this)); this.$el.on('keyup.wrap', $.proxy(this._keyup, this)); } ZdCascader.prototype._wrapClick = function () { event.stopPropagation(); this.$el.focus(); if (!this.$container.hasClass(this.CLASS.checkClass.wrapFocus)) { // if (this.$dropdownWrap.children(this.CLASS.menuWrap).length === 0) // loadFirst(); this.$container.addClass(this.CLASS.checkClass.wrapFocus); } this.$dropdownWrap.find('li.' + this.CLASS.checkClass.nodeAnchor).removeClass(this.CLASS .checkClass.nodeAnchor); this.$dropdownWrap.find(this.CLASS.menuList).eq(0).find('li.' + this.CLASS.checkClass .menuNodeSelected).addClass(this.CLASS.checkClass.nodeAnchor); } ZdCascader.prototype._nodeClick = function (event) { var $that = event.currentTarget ? $(event.currentTarget) : $(event); //li var $wrap = $that.closest('.' + this.CLASS.menuWrap); $that.addClass(this.CLASS.checkClass.menuNodeSelected).siblings().removeClass(this.CLASS.checkClass.menuNodeSelected); var data = $that.data('bindData'); if (!data.children) { $wrap.nextAll().remove(); var prevWrap = $wrap.prevAll(); var value = data.label; var allPathData = [data]; $.each(prevWrap, (i, m) => { var selectedData = $(m).find('li.' + this.CLASS.checkClass .menuNodeSelected).data( 'bindData'); value = selectedData.label + this.options.range + value; allPathData.push(selectedData); }); this.$el.val(value).focus(); this.$container.removeClass(this.CLASS.checkClass.wrapFocus); this.$dropdownWrap.find('.' + this.CLASS.checkClass.nodeSelectedIcon).remove(); $that.prepend($(`<span class="${this.CLASS.checkClass.nodeSelectedIcon}">√</span>`)); this.$el.data('bindData', data); this.$el.data('bindPathData', allPathData); if (this.options.onChange && typeof this.options.onChange === "function") this.options.onChange(this, data, allPathData); event.stopPropagation(); } else this._loadChildren($that); } ZdCascader.prototype._loadChildren = function ($parentNode) { this.$el.focus(); $parentNode.addClass(this.CLASS.checkClass.menuNodeSelected).siblings().removeClass(this.CLASS.checkClass.menuNodeSelected); var $wrap = $parentNode.closest('.' + this.CLASS.menuWrap); var data = $parentNode.data('bindData'); this.$dropdownWrap.find('li.' + this.CLASS.checkClass.nodeAnchor).removeClass(this.CLASS .checkClass.nodeAnchor); $parentNode.addClass(this.CLASS.checkClass.nodeAnchor); if (!data.children) { $wrap.nextAll().remove(); return } var selectedId = []; var pathData = this.$el.data('bindPathData'); if (pathData && pathData.length > 0) { selectedId = $.map(pathData, m => { return m.value }); } var $nextWrap = $wrap.next(); if (!$nextWrap || $nextWrap.length === 0) { $nextWrap = $(`<div class="zd-scrollbar ${this.CLASS.menuWrap}"> <div class="zd-cascader-menu__wrap zd-scrollbar__wrap"> <ul class="${this.CLASS.menuList}"> </ul> </div> </div>`); $nextWrap = $nextWrap.appendTo(this.$dropdownWrap); } $nextWrap.nextAll().remove(); var $ul = $nextWrap.find('.' + this.CLASS.menuList).empty(); $.each(data.children, (i, m) => { var $li = $(`<li class="${this.CLASS.menuNode}"></li>`); var $label = $(`<span class="${this.CLASS.menuNodeLabel}">${m.label}</span>`); var $icon = $(`<svg t="1600158452164" class="icon zd-input__icon zd-icon-arrow-right ${this.CLASS.menuNodePostfix}" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1181" width="200" height="200"> <path d="M538.434046 617.504916c0 3.687996-1.403976 7.356548-4.211928 10.1645-5.615904 5.615904-14.713097 5.615904-20.329001 0L364.187513 476.931297c-5.615904-5.615904-5.615904-14.713097 0-20.329001 5.615904-5.615904 14.713097-5.615904 20.329001 0l149.705604 150.739143C537.03007 610.148367 538.434046 613.817943 538.434046 617.504916z" p-id="1182" fill="#515151"></path> <path d="M689.172165 466.767819c0 3.687996-1.403976 7.356548-4.211928 10.1645L534.222117 627.670439c-5.615904 5.615904-14.713097 5.615904-20.329001 0-5.615904-5.615904-5.615904-14.713097 0-20.329001L664.631236 456.603319c5.615904-5.615904 14.713097-5.615904 20.329001 0C687.768189 459.411271 689.172165 463.079824 689.172165 466.767819z" p-id="1183" fill="#515151"></path> </svg>`); $li.append($label).data('bindData', m); if (m.children && m.children.length > 0) $li.append($icon); else if (selectedId.indexOf(m.value) >= 0) { this.$dropdownWrap.find('.' + this.CLASS.checkClass.nodeSelectedIcon).remove(); $li.addClass(this.CLASS.checkClass.menuNodeSelected).prepend($( `<span class="${this.CLASS.checkClass.nodeSelectedIcon}">√</span>`)); } $li.appendTo($ul); }); } //銷燬 ZdCascader.prototype.destroy = function () { $(this.$el).insertAfter(this.$el_); this.$el.remove(); } //重新載入下拉資料 ZdCascader.prototype.reload = function (data) { data = data || this.options.data; this.$el.val('').removeData('bindData').removeData('bindPathData'); this.$dropdownWrap.empty(); var selectedData = this.$el.data('bindData'); var $firstWrap = $(`<div class="zd-scrollbar ${this.CLASS.menuWrap}"> <div class="zd-cascader-menu__wrap zd-scrollbar__wrap"> <ul class="${this.CLASS.menuList}"> </ul> </div> </div>`); var $ul = $firstWrap.find('.' + this.CLASS.menuList); $.each(data, (i, m) => { var $li = $(`<li class="${this.CLASS.menuNode}"></li>`); var $label = $(`<span class="${this.CLASS.menuNodeLabel}">${m.label}</span>`); var $icon = $(`<svg t="1600158452164" class="icon zd-input__icon zd-icon-arrow-right ${this.CLASS.menuNodePostfix}" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1181" width="200" height="200"> <path d="M538.434046 617.504916c0 3.687996-1.403976 7.356548-4.211928 10.1645-5.615904 5.615904-14.713097 5.615904-20.329001 0L364.187513 476.931297c-5.615904-5.615904-5.615904-14.713097 0-20.329001 5.615904-5.615904 14.713097-5.615904 20.329001 0l149.705604 150.739143C537.03007 610.148367 538.434046 613.817943 538.434046 617.504916z" p-id="1182" fill="#515151"></path> <path d="M689.172165 466.767819c0 3.687996-1.403976 7.356548-4.211928 10.1645L534.222117 627.670439c-5.615904 5.615904-14.713097 5.615904-20.329001 0-5.615904-5.615904-5.615904-14.713097 0-20.329001L664.631236 456.603319c5.615904-5.615904 14.713097-5.615904 20.329001 0C687.768189 459.411271 689.172165 463.079824 689.172165 466.767819z" p-id="1183" fill="#515151"></path> </svg>`); $li.append($label).data('bindData', m); if (m.children && m.children.length > 0) $li.append($icon); else if (selectedData && m.value == selectedData.value) { this.$dropdownWrap.find('.' + this.CLASS.checkClass.nodeSelectedIcon).remove(); $li.prepend($(`<span class="${this.CLASS.checkClass.nodeSelectedIcon}">√</span>`)); } $ul.append($li); }); this.$dropdownWrap.find('li.' + this.CLASS.checkClass.nodeAnchor).removeClass(this.CLASS.checkClass.nodeAnchor); this.$dropdownWrap.append($firstWrap).find(this.CLASS.menuNode).eq(0).focus().addClass(this.CLASS.checkClass .nodeAnchor); } ZdCascader.prototype._keyup = function (event) { var keycode = event.which; switch (keycode) { case _keyCodes.DOWN: this._movedown(); break; case _keyCodes.UP: this._moveup(); break; case _keyCodes.LEFT: this._moveleft(); break; case _keyCodes.RIGHT: this._moveright(); break; case _keyCodes.ENTER: this._keyenter(); break; case _keyCodes.ESC: this._keyesc(); break; default: break; } } ZdCascader.prototype._movedown = function () { var $selected; if (!this.$container.hasClass(this.CLASS.checkClass.wrapFocus)) { this.$container.trigger('click'); return } $selected = this.$dropdownWrap.find('.' + this.CLASS.menuNode + '.' + this.CLASS .checkClass .nodeAnchor); if ($selected.length === 0) $selected = this.$dropdownWrap.find('.' + this.CLASS.menuWrap).eq(0).find('.' + this.CLASS .menuNode).eq(0) .addClass( this.CLASS.checkClass.nodeAnchor); else if ($selected.next().length > 0) $selected = $selected.removeClass(this.CLASS.checkClass.nodeAnchor).next() .addClass( this.CLASS .checkClass.nodeAnchor); this._loadChildren($selected); } ZdCascader.prototype._moveup = function () { if (!this.$container.hasClass(this.CLASS.checkClass.wrapFocus)) return; var $selected = this.$dropdownWrap.find('.' + this.CLASS.menuNode + '.' + this.CLASS .checkClass.nodeAnchor); if ($selected.length === 0) return; if ($selected.prev().length > 0) $selected = $selected.removeClass(this.CLASS.checkClass.nodeAnchor).prev() .addClass( this.CLASS .checkClass.nodeAnchor); this._loadChildren($selected); } ZdCascader.prototype._moveleft = function () { if (!this.$container.hasClass(this.CLASS.checkClass.wrapFocus)) return; var $selected = this.$dropdownWrap.find('.' + this.CLASS.menuNode + '.' + this.CLASS .checkClass.nodeAnchor); if ($selected.length === 0) return; var $leftWrap = $selected.closest('.' + this.CLASS.menuWrap).prev(); if ($leftWrap.length === 0) return; $selected.removeClass(this.CLASS.checkClass.nodeAnchor); $selected = $leftWrap.find('li.' + this.CLASS.checkClass.menuNodeSelected) .length > 0 ? $leftWrap.find('li.' + this.CLASS.checkClass.menuNodeSelected).eq(0) : $leftWrap.find('li' + this.CLASS.menuNode).eq(0); $selected.addClass(this.CLASS.checkClass.nodeAnchor); this._loadChildren($selected); } ZdCascader.prototype._moveright = function () { if (!this.$container.hasClass(this.CLASS.checkClass.wrapFocus)) return; var $selected = this.$dropdownWrap.find('.' + this.CLASS.menuNode + '.' + this.CLASS .checkClass.nodeAnchor); if ($selected.length === 0) return; var $rightWrap = $selected.closest('.' + this.CLASS.menuWrap).next(); if ($rightWrap.length === 0) return; $selected.removeClass(this.CLASS.checkClass.nodeAnchor); $selected = $rightWrap.find('li.' + this.CLASS.menuNode).eq(0).addClass( this.CLASS.checkClass .nodeAnchor); this._loadChildren($selected); } ZdCascader.prototype._keyenter = function () { if (!this.$container.hasClass(this.CLASS.checkClass.wrapFocus)) return; var $selected = this.$dropdownWrap.find('.' + this.CLASS.menuNode + '.' + this.CLASS .checkClass.nodeAnchor); if ($selected.length === 0) return; var $rightWrap = $selected.closest('.' + this.CLASS.menuWrap).next(); if ($rightWrap.length !== 0) return; $selected.trigger('click'); } ZdCascader.prototype._keyesc = function () { if (!this.$container.hasClass(this.CLASS.checkClass.wrapFocus)) return; this.$container.removeClass(this.CLASS.checkClass.wrapFocus); this.$el.focus(); } $.fn.zdCascader = function (option) { var value, args = Array.prototype.slice.call(arguments, 1); this.each(function () { var $this = $(this), data = $this.data('zdCascader'), options = $.extend({}, ZdCascader.DEFAULTS, $this.data(), typeof option === 'object' && option); if (typeof option === 'string') { if ($.inArray(option, ZdCascader.METHODS) < 0) { throw new Error("Unknown method: " + option); } if (!data) { return; } value = data[option].apply(data, args); if (option === 'destroy') { $this.removeData('zdCascader'); } } if (!data) { $this.data('zdCascader', (data = new ZdCascader(this, options))); } }); return typeof value === 'undefined' ? this : value; }; })(jQuery);
css
.zd-input { width: 100%; position: relative; display: inline-block; } .zd-input__inner { -webkit-appearance: none; background-color: #fff; background-image: none; border-radius: 4px; border: 1px solid #dcdfe6; box-sizing: border-box; color: #606266; display: inline-block; font-size: inherit; height: 30px; line-height: 30px; outline: none; padding: 0 15px; transition: border-color .2s cubic-bezier(.645, .045, .355, 1); width: 100%; } .zd-input--suffix .zd-input__inner { padding-right: 30px; } .zd-input__suffix { position: absolute; height: 100%; right: 5px; top: 0; text-align: center; color: #c0c4cc; transition: all .3s; pointer-events: none; } .zd-input__suffix-inner { pointer-events: all; } .zd-cascader-wrap .zd-input__inner { text-overflow: ellipsis; } .zd-input__icon { height: 100%; text-align: center; width: 25px; font-style: normal; font-weight: 400; font-variant: normal; text-transform: none; line-height: 1; vertical-align: baseline; display: inline-block; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; } .zd-input__icon.zd-icon-arrow-down { transition: transform .3s; font-size: 13px; } .zd-input__icon.zd-icon-arrow-right { transition: transform .3s; font-size: 13px; transform: rotate(270deg); } .zd-cascader-wrap { width: 200px; height: 30px; line-height: 30px; position: relative; display: inline-block; font-size: 13px; } .zd-cascader__dropdown { position: absolute; top: 30px; left: 0; z-index: 2009; margin: 5px 0; margin-bottom: 12px; font-size: 13px; background: #fff; border: 1px solid #e4e7ed; border-radius: 4px; box-shadow: 0 2px 12px 0 rgba(0, 0, 0, .1); display: none; } .zd-cascader-panel { display: flex; border-radius: 4px; font-size: 13px; } .zd-scrollbar { overflow: hidden; position: relative; } .zd-scrollbar__wrap { overflow: scroll; height: 100%; } .zd-cascader-menu { min-width: 160px; box-sizing: border-box; color: #606266; border-right: 1px solid #e4e7ed; } .zd-cascader-menu:last-child { border-right: none; } .zd-cascader-menu__wrap { margin-bottom: -17px; margin-right: -17px; height: 204px; } .zd-cascader-menu__list { position: relative; min-height: 100%; margin: 0; padding: 6px 0; list-style: none; box-sizing: border-box; } .zd-cascader-node { position: relative; display: flex; align-items: center; padding: 0 30px 0 20px; height: 34px; line-height: 34px; outline: none; } .zd-cascader-node:not(.is-disabled) { cursor: pointer; } .zd-cascader-node__label { flex: 1; padding: 0 10px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } .zd-cascader-node__postfix { position: absolute; right: 10px; } .zd-cascader-node:not(.is-disabled):focus, .zd-cascader-node:not(.is-disabled):hover, .zd-cascader-node:not(.is-disabled).is-prepare { background: #f5f7fa; } .zd-cascader-node.in-active-path, .zd-cascader-node.is-active, .zd-cascader-node.is-selectable.in-checked-path { color: #409eff; font-weight: 700; } .zd-cascader-node.in-active-path .zd-input__icon path, .zd-cascader-node.is-active .zd-input__icon path, .zd-cascader-node.is-selectable.in-checked-path .zd-input__icon path { fill: #409eff; } .zd-cascader-wrap:not(.is-disabled):hover .zd-input__inner { cursor: pointer; border-color: #c0c4cc; } .zd-cascader-wrap.is-focus .zd-input .zd-input__inner { border-color: #409eff; } .zd-cascader-wrap.is-focus .zd-input .zd-input__icon { transform: rotate(180deg); } .zd-cascader-wrap.is-focus .zd-cascader__dropdown { display: inline-block; } .zd-cascader-wrap:focus-within .zd-input__inner { border-color: #409eff; } .is-selected-icon { position: absolute; left: 10px; font-size: 13px; }
[原地址](https://www.cnblogs.com/stupid-dong/p/13826540.html)