aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJohn Resig <jeresig@gmail.com>2009-09-07 20:55:36 +0000
committerJohn Resig <jeresig@gmail.com>2009-09-07 20:55:36 +0000
commit520f1a26845252dd6d7fd5f3b5bb7779ba91eb2c (patch)
tree924ffe7ca3de200ac508224b806e1ef98f7e7035
parent9d8d74569c8114f9c9b0f42bca71536e154c5944 (diff)
downloadjquery-520f1a26845252dd6d7fd5f3b5bb7779ba91eb2c.tar.gz
jquery-520f1a26845252dd6d7fd5f3b5bb7779ba91eb2c.zip
Broke the logic for .clean() wrap out into a separate, static, data structure. Also improved the performance of .html() looking for the case where .innerHTML can be used without problems. Also tweaked some cases where cleanData() was used, no need to use jQuery selectors in these cases.
-rw-r--r--Makefile4
-rw-r--r--build.xml4
-rw-r--r--src/manipulation.js85
-rw-r--r--test/unit/manipulation.js4
4 files changed, 54 insertions, 43 deletions
diff --git a/Makefile b/Makefile
index c23612058..95e376987 100644
--- a/Makefile
+++ b/Makefile
@@ -10,12 +10,12 @@ PLUG_DIR = ../plugins
BASE_FILES = ${SRC_DIR}/core.js\
${SRC_DIR}/data.js\
+ ${SRC_DIR}/event.js\
+ ${SRC_DIR}/support.js\
${SRC_DIR}/selector.js\
${SRC_DIR}/traversing.js\
${SRC_DIR}/attributes.js\
${SRC_DIR}/manipulation.js\
- ${SRC_DIR}/event.js\
- ${SRC_DIR}/support.js\
${SRC_DIR}/css.js\
${SRC_DIR}/ajax.js\
${SRC_DIR}/fx.js\
diff --git a/build.xml b/build.xml
index 095c52eb7..d0ab83c16 100644
--- a/build.xml
+++ b/build.xml
@@ -54,12 +54,12 @@
<fileset dir="${SRC_DIR}" includes="intro.js" />
<fileset dir="${SRC_DIR}" includes="core.js" />
<fileset dir="${SRC_DIR}" includes="data.js" />
+ <fileset dir="${SRC_DIR}" includes="event.js" />
+ <fileset dir="${SRC_DIR}" includes="support.js" />
<fileset dir="${SRC_DIR}" includes="selector.js" />
<fileset dir="${SRC_DIR}" includes="traversing.js" />
<fileset dir="${SRC_DIR}" includes="attributes.js" />
<fileset dir="${SRC_DIR}" includes="manipulation.js" />
- <fileset dir="${SRC_DIR}" includes="event.js" />
- <fileset dir="${SRC_DIR}" includes="support.js" />
<fileset dir="${SRC_DIR}" includes="css.js" />
<fileset dir="${SRC_DIR}" includes="ajax.js" />
<fileset dir="${SRC_DIR}" includes="fx.js" />
diff --git a/src/manipulation.js b/src/manipulation.js
index 30ba5abf5..95e2f7abf 100644
--- a/src/manipulation.js
+++ b/src/manipulation.js
@@ -2,14 +2,32 @@ var rinlinejQuery = / jQuery\d+="(?:\d+|null)"/g,
rleadingWhitespace = /^\s+/,
rxhtmlTag = /(<(\w+)[^>]*?)\/>/g,
rselfClosing = /^(?:abbr|br|col|img|input|link|meta|param|hr|area|embed)$/i,
- rinsideTable = /^<(thead|tbody|tfoot|colg|cap)/,
+ rtagName = /<(\w+)/,
rtbody = /<tbody/i,
fcloseTag = function(all, front, tag){
return rselfClosing.test(tag) ?
all :
front + "></" + tag + ">";
+ },
+ wrapMap = {
+ option: [ 1, "<select multiple='multiple'>", "</select>" ],
+ legend: [ 1, "<fieldset>", "</fieldset>" ],
+ thead: [ 1, "<table>", "</table>" ],
+ tr: [ 2, "<table><tbody>", "</tbody></table>" ],
+ td: [ 3, "<table><tbody><tr>", "</tr></tbody></table>" ],
+ col: [ 2, "<table><tbody></tbody><colgroup>", "</colgroup></table>" ],
+ _default: [ 0, "", "" ]
};
+wrapMap.optgroup = wrapMap.option;
+wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead;
+wrapMap.th = wrapMap.td;
+
+// IE can't serialize <link> and <script> tags normally
+if ( !jQuery.support.htmlSerialize ) {
+ wrapMap._default = [ 1, "div<div>", "</div>" ];
+}
+
jQuery.fn.extend({
text: function( text ) {
if ( typeof text !== "object" && text !== undefined )
@@ -149,11 +167,29 @@ jQuery.fn.extend({
},
html: function( value ) {
- return value === undefined ?
- (this[0] ?
+ if ( value === undefined ) {
+ return this[0] ?
this[0].innerHTML.replace(rinlinejQuery, "") :
- null) :
+ null;
+
+ // See if we can take a shortcut and just use innerHTML
+ } else if ( typeof value === "string" && !/<script/i.test( value ) &&
+ !wrapMap[ (rtagName.exec( value ) || ["", ""])[1].toLowerCase() ] ) {
+
+ for ( var i = 0, l = this.length; i < l; i++ ) {
+ // Remove element nodes and prevent memory leaks
+ if ( this[i].nodeType === 1 ) {
+ cleanData( this[i].getElementsByTagName("*") );
+ }
+
+ this[i].innerHTML = value;
+ }
+
+ } else {
this.empty().append( value );
+ }
+
+ return this;
},
replaceWith: function( value ) {
@@ -269,7 +305,8 @@ jQuery.each({
remove: function( selector, keepData ) {
if ( !selector || jQuery.multiFilter( selector, [ this ] ).length ) {
if ( !keepData && this.nodeType === 1 ) {
- cleanData( jQuery("*", this).add(this) );
+ cleanData( this.getElementsByTagName("*") );
+ cleanData( [ this ] );
}
if ( this.parentNode ) {
@@ -281,7 +318,7 @@ jQuery.each({
empty: function() {
// Remove element nodes and prevent memory leaks
if ( this.nodeType === 1 ) {
- cleanData( jQuery("*", this) );
+ cleanData( this.getElementsByTagName("*") );
}
// Remove any remaining nodes
@@ -319,41 +356,15 @@ jQuery.extend({
elem = elem.replace(rxhtmlTag, fcloseTag);
// Trim whitespace, otherwise indexOf won't work as expected
- var tags = elem.replace(rleadingWhitespace, "")
- .substring(0, 10).toLowerCase();
-
- var wrap =
- // option or optgroup
- !tags.indexOf("<opt") &&
- [ 1, "<select multiple='multiple'>", "</select>" ] ||
-
- !tags.indexOf("<leg") &&
- [ 1, "<fieldset>", "</fieldset>" ] ||
-
- rinsideTable.test(tags) &&
- [ 1, "<table>", "</table>" ] ||
-
- !tags.indexOf("<tr") &&
- [ 2, "<table><tbody>", "</tbody></table>" ] ||
-
- // <thead> matched above
- (!tags.indexOf("<td") || !tags.indexOf("<th")) &&
- [ 3, "<table><tbody><tr>", "</tr></tbody></table>" ] ||
-
- !tags.indexOf("<col") &&
- [ 2, "<table><tbody></tbody><colgroup>", "</colgroup></table>" ] ||
-
- // IE can't serialize <link> and <script> tags normally
- !jQuery.support.htmlSerialize &&
- [ 1, "div<div>", "</div>" ] ||
-
- [ 0, "", "" ];
+ var tag = (rtagName.exec( elem ) || ["", ""])[1].toLowerCase(),
+ wrap = wrapMap[ tag ] || wrapMap._default,
+ depth = wrap[0];
// Go to html and back, then peel off extra wrappers
div.innerHTML = wrap[1] + elem + wrap[2];
// Move to the right depth
- while ( wrap[0]-- ) {
+ while ( depth-- ) {
div = div.lastChild;
}
@@ -362,7 +373,7 @@ jQuery.extend({
// String was a <table>, *may* have spurious <tbody>
var hasBody = rtbody.test(elem),
- tbody = !tags.indexOf("<table") && !hasBody ?
+ tbody = tag === "table" && !hasBody ?
div.firstChild && div.firstChild.childNodes :
// String was a bare <thead> or <tfoot>
diff --git a/test/unit/manipulation.js b/test/unit/manipulation.js
index 8a61ba618..c942bfd38 100644
--- a/test/unit/manipulation.js
+++ b/test/unit/manipulation.js
@@ -639,9 +639,9 @@ var testHtml = function(valueObj) {
stop();
- jQuery("#main").html(valueObj('<script type="text/javascript">ok( true, "jQuery().html().evalScripts() Evals Scripts Twice in Firefox, see #975" );</script>'));
+ jQuery("#main").html(valueObj('<script type="text/javascript">ok( true, "jQuery().html().evalScripts() Evals Scripts Twice in Firefox, see #975 (1)" );</script>'));
- jQuery("#main").html(valueObj('foo <form><script type="text/javascript">ok( true, "jQuery().html().evalScripts() Evals Scripts Twice in Firefox, see #975" );</script></form>'));
+ jQuery("#main").html(valueObj('foo <form><script type="text/javascript">ok( true, "jQuery().html().evalScripts() Evals Scripts Twice in Firefox, see #975 (2)" );</script></form>'));
// it was decided that waiting to execute ALL scripts makes sense since nested ones have to wait anyway so this test case is changed, see #1959
jQuery("#main").html(valueObj("<script>equals(jQuery.scriptorder++, 0, 'Script is executed in order');equals(jQuery('#scriptorder').length, 1,'Execute after html (even though appears before)')<\/script><span id='scriptorder'><script>equals(jQuery.scriptorder++, 1, 'Script (nested) is executed in order');equals(jQuery('#scriptorder').length, 1,'Execute after html')<\/script></span><script>equals(jQuery.scriptorder++, 2, 'Script (unnested) is executed in order');equals(jQuery('#scriptorder').length, 1,'Execute after html')<\/script>"));