基于jQuery的三级联动控件

三级联动控件在日常开发中经常会用到,比如选择省市区,年月日等情况,而原生的html并没有这样的一个控件,闲暇之余,写了这么一个控件,预览效果如下:
这里写图片描述
废话不多说,直接贴代码:
jquery.dropmenu.css

.dropmenu {
    width: auto;
    height: auto;
}
.dropmenu > .top {
    position: relative;
    width: 100%;
    height: 30px;
    border: 1px #cccccc solid;
    font-size: 0;
    overflow:hidden;
}
.dropmenu > .top >.data {
    float: left;
    padding: 0 5px;
    width: 100%;
    height: 30px;
    line-height: 30px;
    font-size: 16px;
    border-right: 1px #cccccc solid;
    background: #dddddd;
}
.dropmenu > .top > .data > p {
    padding: 0 30px 0 0;
    margin: 0;
    white-space:nowrap;
    word-break:break-all;
    text-overflow:ellipsis;
    overflow:hidden;
}
.dropmenu > .top > .btn {
    position: absolute;
    right: 0;
    width: 30px;
    height: 30px;
    line-height: 30px;
    font-size: 16px;
    text-align: center;
    cursor: pointer;
    z-index: 1;
    background: #ffffff;
}
.dropmenu > .drop {
    position: absolute;
    margin-top: -1px;
    height: auto;
    width: auto;
    z-index: 999;
    background: #fff;
    font-size: 0;
}
.dropmenu > .drop > .options {
    display: inline-block;
    vertical-align: top;
    height: auto;
    width: auto;
    border-left: 1px #cccccc solid;
    border-right: 1px #cccccc solid;
    border-top: 1px #cccccc solid;
}
.dropmenu > .drop > .options > ul {
    margin: 0;
    padding:0;
    list-style-type: none;
}
.dropmenu > .drop > .options > ul > li {
    padding:0 5px;
    height: 30px;
    line-height: 30px;
    border-bottom: 1px #cccccc solid;
    cursor: pointer;
    font-size: 14px;
}
.dropmenu > .drop > .options > ul > li:hover {
    background: #cccccc
}

jquery.dropmenu.js

if (jQuery === undefined)
    throw new Error("本控件基于jQuery,请先引入jQuery相关文件!")
$.fn.dropmenu = function(config) {
    return DropMenu.call(this,config)
}
var DropMenu = function(config) {
    this.top = null//顶部部分
    this.drop = null//下拉部分
    this.width = null//top的宽度
    this.optionsWidth = null//options区域宽度
    this.last = false//是否允许选择非末级
    this.cache = {}//缓存解析的数据
    this.options = [] //下拉数据
    this.data = {}//被选中的数据
    this.interface = null//如果需要从网络请求数据
    this.listener = {}//事件监听
    $.extend(this,DropMenu.prototype,config)
    this.init()
    this.bind()
    this.adjust()
    return this
}
/**
 * 初始化控件视图
 */
DropMenu.prototype.init = function() {
    this.top = $("<div class='top'>")
    this.top.append("<div class='data'><p></p></div>")
    this.top.append("<div class='btn'>▼</div>")
    this.drop = $("<div class='drop'>")
    this.drop.hide()
    if (this.width !== null)
        this.top.css("width",this.width)
    this.append(this.top)
    this.append(this.drop)
}
/**
 * 绑定事件
 */
DropMenu.prototype.bind = function () {
    this.top.on("click.api.dropmenu.display",".btn",this,DropMenu.prototype.display)
    this.drop.on("click.api.dropmenu.click",".options > ul > li",this,DropMenu.prototype.click)
    this.drop.on("mouseleave.api.dropmenu.leave",".options",this,DropMenu.prototype.leave)
    this.drop.on("mouseover.api.dropmenu.slide",".options > ul > li",this,DropMenu.prototype.slide)
}
/**
 * 调整和绑定数据
 * @param level 需要加载的数据的级别(1,2,3),默认为1
 * @param offsetTop 偏移
 * @param parent 父级关键字
 */
DropMenu.prototype.adjust = function(level,offsetTop,parent) {
    if (level === undefined || isNaN(level))
        level = "1"
    var data = this.parse(level,parent)
    if (data === undefined || data.length === 0)
        return;
    var options = $("<div class='options' data-level='"+level+"'>")
    var ul = $("<ul>")
    for (var i=0 ; i < data.length ; i++) {
        ul.append("<li data-key='"+data[i].key+"'>"+data[i].value+"</li>")
    }
    options.append(ul)
    if (offsetTop !== undefined && !isNaN(offsetTop))
        options.css("margin-top",offsetTop+"px")
    if (this.optionsWidth !== null)
        options.css("width",this.optionsWidth)
    this.drop.append(options)
}
/**
 * 解析options,并将解析过的直接存入缓存,方便直接使用
 */
DropMenu.prototype.parse = function(level,parent){
    if (this.options === undefined || this.options.length === 0)
        return
    if (level === undefined)
        level = "1"
    if (parent !== undefined && this.cache[parent] !== undefined)
        return this.cache[parent]
    var result = new Array
    for (var i=0;i<this.options.length;i++) {
        if (level === this.options[i].level && parent === this.options[i].parent) {
            result.push(this.options[i])
        }
    }
    if (parent === undefined)
        this.cache["top"] = result
    else
        this.cache[parent] = result
    return result
}
/**
 * btn点击事件
 * @param event
 */
