The introduction

Message prompt boxes are common in practical application scenarios. The most common one is the Message prompt box of element UI. We usually use them directly, but have we tried to explore the implementation principle and implement it ourselves? In order to enhance our personal ability and competitiveness, we can try to achieve such a message prompt box.

Implementation effect

Let’s take a look at the final implementation, as shown below:

The preparatory work

Set up the basic project structure

Let’s create a message folder, and then create an index. HTML file, along with message.js and message.css files, as follows:

Layout the message prompt box

In the HTML file, we can first implement a static message prompt as follows:

<div class="message">
    <p>This is a prompt box</p>
    <i class="message-close-btn">&times;</i>
</div>
Copy the code

And then message.css we put the basic CSS code:

* {
    margin: 0;
    padding: 0;
    box-sizing: border-box;
}
/* Message prompt container style */
.message {
    position: fixed;
    left: 50%;
    transform: translateX(50%);display: flex;
    align-items: center;
    min-width: 300px;
    background-color: #edf2fc;
    border: 1px solid #edf2fc;
    padding: 16px 17px;
    top: 25px;
    border-radius: 6px;
    overflow: hidden;
    z-index: 1000;
}
/* Close button style */
.message > .message-close-btn {
    position: absolute;
    right: 15px;
    top: 50%;
    transform: translateY(50%);color: #c0c0c4;
    font-size: 17px;
    cursor: pointer;
}
.message > .message-close-btn:hover..message > .message-close-btn:active {
    color: # 909399;
}
/* Message prompt content style */
.message p {
    line-height: 1;
    font-size:14px;
    color: # 909399;
}
Copy the code

There are four types of prompt boxes, and to center the content, we simply add a class name to the CSS style. For example, to center the content, we just need to add a class name to the CONTAINER element of the HTML prompt box, as follows:

<div class="message message-center">
    <p>This is a prompt box</p>
    <i class="message-close-btn">&times;</i>
</div> 
Copy the code

Add the following CSS code to the CSS file:

/* Content centered */
.message.message-center {
    justify-content: center;
}
Copy the code

Add a class name, and then change the background color and font color, so the HTML code looks like this:

<div class="message message-success">
    <p>This is a success message box</p>
    <i class="message-close-btn">&times;</i>
</div>
<div class="message message-warning">
    <p>This is a warning box</p>
    <i class="message-close-btn">&times;</i>
</div>
<div class="message message-error">
    <p>This is an error message box</p>
    <i class="message-close-btn">&times;</i>
</div>
Copy the code

CSS code is as follows:

/* Successful message box style */
.message.message-success {
    background-color: #e1f3d8;
    border-color:#e1f3d8;
}
.message.message-success p {
    color: #67c23a;
}
/* Warning box style */
.message.message-warning{
    background-color: #fdfce6;
    border-color: #fdfce6;
}
.message.message-warning p{
    color: #e6a23c;
}
/* Error box style */
.message.message-error {
    background-color: #fef0f0;
    border-color: #fef0f0;
}
.message.message-error p {
    color: #f56c6c;
}
Copy the code

With that done, it’s time for our main focus, the JavaScript code, to try and comment it out.

Dynamically create a message box

Define four types of message prompt boxes

We define an object to represent the type of the message prompt, as follows:

// There are four types of message prompt boxes
let typeMap = {
    info: "info".warning: "warning".success: "success".error: "error"
}
Copy the code

Add default configuration items

We analyze the configuration items that need to be passed in, such as content, closeTime, showClose button, center and message prompt box type. So the configuration items are defined as follows:

// Default configuration items of the prompt box
let messageOption = {
    type: "info".closeTime: 600.center: false.showClose: false.content: "Default content"
}
Copy the code

Create a message prompt class

We use object-oriented programming thinking to think of the message prompt as a class object, so we just need to create a class. It can be created using es6’s class syntax, but for convenience, we use the constructor. Create a constructor Message that looks like this:

function Message(option) {
    // This is an initialization
    this.init(option);
}
Copy the code

Initialize the

After creating the message prompt constructor, we need to pass in the configuration items, and we do the initialization in the function. Let’s do the initialization.

Message.prototype.init = function (option) {
    // Here we create the prompt box element and add the entire prompt box container element to the page
    document.body.appendChild(this.create(option));
    // Here set the top of the prompt box
    this.setTop(document.querySelectorAll('.message'));
    If closeTime is greater than 0, the prompt box will be closed by default
    if (option.closeTime > 0) {
        this.close(option.container, option.closeTime);
    }
    // Click the Close button to close the prompt box
    if (option.close) {
        option.close.onclick = (e) = > {
            this.close(e.currentTarget.parentElement, 0); }}}Copy the code

