如何制作一个自己的选择框

开发工具与关键技术:VS2015、JS、JQuery
作者:曾浩源
撰写时间:2019.3.28
无论是在前端或者后端,一些表单是必不可少的,有了表单,那么表单的样式也是五花八门。
一个精美的表单或许可以让你的页面焕然一新。
文本框、复选框、单选框、按钮等等都可以通过css样式从而去改变它,但唯独选择下拉框不可以。选择的下拉框是根据浏览器的样式而改变的,各个浏览器的选择下拉框样式也有差异,但也是默认的。
我们用css样式,只能改变回填框(select)样式和选择框(option)的字体、背景,
样式如下: 代码:
在这里插入图片描述在这里插入图片描述
发现(option)的边框,边距等等都是无法改变的,那怎么办?
所以我就参考了layui的选择框和网上下载的一个选择框,都是利用js,新建div标签或者ul li标签存放选择框内容,最后再利用js将选择框的一些功能也能在新建的标签内实现。
下面是我参考完后自己制作的一个选择框:
在这里插入图片描述在这里插入图片描述
主要改变的有:改变滚动条,鼠标划过伪类,右边小三角旋转,背景颜色透明和展开与收回效果(同时包含原有功能,disabled属性无法选择,selected属性选中回填)。
要制作一个选择框,当然首先写一个普通的选择框如下:

<select name="selects">
   <option value="new">最新的</option>
    <option value="unaudited" disabled="">未审核</option>
    <option value="nothrough" selected="">未通过</option>
    <option value="audit">正在审核</option>
    <option value="测试1">测试1</option>
    <option value="测试2">测试2</option>
    <option value="测试3">测试3</option>
    <option value="测试4">测试4</option>
    <option value="测试5">测试5</option>
</select>

然后写一个新的“选择框”
里面装着(input)和一个(i)小图标:(input)设置只读和text类型

<div class="select_text">
	<input class="select_title hiddeninput" type="text" readonly="">
	<i class="select_icon"></i>
</div>

新建一个js文件,扩展 jQuery 元素集来提供新的方法
jQuery.fn.extend 利用该方法创建属于自己的插件 selectFrom 名字可以随意起

jQuery.fn.selectForm = function (options) {//接收
    var defaults = {
        callBack: function (res) { }
    };
    var ops = $.extend({}, defaults, options);//返回被扩展的对象。不修改defaults 的情况下添加 options内容
    var selectList = $(this).find('select option');//根据传来 包括新旧选择框的div 获取它的option标签的内容 以数组的格式存储
    var that = this;//声明变量that,作为局部变量
    var html = '';//声明变量html 作为css样式
}

在旧下拉框和“新下拉框”外用一个div包括两个下拉框
在这里插入图片描述
然后在js文件里面,并且在创建插件的方法下面如下面的方法

 $('.select_box0').selectForm({//传递
        callBack: function (val) { }
    });

