2

This is an interesting question and I want to hear all of your opinions on it.

A jQuery ajax call strips out the following tags:

 <html>, <head>, <body> etc.

You are unable to access them through the data. For example:

 $.ajax({
   async: 'false',
   dataType: 'html',
   type 'GET',
   url: '/hello.html',
   success: function (data) {
     $(data).find('body'); //would be undefined
   }
 });

You can not access the first child element inside these elements either. For example:

 <body>
    <div id="cantTouchThis"> <!-- Not found -->
       <div class="orThis"></div>
    </div>
 </body>

I have read online that parseHTML (jQuery 1.8+) can solve this issue. This is ok, but what if the user can't use a jQuery higher than 1.7.0?

I have read many solutions saying an extra element around the body tag or inside it also works. I feel this approach is not very good as your adding extra HTML.

I have also seen people use a regular expression/ replace on these elements. This is better, but still has the same affect on the HTML.

Finally, I know about the filter solution. This is ok if you know the exact element, but if you don't, another element might be used. Filter will not be able to find it if its not the child:

 $(data).filter(‘#cantTouchThis'); //Found
 $(data).filter(‘.orThis'); //Not found

One interesting solution was createDocumentFragment(). Read more about it on this page somewhere: http://www.smashingmagazine.com/2012/11/05/writing-fast-memory-efficient-javascript/.

This type of coding is meant to be great for site performance. There is a great example on the website above.

Following on from this I read you could do this:

 $.ajax({
   async: 'false',
   dataType: 'html',
   type 'GET',
   url: '/hello.html',
   success: function (data) {
     var data = $(data),
         frag = document.createDocumentFragment();

    frag.appendChild($data[0]); //appends nothing
    $(frag).find('#cantTouchThis'); //finds nothing
   }
 });

This did not work however: How do I filter body html the returned data from ajax?

I then took a look at it further.

 $.ajax({
   async: 'false',
   dataType: 'html',
   type 'GET',
   url: '/hello.html',
   success: function (data) {
     var data = $(data),
         frag = document.createDocumentFragment(),
         $frag;

    for (var i = 0; i < $data.length; i += 1) {
       frag.appendChild($data[i]); //Appends the data to the fragment
    }
    $frag = $(frag);
    $frag.find('#cantTouchThis'); //still finds nothing, find does not work
    $frag.children('#cantTouchThis'); //finds it
    $frag.children('.orThis'); // not found
    $frag.children('#cantTouchThis').find('.orThis'); //finds it
   }
 });

Finally I expanded on it a little:

$.ajax({
   async: 'false',
   dataType: 'html',
   type 'GET',
   url: '/hello.html',
   success: function (data) {
     var data = $(data),
         frag = document.createDocumentFragment(),
         $frag,
         $dataWrap = document.createElement('div'); //Create a div

    $dataWrap.setAttribute('id', 'ajaxContent'); //set an attr
    frag.appendChild($dataWrap); //append it into the dataWrap

    for (var i = 0; i < $data.length; i += 1) {
       frag.getElementById('ajaxContent').appendChild($data[i]); //Appends the data to the fragment child
    }
    $frag = $(frag).children(); //Targets ajaxContent and then you can target everything else
    $frag.find('#cantTouchThis'); //finds it 
    $frag.find('.orThis'); //finds it this time!
   }
 });

Is this approach bad? It is a little JS heavy and I am not sure it is a good solution. Would this make it run slower (for loop of data) or help speed it up.

Is there a way of accessing body tags without updating jQuery.

I am curious on everybody's views. I hope I missed nothing out.

EDIT:

It turns out Internet Explorer does not like getElementById on the fragment itself.

You can get around this using the following:

  for (var i = 0; i < $data.length; i += 1) {
       frag.firstChild.appendChild($data[i]); //firstChild works
    }

Thanks for giving this a read.

Community
  • 1
  • 1
Paddy
  • 1,175
  • 1
  • 14
  • 23
  • 1
    `console.log($(data).filter("div"));` – epascarello Aug 19 '14 at 17:09
  • Not JS heavy unless you are filtering data of about thousands. What are you trying to accomplish by the way? – Mike Ante Aug 19 '14 at 17:19
  • A plugin where the user can pass in target elements and bring back data they choose. A target element could possibly be the child of the body. I may come across this in future projects as well. – Paddy Aug 19 '14 at 18:35
  • I just had the same problem. Like you said in the beginning of your post, you can't access the first element. If you have access to the page, just wrap everything after `` inside a "dummy-div": `` – gatzkerob Nov 29 '17 at 05:25

0 Answers0