DropMenu.prototype.display = function(event) {
    var plugin = event.data
    plugin.drop.fadeToggle()
}
/**
 * 下拉列表中选项的鼠标移动事件
 * @param event
 */
DropMenu.prototype.slide = function(event) {
    var plugin = event.data
    var level = $(this.closest(".options")).attr("data-level")
    var nextLevel = "1"
    if (level === "1") {
        plugin.drop.find(".options:gt(0)").remove()
        nextLevel = "2"
    }else if (level === "2") {
        plugin.drop.find(".options:gt(1)").remove()
        nextLevel = "3"
    }else if (level === "3") {
        return
    }
    var offsetTop = this.offsetTop - 1
    var parent = $(this).attr("data-key")
    plugin.adjust(nextLevel,offsetTop,parent)
}
/**
 * item点击事件
 * @param event
 */
DropMenu.prototype.click = function (event) {
    var plugin = event.data
    var level = $(this).closest(".options").attr("data-level")
    var parent = $(this).attr("data-key")
    var key = $(this).attr("data-key")
    var value = $(this).text()
    var p = plugin.top.find(".data > p")
    var children = null
    if (!plugin.last && level === "1" ) {
        children = plugin.parse("2",parent)
    }else if (!plugin.last && level === "2") {
        children = plugin.parse("3",parent)
    }
    if (children === null || children.length === 0) {
        p.text(value)
        p.attr("key",key)
        plugin.drop.hide()
        plugin.data["key"]=key
        plugin.data["value"]=value
        if (plugin.listener.select !== undefined)
            plugin.listener.select(plugin.data,this,plugin)
    }
}
/**
 * 鼠标离开options区域事件
 * @param event
 */
DropMenu.prototype.leave = function (event) {
    var plugin = event.data
    var to = event.toElement
    if (to.closest(".options") == null) {
        plugin.drop.hide()
        plugin.drop.find(".options:gt(0)").remove()
    }
}
DropMenu.prototype.request = function() {

}
DropMenu.prototype.getData = function () {
    return this.data
}

index.html

<!DOCTYPE html>
<html>
<head>
    <title>测试</title>
    <meta charset="UTF-8">
    <script src='https://cdn.bootcss.com/jquery/3.2.1/jquery.min.js'></script>
    <link rel="stylesheet" type="text/css" href="jquery.dropmenu.css">
    <script type="text/javascript" src="jquery.dropmenu.js"></script>
</head>
<body>
    <div class="dropmenu"></div>
    <script type="text/javascript">
        $(function(){
            var obj=$(".dropmenu").dropmenu({
                "width":"210px",
                "optionsWidth" : "210px",
                "options":[
                    {"key":"1","value":"湖南省","level":"1"},
                    {"key":"2","value":"湖北省","level":"1"},
                    {"key":"3","value":"河北省","level":"1"},
                    {"key":"4","value":"河南省","level":"1"},
                    {"key":"5","value":"广东省","level":"1"},
                    {"key":"6","value":"广西省","level":"1"},
                    {"key":"7","value":"福建省","level":"1"},
                    {"key":"8","value":"安徽省","level":"1"},
                    {"key":"21","value":"长沙市","level":"2","parent":"1"},
                    {"key":"22","value":"株洲市","level":"2","parent":"1"},
                    {"key":"23","value":"衡阳市","level":"2","parent":"1"},
                    {"key":"24","value":"邵阳市","level":"2","parent":"1"},
                    {"key":"21","value":"武汉市","level":"2","parent":"2"},
                    {"key":"22","value":"黄石市","level":"2","parent":"2"},
                    {"key":"23","value":"十堰市","level":"2","parent":"2"},
                    {"key":"24","value":"宜昌市","level":"2","parent":"2"},
                    {"key":"25","value":"襄阳市","level":"2","parent":"2"},
                    {"key":"26","value":"鄂州市","level":"2","parent":"2"},
                    {"key":"27","value":"荆门市","level":"2","parent":"2"},
                    {"key":"28","value":"孝感市","level":"2","parent":"2"},
                    {"key":"21","value":"石家庄市","level":"2","parent":"3"},
                    {"key":"22","value":"唐山市","level":"2","parent":"3"},
                    {"key":"23","value":"秦皇岛市","level":"2","parent":"3"},
                    {"key":"24","value":"邯郸市","level":"2","parent":"3"},
                    {"key":"21","value":"邢台市","level":"2","parent":"3"},
                    {"key":"41","value":"开封市","level":"2","parent":"4"},
                    {"key":"42","value":"洛阳市","level":"2","parent":"4"},
                    {"key":"43","value":"安阳市","level":"2","parent":"4"},
                    {"key":"231","value":"茅箭区","level":"3","parent":"23"},
                    {"key":"232","value":"张湾区","level":"3","parent":"23"},
                    {"key":"233","value":"十堰经济技术开发区","level":"3","parent":"23"},
                    {"key":"234","value":"郧阳区","level":"3","parent":"23"},
                    {"key":"235","value":"郧西县","level":"3","parent":"23"},
                    {"key":"236","value":"竹山县","level":"3","parent":"23"},
                    {"key":"237","value":"竹溪县","level":"3","parent":"23"},
                    {"key":"238","value":"房县","level":"3","parent":"23"}
                ]
            });
        })
    </script>
</body>
</html>

本控件仅供学习使用,可能存在一定的BUG,欢迎大家指正。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值