Popover.js 5.77 KB
import template from "./Popover.html";
import style from "antd/lib/popover/style/index.css";

class Popover {
    template = template;

    useModules = ["$compile", "$timeout", "esNgAntd"];

    props = {
        title: String,
        content: String,
        context: Object,
        placement: String,
        getPopupContainer: Function,
        trigger: String,
    };

    state = {
        visible: false,
        content: this.props.content ? this.props.content : "",
        clickTarget: null,
        trigger: this.props.trigger || "hover",
        closing: false,
    };

    constructor() {
        esNgAntd.createStyle("ant-popover", style);
        this.state.target = $element[0];
        let title = this.props.title
            ? `<div class="ant-popover-title"><span>${this.props.title}</span></div>`
            : "";
        let content = `<div>
            <div style="outline:none" ng-class="'ant-popover ant-popover-placement-${this.props.placement}'+(!state.visible?' ant-popover-hidden': '')+(state.visible?' ant-zoom-big-enter ant-zoom-big-enter-active': '')" ng-mouseleave="onMouseLeave()" ng-mouseenter="onMouseEnter()">
                <div class="ant-popover-content">
                    <div class="ant-popover-arrow">
                        <span class="ant-popover-arrow-content"></span>
                    </div>
                    <div class="ant-popover-inner">
                        <div>
                            ${title}
                            <div class="ant-popover-inner-content"></div>
                        </div>
                    </div>
                </div>
            </div>
        </div>`;
        let div = document.createElement("div");
        if (typeof this.props.getPopupContainer() === "function") {
            this.state.popupContainer = this.props.getPopupContainer()();
        }
        if (!this.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 {
            this.state.popupContainer.appendChild(div);
        }
        div.addEventListener("click", function (event) {
            event.stopPropagation();
        });
        this.state.target.addEventListener("click", (e) => {
            e.stopPropagation();
        });
        $compile(div)($scope);
        div.querySelector(".ant-popover-inner-content").innerHTML =
            this.state.content;
        $compile(div.querySelector(".ant-popover-inner-content"))(
            $scope.$parent
        );
        this.state.popover = div;
    }

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

    handleClick() {
        if (this.state.trigger !== "click") {
            return;
        }
        if (this.state.visible === false) {
            // 气泡层(显示)
            this.state.visible = true;
            // 处理位置
            this.handlePosition();
            // 事件绑定
            document.body.addEventListener("click", this.myEvent);
        } else {
            setTimeout(() => {
                this.state.visible = false;
                this.$apply();
                document.body.removeEventListener("click", this.myEvent);
            }, 0);
        }
    }

    showPopover() {
        // 气泡层(显示)
        this.state.visible = true;
        // 调整位置
        this.handlePosition();
    }

    hidePopover() {
        this.state.closing = true;
        $timeout(function () {
            if (this.state.closing === false) {
                return;
            }
            this.state.visible = false;
        }, 100);
    }

    onMouseEnter() {
        if (this.state.trigger !== "hover") {
            return;
        }
        if (this.state.closing === true) {
            this.state.closing = false;
        }
        this.showPopover();
    }

    onMouseLeave() {
        if (this.state.trigger !== "hover") {
            return;
        }
        this.hidePopover();
    }

    handlePosition() {
        setTimeout(function () {
            let popover = this.state.popover.querySelector(".ant-popover");
            if (this.props.placement === "top") {
                popover.style["top"] = this.getTop();
            } else if (this.props.placement === "bottom") {
                popover.style["top"] = this.getTop();
            }
            popover.style.left = this.getLeft() + "px";
        }, 0);
    }

    getLeft() {
        let parent = this.props.getPopupContainer();
        let popover = this.state.popover.querySelector(".ant-popover");
        let target = this.state.target;
        if (parent) {
            return -(popover.clientWidth / 2 - target.clientWidth / 2);
        } else {
            let offset = esNgAntd.getOffset(target);
            return (
                offset.left - (popover.clientWidth / 2 - target.clientWidth / 2)
            );
        }
    }

    getTop() {
        let parent = this.props.getPopupContainer();
        let popover = this.state.popover.querySelector(".ant-popover");
        let target = this.state.target;
        if (parent) {
            if (this.props.placement === "top") {
                return -popover.clientHeight + "px";
            } else if (this.props.placement === "bottom") {
            }
        } else {
            let offset = esNgAntd.getOffset(target);
            if (this.props.placement === "top") {
                return offset.top - popover.clientHeight - 4 + "px";
            } else if (this.props.placement === "bottom") {
                return offset.top + target.clientHeight + 4 + "px";
            }
        }
    }
}