zoukankan      html  css  js  c++  java
  • Combobox

    思路:

    控件封装首先应该考虑到兼容任何web框架,这样可以达到重复使用的效果。这里使用jquery方式来实现控件主体部分。

    全局事件管理:

    (function (global, $, factory) {
        global = factory.call(global, $);
    })(window, $, function ($) {
        var DUI = {};
        window.DUI = window.$$ = DUI;
        window.$$.Event = function (props) {
            if (!(this instanceof $$.Event))
                return new $$.Event(props);
            this.oldValue = null;
            this.newValue = null;
            this.element = null;
            this.params = {};
            $.extend(this, props);
        };
    
        window.$$.trigger = function (type, el, args) {
            var event = $.Event(type, args);
            el.trigger(event, args);
        };
    })
    View Code

    jquery主体实现:

      /*
         combobox UI
         */
        var uuid = -1;
        var __Combobox__ = function (ops) {
            this.__eventNameSpave__ = ".combobox-event";
            this.__ComboboxC__ = {
                root: $('body'),
                inputId: 'ui-combobox-input-',
                dorpdownId: 'ui-combobox-dropdown-',
                popupId: 'ui-combobox-popup-',
                placeHolderId: 'ui-combobox-placeholder-',
                listboxId: 'ui-combobox-listboxId-',
                items: [],
                popupOpend: false,
                oldValue: {},
                newValue: {},
                selectedIndex: -1,
                selectedItem: {}
            };
            this.__delay__ = 200;
            this.__$Dom__ = {};
            this.__filterSelectionResultIndex__ = [];
            this.__extends__(ops, this.__ComboboxC__);
            this.__element__ = this.__ComboboxC__.root;
            this.__initId__().__init__().__load__();
        }
    
        __Combobox__.prototype = {
            __initId__: function () {
                this.__uuId = ++uuid;
                this.__ComboboxC__.inputId += uuid;
                this.__ComboboxC__.dorpdownId += uuid;
                this.__ComboboxC__.popupId += uuid;
                this.__ComboboxC__.placeHolderId += uuid;
                this.__ComboboxC__.listboxId += uuid;
                return this;
            },
            __init__: function () {
                this.__element__.css('width', this.__ComboboxC__.width + 'px')
                    .css('height', this.__ComboboxC__.height + 'px')
                    .addClass('ui-combobox');
                this.__createCombobox__()
                    .__createDropDown__()
                    .__createPopup__()
                    .__initDom__()
                    .__bindEvent__();
                return this;
            },
            __createCombobox__: function () {
                var h = -1, fragement = [];
                fragement[++h] = "<input id='" + this.__ComboboxC__.inputId + "' class="ui-combobox-input" />";
                fragement[++h] = "<div class="ui-combobox-placeholder">";
                fragement[++h] = "<div id='>" + this.__ComboboxC__.placeHolderId + "<' /div>";
                fragement[++h] = "</div>";
                this.__element__.append(fragement.join(''));
                return this;
            },
            __createDropDown__: function () {
                var h = -1, fragement = [];
                fragement[++h] = "<div id=" + this.__ComboboxC__.dorpdownId + " class="ui-combobox-dropdown-container">";
                fragement[++h] = "<div class="ui-dorpdown-icon"></div>";
                fragement[++h] = "</div>";
                this.__element__.append(fragement.join(''));
                return this;
            },
            __createPopup__: function () {
                var h = -1, fragement = [];
                fragement[++h] = "<div class="ui-combobox-popup" id=" + this.__ComboboxC__.popupId + ">";
                fragement[++h] = "<div class="ui-combobox-listbox">";
                fragement[++h] = "<div class="ui-combobox-listbox-container" id=" + this.__ComboboxC__.listboxId + ">";
                fragement[++h] = "</div>";
                fragement[++h] = "</div>";
                fragement[++h] = "</div>";
                $('body').append(fragement.join(''));
                return this;
            },
            __initDom__: function () {
                this.__$Dom__.$listbox = $('#' + this.__ComboboxC__.listboxId);
                this.__$Dom__.$input = $('#' + this.__ComboboxC__.inputId);
                this.__$Dom__.$popup = $('#' + this.__ComboboxC__.popupId);
                return this;
            },
            __load__: function () {
                this.__seSelectionItems__().__setSelectionEvent__();
                this.__$Dom__.$popup.hide();
            },
            setOptions: function (key, ops) {
                var self = this,
                    clr = {
                        setStyle: self.__setSytle__.bind(this),
                        setItems: self.__setItems__.bind(this),
                        setSelectedItem: self.__setSelectedItem__.bind(this)
                    };
                clr[key](ops);
            },
            __setSytle__: function (ops) {
                this.__$Dom__.$popup.css('width', ops.popupWidth)
                    .css('height', ops.popupHeight)
                    .css('max-width', ops.popupMaxWidth)
                    .css('max-height', ops.popupMaxHeight)
                return this;
            },
    
            __setItems__: function (ops) {
                this.__ComboboxC__.items = ops.items;
                this.__seSelectionItems__()
                    .__setSelectionEvent__()
                    .__setSelectedItem__(ops.selectedItem);
            },
            __seSelectionItems__: function () {
                var tempItems = this.__ComboboxC__.items;
                var i = 0, len = tempItems.length, fragement = [];
                this.__$Dom__.$listbox.empty();
                for (; i < len; i++) {
                    fragement.push("<div class="ui-combobox-selection-container">");
                    fragement.push("<div role='option' class="ui-combobox-selection" id=ui-combobox-selection-select-option-" + i + ">");
                    fragement.push(tempItems[i].name);
                    fragement.push("</div>");
                    fragement.push("</div>");
                }
                this.__$Dom__.$listbox.append(fragement.join(''));
                return this;
            },
            __setSelectedItem__: function (selectedItem) {
                var self = this,
                    clr = {
                        object: function () {
                            return selectedItem.name;
                        },
                        string: function () {
                            return selectedItem;
                        },
                        undefined: function () {
                            return self.__ComboboxC__.items[0];
                        }
                    }, selectedText = "";
                selectedText = clr[typeof selectedItem]();
                for (var i = 0; i < this.__ComboboxC__.items.length; i++) {
                    if (this.__ComboboxC__.items[i].name == selectedText) {
                        this.__ComboboxC__.selectedIndex = i;
                    }
                }
                this.__$Dom__.$selections.removeClass('ui-combobox-selection-selected');
                if (this.__ComboboxC__.selectedIndex != -1) {
                    var inputValue = this.__ComboboxC__.items[this.__ComboboxC__.selectedIndex].name;
                    this.__$Dom__.$input[0].value = inputValue;
                    this.__$Dom__.$selections[this.__ComboboxC__.selectedIndex].classList.add('ui-combobox-selection-selected');
                    this.__ComboboxC__.newValue = this.__ComboboxC__.items[this.__ComboboxC__.selectedIndex];
                } else {
                    this.__$Dom__.$input[0].value = '';
                    this.__$Dom__.$selections[0].classList.add('ui-combobox-selection-selected');
                    this.__ComboboxC__.newValue = null;
                }
                this.__hide__();
                return this;
            },
    
            __bindEvent__: function () {
                var self = this;
                this.__$Dom__.$input.on('mousedown' + this.__eventNameSpave__, function (e) {
                    self.__hideShow__();
                }).on('focus' + this.__eventNameSpave__, function (e) {
                    self.__element__.addClass('ui-combobox-focused');
                }).on('blur' + this.__eventNameSpave__, function (e) {
                    self.__element__.removeClass('ui-combobox-focused');
                    self.__hide__();
                }).on('mouseover' + this.__eventNameSpave__, function () {
                    self.__element__.addClass('ui-combobox-mouseover');
                }).on('mouseleave' + this.__eventNameSpave__, function () {
                    self.__element__.removeClass('ui-combobox-mouseover');
                }).on('keyup', + this.__eventNameSpave__, this.__onInputkeyDown__.bind(this));
    
                this.__debounceHandler__ = this.__debounce__(this.__filterSelection__.bind(this));
    
                this.__$Dom__.$listbox.on('mousedown' + this.__eventNameSpave__, function (e) {
                    e.stopPropagation();
                    e.preventDefault();
                });
                $('#' + this.__ComboboxC__.dorpdownId).on('click' + this.__eventNameSpave__, function (e) {
                    self.__hideShow__();
                });
    
            },
    
            __setSelectionEvent__: function () {
                var self = this;
                this.__$Dom__.$selections = $('#' + this.__ComboboxC__.listboxId + ' .ui-combobox-selection');
                this.__$Dom__.$selections.on('click' + this.__eventNameSpave__, function (e) {
                    var text = e.currentTarget.textContent;
                    self.__setSelectedItem__(text);
                    $$.trigger("selectionChanged", self.__element__, $$.Event({
                        element: self.__element__,
                        oldValue: self.__ComboboxC__.oldValue,
                        newValue: self.__ComboboxC__.newValue
                    }))
                    self.__ComboboxC__.oldValue = self.__ComboboxC__.newValue;
                });
                return this;
            },
    
            __onInputkeyDown__: function (e) {
                var self = e.data,
                    keyCode = e.which;
                this.__debounceHandler__(e.target.value);
            },
    
            __debounce__: function (fn) {
                var
                    timer,
                    self = this;
                return function (e) {
                    clearTimeout(timer);
                    timer = setTimeout(function () {
                        fn.apply(self, [e])
                    }, self.__delay__);
                }
            },
    
            __filterSelection__: function (e) {
                console.log(e);
                var condition = this.__getCondition__();
                var i = 0,
                    len = this.__ComboboxC__.items.length,
                    items = this.__ComboboxC__.items;
                for (var i = 0; i < len; i++) {
                    var name = this.__getInputValue__(items[i]);
                    if (name.indexOf(condition) > -1) {
                        this.__filterSelectionResultIndex__.push(i);
                    }
                };
                this.__updateFilteredSelections__();
                this.__filterSelectionResultIndex__.length = 0;
            },
            __getCondition__: function () {
                var value = '';
                value = this.__$Dom__.$input.val().toLowerCase();
                return value;
            },
    
            __getInputValue__: function (item) {
                return item['name'];
            },
    
            __updateFilteredSelections__: function () {
                var items = this.__ComboboxC__.items,
                    i = 0,
                    len = items.length;
                for (; i < len; i++) {
                    if (this.__filterSelectionResultIndex__.includes(i)) {
                        $(this.__$Dom__.$listbox.children()[i]).show();
                    } else {
                        $(this.__$Dom__.$listbox.children()[i]).hide();
                    }
                }
                this.__show__();
            },
    
            __hideShow__: function () {
                this.__ComboboxC__.popupOpend = !this.__ComboboxC__.popupOpend;
                if (this.__ComboboxC__.popupOpend)
                    this.__show__();
                else
                    this.__hide__();
            },
    
            __hide__: function () {
                this.__ComboboxC__.popupOpend = false;
                this.__$Dom__.$popup.hide();
            },
    
            __show__: function () {
                this.__ComboboxC__.popupOpend = true;
                this.__$Dom__.$popup.show();
                this.__setPopupPosition__();
                this.__$Dom__.$selections.removeClass('ui-combobox-selection-selected');
                if (this.__filterSelectionResultIndex__.length == 0 && this.__$Dom__.$selections.length == this.__ComboboxC__.items.length) {
                    if (this.__ComboboxC__.selectedIndex == -1)
                        $(this.__$Dom__.$selections[0]).addClass('ui-combobox-selection-selected');
                    else
                        $(this.__$Dom__.$selections[this.__ComboboxC__.selectedIndex]).addClass('ui-combobox-selection-selected');
                    return;
                }
                if (this.__filterSelectionResultIndex__.includes(this.__ComboboxC__.selectedIndex)) {
                    $(this.__$Dom__.$selections[this.__ComboboxC__.selectedIndex]).addClass('ui-combobox-selection-selected');
                    return;
                } else {
                    $(this.__$Dom__.$selections[this.__filterSelectionResultIndex__[0]]).addClass('ui-combobox-selection-selected');
                    return;
                }
                console.log('no select items.');
            },
    
            __setPopupPosition__: function () {
                var self = this;
                this.__$Dom__.$popup
                    .css({ top: 0 })
                    .position({
                        my: "left top",
                        at: "left bottom",
                        of: self.__element__,
                        collision: "flip"
                    })
            },
    
            __extends__: function (ops, target) {
                for (var i in ops) {
                    if (typeof ops[i] !== undefined) target[i] = ops[i];
                }
            }
        }
    View Code

    react外层包装:

    import ReactWidget from './react-widget';
    class Combobox extends ReactWidget {
        constructor(props) {
            super(props);
            this.element = {};
            this.state = {
                items: []
            };
        }
    
        componentWillReceiveProps(newPorps) {
            if (newPorps.items.length !== 0)
                this.element.setOptions('setItems', {
                    items: newPorps.items
                })
            if (newPorps.selectedItem != null)
                this.element.setOptions('setSelectedItem', newPorps.selectedItem)
        }
    
        componentDidMount() {
            this.element = new aui.Combobox({
                root: $(ReactDOM.findDOMNode(this)),
                items: this.props.items
            });
            $(ReactDOM.findDOMNode(this)).on('selectionChanged', this.selectionChangedHandler.bind(this));
        }
    
        selectionChangedHandler(e, args) {
            this.props.selectionChanged(e, args);
        }
    
        render() {
            return <div></div>
        }
    }
    
    window.$$.Combobox = Combobox;
    View Code

    样式:

    section {
        border-bottom: 1px solid #FF9900;
        padding: 5px;
    }
    
    /*
        icon
    */
    .ui-dorpdown-icon {
        height: auto;
        width: 20px;
    
        &:after {
            content: '25BC'
        }
    }
    
    /*
        dialog 
    */
    button {
        border: 1px solid #9D9D9D;
        background-color: #fff;
        height: auto;
        padding: 5px 20px;
        border-radius: 5px;
        color: #9D9D9D;
        font-weight: inherit;
        font-style: inherit;
        font-family: inherit;
        cursor: pointer;
    
        &:hover {
            background: #9D9D9D;
            color: #fff;
        }
    }
    
    .ui-backdrop {
        POSITION: fixed;
        left: 0;
        top: 0;
        right: 0;
        bottom: 0;
        background-color: rgba(34, 34, 34, 0.5);
        z-index: 99;
    }
    
    .dialog {
        position: fixed;
        z-index: 100;
        top: 50%;
        left: 50%;
        right: 0;
        bottom: 0;
        border: 1px solid #ff9900;
        border-radius: 5px;
        text-align: center;
        background: #ffffff;
    
        .dialog-title {
            width: auto;
            height: 40px;
            line-height: 40px;
            background-color: #ff9900;
            font-weight: bold;
            color: #ffffff;
        }
    
        .dialog-content {
            padding: 10px;
        }
    
        .dialog-footer {
            position: absolute;
            bottom: 0px;
            background-color: #ff9900;
            width: 100%;
            height: auto;
            padding: 2px 0;
        }
    }
    
    /* 
        banner 
    */
    .banner {
        position: relative;
        width: 100%;
        height: 400px;
    
        .banner-indicators {
            position: absolute;
            bottom: 20px;
            z-index: 10;
            width: 60%;
            padding-left: 0;
            list-style: none;
            text-align: center;
            width: 25%;
            left: 42%;
    
            .banner-indicators-item {
                list-style: none;
                float: left;
                width: 50px;
                padding: 5px 0;
                margin: 0 2px;
                opacity: 0.5;
                border: 0;
                background-color: #fff;
                height: auto;
                border-radius: 5px;
                margin-right: 50px;
                cursor: pointer;
            }
    
            .active {
                background-image: -webkit-linear-gradient(left, #9D9D9D, #000000 25%, #4F4F4F 50%, #000000 75%, #9D9D9D 100%);
                -webkit-text-fill-color: transparent;
                -webkit-animation: indicators-animation 2s infinite linear;
            }
    
            @-webkit-keyframes indicators-animation {
                0% {
                    background: #9D9D9D;
                    border: 3px solid #ffffff;
                }
    
                50% {
                    background: #000000;
                    border: 3px solid #9D9D9D;
                }
    
                100% {
                    background: #9D9D9D;
                    border: 3px solid #ffffff;
                }
            }
        }
    
        .banner-inner {
            width: 100%;
            height: 100%;
            overflow: hidden;
    
            .banner-content {
                width: 300%;
                height: 100%;
                transform: translate3d(-66.66666666%, 0, 0);
                transition: transform 0.6s ease-in-out;
                -webkit-transition: -webkit-transform 0.6s ease-in-out;
    
                .banner-item {
                    display: inline-block;
                    position: relative;
                    width: 33.333333333%;
                    height: 100%;
                    background-repeat: no-repeat;
                    background-size: cover;
    
                    &:nth-child(1) {
                        background-image: url('./Image/banner0.jpg');
                    }
    
                    &:nth-child(2) {
                        background-image: url('./Image/banner1.jpg');
                    }
    
                    &:nth-child(3) {
                        background-image: url('./Image/banner2.jpg');
                    }
    
                    .banner-item-inner {
                        .title {
                            visibility: hidden;
                            transform: translate3d(-15%, 350%, 0);
                            transition: transform 0.3s ease-in-out;
                            -webkit-transition: -webkit-transform 0.3s ease-in-out;
                        }
    
                        .description {
                            visibility: hidden;
                            transform: translate3d(100%, 300%, 0);
                            transition: transform 0.3s ease-in-out;
                            -webkit-transition: -webkit-transform 0.3s ease-in-out;
                        }
                    }
    
                    .active {
                        .title {
                            visibility: visible;
                            transform: translate3d(30%, 350%, 0);
                        }
    
                        .description {
                            visibility: visible;
                            transform: translate3d(60%, 300%, 0);
                        }
                    }
    
                    .banner-item-inner {
                        p {
                            font-size: 40px;
                            font-weight: bold;
                            color: #fff;
                            font-style: italic;
                        }
                    }
                }
            }
        }
    }
    
    .ui-combobox {
        position: relative;
        width: 200px;
        min-width: 50px;
        height: 30px;
        line-height: 30px;
        background-color: #fff;
        border: 1px solid #bbb;
        outline: 0;
        -moz-box-sizing: border-box;
        -webkit-box-sizing: border-box;
        box-sizing: border-box;
    
        .ui-combobox-input {
            position: absolute;
            width: 100%;
            height: 100%;
            margin: 0 auto;
            outline: 0;
            overflow: hidden;
            resize: none;
            border: none;
            background: #fff;
            cursor: default;
            padding: 1px 30px 1px 5px;
            -moz-box-sizing: border-box;
            -webkit-box-sizing: border-box;
            box-sizing: border-box;
        }
    
        .ui-combobox-dropdown-container {
            position: absolute;
            height: 100%;
            right: 0;
            top: 0;
            border-left: 1px solid transparent;
            cursor: default;
        }
    
        .ui-combobox-placeholder {
            position: absolute;
            display: table;
            table-layout: fixed;
            height: 100%;
            top: 0;
            left: 5px;
            -moz-box-sizing: border-box;
            -webkit-box-sizing: border-box;
            box-sizing: border-box;
            color: #aaa;
        }
    }
    
    .ui-combobox-focused {
        border-color: #49d;
    }
    
    .ui-combobox-mouseover {
        border-color: #49d;
    }
    
    .ui-combobox-popup-shown {
        border-color: #49d;
    }
    
    .ui-combobox-popup {
        position: absolute;
        width: 198px;
        height: auto;
        background-color: #ffffff;
        border: 1px solid #bbb;
        box-sizing: content-box;
    
        .ui-combobox-listbox {
            height: auto;
            max-height: 300px;
            min-height: 22px;
            list-style: none;
            overflow: auto;
            background-color: #ffffff;
            box-sizing: border-box;
    
            .ui-combobox-listbox-container {
                display: table;
                width: 100%;
    
                .ui-combobox-selection-container {
                    display: table-row;
    
                    &:hover {
                        background-color: #F0F0F0;
                    }
    
                    .ui-combobox-selection {
                        display: table-cell;
                        border: 1px solid #ffffff;
                        outline: 0;
                        white-space: nowrap;
                        padding: 13px 0 13px 5px;
                        line-height: 1px;
                        cursor: default;
                    }
    
                    .ui-combobox-selection-selected {
                        background-color: #bbb;
                    }
                }
            }
        }
    }
    
    /*
        loading
    */
    
    .ui-loading {
        position: fixed;
        left: 0;
        right: 0;
        top: 0;
        bottom: 0;
        z-index: 99999;
        display: block;
        text-align: center;
    
        &::before {
            content: '';
            height: 100%;
            width: 0;
            vertical-align: middle;
            display: inline-block;
        }
    
        .ui-loading-dialog {
            position: relative;
            vertical-align: middle;
            display: inline-block;
    
            .ui-loading-circle {
                position: relative;
                height: 60px;
                width: 60px;
                border-radius: 50%;
                background-color: #9D9D9D;
    
                &::before {
                    height: 4px;
                    width: 100%;
                    left: 0;
                    top: 28px;
                    z-index: 1;
                    position: absolute;
                    content: "";
                    background: #fff;
                }
    
                &::after {
                    width: 4px;
                    height: 100%;
                    top: 0;
                    right: 28px;
                    position: absolute;
                    content: "";
                    background: #ffffff;
                }
    
                .left {
                    position: absolute;
                    height: 100%;
                    width: 50%;
                    overflow: hidden;
                    left: 0;
                }
    
                .right {
                    position: absolute;
                    overflow: hidden;
                    height: 100%;
                    width: 50%;
                    left: 50%;
                }
    
                .center {
                    position: absolute;
                    top: 6px;
                    left: 6px;
                    height: 48px;
                    width: 48px;
                    background: #fff;
                    border-radius: 50%;
                }
    
                .anim {
                    position: absolute;
                    left: 100%;
                    top: 0;
                    height: 100%;
                    width: 100%;
                    border-radius: 999px;
                    background-color: #ff9900;
                    -webkit-animation: aui-circle-loading-left 2s infinite;
                    animation: aui-circle-loading-left 2s infinite;
                    -webkit-transform-origin: 0 50% 0;
                    transform-origin: 0 50% 0;
                    -webkit-animation-duration: 2s;
                    -webkit-animation-timing-function: linear;
                    animation-duration: 2s;
                    animation-timing-function: linear;
                }
    
    
                .right .anim {
                    -webkit-animation-name: aui-circle-loading-right;
                    animation-name: aui-circle-loading-right;
                }
    
                .left .anim {
                    border-bottom-left-radius: 0;
                    border-top-left-radius: 0;
                }
    
                .right .anim {
                    border-bottom-right-radius: 0;
                    border-top-right-radius: 0;
                    left: -100%;
                    -webkit-transform-origin: 100% 50% 0;
                    transform-origin: 100% 50% 0;
                }
            }
        }
    }
    
    @keyframes aui-circle-loading-left {
        0% {
            transform: rotate(0deg)
        }
    
        25% {
            transform: rotate(0deg)
        }
    
        50% {
            transform: rotate(180deg)
        }
    
        75% {
            transform: rotate(180deg)
        }
    
        100% {
            transform: rotate(360deg)
        }
    }
    
    
    @keyframes aui-circle-loading-right {
        0% {
            transform: rotate(0deg)
        }
    
        25% {
            transform: rotate(180deg)
        }
    
        50% {
            transform: rotate(180deg)
        }
    
        75% {
            transform: rotate(360deg)
        }
    
        100% {
            transform: rotate(360deg)
        }
    }
    View Code

    效果:

  • 相关阅读:
    mysql在第一次查询的时候很慢,第二次查询就比较快的原因?
    mysql的递归(使用函数)
    什么样的男人才是女人眼中最帅的男人
    面试题总结
    java的重载总结
    arduino读取GPIO数据
    electron+react项目改为typescript
    百度AI训练营笔记
    python读取文件出现ufeff问题
    大端小端
  • 原文地址:https://www.cnblogs.com/moran1992/p/11073102.html
Copyright © 2011-2022 走看看