Select.js 4.26 KB
import template from "./Select.html";
import style from "antd/lib/select/style/index.css";

class Select {
    useModules = ["$compile", "$timeout", "esNgAntd"];

    props = {
        value: String,
        defaultValue: String,
        placeholder: String,
        onChange: Function,
        placeholder: String,
        getPopupContainer: Function,
        size: String,
    };

    state = {
        open: false,
        childrens: [],
        label: null,
        value: this.props.value || this.props.defaultValue,
        popup: null,
    };

    template = template;

    constructor(antdForm, antdFormItem) {
        esNgAntd.createStyle("ant-select", style);
        if (antdForm) {
            this.antdForm = antdForm.getContext();
            this.antdForm.state.formItems.push($scope);
        }
        if (antdFormItem) {
            this.antdFormItem = antdFormItem.getContext();
        }

        $timeout(function () {
            this.setValue(this.props.value || this.props.defaultValue);
        }, 100);
    }

    setValue(value) {
        let option = this.state.childrens.find(function (option) {
            return option.value === value;
        });
        if (option) {
            option.label = option.element.text();
            this.state.label = option.label;
            this.state.value = option.value;
        } else {
            this.state.label = null;
            this.state.value = null;
        }
    }

    addOption(option) {
        this.state.childrens.push(option);
    }

    handleClick(option) {
        this.state.open = !this.state.open;
        this.state.label = option.label;
        this.state.value = option.value;
        this.props.onChange({
            value: this.state.value,
        });
    }

    getOffset(ele) {
        if (!ele || ele.nodeType != 1) {
            return;
        }
        let func = this.props.getPopupContainer();
        if (typeof func === "function" && func() !== undefined) {
            let containerElement = func();
            containerElement.style.position = "relative";
            return {
                top: $element[0].offsetTop,
                left: $element[0].offsetLeft,
            };
        } else {
            let rect = ele.getBoundingClientRect();
            let doc = ele.ownerDocument.documentElement;
            return {
                top: rect.top + window.pageYOffset - doc.clientTop,
                left: rect.left + window.pageXOffset - doc.clientLeft,
            };
        }
    }

    myEvent() {
        $timeout(() => {
            this.state.open = false;
            document.body.removeEventListener("click", this.myEvent);
        }, 0);
    }

    handleBlur() {
        // 事件绑定
        document.body.addEventListener("click", this.myEvent);
    }

    handleOpen(event) {
        event.stopPropagation();
        const { height, width } = $element[0].getBoundingClientRect();
        const { top, left } = this.getOffset($element[0]);

        // 处理标签
        this.state.childrens.forEach(function (item) {
            item.label = item.element.text();
        });

        let div = document.createElement("div");
        div.style.position = "absolute";
        div.style.left = 0;
        div.style.top = 0;
        div.style.width = "100%";
        div.appendChild(
            $compile(`<div><div ng-class="'ant-select-dropdown ant-select-dropdown-placement-bottomLeft'+(!state.open?' ant-select-dropdown-hidden':'')" style="width: ${width}px; left: ${left}px; top: ${
                top + height + 2
            }px;">
            <div class="ant-select-item ant-select-item-option" ng-click="handleClick(option)" ng-repeat="option in state.childrens">
                <div class="ant-select-item-option-content">{{option.label}}</div>
            </div>
        </div></div>`)($scope)[0]
        );
        if (this.state.popup === null) {
            let func = this.props.getPopupContainer();
            if (typeof func === "function" && func() !== undefined) {
                $element[0].style.position = "relative";
                this.props.getPopupContainer()().appendChild(div);
            } else {
                document.body.appendChild(div);
            }
            this.state.popup = div;
        }
        this.state.open = !this.state.open;
        this.handleBlur();
    }
}