4
\$\begingroup\$

It's a user alert script. It worked in every browser I tested. But the function itself looks very messy/repetitive. Is there any way to make this cleaner?

function message(text) {
 var alert = document.createElement('div');
 var alertText = document.createTextNode(text);
 var alertCloseButton = document.createElement('i');
 var buttonText = document.createTextNode('close');
 var shadow = document.createElement('div');
 alert.className = 'alert-text';
 alertCloseButton.className = 'material-icons';
 alertCloseButton.id = 'close-alert';
 alertCloseButton.setAttribute('onclick', 'function() { var a = this.parentNode; var s = a.parentNode; s.parentNode.removeChild(s)}');
 alertCloseButton.onclick = function() { var a = this.parentNode; var s = a.parentNode; s.parentNode.removeChild(s) };
 alertCloseButton.appendChild(buttonText);
 alert.appendChild(alertCloseButton);
 alert.appendChild(alertText);
 shadow.className = 'shadow';
 shadow.appendChild(alert);
 document.body.appendChild(shadow);
}
var button = document.querySelector('button');
button.addEventListener('click', function(){
 message('Button clicked');
});

Here's the code working: https://jsfiddle.net/3aouyfz7/

200_success
145k22 gold badges190 silver badges478 bronze badges
asked Mar 6, 2019 at 6:36
\$\endgroup\$

1 Answer 1

2
\$\begingroup\$

Explanation:

It's true that using objects can become messy after a while. That's why Template Literals and innerHTML are so powerful in this situation.

I would highly advise to avoid using parentNode when attempting to remove HTML, you may unintentionally remove something in the future if you decide to make your alert HTML more complex.

To solve this, create a container element that is accessible by your onclose method.

Also, I would also advise to not overwrite existing objects. Why not name alert to something else?

Don't add onclick events directly in the HTML, it's messy.

Solution:

function message(text) {
 const container = document.createElement("div");
 const onClose = ()=>container.remove();
 container.innerHTML = `
 <div class="shadow">
 <div class="alert-text">
 <i id="close-alert" class="material-icons">close</i>
 ${text}
 </div>
 </div>
 `;
 document.body.appendChild(container);
 document
 .querySelector('i#close-alert')
 .addEventListener("click", onClose);
}

Working Example:

function message(text) {
 const container = document.createElement("div");
 const onClose = ()=>container.remove();
 container.innerHTML = `
 <div class="shadow">
 <div class="alert-text">
 <i id="close-alert" class="material-icons">close</i>
 ${text}
 </div>
 </div>
 `;
 
 document.body.appendChild(container);
 
 document
 .querySelector('i#close-alert')
 .addEventListener("click", onClose);
}
const button = document.querySelector('button');
button.addEventListener('click', function() {
 message('Button clicked');
});
* {
 box-sizing: border-box;
}
.shadow {
 width: 100%;
 height: 100%;
 background-color: rgba(0, 0, 0, .5);
 position: fixed;
 top: 0;
 left: 0;
 display: flex;
 align-items: center;
 justify-content: center;
 z-index: 98;
}
.alert-text {
 border: 1px solid #aaa;
 padding: 2.5em;
 min-height: 10%;
 width: auto;
 max-width: 80%;
 background: #fff;
 z-index: 99;
 position: relative;
 text-align: center;
}
.alert-text i {
 position: absolute;
 top: 0;
 right: 0;
 color: #777;
 cursor: pointer;
 padding: .5rem;
}
.alert-text i:hover {
 color: #444
}
<!DOCTYPE html>
<html>
<head>
 <title></title>
 <link rel="stylesheet" type="text/css" href="https://fonts.googleapis.com/icon?family=Material+Icons">
</head>
<body>
 <h3>Page content</h3>
 <button>alert</button>
</body>
</html>

answered Mar 6, 2019 at 12:33
\$\endgroup\$
1
  • 1
    \$\begingroup\$ thanks for the clean up, i've learned a lot from your answer. \$\endgroup\$ Commented Mar 6, 2019 at 19:49

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.