SitePoint Sponsor

User Tag List

Page 1 of 2 12 LastLast
Results 1 to 25 of 33
  1. #1
    SitePoint Addict
    Join Date
    Feb 2002
    Location
    Atlanta, GA
    Posts
    342
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    Tricky JavaScript - DOM problem

    This is one that I have been wrestling with for the better part of a day now and if anyone knows a solution I'd really appreciate hearing it.

    The application is a classic ASP (3.0) application hosted in a portal environment which I have inherited. The client receives from the back end the Html and JavaScript to run the page. Due to performance concerns the code received from the back end is called for asynchronously using some JavaScript and the XMLHttp object and the results of the call are then stored in a JS variable until the containing page has completed loading at which point the contents of the variable are assigned to the innerHTML property of a DIV tag for display. The problem is I have had to copy and paste the JavaScript functions necessary to run the page, which is sent from the back end, in to the client code because I can't access the functions contained in the DIV tag which was originally created by the XSLT. So here's the question: how does one access JavaScript which is created a runtime, pushed to the client, and stored in a DIV tag? Note: the JavaScript being sent to the client is created in a very complex XSLT layer and it's a common XSLT file used by numerous other applications so I'm none to keen on mucking about in there....


  2. #2
    SitePoint Aficionado JVLB's Avatar
    Join Date
    Jan 2002
    Location
    N 44 56.537' W 123 3.683'
    Posts
    1,127
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Access in what regard? Reading, modifying, or executing?

  3. #3
    SitePoint Addict
    Join Date
    Feb 2002
    Location
    Atlanta, GA
    Posts
    342
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Specifically the ability for event handlers which are attached to the onClick event of 'a' links to execute. It seems the JavaScript functions/event handlerts are not available for execution.


  4. #4
    SitePoint Wizard
    Join Date
    Mar 2001
    Posts
    3,537
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Due to performance concerns the code received from the back end is called for asynchronously using some JavaScript and the XMLHttp object
    Whoa. That turns one request into two requests. What performance are you concerned about?

    how does one access JavaScript which is created a runtime, pushed to the client, and stored in a DIV tag?
    You can't. It's just a string, so it's not executable code. You have to make the browser call the js engine and parse the text to turn it into executable code. That normally happens when the page loads and <script> tags are encountered as the browser parses the html, or when you dynamically add some <script> tags with a src attribute.

    You can also make js parse some text by using eval() on the text--however that is heavily frowned upon because there is almost always a better way to write the code that avoids having to use eval(). When eval() is present in js code, it alerts anyone who sees the code that the person who wrote the code is most likely an amateur.

  5. #5
    I'll take mine raw silver trophy MikeFoster's Avatar
    Join Date
    Dec 2002
    Location
    Alabama, USA
    Posts
    2,560
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    How is it stored in the DIV - is it a CDATA section?

  6. #6
    SitePoint Evangelist
    Join Date
    Mar 2006
    Location
    Sweden
    Posts
    451
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by 7stud View Post
    You can also make js parse some text by using eval() on the text--however that is heavily frowned upon because there is almost always a better way to write the code that avoids having to use eval(). When eval() is present in js code, it alerts anyone who sees the code that the person who wrote the code is most likely an amateur.
    I do agree, but how about using eval() for JSON? How would one make the JSON text into JS code without it?

  7. #7
    SitePoint Addict
    Join Date
    Feb 2002
    Location
    Atlanta, GA
    Posts
    342
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by 7stud View Post
    Whoa. That turns one request into two requests. What performance are you concerned about?
    The back end system we are calling data from takes 4 to 7 seconds, on average, to return the data we are requesting (under load I've seen it take 15 seconds). We have no control over that system and the folks who do tell us they've optimized it much as possible. Rather than block and wait for the data we decided to make the call asynchronously which allows the rest of the page to load. I show a progress bar while the operation is taking place and the rest of the page loads.


  8. #8
    SitePoint Addict
    Join Date
    Feb 2002
    Location
    Atlanta, GA
    Posts
    342
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by MikeFoster View Post
    How is it stored in the DIV - is it a CDATA section?
    No. It's stored as you might normally see it written inline.


  9. #9
    &#083;itePoint Aficionado JVLB's Avatar
    Join Date
    Jan 2002
    Location
    N 44 56.537' W 123 3.683'
    Posts
    1,127
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Some elements, but not divs, support the click() method, allowing a script to trigger the onclick event. A kludge that might help you is simply to create an element, such as a button, which supports click() and assign the div's onclick value to the button's onclick value, then execute click() on the button. Unfortunately, I've only found this to work on IE and Firefox.

  10. #10
    I'll take mine raw silver trophy MikeFoster's Avatar
    Join Date
    Dec 2002
    Location
    Alabama, USA
    Posts
    2,560
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    note to self: get awake before posting
    Last edited by MikeFoster; Feb 24, 2007 at 09:53.

  11. #11
    SitePoint Addict
    Join Date
    Feb 2002
    Location
    Atlanta, GA
    Posts
    342
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    My apologies.

    Code:
    response = asyncRequest.responseText;
    divDataDisplay = document.getElementById("dataDisplay");
    divDataDisplay.innerHTML = response;

    asyncRequest.responseText contains all the script and markup we're rendering for the portion of the page in which our content is running. It could be a table, an image reference or an entire page, minus the body tags which are reserved for the parent page in which we're running.
    Last edited by phpPete; Feb 25, 2007 at 06:07.


  12. #12
    I'll take mine raw silver trophy MikeFoster's Avatar
    Join Date
    Dec 2002
    Location
    Alabama, USA
    Posts
    2,560
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Sorry Pete... I haven't had my coffee yet

    So it could look like this?

    <div><script>code here</script></div>

    Can you give us a link to the page?

  13. #13
    SitePoint Addict
    Join Date
    Feb 2002
    Location
    Atlanta, GA
    Posts
    342
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by MikeFoster View Post
    Sorry Pete... I haven't had my coffee yet

    So it could look like this?

    <div><script>code here</script></div>

    Can you give us a link to the page?
    No problem. And that's exactly how it can look.

    I realize this complicates things but unfortunately I can't provide a link, I'm prevented from doing so by an NDA, which is why I've been somewhat general / theorectical in my questions.

    I've got it working for now by hardcoding the script code in the portion of the page I have access to. It's a hack but it works in this case.

    If one were to peek in a DIV tag, locate some javascript and find a way to execute it I'd love to know. The only approach I can think of is to regex (parse) the hell out of the innerHTML and then eval the relevant code.


  14. #14
    &#083;itePoint Aficionado JVLB's Avatar
    Join Date
    Jan 2002
    Location
    N 44 56.537' W 123 3.683'
    Posts
    1,127
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Try this and see if it helps:

    funNam=document.getElementById('elementInQuestion').onclick;funNam();

    Or, even shorter:

    document.getElementById('elementInQuestion').onclick();

  15. #15
    I'll take mine raw silver trophy MikeFoster's Avatar
    Join Date
    Dec 2002
    Location
    Alabama, USA
    Posts
    2,560
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I think I have a way that works... brb...

  16. #16
    I'll take mine raw silver trophy MikeFoster's Avatar
    Join Date
    Dec 2002
    Location
    Alabama, USA
    Posts
    2,560
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I tested the following on WinXP in Opera 9.10, Firefox 2, IE 5 and IE 7.
    Also tested on WinNT in Firefox 1.0.2 and IE 6.
    Here is the demo online.

    Code:
    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
    "http://www.w3.org/TR/html4/strict.dtd">
    <html>
    <head>
    <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
    <title>Cross-Browser.com</title>
    <style type='text/css'>
    .btn {
      cursor: pointer;
      border-bottom: 1px dotted red;
    }
    </style>
    <script type='text/javascript'>
    window.onload = function()
    {
      document.getElementById('btnInit').onclick = init;
      document.getElementById('btnTest').onclick = test;
    }
    function init()
    {
      //
      var c = "<h1>Test<\/h1><script type='text/javascript'>function foo(){alert('In foo()');}<\/script><p>This is a test.<\/p>";
      var d = document.getElementById('div1');
      d.innerHTML = c;
      //
      var i, se, sa = d.getElementsByTagName('script');
      for (i = 0; i < sa.length; ++i) {
        se = document.createElement('script');
        se.type = 'text/javascript';
        //alert(sa[i].innerHTML);
        se.text = sa[i].text;
        document.getElementsByTagName('head')[0].appendChild(se);
        d.removeChild(sa[i]); // optional
      }
    }
    function test()
    {
      foo();
    }
    </script>
    </head>
    <body>
    
    <p>Run init() then run the two tests.</p>
    <p><span id='btnInit' class='btn'>init()</span></p>
    <p><span id='btnTest' class='btn'>test()</span></p>
    <p><span class='btn' onclick='foo()'>foo() (inline call)</span></p>
    
    <div id='div1'>
    </div>
    
    </body>
    </html>
    Edit:

    This function changed as the discussion progressed. For the latest code, see posts later in the thread and the online demo.
    Last edited by MikeFoster; Feb 26, 2007 at 19:25. Reason: update

  17. #17
    SitePoint Addict
    Join Date
    Feb 2002
    Location
    Atlanta, GA
    Posts
    342
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Mike;

    Thanks for the code. I'll can test it later and I'll get back to you, probably early evening. I appreciate your efforts!


  18. #18
    SitePoint Wizard
    Join Date
    Nov 2004
    Location
    Nelson BC
    Posts
    2,310
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Isn't there a simpler way to go about this? What about a blank iframe which you document.write the received ajax html into? What about not using ajax at all but dynamically loading an iframe?

  19. #19
    I'll take mine raw silver trophy MikeFoster's Avatar
    Join Date
    Dec 2002
    Location
    Alabama, USA
    Posts
    2,560
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I've been learning about the pros and cons of the technique I used. It might be that the following is better, I'm not sure - I think this needs much testing on a variety of browsers/OSs.
    Code:
    function init()
    {
      //
      var c = "<h1>Test<\/h1><script type='text/javascript'>function foo(){alert('In foo()');}<\/script><p>This is a test.<\/p>";
      var d = document.getElementById('div1');
      d.innerHTML = c;
      //
      var i, t, se, sa = d.getElementsByTagName('script');
      for (i = 0; i < sa.length; ++i) {
        se = document.createElement('script');
        se.type = 'text/javascript';
        /*@cc_on
        @if (@_jscript) 
        se.text = sa[i].text;
        @else @*/
        t = document.createTextNode(sa[i].innerHTML); // modified per 7stud's test results below
        se.appendChild(t);
        /*@end @*/
        document.getElementsByTagName('head')[0].appendChild(se);
        d.removeChild(sa[i]); // optional
      }
    }
    Jim, I thought about alternatives too - but they all have pros and cons. In this case I can see why Pete doesn't want to make changes to "a very complex XSLT layer".

    Edit:

    This function changed as the discussion progressed. For the latest code, see posts later in the thread and the online demo.
    Last edited by MikeFoster; Feb 26, 2007 at 19:25. Reason: edit in red

  20. #20
    I'll take mine raw silver trophy MikeFoster's Avatar
    Join Date
    Dec 2002
    Location
    Alabama, USA
    Posts
    2,560
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    One interesting thing about "Dynamic Script Insertion" is that it allows cross-domain scripts - as opposed to the XHR and iFrame techniques, which do not.

    However, I do see that what Pete is doing here is XHR combined with DSI.

  21. #21
    SitePoint Wizard
    Join Date
    Nov 2004
    Location
    Nelson BC
    Posts
    2,310
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    To me it sounds like this XSLT layer is its own <html> document, which is why I thought of just sticking it in an iframe and letting it do its stuff by itself.

    The problem with trying to parse and sort out a string filled with javascript is when you get into the more complex stuff...what do you do with window.onloads? What if you overwrite already defined functions/variables? Try changing the line where you define c to
    Code:
      var c = "<h1>Test<\/h1><script type='text/javascript'>var d='this is no longer a reference to a script tag';function foo(){alert('In foo()');}<\/script><p>This is a test.<\/p>";
    I know that you can just rename all your variables to weird names but that was just an example of the headaches that I predict with this method. Hopefully you will now prove me wrong!

  22. #22
    SitePoint Wizard
    Join Date
    Mar 2001
    Posts
    3,537
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    The code doesn't work in Safari:
    Object (result of expression foo) does not allow calls.
    Code:
    function test()
    {
      foo();
    }
    
    ...
    ...
    
    <p><span class='btn' onclick='foo()'>foo() (inline call)</span></p>

  23. #23
    SitePoint Wizard
    Join Date
    Mar 2001
    Posts
    3,537
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Safari doesn't understand .text (and it shouldn't although FF doesn't object). Making the following change allows the code work in Safari 2.0.4:
    Code:
    @else @*/
        t = document.createTextNode(sa[i].innerHTML);
    No appending to script tags in IE?

  24. #24
    SitePoint Addict
    Join Date
    Feb 2002
    Location
    Atlanta, GA
    Posts
    342
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by jimfraser View Post
    Isn't there a simpler way to go about this? What about a blank iframe which you document.write the received ajax html into? What about not using ajax at all but dynamically loading an iframe?
    We prototyped IFrames first and the client/customer/boss rejected them out of hand. No real reason other than it looked bad to him - even with no borders. Never before did I appreciate the meaning of the saying 'this job would be so much easier without the users!'. Anyhow, we then went the AJAX route and that was what they liked and we were told to implement.

    The difficulty in all of this is shoehorning in code and updates to a multi-layer and multi tier application of significant complexity without a cascade of breaks throughout this particular application which is anything but robust!


  25. #25
    SitePoint Addict
    Join Date
    Feb 2002
    Location
    Atlanta, GA
    Posts
    342
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by MikeFoster View Post
    I've been learning about the pros and cons of the technique I used. It might be that the following is better, I'm not sure - I think this needs much testing on a variety of browsers/OSs.

    ...snip...

    Jim, I thought about alternatives too - but they all have pros and cons. In this case I can see why Pete doesn't want to make changes to "a very complex XSLT layer".
    Very nifty! As stated I'll have to test this pretty thoroughly but a very nice solution (I think...)



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
  •