Popover.js 6.22 KB
import template from "./Popover.html";
angular.module("esNgAntd").directive("esPopover", function ($compile) {
    return {
        controllerAs: "esPopover",
        restrict: "E",
        transclude: true,
        replace: true,
        scope: {
            title: "@",
            content: "@",
            context: "=",
            placement: "@",
            getPopupContainer: "&",
        },
        template: template,
        controller: function ($scope, $element) {
            this.getContext = function () {
                return $scope;
            };

            $scope.state = {
                visible: false,
                content: $scope.content ? $scope.content : "",
                clickTarget: null,
            };

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

            $scope.handleClick = function () {
                if ($scope.state.visible === false) {
                    // 气泡层(显示)
                    $scope.state.visible = true; // j

                    $scope.handlePosition(); // 事件绑定

                    document.body.addEventListener("click", $scope.myEvent);
                } else {
                    setTimeout(() => {
                        $scope.state.visible = false;
                        $scope.$apply();
                        document.body.removeEventListener(
                            "click",
                            $scope.myEvent
                        );
                    }, 0);
                }
            };

            $scope.showPopover = function () {
                let popover = $scope.state.popover;
                popover.classList.remove("ant-popover-hidden");
            };

            $scope.handlePosition = function () {
                setTimeout(function () {
                    let popover =
                        $scope.state.popover.querySelector(".ant-popover");

                    if ($scope.placement === "top") {
                        popover.style["top"] = $scope.getTop();
                    } else if ($scope.placement === "bottom") {
                        popover.style["top"] = $scope.getTop();
                    }

                    popover.style.left = $scope.getLeft() + "px";
                }, 0);
            };

            $scope.getLeft = function () {
                let parent = $scope.getPopupContainer();
                let popover =
                    $scope.state.popover.querySelector(".ant-popover");
                let target = $scope.state.target;

                if (parent) {
                    return -(popover.clientWidth / 2 - target.clientWidth / 2);
                } else {
                    return (
                        $(target).offset().left -
                        (popover.clientWidth / 2 - target.clientWidth / 2)
                    );
                }
            };

            $scope.getTop = function () {
                let parent = $scope.getPopupContainer();
                let popover =
                    $scope.state.popover.querySelector(".ant-popover");
                let target = $scope.state.target;

                if (parent) {
                    if ($scope.placement === "top") {
                        return -popover.clientHeight + "px";
                    } else if ($scope.placement === "bottom") {
                    }
                } else {
                    if ($scope.placement === "top") {
                        return (
                            $(target).offset().top -
                            popover.clientHeight -
                            4 +
                            "px"
                        );
                    } else if ($scope.placement === "bottom") {
                        return (
                            $(target).offset().top +
                            target.clientHeight +
                            4 +
                            "px"
                        );
                    }
                }
            };
        },
        link: function ($scope, $element, $attrs, $controllers, $transclude) {
            $scope.state.target = $element[0];
            let title = $scope.title
                ? `<div class="ant-popover-title"><span>${$scope.title}</span></div>`
                : "";
            let content = `<div>
            <div style="outline:none" ng-class="'ant-popover ant-popover-placement-${
                $scope.placement
            }'+(!state.visible?' ant-popover-hidden': '')">
                <div class="ant-popover-content">
                    <div class="ant-popover-arrow"></div>
                    <div class="ant-popover-inner">
                        <div>
                            ${title}
                            <div class="ant-popover-inner-content">
                                ${$scope.state.content.replace(
                                    /\$scope/g,
                                    "context"
                                )}
                            </div>
                        </div>
                    </div>
                </div>
            </div>
        </div>`;
            let div = document.createElement("div");

            if (typeof $scope.getPopupContainer() === "function") {
                $scope.state.popupContainer = $scope.getPopupContainer()();
            }

            if (!$scope.state.popupContainer) {
                div.style.position = "absolute";
                div.style.top = "0px";
                div.style.left = "0px";
                div.style.width = "100%";
                div.innerHTML = content;
                document.body.appendChild(div);
            } else {
                div.innerHTML = content;
                $scope.state.popupContainer.appendChild(div);
            }

            div.addEventListener("click", function (event) {
                event.stopPropagation();
            });
            $scope.state.target.addEventListener("click", (e) => {
                e.stopPropagation();
            });
            $compile(div)($scope);
            $scope.state.popover = div;
        },
    };
});