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:
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 );
},