简体   繁体   中英

Javascript - Div tag auto closing

I am changing my website to a modern web app of sorts, here is my HTML code..

<joexn-profile>
<joexn-logo></joexn-logo>
<joexn-text></joexn-text>
</joexn-profile>

and this is the JavaScript I use for the <joexn-profile> tags.

var joexnprofile = document.querySelector('joexn-profile');
joexnprofile.insertAdjacentHTML( 'afterBegin', '<center><div class="joexn-profile">');
joexnprofile.insertAdjacentHTML( 'afterEnd', '</div></center>');

The issue is, the <div class="joexn-profile"> tag automatically closes.

Take a look at the inspect element view:

在此处输入图片说明





JavaScript Only

As already explained by Quentin, you can't insert only half of a Node.

On the other hand, why do you want to do that at all?

1st: avoid tags like <center> or <font> or <b> , ... If you want to style sth. do it with CSS.

and 2nd: what's the point in replacing <joexn-profile> with <div class="joexn-profile"> ?
Every style that you apply to the .joexn-profile CSS-Selector you can also apply to the joexn-profile CSS-Selector.

The only difference is, that you have to declare display:block for joexn-profile so that the browser knows how to render this Node; block or inline or whatever.


But if you insist in going your way, here a little utility to handle such compositions of html-markup (even partial) and DON-Nodes.

Disclaimer: Code not fully tested, it may still contain bugs. And fragment() doesn't handle cyclic references!

https://jsfiddle.net/mkapLz1k/1/

//just to be clear: this ain't a replacement for jQuery, nor does it interfere with it's purposes.
//it's a set of utilities to enable working with compositions of HTML-Markup and plain DOM-Nodes
var nodeUtils = (function(){
    var container = document.createElement("div"), 
        placeholder = document.createElement("div"),
        forEach = Array.prototype.forEach;

    function _replacePlaceholder(node){
        var parent = node.parentNode;
        parent.insertBefore(this[node.id], node);
        parent.removeChild(node);
    }

    function _randomId(){
        return ("id"+Math.random()+Math.random()+Math.random()).replace(/0\./g, "-")
    }

    function _fragment(src){
        var markup = [], 
            nodesById = {}, 
            id = "", 
            ids = [];

        function _addNode(node){
            if(!id){
                nodesById[id=_randomId()] = fragment();
                ids.push("#"+id);
                //add placeholder into the html-markup.
                //These placeholder get eventually replaced.
                markup.push('<div id="'+id+'"></div>');
            }
            nodesById[id].appendChild( node );
        }

        function _parse(node){
            if(node == null || node === "" || typeof node === "function") return;

            if(typeof node === "object"){
                if("nodeType" in node){
                    //processes DOM Nodes, of all shapes and sizes ;)
                    //including Comment-Nodes, TextNodes and DocumentFragments, ...
                    _addNode( node );
                }else if(this.NodeList && node instanceof NodeList){
                    //nodeLists change
                    //so I have to process them differently than regular lists
                    while(node.length) _addNode( node[0] );
                }else{
                    //processes anything ArrayLike
                    for(var i = 0, len = ("length" in node && node.length)|0; i<len; ++i)
                        i in node && _parse( node[i] );
                }
            }else{
                //processes primitives as html-markup
                id = "";
                markup.push( node );
            }
        }

        _parse( src );

        if(ids.length === markup.length){ //=> 0 or 1
            //src contained only Nodes, no strings or primitives
            return id? nodesById[id]: void 0;
        }

        //src contained html-markup that needs to be parsed
        container.innerHTML = markup.join("");
        if(ids.length){
            //injecting the DOM-Nodes
            forEach.call( container.querySelectorAll( ids.join(",") ), _replacePlaceholder, nodesById );
        }

        for(var frag = fragment(), fc; fc = container.firstChild; )
            frag.appendChild( fc );
        return frag;
    }


    //`fragment()` is shorthand for `document.createDocumentFragment()`
    //`fragment(composition)` returns a DocumentFragment, that can be used with `node.appendChild()`.

    //takes an arbitrary composition of nested Arrays (or ArrayLike-structures, like jQuery-Objects, NodeLists, ...), containing DOM-Nodes or strings/primitives and builds a DocumentFragment out of that
    function fragment(composition){
        return composition != null && _fragment(composition) || document.createDocumentFragment();
    }


    //all the following functions can take anything that `fragment()` can handle as input:
    //only `node` has to be a real DOM-Node!

    //almost like setting a Nodes innerHTML, but it takes more than just HTML-Markup
    function content(node, composition){
        for(var frag = fragment(composition), fc; fc=node.firstChild;) node.removeChild(fc);
        node.appendChild(frag);
        return node;
    }

    //replace a Node with the provided 
    function replace(node, composition){
        var parent = node.parentNode;

        parent.insertBefore(placeholder, node);
        parent.insertBefore(fragment(composition), placeholder);
        parent.removeChild(placeholder);

        //how parent could have changed? maybe you referenced node somewhere in composition.
        if(parent === node.parentNode) parent.removeChild(node);

        return node;
    }

    //wraps a Node in the provided markup.
    //beforeBegin and afterEnd CAN contain associated markup. Like opening and closing Tag of the same Node.
    //e.g.: wrapNode(node, "<div>", "</div>");
    function wrapNode(node, beforeBegin, afterEnd){
        return replace(node, [beforeBegin, node, afterEnd]);
    }

    //wraps the content of the node in the provided Markup.
    //afterBegin and beforeEnd CAN contain associated markup. Like opening and closing Tag of the same Node.
    function wrapContent(node, afterBegin, beforeEnd){
        node.appendChild(fragment([afterBegin, node.childNodes, beforeEnd]));
        return node;
    }

    return {
        fragment: fragment,
        replace: replace,
        wrapNode: wrapNode,
        wrapContent: wrapContent,
        content: content,
    }   
})();

and your Markup:

var joexnprofile = document.querySelector('joexn-profile');

//telling by your code, it's not entirely clear 
//wich of these you actually want to do:

nodeUtils.wrapNode(
    joexnprofile,
    '<center><div class="joexn-profile">',
    '</div></center>'   
);

//or
nodeUtils.wrapContent(
    joexnprofile,
    '<center><div class="joexn-profile">',
    '</div></center>'   
);

//or maybe
nodeUtils.replace(
    //replace this:
    joexnprofile, 

    //with this:
    [
        '<center><div class="joexn-profile">',
        joexnprofile.childNodes,
        '</div></center>'
    ]
);

Take a look at the code-examples and you get a first impression of what fragment() is able to handle

var frag = nodeUtils.fragment([ 
    //you can build this Array inline, no need to do that beforehand
    condition? 
        window.title: 
        //simply inject `null` or `undefined` or `""` and this entry will be ignored
        null,

    //nest Arrays, they get parsed recursively
    [
        //mix (partial) HTML with other types
        '<div class="columns">',
            //real Nodes in the middle of some Markup: check
            document.getElementById('leftColumn'),

            //even more nesting, no problem
            [
                '<div class="middle">', 

                //handles anything Arraylike that contains Nodes or Markup
                jQuery('.someClass'),

                "</div>"
            ]
        '</div>'
    ],

    //NodeLists, no Problem
    document.querySelectorAll("#footer > div")
])

Now it's up to you how you use this.

Despite the abstraction offered by insertAdjacentHTML , you are still working on a DOM. It has elements in a strict hierarchy, it doesn't have start and end tags.

The HTML will be converted to DOM nodes and inserted. You aren't editing the raw source code.

Use createElement instead. Get the element you want inside the new element using querySelector and then use appendChild to move it inside the new element.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM