Select.js 6.44 KB
import template from "./Select.html";
import style from "antd/lib/select/style/index.css";
angular
    .module("esNgAntd")
    .directive("esSelect", function ($compile, $timeout, esNgAntd) {
        return {
            controllerAs: "esSelect",
            restrict: "E",
            transclude: true,
            replace: true,
            scope: {
                value: "@",
                defaultValue: "@",
                placeholder: "@",
                onChange: "&",
                placeholder: "@",
                getPopupContainer: "&",
                size: "@",
            },
            template: template,
            controller: function ($scope, $element, $attrs) {
                this.getContext = function () {
                    return $scope;
                };

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

                $scope.setValue = function (value) {
                    let option = $scope.state.childrens.find(function (option) {
                        return option.value === value;
                    });

                    if (option) {
                        option.label = option.element.text();
                        $scope.state.label = option.label;
                        $scope.state.value = option.value;
                    } else {
                        $scope.state.label = null;
                        $scope.state.value = null;
                    }
                };

                $scope.addOption = function (option) {
                    $scope.state.childrens.push(option);
                };

                $scope.handleClick = function (option) {
                    $scope.state.open = !$scope.state.open;
                    $scope.state.label = option.label;
                    $scope.state.value = option.value;
                    $scope.onChange({
                        value: $scope.state.value,
                    });
                };

                $scope.getOffset = function (ele) {
                    if (!ele || ele.nodeType != 1) {
                        return;
                    }

                    let func = $scope.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,
                        };
                    }
                };

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

                $scope.handleBlur = function () {
                    // 事件绑定
                    document.body.addEventListener("click", $scope.myEvent);
                };

                $scope.handleOpen = function (event) {
                    event.stopPropagation();
                    const { height, width } =
                        $element[0].getBoundingClientRect();
                    const { top, left } = $scope.getOffset($element[0]); // 处理标签

                    $scope.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 ($scope.state.popup === null) {
                        let func = $scope.getPopupContainer();

                        if (
                            typeof func === "function" &&
                            func() !== undefined
                        ) {
                            $element[0].style.position = "relative";
                            $scope.getPopupContainer()().appendChild(div);
                        } else {
                            document.body.appendChild(div);
                        }

                        $scope.state.popup = div;
                    }

                    $scope.state.open = !$scope.state.open;
                    $scope.handleBlur();
                };
            },
            require: ["?^esForm", "?^esFormItem"],
            link: function (
                $scope,
                $element,
                $attrs,
                $controllers,
                $transclude
            ) {
                let [esForm, esFormItem] = $controllers;
                esNgAntd.createStyle("ant-select", style);

                if (esForm) {
                    $scope.esForm = esForm.getContext();
                    $scope.esForm.state.formItems.push($scope);
                }

                if (esFormItem) {
                    $scope.esFormItem = esFormItem.getContext();
                }

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