May 21, 2013

jQuery complete replace DOM of element with another DOM – faster way?

Tomis’s Question:

I’m using jQuery’s AJAX for getting new content from server. Data is loaded in JSON:

$.ajax({
    url: url,
    data: {
        'ajax': '1',
    },
    dataType: 'json',
    success: somefunction
});

For server-side application limitation, I’m not able to setup more JSON variables inside so I have to load everything into content. That is why I have to load result into jQuery, than search and replace some elements on page, like this (used in somefunction):

var somefunction = function(data) {
    var con = $('<div></div>').html(data.content); // just $(data.content) is not working
    $('div#mainContent').html(con.find('div#ajax-content').html());
    ... // same process with three more divs
}

EDIT: Please, note that I have to do same process to replace three divs!

There is more about that, but as example, it’s enough I hope. My question: For some logic way, I expect that loading result into DOM ($(data.content)), parsing to html (con.find('dix#ajax-content').html()) and back to DOM ($('div#mainContent').html()) seems to me like loosing some resources and decreasing the perfomance so I would like to know if there is any faster way to do it and load DOM directly, like:

$('div#mainContent').dom(con.find('div#ajax-content').dom());

I tried to google it but maybe I don’t know what to type in. Also jQuery documentation does not helped me a lot.

Some facts:

  • jQuery 1.9.1
  • jQuery UI 1.10.3 available

Finally, I know that it would be much more better to do something with server-side app to provide more JSON variables, however, I need to write not-so-easy peace of code which is requiring longer time to develop which I don’t have right now. Doing it on client side would be temporary solution for now, however, I don’t want to decrease performace a lot.

Side-question:

is it correct to use find() function in this case or there is any better one?

EDIT 2 (not working parsing string)
I’m expecting this working but it’s not:

content = '<div id="ajax-title">Pečivo běžné, sladké, slané</div>
<div id="ajax-whereami"><a href="/category/4">Chléba a pečivo</a> » Pečivo běžné, sladké, slané</div>';
$(content);

Actually, $(data.content) should work just fine, but you have to keep in mind that the top level elements can only be reached via .filter() instead of .find(). If the elements you wish to target are at least one level deeper than the root you should use .find() though; in the examples below you can replace .filter() with .find() where appropriate.

var $con = $(data.content);
$('div#mainContent')
  .empty()
  .append($con.filter('div#ajax-content'))
  .append($con.filter('div#another-id'))
  .append($con.filter('div#and-another-id'));

You can also combine the selectors together:

  .append($con.filter('div#ajax-content, div#another-id, div#and-another-id'));

Lastly, since identifiers should only appear once inside a document, you can drop the div part:

  .append($con.filter('#ajax-content, #another-id, #and-another-id'));

Update

Okay, it seems that jQuery doesn’t evaluate data.content properly when there are newlines in the wrong places; this should work in all cases:

var wrapper = document.createElement('div');
wrapper.innerHTML = data.content;

var $con = $(wrapper);

No, There aren’t any other way that will speed up the performance.

In order to traverse along the content, the content has to be loaded somewhere. So what you are doing is perfectly valid.

Author: Nabin Nepal (Starx)

Hello, I am Nabin Nepal and you can call me Starx. This is my blog where write about my life and my involvements. I am a Software Developer, A Cyclist and a Realist. I hope you will find my blog interesting. Follow me on Google+

...

Please fill the form - I will response as fast as I can!