diff options
-rw-r--r-- | Makefile | 4 | ||||
-rw-r--r-- | build.xml | 4 | ||||
-rw-r--r-- | src/manipulation.js | 85 | ||||
-rw-r--r-- | test/unit/manipulation.js | 4 |
4 files changed, 54 insertions, 43 deletions
@@ -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\ @@ -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>")); |