惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Attack and Defense Labs
Attack and Defense Labs
T
Threatpost
C
Cybersecurity and Infrastructure Security Agency CISA
H
Hackread – Cybersecurity News, Data Breaches, AI and More
I
Intezer
C
Cyber Attacks, Cyber Crime and Cyber Security
The Register - Security
The Register - Security
量子位
Security Latest
Security Latest
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
大猫的无限游戏
大猫的无限游戏
小众软件
小众软件
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
C
CXSECURITY Database RSS Feed - CXSecurity.com
MyScale Blog
MyScale Blog
J
Java Code Geeks
Apple Machine Learning Research
Apple Machine Learning Research
Google DeepMind News
Google DeepMind News
WordPress大学
WordPress大学
Spread Privacy
Spread Privacy
Jina AI
Jina AI
博客园 - 【当耐特】
P
Palo Alto Networks Blog
Last Week in AI
Last Week in AI
SecWiki News
SecWiki News
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
G
GRAHAM CLULEY
宝玉的分享
宝玉的分享
Hacker News - Newest:
Hacker News - Newest: "LLM"
T
The Blog of Author Tim Ferriss
V
Vulnerabilities – Threatpost
有赞技术团队
有赞技术团队
T
Tor Project blog
H
Hacker News: Front Page
A
Arctic Wolf
NISL@THU
NISL@THU
A
About on SuperTechFans
云风的 BLOG
云风的 BLOG
Engineering at Meta
Engineering at Meta
V
V2EX
N
News and Events Feed by Topic
Webroot Blog
Webroot Blog
Know Your Adversary
Know Your Adversary
P
Privacy International News Feed
I
InfoQ
D
Docker
L
LINUX DO - 最新话题
K
KPMG report finds enterprise disconnect between AI and its ROI | CIO
U
Unit 42

JavaScript iDiallo.com

How to tell an element is in view using JavaScript. Complex function call delays without nesting in JavaScript How to use pushState without breaking the back button Uncaught TypeError: Cannot read property of null Why Use Prototype in JavaScript Optimization: Minimize look-ups in for loops. Uncaught SyntaxError: Unexpected token < Magical JavaScript Live Collection Creating a class in JavaScript
How to create DOM elements efficiently with JavaScript
Ibrahim Dial · 2020-02-16 · via JavaScript iDiallo.com

At some point, every web application needs an overlay. A sort of pop-up that obscures the background and asks the user to perform an action. Here is how you do it.

First you create the HTML, give the overlay an absolute position, and then set the display to none by default. But what if you don’t have access to the HTML? Luckily, JavaScript has a convenient method for that.

document.createElement(elementName);

You can create any element using this method. The challenge starts when you have a complicated nested hierarchy of elements. Here is an example of an overlay:

<div id="overlay">
    <div class="overlay__inner">
        <div class="overlay__box">
            <div class="overlay__hdr">
                <span class="overlay__close-btn">X</span>
                <h3>The Overlay Title</h3>
                <p>The purpose of this overlay</p>
            </div>
            <div class="overlay__content">
                ...
            </div>
        </div>
    </div>
</div>

Recreating this in JavaScript is easy, but not simple. You have to keep track of every element that needs to be nested. Applying the correct attributes is also tedious. Let's see what it looks like.

var overElem = document.createElement("div");
overElem.id = "overlay";
var overInner = document.createElement("div");
overInner.className = "overlay__inner";
var overBox = document.createElement("div");
overBox.className = "overlay__box";
var overHdr = document.createElement("div");
overHdr.className = "overlay__hdr";
var clsBtn = document.createElement("span");
clsBtn.className = "overlay__close-btn";
var title = document.createElement("h3");
title.innerText = "The Overlay Title";
var subtitle = document.createElement("p");
subtitle.innerText = "The purpose of this overlay";

// a long while later

overHdr.appendChild(clsBtn);
overHdr.appendChild(title);
overHdr.appendChild(subtitle);
overBox.appendChild(overHdr);
...

It is a tedious task. Not only you have to define all elements, you have to make sure you append them in the correct order. This can cause bugs that are hard to track. To make the process easier, I created a couple of functions that turn the process into a more manageable tree.

JavaScript Markup Language or jml

I was inspired by the syntax of a popular JavaScript framework called Hyperapp. Here is how I want my code to create DOM elements to look like.

var overlay = ml("div", { id: "overlay"}, 
    ml("div", { class: "overlay__inner"}, 
        ml("div", { class: "overlay__box"}, [
            ml("div", { class: "overlay__hdr"}, [
                ml("span", {
                    class: "overlay__close-btn",
                    onClick: function() {
                        console.log("closing the overlay")
                    },
                }, "X"),
                ml("h3", {}, "The Overlay Title"),
                ml("p", {}, "The purpose of this overlay"),
            ]),
            ml("div", { class: "overlay__content"}, ["more content"]),
        ])
    )
);

document.body.appendChild(overlay);

This elegant style looks similar enough to the resulting HTML and is flexible enough to debug. What we are doing in this code is we call a function ml(a,b,c) that can have 3 arguments.

The first argument is the type of element we want to create. It can be div, h1, span or any valid HTML tag.

The second argument is the list of attributes we want the element to have. Note that we can also use this to attach events to the element. You can have onClick, onMouseover or any valid element event.

Then the third argument can be 3 things. A string, a DOM element, or an array of strings and DOM elements. This third parameter is automatically converted to an element and then appended to the parent. Note that strings are converted to a TextNode. So including HTML in the string automatically converts it to the corresponding HTML entity.

The library

Let's write the code needed to support this functionality:

function ml(tagName, props, nest) {
    var el = document.createElement(tagName);
    if(props) {
        for(var name in props) {
            if(name.indexOf("on") === 0) {
                el.addEventListener(name.substr(2).toLowerCase(), props[name], false)
            } else {
                el.setAttribute(name, props[name]);
            }
        }
    }
    if (!nest) {
        return el;
    }
    return nester(el, nest)
}

function nester(el, n) {
    if (typeof n === "string") {
        var t = document.createTextNode(n);
        el.appendChild(t);
    } else if (n instanceof Array) {
        for(var i = 0; i < n.length; i++) {
            if (typeof n[i] === "string") {
                var t = document.createTextNode(n[i]);
                el.appendChild(t);
            } else if (n[i] instanceof Node){
                el.appendChild(n[i]);
            }
        }
    } else if (n instanceof Node){
        el.appendChild(n)
    }
    return el;
}

The ml() function creates the parent element and sets its attributes and events. The nester() function, reads the third parameter and appropriately creates the child elements. Then the results is appended to the parent.

These two very simple functions make it much easier to deal with DOM elements in JavaScript. Plus you don't have to worry about figuring out which elements is the child of which. The hierarchy is in the design.


Did you like this article? Subscribe for more and follow updates via RSS.

Back to JavaScript articles