Implementing a Message Alert Component

In a web page, a common message alert component can generally be divided into static local alerts and dynamic global alerts, which are used to provide feedback on information that users need to pay attention to and are used frequently.

Implementation

To implement the message alert component, the dynamic global alert is mainly implemented using native JavaScript. The implemented code is extensively commented.

<!DOCTYPE html>
<html>
<head>
    <title>Message</title>
    <style type="text/css">
        @keyframes enter { /* Entrance animation */
          0% {
            transform: translateY(-50px);
            opacity: 0;
          }
          100% {
            transform: translateY(0);
            opacity: 1;
          }
        }
        .msg-unit{ /* Banner container */
            font-size: 13px;
            position: fixed;
            left: calc(50% - 150px);
            width: 300px;
            padding: 10px;
            border-radius: 3px;
            animation: enter 0.3s;
            transition: all .5s;
            display: flex;
            align-items: center;
        }
        .msg-hide{ /* Hide animation */
            opacity: 0;
            transform: translateY(-50px);
        }
        .msg-unit > .msg-icon{ /* Icon */
            font-size: 15px;
            margin: 0 7px;
        }
    </style>
    <!-- Import icon library -->
    <link rel="stylesheet" href="https://cdn.staticfile.org/font-awesome/4.7.0/css/font-awesome.css">
</head>
<body>
    <button onclick="msg('This is an info message', 'info')">Info</button>
    <button onclick="msg('This is a success message', 'success')">Success</button>
    <button onclick="msg('This is a warning message', 'warning')">Warning</button>
    <button onclick="msg('This is an error message', 'error')">Error</button>
</body>
<script type="text/javascript">
    (function(win, doc){
        const body = doc.body; // Container
        const msgList = []; // Maintain message array queue
        const baseTop = 15; // Base top distance
        const multiplyTop = 46; // Multiplication base height
        const msgTypeMap = { // Types
            "info": {background: "#EBEEF5", border: "#EBEEF5", color: "#909399", icon: "fa fa-info-circle"},
            "success": {background: "#f0f9eb", border: "#e1f3d8", color: "#67C23A", icon: " fa fa-check-circle-o"},
            "warning": {background: "#fdf6ec", border: "#faecd8", color: "#E6A23C", icon: " fa fa-exclamation-circle"},
            "error": {background: "#fef0f0", border: "#fde2e2", color: "#F56C6C", icon: "fa fa-times-circle-o"},
        }
        const create = (msg, type) => {
            const unit = doc.createElement("div"); // Outer container
            unit.className = "msg-unit"; // Set style
            const typeInfo = msgTypeMap[type] === void 0 ? msgTypeMap["info"] : msgTypeMap[type]; // Get type
            unit.style.background = typeInfo.background; // Set background color
            unit.style.color = typeInfo.color; // Set text color
            unit.style["border"] = `1px solid ${typeInfo.border}`; // Set border color
            const i = doc.createElement("i"); // Icon container
            i.className = `${typeInfo.icon} msg-icon`; // Set icon type and style
            const span = doc.createElement("span"); // Text container
            span.innerText = msg; // Avoid XSS
            unit.appendChild(i); // Add to outer container
            unit.appendChild(span); // Add to outer container
            unit.style.top = msgList.length * multiplyTop + baseTop + "px"; // Calculate height
            return unit; // Return the outermost container
        }
        const computedTop = () => msgList.forEach((v, index) => v.style.top = index * multiplyTop + baseTop + "px"); // Traverse and calculate the distance from the top
        const show = (msg, type) => {
            const unit = create(msg, type); // Create element
            msgList.push(unit); // Add to queue
            body.appendChild(unit); // Add to body
            setTimeout(() => { // Timer
                msgList.shift(unit); // Dequeue
                computedTop(); // Recalculate height
                const finish = () => {
                    body.removeChild(unit); // Remove from body
                    unit.removeEventListener("transitionend", finish); // Remove listener
                }
                unit.addEventListener("transitionend", finish); // Add listener
                unit.classList.add("msg-hide"); // Trigger removal transition animation
            }, 3000); // Trigger after 3 seconds delay
        }
        win.msg = (msg, type = "info") => show(msg, type); // Add to window object
    })(window, document);
</script>
</html>

Daily Question

https://github.com/WindrunnerMax/EveryDay

References

https://element.eleme.cn/#/en-US/component/message http://kmanong.top/kmn/qxw/form/article?id=62470&cate=52 https://jancat.github.io/post/2020/design-a-pair-of-general-message-prompt-components-alert-and-toast/