jQuery source parsing DOM operation module package element details

Keywords: Javascript JQuery Fragment

This section describes the package element sub module in the DOM operation module, which can replace the currently matched element with the specified DOM element, as follows:

  • wrap(html) adds a layer of DOM elements to the outer layer of each matching element. This method traverses the matching element collection and calls the. wrapAll() method on each element. Unlike wrapAll(), this method sets a layer of html elements outside each matching element.
  • Wrap all (html) will convert html into a DOM node and put it in front of the first matching element, and then put other matching elements in turn. html can be html fragment, selector expression, jQuery object, DOM element or function, the same below.
  • wrapInner(html) wraps HTML elements before and after the content of each matching element. This method traverses the set of matching elements and wraps an HTML structure for all the content of each matching element by calling method. wrapAll().
  • unwrap(); removes the parent label of each element in the matching element collection and leaves the matching element in the parent element's position

Here's a chestnut:

writer by: Desert QQ:22969969

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
    <script src="http://libs.baidu.com/jquery/1.7.1/jquery.min.js"></script>
</head>
<body>
    <p>Hello</p>
    <p>Hello World</p>
    <div>
        <i>
            <span>Test text</span>
        </i>
    </div>

    <button id="b1">Button 1</button> <br/>
    <button id="b2">Button 2</button><button id="b3">Button 3</button> <br/>
    <button id="b4">Button 4</button><br/><button id="b5">Button 5</button>
    <script>
        b1.onclick=function(){$('p').wrap('<div></div>')}              //Internal will<div></div>Translate into jQuery Object to first matching element<p>Hello</p>Before, move the matching element to the DOM Node interior

        b2.onclick=function(){$('p').wrapAll('<div></div>')}           //Internal will<div></div>Translate into jQuery Object to first matching element<p>Hello</p>Before, move the matching element to the DOM Node interior
        b3.onclick=function(){$('p').wrapAll('<div><p></p></div>')}    //If there is a child node, the matching element will be moved to the child node

        b4.onclick=function(){$('p').wrapInner('<div></div>')}         //Add a layer before and after the content of each matching element DOM node(Inclusion layer)

        b5.onclick=function(){$('span').unwrap() }                     //Remove the parent element of each matching element and let the matching element occupy the node position
    </script>
</body>
</html>

Render as follows:

The corresponding DOM tree is as follows:

Click button 1 to add a div parent node to all P tags, as follows:

Click button 2 to add a div before the first p tag, and then put all P tags under the div, as follows:

Click button 3 to add a div > P double-layer DOM before the first p tag, and then put all P tags under the div, as follows:

Click button 4 to nest a layer of div tags in the outermost layer of p tags, as follows:

Click button 5 to remove the DOM node on the previous layer of span, as follows:

If you click again, the DOM of the previous layer of span will be removed until the body node is encountered

 

Source code analysis

wrapInner and wrap are implemented based on wrapAll. wrapAll is implemented as follows:

jQuery.fn.extend({
    wrapAll: function( html ) {                //Place outside matching elements html Element. html Parameters can be html Clip, selector expression jQuery Object, DOM Element or function.
        if ( jQuery.isFunction( html ) ) {        //If html It's a function.
            return this.each(function(i) {
                jQuery(this).wrapAll( html.call(this, i) );    //Traverse matching elements, execute on each matching element html Function and call iteratively with the return value of the function as a parameter.wrapAll()Function.
            });
        }

        if ( this[0] ) {                        //If there are currently matching elements
            // The elements to wrap the target around
            var wrap = jQuery( html, this[0].ownerDocument ).eq(0).clone(true);        //take html Convert to a jQuery object

            if ( this[0].parentNode ) {                                                //If the current first matching element has a parent,
                wrap.insertBefore( this[0] );                                            //Then insert the created package element before the first matching element.
            }

            wrap.map(function() {                            //ergodic wrap element
                var elem = this;                                //elem Is a reference to the created package element

                while ( elem.firstChild && elem.firstChild.nodeType === 1 ) {    //If html Contains a child node
                    elem = elem.firstChild;                                            //Reset elem by html Children of,Button 3 above will execute here
                }

                return elem;
            }).append( this );                                    //This line this Is currently matched jQuery Object to move each matching element after the inserted element
        }

        return this;
    },
})

wrapAll will first convert the parameter to a jQuery object, then insert it in front of the current first matching element, and finally take the generated jQuery object as the main sentence, call append() to add all the currently matched elements to the DOM node corresponding to the newly generated jQuery object. Corresponding to button 2 above

wrap() is implemented as follows:

jQuery.fn.extend({
    wrap: function( html ) {                //Add a layer to the outer layer of each matching element DOM element
        var isFunction = jQuery.isFunction( html );        //Wrap a section around each matching element HTML Structure, which traverses the set of matching elements and calls on each element.wrapAll()Method.
        return this.each(function(i) {
            jQuery( this ).wrapAll( isFunction ? html.call(this, i) : html );    //Call in turn wrapALl()function
        });
    },
})

The implementation of wrapInner is as follows:

jQuery.fn.extend({
    wrapInner: function( html ) {            //Used to wrap a segment around the contents of each element in the matching element set HTML Structure, which traverses the set of matching elements
        if ( jQuery.isFunction( html ) ) {                //If html It's a function.
            return this.each(function(i) {
                jQuery(this).wrapInner( html.call(this, i) );    //Traverse matching elements, execute on each matching element html Function and call iteratively with the return value of the function as a parameter.wrapInner()Function.
            });
        }

        return this.each(function() {                    //Traversal matching element set
            var self = jQuery( this ),
                contents = self.contents();                    //Get all children first

            if ( contents.length ) {                        //If there are child nodes
                contents.wrapAll( html );                        //call wrapAll(html)Wrap a paragraph around all the contents of the current element HTML Code.
            } else {
                self.append( html );                        //If the current element has no content, the parameter html Insert the current content.
            }
        });
    },
})

The implementation of unwrap is as follows:

Query.fn.extend({
    unwrap: function() {                        //Remove the parent label of each element in the matching element collection, and leave the matching element at the position of the parent element
        return this.parent().each(function() {            //Traverse the parent node first
            if ( !jQuery.nodeName( this, "body" ) ) {        //If not body element
                jQuery( this ).replaceWith( this.childNodes );    //Then call replaceWith take this.childNodes Replace with this,Notice here this Context is parent
            }
        }).end();
    }
})

Posted by travelbuff on Thu, 14 Nov 2019 20:43:43 -0800