Basic Javascript not working after Ajax call

I have a web page that lists holiday properties.Each Listing has a link (‘Contact the owners’) that visitors can use to pull up an enquiry form. The form is contained in an absolutely positioned ‘div’ that is initially hidden. Clicking a link toggles the visibility, and the form appears on top of the other page content.

You can see a demo at: http://holidaymullandiona.com/bb-sw
Click on any of the links ‘Contact the owner’. All messages will be sent to me!

When the form is submitted an Ajax call gathers the data and re-loads the form script which sends the e-mail and shows a ‘success’ meaaage. It works, no problems. (Selection between the e-mail form and success message is via an ‘if submitted’ conditional). But there’s a problem if the visitor doesn’t cancel the success message.

I want to introduce some JS to cancel (submit) the success message automatically (after a delay) if the visitor doesn’t do it. (Otherwise clicking on further links doesn’t work as it should). But I’ve found that even very basic JS (like an ‘alert’) won’t wotk after the Ajax call.

I’ve read several pages on the internet about ‘binding’ the JS to an element after the Ajax call. But surely I shouldn’t need to bind something as simple as an alert message? What would I bind it to? I can see I’d need to do more to make my ‘click’ work on the submit button, but the fact that the ‘alert’ won’t work makes me wonder if my problem isn’t more fundamental?

Here’s the form ‘div’ - with pseudo code for the e-mail sending and form display. There are no ‘div’ tags because they’re on a different file, in which the form logic is ‘included’. I can see the JS in Inspector, but it doesn’t trigger the ‘Alert’:

        if (the form has been submitted) {
    
            // Set error flag if there are errors
            // If no errors do stuff to send the e-mail...
        }
    
        if (there are erros OR the form has NOT been submitted) {
    
            // Display the form (make the 'div' visible)
    
        } else {
            // The 'div' will already be visible at this point
            // Display Success message using the following code:
    
            $output = "
                <h2>Thank you for your enquiry</h2>
                <p><b>Your message has been sent successfully to:</b><br />";
    
            $output .= $bus_list . "<br />";
            $output .= '</p>';
    
            $output .= '
                <form method="post" id="contactform" action="#" onsubmit="return false">
                    <input type="submit" name="submit" value="Close" onclick="toggle_class(\'mail\')" />
                </form>';
    
                $output .= "<script>
                    alert ('success message');
                </script>";

                echo $output;
            }

Everything except the JS ‘Alert’ on that snippet works as intended. I will need to introduce more JS to achieve my eventual aim, but I’d like to understand how to get the Alert to work first! I have tried writing the HTML directly rather than echoing it, but it doesn’t make any different to my JS problem. Any suggestions ,please?

Instead of using the built-in alert, you can instead use custom alert that you will have more command over.

A basic example can be seen at https://jqueryui.com/dialog/

Thanks for the suggestion. I’m only using an Alert here to prove that the JS is working after the Ajax call. I hesitate to try using something more complex when I can’t get the basics to work.

The standard alert dialog box cannot be controlled by JavaScript. When an alert is shown or the user, it cannot be removed any other way than direct action by the user.

This is why you need to look at other modal dialog box solutions, if you want to have more control over things.

Edit:

Oh hang on, perhaps I’ve misread things. Are you trying to have a time-delay on a window.alert message?

Have you looked at my demonstration?
The end result I’m seeking is to close the Success message automatically after (say) ten seconds if the visitor has not done so. That would seem to require some sort of JS/jQuery ‘click’ to be applied to the submit button (or a direct JS submit, I suppose).

But I couldn’t get anything to work in the Success message, which is inserted using an Ajax call. I’m not interested in the ‘Alert’ in the long term. It’s only there to test that JS is working (which it isn’t).

I am surprised that a simple thing like ‘Alert’ isn’t working here. I’m looking for help in working out why. It’s quite possible I’ve made some elementary error, of course.

[quote=“ramasaig, post:5, topic:224091, full:true”]
The end result I’m seeking is to close the Success message automatically after (say) ten seconds if the visitor has not done so.[/quote]

Good, so I am understanding what you require correctly.

