// jQuery 2.2.2
var set = $('<p></p><b></b><i></i>');
set.filter('b').replaceWith('<a></a>');
console.log( set );
I would expect <b> to be changed to an <a> element, but that is not the case.
How can one replace an element if not by using filter then replaceWith ?
Since filter creates a _new_ jQuery Object, this creates a problem.
Sadly, this seems the awkward way of doing such a simple thing:
http://stackoverflow.com/a/36289638/104380
I suggest updating the API with some kind of a way to do such a replace more easily
replaceWith is a DOM operation; it doesn't change the context collection, just ensures that it becomes detached with new content inserted into the DOM where its members used to be (cf. http://jquery.com/upgrade-guide/1.9/#after-before-and-replacewith-with-disconnected-nodes ). To modify the collection itself, follow the linked StackOverflow answer or use .map as suggested later.
@gibson042 - using map with the is method inside it seems less performant than using the answer i've provided in this ticket, no?
jQuery is a library of useful DOM functions, yet it doesn't do this most simple thing out-of-the-box.
Any reason why not? Thanks.
I haven't checked, but I'd expect a proper map to be faster since no DOM manipulation is required (and note that the behavior you seek is _not_ a DOM operation). As for why replaceWith no longer manipulates the collection, refer to http://jquery.com/upgrade-guide/1.9/#after-before-and-replacewith-with-disconnected-nodes .
@gibson042 - Actually map wouldn't work well since you will loose all the jQuery data and events bound on the element <a> which is to replace <b>.
you can't just do this:
var set = $('<p></p><b></b><i></i>');
var a = $('a').data('a', 111);
a.on('click', ()=>{alert(1)})
set = set.map(function(){
return $(this).is('b') ? a[0] : this;
})
You want a full-on replace, with the data and events and the whole party.
I don't think this is a common need, evidenced by the lack of complaints in the past 10 years.. What is the use case here?
jQuery is primarily for selecting and manipulating DOM elements in a document. If you have a collection of DOM elements disconnected from a document, put them in a plain JavaScript array and manipulate them that way, then use $(array) to convert them to a collection.
you can't just do this…
Yes you can: https://jsfiddle.net/xu8epgak/
@dmethvin - The use case is for using in a very simple UI framework:
HTML template describes the page and it's components, Example:
<h1>My Page<h1>
<div>
<div class='foo'>
<h2>{{= barName }}</h2>
<component class='bar'></component>
</div>
<section class='tabsWrap'>
<div>{{= tabsCount }} tabs open:</div>
<component class='tabsComp'></component>
</section>
</div>
<component class='widgetStore'></component>
<section class='tabsContent'></section>
A javascript file, which is the controller, compile the page's template and then send the result to be rendered. Some components are async and needs ajas to retrieve their data from the server, and once that is done, those components' DOM structure, from their own templates, will replace the components on the screen with the real ones.
This whole thing is done in the page controller is not placing anything in the DOM itself, but rather pass a jQuery collection of the rendered template upwards to it's parent controller, and that one renders it. The page controller has no knowledge of the real browser's DOM, only the collection which is associated to the page, and for all it knows, it might or might not have been rendered, which isn't important at all. the page controller loads needed components and replaces the elements in the known set that needs to be replaced (<component>) with real, data-binded, events-binded components.
I hope I explained the situation well. I think it's a very trivial thing to do in jQuery, to replace one element in the set with another while keeping the integrity of the collection, wouldn't you say? of course I could turn the collection intro a real Array, iterate it, find the thing I want to replace and so on, but it would be nicer if it was more of an automatic thing. I've been writing jQuery for 10 years now, and I don't think I've encountered this myself, and I am very amazed at how haven't I.
Maybe something like:
var bar = $("<p>").data("a", 1); // whatever
collection.replaceItem('.foo', bar); // find an item of the collection which is '.foo' and replaces it with bar.
I might just extend jQuery with such a thing for my own use..
Most helpful comment
Yes you can: https://jsfiddle.net/xu8epgak/