Cybrix
Cybrix

Reputation: 3318

How do I merge two tags together in jQuery?

That one is a tricky one I believe. I would like to merge two tags together. For exemple, those two <span> with different IDs are beside each others like this:

Lorem ipsum <span id="selected-1">dolor sit</span><span id="selected-2" title="important info here"> amet, consectetur</span> adipiscing elit.

At the end, I would like to merge selected-1 and selected-2 and keeping the attributes of selected-2 to finally comes with something like:

Lorem ipsum <span id="selected-2" title="important info here">dolor sit amet, consectetur</span> adipiscing elit.

Any tips? I really can't figure out this one.

Thanks.

Upvotes: 1

Views: 4290

Answers (6)

user663031
user663031

Reputation:

There is really no need to use jQuery here, which has to go to all the work of stringizing the DOM nodes and then reparsing them to put them back into the DOM.

var span1=document.getElementById("selected-1"), 
    span2=document.getElementById("selected-2"),
    insert=span2.firstChild,
    elt;

while (elt=span1.lastChild) {
  insert=span2.insertBefore(elt,insert); // removes the node from span1
}

span1.parentNode.removeChild(span1);

It's true that the OP asked about a jQuery solution. But if someone asks how to pound in a nail with a Swiss army knife, it still seems reasonable to suggest using a hammer instead, especially if they already have a hammer, should know how to use it, and using it would be 100x faster.

I'm aware that the majority of applications use jQuery and so there is no incremental cost for loading it. And it does indeed provide a satisfying brevity in many cases--that little oxytocin rush when you get everything on one line. But there are also costs. There is the performance cost, which can be up to two orders of magnitude, and then there is the cost of hiding the programmer from what is really going on.

In this case, if the OP had known about four of the basic DOM APIs, he could have presumably figured out himself how to write the simple one-line while loop moving elements from one place to another, rather than trying to figure out what magic sequence of jQuery incantations to chain together to accomplish that, getting stuck, and having to post to SO.

Consider the performance comparison at http://jsperf.com/combine-dom-nodes which shows that the jQuery solution is 100 times slower.

On the other hand, even Brendan Eich seems to be coming around to the jQuery chained one-liner paradigm, giving the following example:

$(document).getTDs().getEven().hover().css("yellow").addCustomEvent("setSelected").setSelected(this.currentMagicNode).get.out("white").getTDs().getOdd().hover().css("yellow").addCustomEvent("setSelected").setSelected(this.currentMagicNode).out("white");

and commenting, "In hindsight I can see why JavaScript never caught on", said Brendan. "All of those semi-colons and line breaks makes the code very difficult to read. And you read code horizontally, not vertically — DUHHHH! JavaScript is NOT winning!" See http://clubajax.org/brendan-eich-redesigns-javascript-to-look-like-jquery/#more-1491.

Upvotes: 1

arttronics
arttronics

Reputation: 9955

Here's my 1 line version:

$('#selected-2').html( $('#selected-1').html() + $('#selected-2').html() ).prev().remove();

...and even a shorter version at that.

$('#selected-2').prepend($('#selected-1').html()).prev().remove();

Shorter version = Less code to download (especially for mobile browsers).


Edit: Since my short one-line answer was plunged in the ring and is going head-to-head with the longest markup answer on this page, it's not always about benchmark speed that is important, but simply functionality and maintenance of code.

Besides, calculations-per-second does not equate to real-world and real-browser page rendering which then will reveal no real performance gain in the end.

IMHO, the real-world markup use of one line makes more practical and common sense vs a goliath of code that is prone to user created errors (dot every i and cross every t) which also creates more data (the .js file) to download and parse.

Upvotes: 1

Pablo Mescher
Pablo Mescher

Reputation: 27467

var s1= $('#selected-1');
var s2= $('#selected-2');
s2.html(s1.html()+s2.html());
s1.remove();

Basically, I get the elements individually. Then I insert into the second element the html from the first element and the html currently inside the second element (or it will get overwritten). At last, but not least, I remove the first element.

->>>>>>> jsFiddle <<<<<<-

Upvotes: 0

Cybrix
Cybrix

Reputation: 3318

I didn't test all your solutions but I came with this piece of code:

var $wrapper = $( "#selected-1, #selected-2" )
    .wrapAll( "<span title='" + $( "#selected-2" ).attr( "title" ) + "'></span>" )
    .parent();

$( "#selected-1, #selected-2" ).replaceWith(function() {
    return $( this ).html();
});

$wrapper.attr( "id", "selected-2" );

I don't know if my way is faster or not though...

Upvotes: 0

Erik
Erik

Reputation: 935

Hopefully this is the easiest way (going strictly by the example):

var s1 = $('#selected-1').html();
$('#selected-1').remove();
$('#selected-2').prepend(s1);

You can verify this at http://jsfiddle.net/KFXRe/.

Upvotes: 1

nathancahill
nathancahill

Reputation: 10850

Three lines should do it:

$("#selected-1").html($("#selected-1").html() + $("#selected-2").html());
$("#selected-1").attr("title", $("#selected-2").attr("title"));
$("#selected-2").remove()

Upvotes: 1

Related Questions