Create prompt Box

In the previous initialization, we did a few things, first creating the prompt box container element and adding the prompt box container element to the page BOD. We also do dynamic calculation of the top of the prompt box and determine the default closing time passed in to close the prompt box, click the close button to close the prompt box. Let’s look at the method for creating the prompt box, which is the writing action of the create method. As follows:

Message.prototype.create = function (option) {
    If showClose is set to false and closeTime is set to 0, then the close button will not be displayed
    if(! option.showClose && option.closeTime <=0)option.showClose = true;
    // Create the container element
    let element = document.createElement('div');
    // Set the class name
    element.className = `message message-${option.type}`;
    if (option.center) element.classList.add('message-center');
    // Create the close button element and set the class name and content
    let closeBtn = document.createElement('i');
    closeBtn.className = 'message-close-btn';
    closeBtn.innerHTML = '× ';
    // Create the content element
    let contentElement = document.createElement('p');
    contentElement.innerHTML = option.content;
    // Determine if the close button is displayed, then add the close button element to the prompt box container element
    if (closeBtn && option.showClose) element.appendChild(closeBtn);
    // Add the content element to the prompt container
    element.appendChild(contentElement);
    // Store the prompt container element and the close button element in the configuration item object
    option.container = element;
    option.close = closeBtn;
    // Return to the prompt box container element
    return element;
}
Copy the code

Realize the closing of the prompt box

As you can see, we create a close method and pass in the prompt container element to close a prompt box. Next, we implement the close method. As follows:

Message.prototype.close = function (messageElement, time) {
    // Delay closing based on the time passed in. In effect, remove the element
    setTimeout((a)= > {
        // Check if there are two cases in which the prompt box container elements are passed in. If there are multiple prompt box container elements, then iterate to delete them; if there is a single prompt box container element, then delete them directly
        if (messageElement && messageElement.length) {
            for (let i = 0; i < messageElement.length; i++) {
                if(messageElement[i].parentElement) { messageElement[i].parentElement.removeChild(messageElement[i]); }}}else if (messageElement) {
            if(messageElement.parentElement) { messageElement.parentElement.removeChild(messageElement); }}// After the prompt container element is closed, we reset the top value of the prompt
        this.setTop(document.querySelectorAll('.message'));
    }, time * 10);
}
Copy the code

Realize the prompt box dynamic top

The last thing we need to implement is to dynamically calculate the top of the message prompt boxes, and then keep the message prompt boxes from overlapping. The code is as follows:

Message.prototype.setTop = function (messageElement) {
    // The reason for this is that when you click the last prompt in the page, it will be called again, and the prompt container element will not be retrieved, so the next set of top will not be performed
    if(! messageElement || ! messageElement.length)return;
    // Since the height of each prompt is the same, we only need to get the height of the first prompt element
    const height = messageElement[0].offsetHeight;
    for (let i = 0; i < messageElement.length; i++) {
        // The top of each prompt box consists of a fixed value plus its height, and we want to multiply it by one of its indexes
        messageElement[i].style.top = (25 * (i + 1) + height * i) + 'px'; }}Copy the code

Finally, implement encapsulation so that we can invoke the element UI as we would the element UI

If we want to call $message() or $message.info(), we can do this:

let $message = {};
window['$message'] = $message = function (option) {
    let newMessageOption = null;
    if (typeof option === 'string') {
        newMessageOption = Object.assign(messageOption, { content: option });
    } else if (typeof option === 'object'&&!!!!! option) { newMessageOption =Object.assign(messageOption, option);
    }
    return new Message(newMessageOption);
}
for (let key in typeMap) {
    window['$message'][key] = function (option) {
        let newMessageOption = null;
        if (typeof option === 'string') {
            newMessageOption = Object.assign(messageOption, { content: option,type:typeMap[key] });
        } else if (typeof option === 'object'&&!!!!! option) { newMessageOption =Object.assign(JSON.parse(JSON.stringify(messageOption)),option,{ type:typeMap[key] });
        }
        return newMessage(newMessageOption); }}Copy the code

The logic is simple enough to determine the incoming configuration items, merge them, and pass them into the instantiated Message.

In this way, we complete a message prompt box.

Record video

If that doesn’t make sense, check out this video I made: