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

            $scope.state = {
                open: false,
                childrens: [],
                label: null,
                value: null,
                popup: 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) {
                    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]);
                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--single ant-select-dropdown-placement-bottomLeft'+(!state.open?' ant-select-dropdown-hidden':'')" style="width: ${width}px; left: ${left}px; top: ${
                        top + height + 2
                    }px;">
            <ul class="ant-select-dropdown-menu ant-select-dropdown-menu-root ant-select-dropdown-menu-vertical">
                <li class="ant-select-dropdown-menu-item" ng-click="handleClick(option)" ng-repeat="option in state.childrens">{{option.label}}</li>
            </ul>
        </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();
            };
        },
        link: function ($scope, $element, $attrs, $controllers, $transclude) {
            let option = $scope.state.childrens.find(function (option) {
                return option.value === $scope.value;
            });
            $scope.state.label = option.label;
        },
    };
});