传递接受后,就开始读取select标签的值,继续在创建插件的方法里,遍历select标签的值,放到各个

  • 标签里面,如下:
  • // 读取select 标签的值
        html += '<ul class="select_list select_ul custom-scroll">';//新选择框的头
        //新选择框的内容
        $(selectList).each(function (idx, item) {//遍历所有选项,一一添加进新下拉框内
            var val = $(item).val();//获取选项的值
            var valText = $(item).html();//获取选项的html内容
            var selected = $(item).attr('selected');//获取选项的selected属性
            var disabled = $(item).attr('disabled');//获取选项的disabled属性
            var isSelected = selected ? 'select_selected' : '';//利用三目运算判断selected是否为true 有值为true undefined为false
            var isDisabled = disabled ? 'select_disabled' : '';//利用三目运算判断disabled是否为true 有值为true undefined为false
            if (selected) {//判断该选项是否有selected属性 有就添加select_selected类
                html += '<li class="' + isSelected + ' select_li" data-value="' + val + '"><a title="' + valText + '">' + valText + '</a></li>';
                $(that).find('.select_title').val(valText);
            } else if (disabled) {//判断该选项是否有disabled属性 有就添加select_disabled类
                html += '<li class="' + isDisabled + ' select_li" data-value="' + val + '"><a>' + valText + '</a></li>';
            } else {//没有就平常添加
                html += '<li class="select_li" data-value="' + val + '"><a title="' + valText + '">' + valText + '</a></li>';
            };
        });
    
        html += '</ul>';//新选择框的尾
        $(that).append(html);//在大div里追加该新下拉框
        $(that).find('select').hide();//而旧的下拉框则隐藏
    

    这样就完成了最基本下拉框显示,当然还有一些样式,例如:

    /*select*/
    .my_MenuSelect{
        display: inline-flex;
    }
    /*下拉框ul样式*/
    .select_ul{
        position: absolute;
        background: rgba(6, 0, 255, 0.3);
        width: 100px;
        height:100px;
        overflow-x:auto;
        margin-left: -6px;
        margin-top: 24px;
        display:none;
        border:0.1px solid transparent;
    }
    /*下拉框li样式*/
    .select_li{
        padding-top: 5px;
        padding-left: 9px;
        border:0.1px solid transparent;
    }
    /*下拉框鼠标hover伪类*/
    .select_li:hover{
        background: rgba(255, 255, 255, 0.3);
        border:0.1px solid rgba(255, 255, 0, 0.2);
    }
    /*下拉框选项选中样式*/
    .select_li.select_selected{
        background: rgba(95, 184, 120, 0.4);
        border:0.1px solid rgba(255, 255, 0, 0.2);
    }
    /*包括下拉框和图标的div样式*/
    .select_text{
        height:25px;
    }
    /*下拉框input样式*/
    .hiddeninput{
        width: 100%;
        height: 25px;
        line-height: 25px;
        border: 0;
        background-color: transparent;
        white-space: nowrap;
        overflow: hidden;
        text-overflow: ellipsis;
        padding: 0;
        cursor: pointer;    
        margin-top: 0px;
        margin-left: 3px;
        text-shadow: 0px -1px 6px white, 0px -2px 20px yellow, 0px -5px 20px #ff8000, 0px -10px 40px red;
    }
    /*图标样式*/
    .select_icon {
        width: 8px;
        height: 6px;
        background-repeat: no-repeat;
        background-image: url('../image/icon_arrow_down_x2.png');
        opacity:0.4;
        background-size: 100%;
        right: -82px;
        top: -24px;
        position: relative;
        transition: all .2s;
        display: inline-block;
    }
    /*展开下拉框图标旋转样式*/
    .select_icon_arrow {
        -webkit-transform: rotate(-180deg);
        transform: rotate(-180deg);
    }
    /*下拉框选项锁定样式*/
    .select_disabled.select_li{
        cursor: no-drop;
        -moz-user-select: none;
        -webkit-user-select: none;
        -ms-user-select: none;
    }
    

    还有下拉框的功能没完成呢,继续:
    下面是选中的选项回填到“下拉框内”
    首先是点击“新下拉框”选项下拉框展开,小图标旋转

     //点击选择
        $(that).on('click', '.select_text', function () {
            $(that).find('.select_list').slideToggle(100);
            $(that).find('.select_icon').toggleClass('select_icon_arrow');
        });
    

    然后就是选中选项,添加 选中类 并且回填数据到新旧下拉框

     //点击选择列表 
        $(that).find('.select_list li').not('.select_disabled').on('click', function () {//当点击到没有disabled属性的选项时
            var val = $(this).data('value');//获取该选项的值
            var valText = $(this).find('a').html();//获取该选项下的a标签的html
            $(that).find('.select_title').val(valText);//找到“新下拉框”的文本框,将获取到的valText赋值给它
            $(that).find('.select_icon').toggleClass('select_icon_arrow');//图标旋转  toggleClass()对设置或移除被选元素的一个或多个类进行切换。
            $(this).addClass('select_selected').siblings().removeClass('select_selected');//该选项添加 选中类 并遍历其同胞 删除选中类
            $(this).parent().slideToggle(50);//收起选项框
            for (var i = 0; i < selectList.length; i++) {//遍历循环 旧下拉框选项
                var selectVal = selectList.eq(i).val();//获取每一个值 赋值给变量
                if (val == selectVal) {//判断是否相等
                    $(that).find('select').val(val);//从该大div内找到select标签,赋值(也就是回填旧下拉框)
                    break;//跳出循环
                };
            };
            ops.callBack(val); //返回值
        });
    

    到这里就完成了选中选项回填到新旧下拉框的功能,最后一步就是下拉框选项框的收起,点到下拉框以外是地方,下拉框将会收起。如下:

     //其他元素被点击则收起选择
        $(document).on('mousedown', function (e) {//鼠标按下事件
            closeSelect(that, e);
        });
    

    到这里jQuery.fn.extend 利用该方法创建创建的方法结束
    在外面新建一个方法 closeSelect(that,e);

    function closeSelect(that, e) {
        var selects = $(that).find('.select_list');//获取该大div里的“新下拉框”(用于收起选项框)
        var selectsEl = $(that).find('.select_list')[0];//获取该大div里的“新下拉框”
        var selectsBoxEl = $(that)[0];//获取该大div select_box?
        var target = e.target;//获取鼠标点的地方 例如:点了html
        //判断“新下拉框”是否等于html 和 “新下拉框”是否有 html的内容 和 该大div是否有 html的内容
        if (selectsEl !== target && !$.contains(selectsEl, target) && !$.contains(selectsBoxEl, target)) {
            if ($(that).parent().find('.select_list').css("display") == "block") {//判断“新下拉框是否展开”
                selects.slideUp(50);//展开就选项框收起
                $(that).children().find('.select_icon').toggleClass('select_icon_arrow');// 图标旋转
            }
        };
    }
    

    这样子就整个“新的下拉框”就完成了,但还不完美。如果有多个“新的下拉框”就会出现bug,所以要在传递的方法做一下改动,例如有两个:
    在这里插入图片描述
    Select_box0和select_box1就需要如下:

    var select_boxs = $(".html").find(".my_MenuSelect");
    for (var i = 0; i < select_boxs.length; i++) {
        var classone = select_boxs[i].classList[0];
        $('.' + classone).selectForm({//传递
            callBack: function (val) { }
        });
    }
    

    获取所有my_MenuSelect的类的,for循环遍历获取第一个类的名称然后复制给变量 classone,传递的函数参数化就可以了。

    猜你喜欢

    转载自blog.csdn.net/qq_41657790/article/details/88872930