2

I am very sorry for the long title, but its an adequate representation of the problem.

I am attempting to use AJAX on my WordPress website to load inner pages. I have this functionality working, however, when loading inner pages, any Javascript/jQuery that is meant to load and be run on these inner pages is not running/loading.

There are two steps in order to see and then recreate the problem:

1st - Take a look at this page: http://www.trekradio.net/dev/schedule - this page contains a schedule - the days are tabs, also when you click on a schedule item, it opens a jQuery popup. Javascript is also used on the right sidebar, in the "support us" widget, the dropdown is JS based, and also, the twitter feed loads using the Twitter API script. As you can see, all scripting is present and working fine.

2nd - http://www.trekradio.net/dev/ - goto the main page, then click "schedule" on the main menu - it loads up the schedule page using AJAX, however, all scripts on the page are now missing or have not been executed.

I've tried a number of things to solve this - on the schedule page, several of the scripts are embedded into the page itself, I tried moving these into the header, hoping that, because the header is not reloaded, the scripts might run - they did not.

Also, I have attempted the solution mentioned here: Executing <script> inside <div> retrieved by AJAX - it talks about using a dynamic script pattern, however, I either lack the ability to get it working correctly, or, it does not work properly in the context of what I am trying to accomplish.

I also tried using the solutions suggested here: jquery html() strips out script tags however, again, I could not get it to work.

Here is the contents of my ajax.js which is powering the ajax functionality:

jQuery(document).ready(function($) {
    var $mainContent = $("#ajax-content-container"),
        siteUrl = "http://" + top.location.host.toString(),
        url = ''; 

    $(document).delegate("a[href^='"+siteUrl+"']:not([href*=/wp-admin/]):not([href*=/wp-login.php]):not([href$=/feed/])", "click", function() {
        location.hash = this.pathname;
        return false;
    }); 

    $("#searchform").submit(function(e) {
        location.hash = '?s=' + $("#s").val();
        e.preventDefault();
    }); 

    $(window).bind('hashchange', function(){
        url = window.location.hash.substring(1); 

        if (!url) {
            return;
        } 

        url = url + " #main-content-container"; 

        $mainContent.animate({opacity: "0.1"}).html('<p>Please wait...</>').load(url, function() {
            $mainContent.animate({opacity: "1"});
        });
    });

    $(window).trigger('hashchange');
});

From what I have found by Google-ing - many many folks have this type of problem with their AJAX websites, struggling to get scripts running on loaded pages, so I am hoping that folks here can help come up with a solution which, not only I can apply to my website, but others can use on theirs too.

Would appreciate if folks would include code with their answers or at least explain clearly how I can modify the code to accomplish what is needed. I am still learning jQuery/AJAX, so perhaps I am being stupid and overlooking a relativly simple solution, but well documented answers would be appreciated by, I suspect, the entire community as well as myself.

Community
  • 1
  • 1
Zach Nicodemous
  • 9,097
  • 9
  • 45
  • 68
  • Are you talking about the javascript already in the page or the javascript inside the page that is dynamically loaded ? – mpm May 24 '12 at 17:54
  • javascript is not being executed on/in the content that is dynamically loaded from what I can tell. – Zach Nicodemous May 24 '12 at 17:58

3 Answers3

2

It's because you provided a selector expression as a part of your URL:

http://api.jquery.com/load/

Per the documentation:

However, in the following case, script blocks in the document being loaded into #b are stripped out and not executed:

$('#b').load('article.html #target')

Your URL has the selector:

url = url + " #main-content-container";
  • #main-content-container is not where the content is being loaded, its WHAT is being loaded. If I remove #main-content-container then the script dosen't know what content its pulling. How would I modify? – Zach Nicodemous May 24 '12 at 18:32
  • 1
    I didn't say it wasn't what was being loaded. I simply pointed to the documentation, which states your scripts will not be executed if you provide the selector expression. The problem is you want to grab an entire page, but only load in the main content, and still have scripts execute. This simply won't be possible because it requires you to use a selector expression. –  May 25 '12 at 16:09
  • Is it possible to modify the script? If so, can you demonstrate? – Zach Nicodemous May 25 '12 at 16:24
  • The quickest solution I can think of is that if you're making a request, and getting the entire document back anyhow, then just replace the whole page. You've already done the heavy lifting of sending the request and getting the response. It may not seem ideal, but other than that there isn't a viable alternative. You may wish to review this: http://stackoverflow.com/questions/889967/jquery-load-call-doesnt-execute-javascript-in-loaded-html-file –  May 25 '12 at 17:37
2

I think I have have solved this for myself - I'm not sure if its the most elegant solution, however it seems to work.

Basically, I've taken all of the scripts that would load on my inner pages and put them into a file called "inner-scripts.js" and modified ajax.js to this:

jQuery(document).ready(function($) {
    var $mainContent = $("#ajax-content-container"),
        siteUrl = "http://" + top.location.host.toString(),
        url = ''; 

    $(document).delegate("a[href^='"+siteUrl+"']:not([href*=/wp-admin/]):not([href*=/wp-login.php]):not([href$=/feed/])", "click", function() {
        location.hash = this.pathname;
        return false;
    }); 

    $("#searchform").submit(function(e) {
        location.hash = '?s=' + $("#s").val();
        e.preventDefault();
    }); 

    $(window).bind('hashchange', function(){
        url = window.location.hash.substring(1); 

        if (!url) {
            return;
        } 

        url = url + " #main-content-container"; 

        $mainContent.animate({opacity: "1.0"}).html('<div id="loading">Loading the next page for you.  Please stand by!</div>').load(url, function() {
            $mainContent.animate({opacity: "1"});
            $.getScript('http://www.trekradio.net/dev/wp-content/themes/tr2012/js/inner-scripts.js', function() {});
            $.getScript('http://ui.jquery.com/latest/ui/effects.core.js', function() {});
            $.getScript('http://twitter.com/javascripts/blogger.js', function() {});
        $.getScript('https://api.twitter.com/1/statuses/user_timeline.json?screen_name=trekradio&include_rts=1&count=3&callback=twitterCallback2', function() {});      
        });
    });

    $(window).trigger('hashchange');
});
Zach Nicodemous
  • 9,097
  • 9
  • 45
  • 68
1

I know you've answered the question yourself, but here's another way of doing it.

The conventional way to make ajax requests in wordpress is to use the admin-ajax interface as documented here: http://codex.wordpress.org/AJAX_in_Plugins.

This allows you to attach a function to an ajax request, and the function executes more or less in the context of WordPress. So you could write something roughly like this in your functions.php:

add_action('wp_ajax_trekradio_get_ajax_page', 'trekradio_get_ajax_page');
add_action('wp_ajax_nopriv_trekradio_get_ajax_page', 'trekradio_get_ajax_page');

function trekradio_get_ajax_page() {

    $page_id = $_POST['page_id']; // send this in the ajax request

    if ( the page is a certain page that needs scripts ) {
        print_relevant_script_tags();
    }

    print_page_content( $page_id );

    die(); // you have to do this at the end
}
djb
  • 5,591
  • 5
  • 41
  • 47
  • Yeah, this is a better way. You can have one ajax handler set up and pass it the name of the content you want, and break it up into little php files with includes. And your scripts should always be registered even if you're not printing them. – matchdav Jun 03 '12 at 00:24