Search code examples
javascriptjqueryhtmljquery-load

Jquery load() doesn't load script tags in div


Page 1 has a Menu with id (#navigation), with a link called Page2 and DIV with id (global_content) that shows contents when the link Page2 is clicked. In the same page (Page 1) I wrote a jquery load function, so that when I click the link it should display the content without page reload. The load event works fine, the content is shown, but without the script tags that the Page 2 has.

This is the code in Page 1

<script>
jQuery(document).ready(function() {

    //jQuery('#navigation li a').click(function(){
    jQuery('#navigation li').on('click', 'a', function(){

    var toLoad = jQuery(this).attr('href')+' #global_content';
    jQuery('#global_content').fadeOut('fast',loadContent);
    jQuery('#load').remove();
    jQuery('#wrapper').append('<span id="load">LOADING...</span>');
    jQuery('#load').fadeIn('normal');
    function loadContent() {
        jQuery('#global_content').load(toLoad, function() {
        jQuery('#global_content').fadeIn('fast', hideLoader());

        });
    }
    function showNewContent() {
        jQuery('#global_content').show('normal',hideLoader());
    }
    function hideLoader() {
        jQuery('#load').fadeOut('normal');
    }
    return false;

    });
}); </script>

This is the code in Page 2

<div id="wall-feed-scripts">

  <script type="text/javascript">

    Wall.runonce.add(function () {

      var feed = new Wall.Feed({
        feed_uid: 'wall_91007',
        enableComposer: 1,
        url_wall: '/widget/index/name/wall.feed',
        last_id: 38,
        subject_guid: '',
        fbpage_id: 0      });

      feed.params = {"mode":"recent","list_id":0,"type":""};

      feed.watcher = new Wall.UpdateHandler({
        baseUrl: en4.core.baseUrl,
        basePath: en4.core.basePath,
        identity: 4,
        delay: 30000,
        last_id: 38,
        subject_guid: '',
        feed_uid: 'wall_91007'
      });
      try {
        setTimeout(function () {
          feed.watcher.start();
        }, 1250);
      } catch (e) {
      }

    });

  </script>
</div>

<div class="wallFeed">
some content
</div>

But the output i get is

<div id="wall-feed-scripts"></div>

 <div class="wallFeed">
    some content
    </div>

Can you help please?


Solution

  • You can bypass the restrictions of jQuery.load stripping <script> tags by using jquery.ajax directly, which is the underlying method used for the shorthand methods load, get, post etc.. We'll use jquery.html, which uses innerHTML, to update the DOM.

    var toLoad         = this.href,
        toLoadSelector = '#global_content';
    
    ...
    
    function loadContent() {
        jQuery.ajax({
            url: toLoad,
            success: function(data,status,jqXHR) {
                data = jQuery(data).find( toLoadSelector );
                jQuery('#global_content').html(data).fadeIn('fast', hideLoader());
            }
        });
    }
    

    As you see, we apply the selector toLoadSelector ('#global_content') on the reponse to only insert the desired portion of the page.

    UPDATE

    A better approach is to introduce some parameters to the loadContent function so it is more easily reusable. Here's an updated (and tested) version:

    <script>
    jQuery(function($) {
    
        $('#navigation li a').on('click', function() {
            loadContent( '#global_content', this.href, '#global_content' );
            return false;
        });
    
        function loadContent(target, url, selector) {
    
            $(target).fadeOut('fast', function() {
    
                showLoader();
    
                $.ajax({
                    url: url,
                    success: function(data,status,jqXHR) {
                        $(target).html($(data).find(selector).addBack(selector).children())
                        .fadeIn('fast', hideLoader());
                    }
                });
    
            });
        }
    
        function showLoader() {
            $('#load').remove();
            $('#wrapper').append('<span id="load">LOADING...</span>').fadeIn('normal');
        }
    
        function hideLoader() {
            $('#load').fadeOut('normal');
        }
    });
    </script>
    

    A few notes on the changes:

    jQuery(function() { ... })
    

    is the same as

    jQuery(document).ready( function() { ... } )
    

    Specifying function($) makes jQuery available as $ within the function, which saves some typing.

    Now, regarding this expression:

    $(data).find(selector).addBack(selector).children()
    

    Unfortunately, $("<div id='foo'>").find('#foo') does not return any results: only descendants are matched. This means that if Page2 has the #global_content div directly under <body>, it will not work. Adding addBack(selector) makes it possible to match the top-level element itself. See this so question for more details.

    The .children() makes sure that the <div id='global_content'> tag from Page2 is not itself included, otherwise Page1 will have

    <div id="global_content">
        <div id="global_content">
    

    which is technically illegal, since an id must be unique in a document.