Popover.js 4.68 KB
import template from "./Popover.html";

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

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

    template = template;
    
    useModules = ["$compile"];

    constructor() {
        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': '')">
                <div class="ant-popover-content">
                    <div class="ant-popover-arrow"></div>
                    <div class="ant-popover-inner">
                        <div>
                            ${title}
                            <div class="ant-popover-inner-content">
                                ${this.state.content.replace(
                                    /\$scope/g,
                                    "context"
                                )}
                            </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 {
            div.innerHTML = content;
            this.state.popupContainer.appendChild(div);
        }
        div.addEventListener("click", function (event) {
            event.stopPropagation();
        });
        this.state.target.addEventListener("click", (e) => {
            e.stopPropagation();
        });
        $compile(div)($scope);
        this.state.popover = div;
    }

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

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

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

    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 {
            return (
                $(target).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 {
            if (this.props.placement === "top") {
                return $(target).offset().top - popover.clientHeight - 4 + "px";
            } else if (this.props.placement === "bottom") {
                return $(target).offset().top + target.clientHeight + 4 + "px";
            }
        }
    }
}