AGH that was annoying...After typing this whole thing I went to register with Google+ and now I have to type it all again...anyways...

I have a registration page on a CMS that I'm building. The first step in attempting to register is to enter an email address. Once it's entered, the email address is sent through ajax and checked against the database. If the email address isn't already used, ajax returns text back to the page saying, essentially "all good". If the email address IS already in use, ajax sends text back to the page, essentially saing "not so good".

Here's the page's code:

<script>
function checkEmail(str)
{
     if(str == "") {
          document.getElementById("emailresult").innerHTML = "";
     return;
     } 

     if(window.XMLHttpRequest) {
          xmlhttp = new XMLHttpRequest();
     } else {
          xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
     }

     xmlhttp.onreadystatechange = function()
     {
          if(xmlhttp.readyState == 4) {
               document.getElementById("emailresult").innerHTML = xmlhttp.responseText;
          } else {
               document.getElementById("emailresult").innerHTML = xmlhttp.status;
          } 
     }

     xmlhttp.open("GET","inc/ajax.php?checkemail=" + str, true);
     xmlhttp.send();
}
</script>

<h3>Register for a new account</h3><br /><br />

<div style="border: 1px solid black; padding: 6px;">
<?php echo stripslashes($glo['reg_details']) ?>
</div><br /><br />

<form method="POST" action="">
<b>Please enter your Email Address</b><br />
<input type="email" name="emailaddress" size="45" required="required" placeholder="Enter a valid Email Address" onblur="checkEmail(this.value)" /><br /><br />

<div id="emailresult"></div><br /><hr /><br />

...and here's the processing page (just the stuff you need)...

if($_GET['checkemail']) {
     $eml = $dba2->query_first("SELECT id FROM tbl_users WHERE email_address = '$_GET[checkemail]'");
     if($dba2->affected_rows > 0) {
          echo '<font style="color: red">This email address is already registered in the database.</font>';
     } else {
          echo '<font style="color: green">Email Address is Good!</font>';
     }
}

Now what I have always been a bit lost on is how to run javascript IN ajax. What I want to do is this: When the query finds that the email address is unused "all good", to not only display the text, but to also open up the rest of the form for filling out (I haven't included the rest of the form above, but it'll be in a div with display="none"). This will require javascript to run, and for the likes of me I haven't found a good solution to this that works all the time. I've heard eval() is good, but I've also hear that it's bad...any help would be appreciated. Please include your suggestion in the code itself so I can see where it goes and how it functions. That way I'll remember it forever.

I sort of gleaned a result from several websites and pasted it together as the following:

First create a function (in my case I created a separate js file) in the <head> of the site that looks like the following:

function parseScript(strcode)
{
     var scripts = new Array();         // Array which will store the script's code

     // Strip out tags
     while(strcode.indexOf("<script") > -1 || strcode.indexOf("</script") > -1) {
          var s = strcode.indexOf("<script");
          var s_e = strcode.indexOf(">", s);
          var e = strcode.indexOf("</script", s);
          var e_e = strcode.indexOf(">", e);

          // Add to scripts array
          scripts.push(strcode.substring(s_e+1, e));
          // Strip from strcode
          strcode = strcode.substring(0, s) + strcode.substring(e_e+1);
     }

     // Loop through every script collected and eval it
     for(var i=0; i<scripts.length; i++) {
          try {
               eval(scripts[i]);
          }
          catch(ex) {
               // do what you want here when a script fails
          }
     }
}

Either put the function right in the <head> of the page or create a separate file and load it in the <head> (or anywhere really)

Then, in the processing file, enter your javascript, whatever it might be, as you normally would. In my case I simply changed display="none" to display="block" on a separate div if the email address is unused.

Finally, in the actually ajax script, change this section to the following:

xmlhttp.onreadystatechange = function()
     {
          if(xmlhttp.readyState == 4) {
               var res = xmlhttp.responseText; // just to make things easier
               parseScript(res);  // run the function with all the data returned by ajax
               document.getElementById("emailresult").innerHTML = xmlhttp.responseText;  // you could just use the 'res' variable here too but I was being lazy
          } else {
               document.getElementById("emailresult").innerHTML = xmlhttp.status;
          } 
     }

And that's it! Now you have a function that you can use over and over without any major code changes in the ajax. It DOES add a split second to my script when it changes the div's display status, but that's it. It may take longer on bigger scripts needing to be parsed by the function.

It should seldom (never?) be necessary to serve "executable code" as text as you have indicated. There are much better ways to serve javascript onto a page.

Your first design choice should be to hard code your client-side script(s) and serve them in the web page between '<script></script>' tags or as an external script '<script src="..."></script>' . Thus, you need to do something as simple as :

xmlhttp.onreadystatechange = function(responseText) {
    processValidatedEmail(str, responseText);
}

where processValidatedEmail was served with the page and contains all the logic for testing responseText (and branching appropriately).

Another approach is to dynamically insert a <script> node into the DOM and to set its src attribute to pull in an external script. This is not generally necessary for the provision of conventionally executable code (ie. functions) as such but is highly desirable as a means of circumventing cross-domaion limitations in the browser security model, to serve data in the form of a script. In that case, you need to do something called "JSONP". But please note that as of very recently (the last year or so), JSON is not always necessary in the cross-domain scenario. (I won't go into detail here as JSONP and the other mechanism are both well documented on the web, plus I don't think either applies to this question).

To summarise, the general rules are :

  • if everythig necessary for your web page is provided from the same domain (pragmatically speaking, from the server which served the web page itself), then don't do anything fancy - serve all the necessary functions with the page, even though some of them may not be called.
  • if you are in a cross-domain situation, the consider JSONP for serving/obtaining data but not executable code as such.
Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.