天天看點

單文本框可以下拉進行多選JS特效單文本框可以下拉進行多選JS特效

單文本框可以下拉進行多選JS特效

因需求單個文本框可以選擇多個人,是以做了一個可以進行多選的效果,希望可以幫到有同需求的夥伴。

效果展示:

單文本框可以下拉進行多選JS特效單文本框可以下拉進行多選JS特效
單文本框可以下拉進行多選JS特效單文本框可以下拉進行多選JS特效

文本框可以進行多選,然後可以根據輸入關鍵詞進行搜尋

前端頁面引用和部分代碼

<link rel="stylesheet" type="text/css" href="css/tree.css" target="_blank" rel="external nofollow" />
<script type="text/javascript" src="js/jquery.min.js"></script>
<script type="text/javascript" src="js/comboTreePlugin.js"></script>
<script type="text/javascript" src="js/appraiser.js"></script>

  // 評價人框
<td><div class='text-container align-right' style='width:90px;'>評價人 :&nbsp;</div></td>
<input type='text' id='apprcount' class='apprcount' style=' border:none;width:65px;background-color:transparent;color:#666' readonly></td>");

// 評價人用來存值的隐藏域
<td><input type='text' style='display: none;' id='appraiser'  value='{data["ddesc"]}'  class='appraiser' name='fdata__appraiser'></td>"
           

tree.css

.wrapper {
    width: 1024px;
    margin: 50px auto 0 auto;
}

    .wrapper > div {
        overflow visibility: hidden;
        display: block;
        font-size: 0;
        content: " ";
        clear: both;
        height: 0;
    }


.select-tree-wrap {
    min-height: 24px;
    border: 1px solid #e4e4ea;
    background-color: white;
}

.input-keyword-wrap {
    min-height: 24px;
    position: relative;
}

    .input-keyword-wrap .handle-arrow {
        position: absolute;
        right: 10px;
        top: 10px;
    }

    .input-keyword-wrap .select-menu-input {
        font-size: 12px;
        height: 100%;
        overflow: hidden;
        min-height: 24px;
        cursor: pointer;
        background-color: white;
    }

    .input-keyword-wrap .input-tips {
        font-size: 14px;
        line-height: 24px;
        padding-left: 10px;
        color: #d6d6d6;
    }

    .input-keyword-wrap .single-keyword {
        border: 0px !important;
    }

    .input-keyword-wrap .input-keyword-item {
        width: auto;
        margin: 2px 8px 2px 5px;
        border: 1px solid #e4e4ea;
        color: #666;
        border-radius: 3px;
        display: block;
        float: left;
    }

        .input-keyword-wrap .input-keyword-item span:nth-child(1) {
            line-height: 22px;
            display: block;
            float: left;
            width: auto;
            height: 24px;
            float: left;
            margin-left: 2px;
            margin-right: 0px;
            border: 0 none;
            padding-right: 5px;
            color: #666;
        }

        .input-keyword-wrap .input-keyword-item i {
            width: 20px;
            height: 20px;
            display: block;
            padding: 0;
            margin: 1px 0px 1px 0px;
            float: left;
            text-align: center;
            font-style: normal;
            text-indent: 0px;
            cursor: pointer;
        }



.drop-down-wrap {
    display: none;
    position: absolute;
    background-color: white;
}

    .drop-down-wrap .noresults {
        display: none;
        padding: 10px 0;
        font-size: 12px;
        color: #ccc;
        text-align: center;
    }

/*    .drop-down-wrap .handle-left-icons {
        text-align: center;
        display: inline-block;
        width: 20px;
    }*/

    .drop-down-wrap .title-group-name {
        display: inline-block;
    }

    .drop-down-wrap .handle-checkbox {
        text-align: center;
        width: 30px;
        display: inline-block;
    }


    .drop-down-wrap .keyword-search {
        padding: 6px 10px 6px 10px;
        width: 100%;
        border-top: 1px solid #ccc;
        box-sizing: border-box;
        position: relative;
    }

        .drop-down-wrap .keyword-search input {
            width: 150px;
            outline: 0;
            padding: 0 30px 0 10px;
            height: 20px;
            border: 1px solid #ccc;
            box-sizing: border-box;
            border-radius: 5px;
        }

        .drop-down-wrap .keyword-search .search-icons {
            width: 20px;
            height: 20px;
            display: inline-block;
            position: absolute;
            right: 15px;
            top: 16px;
            color: #ccc;
        }

    .drop-down-wrap .select-tree-list {
        padding: 0;
        margin: 0;
        max-height: 400px;
        height: 170px;
        overflow-x: hidden; // 橫向滾動條隐藏
        /*overflow-x: scroll; // 橫向滾動條顯示*/
    }

        .drop-down-wrap .select-tree-list li {
            list-style-type: none;
            cursor: pointer;
        }

    .drop-down-wrap .title-container {
        line-height: 24px;
        padding: 0 20px
    }

        .drop-down-wrap .title-container:hover {
            background: #f2f2f2;
            color: #0079fe;
        }

    .drop-down-wrap .select-tree-list li .tree-sub-body ul {
        padding: 0;
    }

        .drop-down-wrap .select-tree-list li .tree-sub-body ul li {
            line-height: 0px;
        }

            .drop-down-wrap .select-tree-list li .tree-sub-body ul li .title-container {
                padding-left: 0px
            }

            .drop-down-wrap .select-tree-list li .tree-sub-body ul li .tree-sub-body ul li .title-container {
                padding-left: 0px;
            }


