SitePoint Sponsor

User Tag List

Results 1 to 10 of 10

Hybrid View

  1. #1
    SitePoint Zealot chrisdpucci's Avatar
    Join Date
    Dec 2006
    Location
    On the internets
    Posts
    191
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    Javascript inside of ajax created page....

    Hey guys,

    I've run into this a few times and have never found a way to deal it. Basically I'm building a user administration cms using mostly ajax calls to admin modules. It works great but I'm running into a huge problem that I need to figure out how to fix, (if possible).

    As the title says the issue is including and executing javascript code inside a page that gets called via ajax. One specific example of the problem I'm having is creating sortable lists with scriptalacous. It works great if I access the page directly, but if I access the page using an ajax call the javascript of the page doesn't seem to fire. I'm not sure if it's possible to work around this problem but it seems like it should be a fairly common issue with ajax aps so hopefully someon out there can help.

    thanks,

    Chris

  2. #2
    Programming Since 1978 silver trophybronze trophy felgall's Avatar
    Join Date
    Sep 2005
    Location
    Sydney, NSW, Australia
    Posts
    16,875
    Mentioned
    25 Post(s)
    Tagged
    1 Thread(s)
    You don't call pages using Ajax, you load new content into the current page using Ajax. If the content you are adding into the current page needs to use new JavaScripts then you need to download and then call those scripts in order to run them. If the script isn't running after the page update then either you are not downloading the extra JavaScript or you are not running it from the code that finishes loading the new content into the page.
    Stephen J Chapman

    javascriptexample.net, Book Reviews, follow me on Twitter
    HTML Help, CSS Help, JavaScript Help, PHP/mySQL Help, blog
    <input name="html5" type="text" required pattern="^$">

  3. #3
    SitePoint Zealot chrisdpucci's Avatar
    Join Date
    Dec 2006
    Location
    On the internets
    Posts
    191
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by felgall View Post
    You don't call pages using Ajax, you load new content into the current page using Ajax.
    Symantics are hardly worth mentioning as I'm sure you understood what I meant. For clarification I am making an asynchronous call to the server to request a page which is then included in the current document as content.

    Quote Originally Posted by felgall View Post
    If the content you are adding into the current page needs to use new JavaScripts then you need to download and then call those scripts in order to run them.
    I'm not exactly sure what you mean by "download" the javascript. I've tried everything I can think of from including the js code in the main document, including it in the page that is loaded and even trying to trigger the function using onload in the requested page and that still didn't work.

    Again I am using the prototype and scriptalacous frameworks utilizing the sortable function specifically. The main page loads a sortable list which works perfectly. I then have ajax controls that refine that list based on selections. The goal is to keep the list sortable regardless of whether it's loaded normaly or through the ajax controls.

  4. #4
    SitePoint Evangelist
    Join Date
    Mar 2006
    Location
    Sweden
    Posts
    451
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Are you trying to load an HTML page which contains both HTML and Javascript?

    You're better of loading them seperately, and loading the Javascript by dynamically adding a script-element, and making the Javascript in that file execute itself.

  5. #5
    SitePoint Zealot chrisdpucci's Avatar
    Join Date
    Dec 2006
    Location
    On the internets
    Posts
    191
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Ok, I'm back....

    Over the last few days I've been researching this issue fairly heavily and what I've found is that this is a common issue with ajax requests that contain javascript. Basically ajax requests only and always return text so if your content contains javascript it is simply returned as text and ignored by the browser.

    From what I've read there seems to be two standard work arounds for this. One is using the eval function to execute the javascript and the second one is to create a custom parsing function to parse out the javascript and include it in the current DOM.

    The second solution seems safer and is what I've been working on. I am having a bit of trouble though so I thought I'd come back and see if any gurus here could help.

    Code is below:

    Ajax request
    Code:
    <a href="#" onclick="makerequest('page.php', 'ajax_div'); return false;)" />Ajax Request</a>
    As you can imagine the above is a simple ajax request with the makerequest function taking in the requested page and the output div as paramaters.

    The parsing code I have is this:

    Code:
    function sethtml(div,content) 
    { 
        var search = content; 
        var script; 
              
        while( script = search.match(/(<script[^>]+javascript[^>]+>\s*(<!--)?)/i)) 
        { 
          search = search.substr(search.indexOf(RegExp.$1) + RegExp.$1.length); 
           
          if (!(endscript = search.match(/((-->)?\s*<\/script>)/))) break; 
           
          block = search.substr(0, search.indexOf(RegExp.$1)); 
          search = search.substring(block.length + RegExp.$1.length); 
           
          var oScript = document.createElement('script'); 
          oScript.text = block; 
          document.getElementsByTagName("head").item(0).appendChild(oScript); 
        } 
        
        document.getElementById(div).innerHTML=content; 
    }
    It is designed to take in the returned content and parse it for script tags and then insert the script tags into the current document.

    My problem is that I am not sure how to get the two pieces to work together.

    My ajax request returns the content perfectly and loads it in the div, but trying to call the sethtml function either from the request or afterwards doesn't seem to work.

    Any help is appreciated.

  6. #6
    SitePoint Wizard
    Join Date
    Nov 2004
    Location
    Nelson BC
    Posts
    2,310
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I got the sethtml fn working after a couple of changes...but there's no ajax involved. Test example:
    Code:
    <html>
    <head>
    <script type="text/javascript">
    var myFakeAjaxHTML = "<html><head><scr";
    myFakeAjaxHTML += "ipt type='text/javascript'>var btn=document.getElementById('thebutton'); btn.style.display='block';btn.onclick = function () {alert('worked');};</scr";
    myFakeAjaxHTML += "ipt></head><body><div>Loaded HTML</div><button id='thebutton' style='display:none'>click me</button></body></html>";
    
    
    function sethtml(div,content) 
    { 
        var search = content; 
        var script;
        // we might get more than one script, and it might be dependent on HTML that we are currently loading, 
        // so keep all the script objects in an array and apply them after the HTML
        
        var oScripts = [];
        
        while( script = search.match(/(<script[^>]+javascript[^>]+>\s*(<!--)?)/i)) 
        { 
          search = search.substr(search.indexOf(RegExp.$1) + RegExp.$1.length); 
           
          if (!(endscript = search.match(/((-->)?\s*<\/script>)/))) break; 
           
          block = search.substr(0, search.indexOf(RegExp.$1)); 
          search = search.substring(block.length + RegExp.$1.length); 
           
          var oScript = document.createElement('script'); 
          oScript.text = block; 
          
          oScripts.push(oScript);
          //document.getElementsByTagName("head").item(0).appendChild(oScript); 
        } 
        //apply the html
        document.getElementById(div).innerHTML=content; 
        
        // now apply the scripts
        for (var i=0; i < oScripts.length; i++) {
        	document.getElementsByTagName("head").item(0).appendChild(oScripts[i]); 
        }
        	
    }
    
    </script>
    </head>
    <body>
    <a href="#" onclick="sethtml('ajax_div', myFakeAjaxHTML); return false;" />Ajax Request</a>
    <div id="ajax_div"></div>
    </body>
    </html>

  7. #7
    SitePoint Zealot
    Join Date
    Sep 2007
    Posts
    136
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    What exact Ajax functions are you using? If you're using prototype's Ajax.Updater you can simply add the evalScripts parameter.

  8. #8
    SitePoint Zealot chrisdpucci's Avatar
    Join Date
    Dec 2006
    Location
    On the internets
    Posts
    191
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Basically I'm currently loading content into a div using ajax in the following manner:

    Code:
    <a href="#" onclick="makerequest('page.php', 'ajax_div'); return false;">Ajax Request </a>
    The makerequest function takes in the requested page and the target div as it's parameters and looks like this:

    Code:
    // Create a boolean variable to check for a valid Internet Explorer instance.
    var xmlhttp = false;
    
    // Check if we are using IE.
    try 
          {
    // If the Javascript version is greater than 5.
          xmlhttp = new ActiveXObject("Msxml2.XMLHTTP");
          }
          catch(e)
          {
    // If not then use the older active x object.
          try 
          {
                // If we are using Internet Explorer.
                xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
          }
          catch (E)
          {
                // We must be using a non-IE browser.
                xmlhttp = false;
          }
          }
    
    // If we are using a non-IE browser, create a javascript instance of the object.
    if(!xmlhttp && typeof XMLHttpRequest != 'undefined')
    {
          xmlhttp = new XMLHttpRequest();
    }
    
    // Make Request Function.
    function makerequest(serverPage, objID)
    {
          var obj = document.getElementById(objID);
          obj.innerHTML = "<div align='center'><img src='/loading.gif' /></div>";
          xmlhttp.open("GET", serverPage);
          xmlhttp.onreadystatechange = function() {
          if (xmlhttp.readyState == 4 && xmlhttp.status == 200) 
          {
                obj.innerHTML = xmlhttp.responseText;
          }
          }
    xmlhttp.send(null);
    }
    So that works perfectly and the php page loads in the target div no problem. Now as you can imagine I am running into the problem with executing javascript inside of the loaded php page.

    In this specific instance I have some form input elements that are loading using javascript, (relational lists).

    Normally I just include this in the head of the document

    Code:
    <script language='JavaScript' type='text/javascript' src='/HDWRelationalList/RelationalList.js'></script>
    <SCRIPT language='JavaScript' type='text/javascript'>
    function LoadRelationalList(){
    var RelationalList0 = new RelationalList(list1, 'list2', '/list1.xml', '/list2.xml');
     }</SCRIPT>
    The above of course doesn't work in content loaded via ajax. I'm not really against using prototype's built in ajax functions, I've just been using my own so maybe I should switch to get this to work?

    Thanks for your help,

    Chris

  9. #9
    SitePoint Zealot
    Join Date
    Sep 2007
    Posts
    136
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by chrisdpucci View Post

    Code:
    // Create a boolean variable to check for a valid Internet Explorer instance.
    var xmlhttp = false;
    
    // Check if we are using IE.
    try 
          {
    // If the Javascript version is greater than 5.
          xmlhttp = new ActiveXObject("Msxml2.XMLHTTP");
          }
          catch(e)
          {
    // If not then use the older active x object.
          try 
          {
                // If we are using Internet Explorer.
                xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
          }
          catch (E)
          {
                // We must be using a non-IE browser.
                xmlhttp = false;
          }
          }
    
    // If we are using a non-IE browser, create a javascript instance of the object.
    if(!xmlhttp && typeof XMLHttpRequest != 'undefined')
    {
          xmlhttp = new XMLHttpRequest();
    }
    
    // Make Request Function.
    function makerequest(serverPage, objID)
    {
          var obj = document.getElementById(objID);
          obj.innerHTML = "<div align='center'><img src='/loading.gif' /></div>";
          xmlhttp.open("GET", serverPage);
          xmlhttp.onreadystatechange = function() {
          if (xmlhttp.readyState == 4 && xmlhttp.status == 200) 
          {
                obj.innerHTML = xmlhttp.responseText;
          }
          }
    xmlhttp.send(null);
    }

    Using prototype's abilities you can replace all that code with just this

    Code:
    function makerequest(serverPage, objID)
    {
          $(objID).update("<div align='center'><img src='/loading.gif' /></div>");
          new Ajax.Updater(objID, serverPage, {method:'get', evalScripts:true});
    }
    and that should solve all your problems

  10. #10
    SitePoint Zealot chrisdpucci's Avatar
    Join Date
    Dec 2006
    Location
    On the internets
    Posts
    191
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    That's great and definitely a code saver!

    Your example helped me get standard JS working in the content page, but the relational list code still doesn't work. I think it may be because the code I'm trying to use makes xmlhttp requests as well which looks to be another sticking point with ajax content.

    Anyway, thanks for the help. I think I've followed this road as far as it goes and will probably start working on an alternative design pattern.

    Thanks again,

    Chris


Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •