Difference between the contents () and html () methods

3

I had to get the content of an iframe (which was in the same domain on the same page) with html() , but without success.

I saw that there was a method called contents() , and it worked fine using it.

Why a goddamn one and not another?

I tried to read about it, but it did not fit in the head ...

    
asked by anonymous 09.04.2015 / 22:31

1 answer

7

We can see in the documentation of each method that:

  • .contents()

      

    Collect the children of each element of the combined element set, including text and comment nodes.

    And also the note:

      

    The .contents() method can also be used to get the content document of an iframe , if the iframe is in the same domain as the main page. p>

  • .html()

      

    Gets the HTML content of the first element in the combined element set or sets the HTML content of each element.

Summary

Essentially, the .contents() method is aware of the special needs of an iframe and makes use of its contentDocument property to extract the content if the element is effectively an iframe. The .html() method does not perform such checks and / or use of special properties of the elements.

To know in detail, read on ...

The iframe

To find out why the .contents() method is able to collect what's inside the iframe method and the .html() method, we need to look at several details about how everything works:

W3C - 5. XHTML Abstract Modules

We can observe in the documentation for the abstraction modules, particularly in section 5.13 on the module iframe it has two types of implementations: DTD and XML Schema . What is relevant to this case is the DTD implementation that presents the following structure for the iframe module:

<!-- ...................................................................... -->
<!-- XHTML IFrame Module  ................................................. -->
<!-- file: xhtml-iframe-1.mod

     This is XHTML, a reformulation of HTML as a modular XML application.
     Copyright 1998-2005 W3C (MIT, ERCIM, Keio), All Rights Reserved.
     Revision: $Id: xhtml-iframe-1.mod,v 4.0 2001/04/02 22:42:49 altheim Exp $ SMI

     This DTD module is identified by the PUBLIC and SYSTEM identifiers:

       PUBLIC "-//W3C//ELEMENTS XHTML Inline Frame Element 1.0//EN"
       SYSTEM "http://www.w3.org/MarkUp/DTD/xhtml-iframe-1.mod"

     Revisions:
#2000-10-22: added #PCDATA to <iframe> content model as per HTML 4
     ....................................................................... -->

<!-- Inline Frames

        iframe

     This module declares the iframe element type and its attributes,
     used to create an inline frame within a document.
-->

<!-- Inline Frames .................................... -->

<!ENTITY % iframe.content  "( #PCDATA | %Flow.mix; )*" >
<!ENTITY % iframe.qname  "iframe" >
<!ELEMENT %iframe.qname;  %iframe.content; >
<!ATTLIST %iframe.qname;
      %Core.attrib;
      longdesc     %URI.datatype;           #IMPLIED
      src          %URI.datatype;           #IMPLIED
      frameborder  ( 1 | 0 )                '1'
      marginwidth  %Pixels.datatype;        #IMPLIED
      marginheight %Pixels.datatype;        #IMPLIED
      scrolling    ( yes | no | auto )      'auto'
      height       %Length.datatype;        #IMPLIED
      width        %Length.datatype;        #IMPLIED
>

<!-- end of xhtml-iframe-1.mod -->

Returning to the previous page, we can read:

  

When this module is used, the iframe element is added to the inline content set, as defined by Text Module .

And this essentially answers the question, any text element does not have children, so the .html() method can not collect any of them.

Since the .contents() method, because it collects whatever it is inside the element, collects what lies within the iframe for an object. This allows us to subsequently access the information present in the resulting object.

Examples

$('#sample1').click(function() {
  // devolve um objeto, mesmo só existindo texto na DIV
  alert($("div").contents());
});

$('#sample2').click(function() {
  // devolve um objeto, e depois "undefined" porque não existem nós para poder trabalhar
  alert($("div").contents().html());
});

$('#sample3').click(function() {
  // recolhe um objeto, e devolve o seu texto
  alert($("div").contents().text());
});

$('#sample4').click(function() {
  // devolve texto pois está a trabalhar num nó
  alert($("div").html());
});

$('#sample5').click(function() {
  // devolve texto
  alert($("div").text());
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script><div>Aminhadivémuitobonita!</div><p><buttonid="sample1">.contents()</button>
  <button id="sample2">.contents().html()</button>
  <button id="sample3">.contents().text()</button>
  <button id="sample4">.html()</button>
  <button id="sample5">.text()</button>
</p>
<em>clica nos botões para usar os métodos descritos nos mesmos.</em>

But what does jQuery do

contents: function( elem ) {
    return jQuery.nodeName( elem, "iframe" ) ?
        elem.contentDocument || elem.contentWindow.document :
        jQuery.merge( [], elem.childNodes );
}

We easily note that the .contents() method parses the element where it is working to see if it is an iframe , and if so, will invoke the property .contents() of the iframe element, which is responsible for returning the < in> iframe .

Note: contentDocument is an equivalency for IE8.

While the contentWindow.document method is completely oblivious to the special requirements of an , as we can see from the jQuery source code for line 5842 through 5882:

html: function( value ) {
    return access( this, function( value ) {
        var elem = this[ 0 ] || {},
            i = 0,
            l = this.length;

        if ( value === undefined ) {
            return elem.nodeType === 1 ?
                elem.innerHTML.replace( rinlinejQuery, "" ) :
                undefined;
        }

        // See if we can take a shortcut and just use innerHTML
        if ( typeof value === "string" && !rnoInnerhtml.test( value ) &&
            ( support.htmlSerialize || !rnoshimcache.test( value )  ) &&
            ( support.leadingWhitespace || !rleadingWhitespace.test( value ) ) &&
            !wrapMap[ (rtagName.exec( value ) || [ "", "" ])[ 1 ].toLowerCase() ] ) {

            value = value.replace( rxhtmlTag, "<$1></$2>" );

            try {
                for (; i < l; i++ ) {
                    // Remove element nodes and prevent memory leaks
                    elem = this[i] || {};
                    if ( elem.nodeType === 1 ) {
                        jQuery.cleanData( getAll( elem, false ) );
                        elem.innerHTML = value;
                    }
                }

                elem = 0;

            // If using innerHTML throws an exception, use the fallback method
            } catch(e) {}
        }

        if ( elem ) {
            this.empty().append( value );
        }
    }, null, value, arguments.length );
},
    
10.04.2015 / 01:03