The standard browser alert message can only be closed by the user. If you want to close an alert via scripting, you will need to use something else instead, such as a custom modal dialog box.

[quote=“ramasaig, post:5, topic:224091, full:true”]
I am surprised that a simple thing like ‘Alert’ isn’t working here.[/quote]

It is your expectations of what you think that the standard alert can do that is at fault here. The alert cannot be closed by anything but the user. It’s a security precaution, so that the user has to be involved in the process.

so replace it with a console.log call that writes to the console instead and doesn’t create a modal situation that requires your intervention

2 Likes

Thank you for your replies. I don’t seem to be explaining the problem very well here.
Perhaps I’ve caused confusion with an Alert earlier in the process (showing that the Ajax file had loaded), so I’ve removed it.

You can see a demo at: http://holidaymullandiona.com/bb-sw
Click on any of the links ‘Contact the owner’. All messages will be sent to me, NOT to the property concerned, so it doesn’t matter which ‘Contact the owner’ link you click.

When you complete and submit the form you will see the ‘Success Message’. But you won’t see the Alert because for some reason it isn’t working.

The Alert I’m on about is a temporary measure intended to show me that the JS which I want to add to close the Success message is being ‘seen’ by the browser. At present there is no such JS, only the Alert. But the Alert doesn’t happen. It does not appear. It SHOULD be inserted by this snippet from the end of the code in my original post, but although the PHP in that code works perfectly and creates the Success Message the Alert isn’t popping up (though I can see it in Inspector).

NB: The comments in this snippet are NOT in the original, but there to explain
I do not expect the Alert to do anything more than appear and show me that JS will work at this point in the script. But it doesn’t appear, and I’m trying to work out why.

I have a feeling the issue is that you are using ajax with innerHTML.

innerHTML literally means /just/ HTML. If you want to dynamically add javascript that will be picked up and understood by the browser you must use the document object model to sort-of-like “inject” javascript by appending it to the document.

Check this out: http://stackoverflow.com/questions/3248384/document-createelementscript-synchronously

I’m actually working on a similar issue. Let me know if this helped or if I’m also misunderstanding you.

Thank you, wh33t. I’d begun to wonder if innerHTML was the problem, but hoped I was wrong! In normal HTML you can insert ‘script’ tags almost anywhere (though not good practice) so I hoped the same might be true here. But I’m glad to have that possibility confirmed. It makes sense to me. I will follow up the link you gave.
I’ve read a lot on Stackoverflow about binding JS when using Ajax (some of it very hard to follow), but I don’t recall anyone saying ‘you can’t do this in innerHMTL’, which would have been useful.

1 Like

You’re welcome. I’ve literally posted this exact same issue on sitepoint and also had a lot of trouble trying to explain my issue. You’d think innerHTML would work just like you were writing HTML (mixed up with js) and have it work and then it just doesn’t. One of my main issues with JS at the moment, the more I learn about it the more I come to realize it’s such a cumbersome language in the sense that things just don’t really seem to be all that intuitive and straight forward.

I’m working on the exact same issue you are having right now and I think I’m close. If I get it working I’ll post my code in here.

K managed to get it working for my needs I hope this will help you :smiley:

So here is my test.html page, it contains the special code needed to run an ajax connection and then evaluates some javascript after by appending a newly created javascript block to the HEAD (note “code_to_eval”). Also you won’t have a throbber.gif so adjust accordingly.

<html>
<head>
<script>
function ajax_then_eval(div,url,method,code_to_eval)
{
  var ajax=new XMLHttpRequest();
  
  ajax.onreadystatechange=function() 
  {
    if (ajax.readyState==4 && ajax.status==200) 
    {
      /* //The original
      var n = document.createElement("div");
      n.innerHTML = ajax.responseText;
      document.getElementById(div).appendChild(n);
      */
      
      //Clear the throbber gif
      document.getElementById(div).innerHTML = '';
      
      var n = document.createElement("div");
      n.innerHTML = ajax.responseText;
      document.getElementById(div).appendChild(n);
      
      var head = document.getElementsByTagName('head').item(0);
      var script = document.createElement('script');
      script.setAttribute('type', 'text/javascript');
      script.text = code_to_eval;
      head.appendChild(script);
    }
    else
    {
      document.getElementById(div).innerHTML='<img src="/_css/_defaults/throbber.gif" />';
    }
  }
  ajax.open(method,url,true);
  ajax.send();
}


