We can observe in the documentation of each method that:
.contents()
Collects the children of each element of the combined set of elements, including text and comment nodes.
And also the note:
The method .contents()
can also be used to obtain the content document from a iframe, if the iframe is in the same domain as the main page.
.html()
Fetch the HTML content of the first element in the combined element set or define the HTML content of each corresponding element.
Summary
Essentially, the method .contents()
, is attentive to the special needs of a iframe and makes use of its property contentDocument
to extract the contents if the element is actually an iframe. The method .html()
does not carry out such checks and/or use of special properties of the elements.
For details, continue reading...
To iframe
To know the reason for the method .contents()
be able to collect what is inside the iframe and the method .html()
No, we need to look at various details about how everything works:
We can see in the documentation for the abstraction modules, particularly in section 5.13 on the module iframe that it has two types of implementations: DTD and XML Schema. The relevant for this case is the DTD implementation that presents the following structure for the module iframe:
<!-- ...................................................................... -->
<!-- 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 -->
And going back to the previous page, we can read:
When this module is used, the element iframe is added to the online content set as defined by Text module.
And this essentially answers the question, any text element has no child nodes, hence the method .html()
can’t collect anything from them.
Already the method .contents()
, by collecting whatever is inside the element, collects what is inside 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>A minha div é muito bonita!</div>
<p>
<button id="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
What remains to be seen in jQuery code to justify the ability of .contents()
in relation to iframe, where for this purpose we observe its code, particularly line 3040 to 3044:
contents: function( elem ) {
return jQuery.nodeName( elem, "iframe" ) ?
elem.contentDocument || elem.contentWindow.document :
jQuery.merge( [], elem.childNodes );
}
We easily observe that the method .contents()
makes an analysis of the element where it is working to see if it is a iframe, and if so, will invoke the property contentDocument
of the element iframe, which is responsible for returning the content of the iframe.
Note: contentWindow.document
is an equivalence to IE8.
Already the method .html()
is completely oblivious to the special requirements of a iframe, as we can ascertain in jQuery source code from line 5842 to 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 );
},