.actived_li {
    color: #666;
}

           

comboTreePlugin.js

(function ($, window, document, undefined) {
    let comboTreePlugin = 'comboTree',
        //定義一個存儲資料的數組,用于下面重複選擇判斷,删除标簽,
        defaults = {
            source: [],
            isMultiple: false,
            cascadeSelect: false,
            selected: [],
            selectedlength: 3
        },
        tempstructerarray = [];

    let ComboTree = function (element, options) {
        this.options = $.extend({}, defaults, options);
        this.element = element;
        this.ulcontainer = null;
        this.oliIdArray = [];
        this.copysource = [];
        this.roleSelect = null;
        this.copydom = null;
        this.comboxinput = null;
        this.comboxinputcontainer = null;
        this.comboxulcontainer = null;
        this.selectul = null;
        this.myplaceholder = null;
        this.noresults = null;
        this.init();
    };

    ComboTree.prototype.init = function () {
        $.extend(true, this.copysource, this.options.source);
        this.initstruct();
        this.initdom();
        this.ulcontainer = $(this.element).find('div[_id=comboxulcontainer]');
        this.comboxinput = $(this.element).find('input[_id=comboxinput]');
        this.roleSelect = $(this.element).find('div[_id=role_select]');
        this.comboxinputcontainer = $(this.element).find('div[_id=comboxinputcontainer]');
        this.comboxulcontainer = $(this.element).find('div[_id=comboxulcontainer]')
        this.copydom = this.selectul.clone();
        this.myplaceholder = $(this.element).find('span[_id=myplaceholder]');
        this.noresults = $(this.element).find('.noresults');
        this.initevent();
          
        for (var i = 0; i < this.options.selected.length; i++) {
            console.log(this.options.selected[i]);
            $("[data-id='" + this.options.selected[i] + "']").trigger("click");
        }
    };

    ComboTree.prototype.initstruct = function () {
        for (let i = 0; i < this.copysource.length; i++) {
            this.copysource[i]['class'] = 'first'
        }
    };

    ComboTree.prototype.initevent = function () {
        let _this = this;

        //點選輸入框時候
        $(this.element).on('click', function (event) {

            event = event || window.event;

            let closet = $(event.target).closest('.input-keyword-wrap'),icon = null;
            if (($(event.target).hasClass('imitationSelect') || $(event.target).hasClass('fa')) && closet.length > 0) {
                $(_this.element).find('.drop-down-wrap').toggle();
                if (!icon) {
                    icon = $(_this.element).find('.input-keyword-wrap>i');
                }
                if (icon.hasClass("fa-caret-down")) {
                    icon.removeClass("fa-caret-down").addClass("fa-caret-up"); //點選input選擇适合,小圖示動态切換
                } else {
                    icon.removeClass("fa-caret-up").addClass("fa-caret-down"); //點選input選擇适合,小圖示動态切換
                }
            }

            let target = $(event.target).hasClass('title-container') ? $(event.target) : $(event.target)
                .parent().hasClass('title-container') ? $(event.target).parent() : null;

            if (target) {
                // 如果已選擇的大于設定的數目,并且目前是選擇動作 則不執行
                if ((_this.oliIdArray.length >= _this.options.selectedlength) && !target.hasClass('actived_li') && _this.options.isMultiple) {
                    console.log('最大可選條目已設定');
                    return false;
                }

                if (target.attr('role') !== 'parent') {
                    event.target = target;
                    let oliId = target.attr("data-id");
                    if (target.hasClass('actived_li')) {
                        _this.uncheckrow(oliId);
                    } else {
                        if (!_this.options.isMultiple) { //如果是單選,則已選條目大于零,并且所點選的不是 激活狀态的,不執行
                            if (_this.oliIdArray.length > 0) {
                                for (let j = 0; j < _this.oliIdArray.length; j++) {
                                    _this.uncheckrow(_this.oliIdArray[j]);
                                }
                            }
                        }
                        _this.checkrow(target, oliId, false); //第三個參數表示點選的是否是checkbox
                    }

                    if (!_this.options.isMultiple) {
                        _this.hideul();
                    }
                }
            }

            if ($(event.target).attr('type') === 'checkbox') {
                if ((_this.oliIdArray.length >= _this.options.selectedlength) && $(event.target).prop(
                        'checked')) {
                    console.log('超出最大條目');
                    return false;
                }

                let _target = $(event.target).closest('.title-container');

                if (_target.hasClass('actived_li')) {
                    _this.uncheckrow($(event.target).attr('data-id'));
                } else {
                    _this.checkrow(_target, $(event.target).attr('data-id'), true);
                }
            }

            //點選x關閉事件處理
            if ($(event.target).attr('class') === 'close') {
                _this.uncheckrow($(event.target).attr('data-id'));
            }

            let containerparent = $(event.target).attr('role') === 'parent' ? $(event.target) : $(event
                .target).parent().attr('role') === 'parent' ? $(event.target).parent() : null;

            if (!containerparent) {
                target = $(event.target).attr('tag') === 'closeitem' ?
                    $(event.target) : $(event.target).parent().attr('tag') === 'closeitem' ?
                    $(event.target).parent() : null;
            }

            if( $(event.target).attr('tag') === 'search' || $(event.target).parent().attr('tag') === 'search' ){
                _this.comboxinput.val('');
                _this.comboxinput.trigger('keyup');
            }

            if (target || containerparent) {
                let _parent = null;
                if (containerparent) {
                    _parent = containerparent
                } else {
                    _parent = target.closest('.title-container');
                }

                _parent.next().toggle();
                target = target.find('i');

                if (target.hasClass('fa-caret-down')) {
                    target.removeClass('fa-caret-down').addClass('fa-caret-right');
                } else {
                    target.removeClass('fa-caret-right').addClass('fa-caret-down');
                }
            }

            if (event.stopPropagation) {
                event.stopPropagation(); // 針對 Mozilla 和 Opera
            } else if (window.event) {
                window.event.cancelBubble = true; // 針對 IE
            }
        });

        this.comboxinput.on('keyup', function (event) {
            event = event || window.event;

            _this.selectul.find('.hide').removeClass('hide');


            // 判斷搜尋框裡是否有内容,如果有則添加删除按鈕
            if (event.currentTarget.value != "") {
              $(this).siblings('span').find('i').removeClass('fa-search').addClass('fa-close');
            } else {
              $(this).siblings('span').find('i').removeClass('fa-close').addClass('fa-search');
            }

            let lis = _this.selectul.find('li'),
                targetli = null,
                _tempattr = null;

            lis.each(function (index, item) {
                $(item).attr('matched', '');
            });
            let val = $(event.target).val();

            function getChildren(parent) {
                let lichild = parent.children('li');

                if (lichild.length) {
                    for (let i = 0, _p = lichild, len = _p.length; i < len; i++) {
                        targetli = _p.eq(i), _tempattr = targetli.attr('data-name');

                        if (_tempattr.indexOf(val) >= 0 && _tempattr !== ' ' && _tempattr !== '') {
                            targetli.attr('matched', 'matched');
                        }

                        let subulcontainer = targetli.find('>.tree-sub-body');

                        if (subulcontainer.length > 0) {
                            let _tempul = subulcontainer.find('>ul');
                            getChildren(_tempul);
                        }
                    }
                }
            }
            getChildren(_this.selectul);

            if (val.trim() !== '') {
                let lis1 = _this.selectul.find('li');
                lis1.each(function (index, item) {
                    let _item = $(item);
                    let matched = _item.find('li[matched="matched"]');
                    if (_item.length === 0) {
                        return true; //相當于continue
                    }
                    if (matched.length === 0) {
                        if (_item.attr('matched') === 'matched') { //如果目前元素比對,則保留目前的删除它後面的所有元素

                            let _matcheditem = _item.find('>div.tree-sub-body');
                            _matcheditem.each(function (index, item) {
                                $(item).addClass('hide');
                            });
                        } else {
                            _item.addClass('hide');
                        }
                    }
                });

                let children = _this.comboxulcontainer.find('li[matched=matched]');

                if (children.length === 0) {
                    _this.selectul.hide();
                    _this.noresults.show();
                } else {
                    _this.noresults.hide();
                    _this.selectul.show();
                }

            } else {
                _this.selectul.show();
                _this.selectul.find('.hide').removeClass('hide');
                _this.noresults.hide();
            }

        });

        //點選任意地方隐藏下拉
        $(document).click(function (event) {
            _this.hideul();
        });

        // 點選請選擇人員隐藏下拉下拉
        $(this.element).find('span[_id=myplaceholder]').on('click', function (event) {
            _this.toggleul();
        });
    };

    ComboTree.prototype.initdom = function () {
        $(this.element).append(
            '<div class="input-keyword-wrap">' +
            '<div _id="role_select" class="select-menu-input imitationSelect role_select">'+
            '<span _id="myplaceholder" class="input-tips">請選擇人員</span>'+
            '</div>' +
            '<i class="fa fa-caret-down handle-arrow"></i>' +
            '</div>' +
            '<div class="drop-down-wrap">' +
            '<div _id="comboxinputcontainer" class="comboxinputcontainer keyword-search">' +
            '<input _id="comboxinput" placeholder="輸入關鍵詞搜尋" type="text">' +
            '<span tag="search" class="search-icons"><i class="fa fa-search"></i></span>' +
            '</div>' +
            '<div _id="comboxulcontainer">' +
            '<div _id="noresault" class="noresults">無搜尋結果</div>'+
            '<ul class="select-tree-list" _id="selectUl"></ul>' +
            '</div>' +
            '</div>');

        this.selectul = $(this.element).find('ul[_id=selectUl]');
        this.createitem(this.copysource, this.selectul);

    };

    ComboTree.prototype.createitem = function (SampleJSONData, container) {
        for (let j = 0; j < SampleJSONData.length; j++) {

            var oliName = SampleJSONData[j].title;
            var oliId = SampleJSONData[j].id;
            // li容器
            let item = $('<li data-name="' + oliName + '" data-id="' + oliId + '"></li>'),
                divitem = $('<div data-name="' + oliName + '" data-id="' + oliId +'" class="title-container"></div>');
            spanitem = $('<span tag="closeitem" class="handle-left-icons"></span>');
            divitem.append(spanitem);

            //如果是第一層,給他設定一個屬性叫firstclass
            if (SampleJSONData[j]['class'] === 'first') {
                divitem.attr('role', 'parent');
            }

            if (SampleJSONData[j]['subs']) {
                spanitem.append('<i class="fa fa-caret-down"></i>');
                divitem.append(spanitem);
                divitem.attr('role', 'parent');
            }

            //放入checkbox  ,這段業務表示如果是第一層,并且在配置中寫了,第一層允許選擇才加入checkbox
            if (this.options.isMultiple) {
                if (SampleJSONData[j]['class'] === 'first') {
                    if (this.options.isFirstClassSelectable) {
                        appendcheckbox(divitem, oliId);
                    }
                } else {
                    if (!SampleJSONData[j]['subs']) {
                        appendcheckbox(divitem, oliId);
                    }
                }
            }
            // 放入名稱
            divitem.append('<span class="title-group-name">' + oliName + '</span>');
            item.append(divitem);
            container.append(item);

            if (SampleJSONData[j]['subs']) {
                let titlediv = $('<div class="tree-sub-body"></div>');
                item.append(titlediv);
                let subul = $('<ul></ul>');
                titlediv.append(subul);
                this.createitem(SampleJSONData[j]['subs'], subul);
            }
        }
    };

    ComboTree.prototype.checkrow = function (target, oliId, ischeckbox) {
        let _this = this;
        target.addClass("actived_li"); //點選目前的添加   actived_li這個類;
        // 判斷目前元素前面是否有checkbox,如果有就選中
        let inputcheckbox = target.find('input');
        if (inputcheckbox.length > 0 && !ischeckbox) {
            inputcheckbox.prop('checked', !inputcheckbox.prop('checked'));
        }
        _this.oliIdArray.push(oliId);
        _this.roleSelect.attr("data-id", _this.oliIdArray); //把目前點選的oliId指派到顯示的input的oliId裡面

        if (_this.oliIdArray.length > 0) {
            _this.myplaceholder.hide();
        }

        // 新增人員後将評價人id更新頁面的評價人隐藏域
        $("#appraiser").val(_this.oliIdArray);

        var jslength = 0;
        for (var appr in _this.oliIdArray) {
            jslength++;
        }

        // 更新選擇人員數量
        $("#apprcount").val('已選' + jslength + '人');


        //向input裡面存放的内容,是一個span
        let item = $("<span data-id='" + oliId + "' class='input-keyword-item'></span>"),
                namespan = $("<span>" + target.attr('data-name') + "</span>"),
                checkicon = $("<i class='close' data-id='" + oliId + "' >x</i>");
       
        item.append(namespan);
        if (this.options.isMultiple) {
            item.append(checkicon);
        } else {
            item.addClass('single-keyword')
        }

        _this.roleSelect.append(item);
    };

    ComboTree.prototype.uncheckrow = function (oliId) {
        let _this = this, icon = null;
        let id = null;

        for (let i = 0; i < _this.oliIdArray.length; i++) {
            if (_this.oliIdArray[i] === oliId) { //表示數組裡面有這個元素
                id = i; //元素位置
                _this.oliIdArray.splice(i, 1);
                //把目前點選的oliId指派到顯示的input的oliId裡面
                _this.roleSelect.attr("data-id", _this.oliIdArray);
                // console.log('删除目前的序号' + oliId + ';' + '剩下數組' + _this.oliIdArray)
            }
        }

        $(_this.element).find('.title-container').each(function (index, item) {
            if ($(item).attr('data-id') === oliId) {
                $(item).removeClass('actived_li');
                let $checkbox = $(item).find('input');
                $checkbox.prop('checked', false);
            }
        });

        if (!icon) {
            icon = $(_this.element).find('.input-keyword-wrap>i');
            icon.removeClass("fa-caret-up").addClass("fa-caret-down"); //點選input選擇适合,小圖示動态切換
        }

        _this.roleSelect.find('>span').each(function (index, item) {
            if ($(item).attr('data-id') === oliId) {
                item.remove();

                // 删除人員後将評價人id更新頁面的評價人隐藏域
                $("#appraiser").val(_this.oliIdArray);

                var jslength = 0;
                for (var appr in _this.oliIdArray) {
                    jslength++;
                } 

                // 更新選擇人員數量
                if (jslength != 0) {
                    $("#apprcount").val('已選' + jslength + '人');
                }
                else {
                    $("#apprcount").val('');
                }
            }
        });

        if (_this.oliIdArray.length === 0) {
            _this.myplaceholder.show();
        }
    };

    ComboTree.prototype.hideul = function () {
        // event=event||window.event;
        $(this.element).find('.input-keyword-wrap .fa').removeClass("fa-caret-up").addClass("fa-caret-down"); //當點隐藏ul彈窗時候,把小圖示恢複原狀
        $(this.element).find('.drop-down-wrap').hide(); //當點選空白處,隐藏ul彈窗
    };


    ComboTree.prototype.toggleul = function () {
        // event=event||window.event;
        $(this.element).find('.input-keyword-wrap .fa').toggleClass("fa-caret-up").toggleClass("fa-caret-down"); 
        $(this.element).find('.drop-down-wrap').toggle();  
    };

    /**
     * 清空搜尋輸入框裡面的内容
     */
    ComboTree.prototype.clearSearchValue = function() {
         
    };

    ComboTree.prototype.datas = function () {

        let arr = [];
        $(this.element).find('.input-keyword-item').each(function (index, item) {
            arr.push({
                id:$(item).attr('data-id'),
                val:$(item).find('span').html()
            });
        });
        return arr;
    };

    function appendcheckbox(divitem, oliId) {
        let $checkboxspan = $('<span class="handle-checkbox"></span>'),
            $checkbox = $('<input data-id="' + oliId + '" type="checkbox">');
        $checkboxspan.append($checkbox);
        divitem.append($checkboxspan);
    }

    $.fn[comboTreePlugin] = function (options) {
        var ctArr = [];
        this.each(function () {
            if (!$.data(this, 'plugin_' + comboTreePlugin)) {
                $.data(this, 'plugin_' + comboTreePlugin, new ComboTree(this, options));
                ctArr.push($(this).data()['plugin_' + comboTreePlugin]);
            }
        });

        if (this.length === 1)
            return ctArr[0];
        else
            return ctArr;
    };

})(jQuery, window, document);

           

appraiser.js

$(function () {
	var SampleJSONData = [];
	for (var i in datacustom) {
		SampleJSONData.push({
			id: datacustom[i].id,
			title: datacustom[i].title,
			subs :[]
		});
	}

	let bbb = $('#justAnInputBox').comboTree({
		source: SampleJSONData,
		isMultiple: true,
		isFirstClassSelectable: true, //第一級是否可選
        cascadeSelect: true,
        selected: ($("#appraiser").val() || '').split(','),
		selectedlength: 100 //最多可選
    });
    console.log($("#appraiser").val());

	// bbb.datas(); //擷取資料
});