function test_function()
{
  document.getElementById('ajax_loaded_div').innerHTML = 'test function ran correctly';
}
</script>
</head>
<body>

<div id="the_div"></div>

<script>
ajax_then_eval('the_div','test2.html',"GET",'test_function();');
</script>

</body>
</html>

And here is test2.html

<div onclick="test_function()">Some text in here</div>

<div id="ajax_loaded_div"></div>

As you can see ajax loads test2.html which contains a new DIV with the id of “ajax_loaded_div” and then it runs the code_to_eval which changes it’s output by running test_function();

Hope that helps man! I’ve been struggling with this issue forever! It feels good to get it finally understood.

Thanks Wh33t. It’s always comforting to know someone else has the same problem and that one isn’t making some really crass mistake.

I’ve run your code and it loads ‘test2.html’ with the ‘test function ran correctly’ message, as you’d expect. I’ll take a proper look at it later and I’ll be in touch to let you know how I get on integrating it with mine. It may be a day or two.

I hope I’ve cracked it now, including my original aim of closing the success message automatically after a delay if not closed by the visitor.
Here’s a description of what I’ve done, in the hope it may help others:

Background: The content of my ‘innerHTML’ varies; it’s either the e-mail form for the visitor to complete or it’s the Success Message (if there are errors the form is re-displayed). This is achieved by the usual PHP method of checking whether the form has been submitted. I can tell which by testing for the text on the submit button (I’m sure there would be other ways too). For a fuller explanation see the original post.

Problem: Tacking Javascript or jQuery onto the PHP/HTML being sent to ‘innerHTML’ doesn’t work. It fails silently.

My solution: If the test shows the innerHTML contains the Success Message I append the necessary JS to the surrounding element, using the usual ‘createElement’, ‘appendChild’ procedure. The lines of JS code are just treated as text nodes (be sure to include the necessary ‘;’ in the text node). The function that clicks the submit button of the Success Message is in a separate file (with the Ajax fnctions), all that’s needed with the Success Message is a call to that function.

All surprisingly easy (if a little tedious) once I understood that JS can’t be added directly to ‘innerHTML’.

The code to add stuff to the Success message is:

if (document.getElementById('sub2')) { // test for content of innerHTML
   var cf = document.getElementById('contactform');
   var script = document.createElement('script');
   //var text = document.createTextNode("alert ('success message '); ");
   //script.appendChild(text);

   var doclick = document.createTextNode("closeMessage()");
   script.appendChild(doclick);

   cf.appendChild(script);
  }

This code is placed in the Ajax script
Note the Alert for debugging purposes, commented out

The code for clicking the Submit button of the Success Message is:

 function closeMessage() {
   //alert ('closeMessage fn called');
   setTimeout(function() {
       if (typeof sub2 !== 'undefined') {
          sub2.click();
       }
   }, 5000);
 }

Note that ‘sub2’ may no longer exist if the visitor has closed the message

1 Like

Nice! Sounds like you got it working?

And indeed, completely counter-intuitive solution yet very easy to implement once the issue is understood.

Yes, it’s all working as intended. Thanks, wh33t for your help and encouragement. I hope you solve your problem too.

I think what’s counter-intuitive is that you can’t put JS directly into innerHTML (well, you can, of course, but it doesn’t work and fails silently), It doesn’t help that one can see the JS in Inspector when you do! If I’d known that from the outset I’ve have saved a lot of time.

Having identified the problem I did discover there are some work-arounds (like using ‘eval()’) but in general I felt they were more complicated to implement than my eventual solution.

Some will say “the clue’s in the name ‘innerHTML’”, but I’d say it’s only obvious when you know.

This topic was automatically closed 91 days after the last reply. New replies are no longer allowed.