experts only: alert changes a variabele!!!

Discussion in 'JavaScript' started by EddyInTheSky, Feb 27, 2008.

  1. #1
    Something very strange happens here (only under IE):
    "
    alert("Are there any errors? -> " + errors); //--> gives false
    alert("And now? -> " + errors); //--> gives true
    "

    here is the complete code:

    <html>
    <head>
    <title>I hate IE</title>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
    </head>
    <body>
    <SCRIPT LANGUAGE="JavaScript">
    <!--
    var errors = false;

    function required(HTMLInputElement, message) {
    removeError(HTMLInputElement,message);
    if(!HTMLInputElement.value)
    createError(HTMLInputElement,message);
    }

    function createError(HTMLInputElement, errorMessage){
    if(!errors)
    errors = true;

    var errorMessage = document.createTextNode(errorMessage);
    var divObj = document.createElement("DIV");
    divObj.className = "formErrorLine";
    divObj.appendChild(errorMessage);

    try{
    divObj.attributes["id"] = "errorMessage";
    }catch(e){}

    try{
    divObj.attributes["id"].value = "errorMessage";
    }catch(e){}

    HTMLInputElement.parentNode.parentNode.parentNode.insertBefore(divObj, HTMLInputElement.parentNode.parentNode.nextSibling);
    }

    function removeError(HTMLInputElement, errorMessage){
    if(HTMLInputElement.parentNode.parentNode.nextSibling.nodeType == '1' && HTMLInputElement.parentNode.parentNode.nextSibling.firstChild.data == errorMessage){
    HTMLInputElement.parentNode.parentNode.nextSibling.parentNode.removeChild(HTMLInputElement.parentNod e.parentNode.nextSibling);
    }
    }

    function validateForm(){
    errors = false;
    validateHTMLInputElements();

    /* normally, this would be the last line of this function:
    return (!errors);
    */

    //these alerts are here to show the problem:
    alert("Are there any errors? -> " + errors);
    alert("And now? -> " + errors);


    return false;
    }

    function validateHTMLInputElements(){
    var HTMLInputElements = document.getElementsByTagName("input");
    for(i=0; i < HTMLInputElements.length; i++){
    try {
    var type = HTMLInputElements.attributes["type"].value;
    HTMLInputElements.focus();
    }catch(e){}
    }
    }
    // -->
    </SCRIPT>

    <form name="register" method="post" onSubmit="return validateForm()" >
    <div class='formLine'>
    <div class='formLabelHeader'><label for="f_name">First name: </label></div>
    <div class='formElementHeader'><input type="text" name="f_name" onblur="required(this,'please fill in your first name!'); "></div>
    </div>
    <div class='formLine'>
    <div class='formElementHeader'><input type="submit" class="button" value="REGISTER" ></div>
    </div>
    </form>
    </body>
    </html>

    To get the 'error', just open the page and push register.
    Please help me find a solution without having to use the alert() function.
     

    Attached Files:

    • test.zip
      File size:
      1,011 bytes
      Views:
      82
    EddyInTheSky, Feb 27, 2008 IP
  2. MMJ

    MMJ Guest

    Messages:
    460
    Likes Received:
    12
    Best Answers:
    0
    Trophy Points:
    0
    #2
    Why are you using try...catch so much?
     
    MMJ, Feb 27, 2008 IP
  3. EddyInTheSky

    EddyInTheSky Peon

    Messages:
    5
    Likes Received:
    0
    Best Answers:
    0
    Trophy Points:
    0
    #3
    try{
    divObj.attributes["id"] = "errorMessage";
    }catch(e){}
    
    try{
    divObj.attributes["id"].value = "errorMessage";
    }catch(e){}
    
    Code (markup):
    the first try works with some browsers like Opera & Mozilla,
    the second try works with I.E.
    I use it because I'm to lazy to use:

    if(browser == Mozilla OR browser == Opera OR ....){
      divObj.attributes["id"] = "errorMessage";
    }
    else{
      if (browser == I.E. OR ...){
        divObj.attributes["id"].value = "errorMessage";
      }
      else {
         if(couldn't detect which browser you are using){
           try{
             divObj.attributes["id"] = "errorMessage";
           }catch(e){}
           try{
             divObj.attributes["id"].value = "errorMessage";
           }catch(e){}
         }
      }
    }
    Code (markup):
     
    EddyInTheSky, Feb 27, 2008 IP
  4. LogicFlux

    LogicFlux Peon

    Messages:
    2,925
    Likes Received:
    102
    Best Answers:
    0
    Trophy Points:
    0
    #4
    The error is being created on the blur event from the required() function (actually from its call to createError). Apparently the first alert is being executed before the event either fires or is handled by the required() function. But when you hit the submit button, the text field is blurred, so it triggers that event and hence the required() function.
     
    LogicFlux, Feb 27, 2008 IP
  5. EddyInTheSky

    EddyInTheSky Peon

    Messages:
    5
    Likes Received:
    0
    Best Answers:
    0
    Trophy Points:
    0
    #5
    I'm don't know if you just gave me an answer or just asked me a question. But from what I understand, you are completely correct.

    On the f_name input element is the onBlur trigger (which triggers required() on that element, which creates a DIV with errorText and puts errors on true if needed).

    On the form itself is the onSubmit trigger (which triggers validateForm(), which puts variable errors on false, then just activates the onblur function on each input element by doing focus() and ending with the button, where it focusses last, and then it should return the opposite value of variable errors. This return value determines wheter the form is submitted or not)

    Originaly, instead of working with the variabele errors, the validateForm() triggered all onblurs and then looked whether there was an element with ID = errorMessage.

    This didn't work in IE as well, because of the same reason as it isn't working now.
    Meaning that if I would have done: alert(""); before doing document.getElementByID("errorMessage");
    it would have worked as well in internet explorer. (I didn't knew that this would 'solve' the problem at that time though)

    After that I tried it with looking for all DIV's with classname = formErrorLine
    which also worked perfect on all browsers except for I.E., and then I noticed that when I took all DIV elements into a NodeList, IE didn't include the recently generated errormessage-DIV's. (Doing an empty alert again before retrieving these elements would have been a workaround there again, giving me an unwanted alert, but a working code)

    Now I just made it clearer to understand the problem, but heck, it still blows my mind that I have to do an unwanted alert in order to make it work.

    The best workaround I've found so far was this:
    if(browser == IE)
    alert('please download firefox');

    ;) but since I'm trying to make some professional site, I can't afford this message.

    *while writing all of this, I suddenly realise your point:*

    Obviously, you are right that, in IE, the events attached to an input are activited to late. And since the only way in Javascript to let the code sleep for real is by sending some alert or other kind of message box... I will not be able to use .focus() for IE.

    Which means I'm now looking for a way to activate the onblur function directly, and since I'm not at work now, It will be for tomorow.

    Anyways, I was really stuck on this since I'm used to program in OO languages, where this behavior is not normal. So thank you very, VERY much! You are a true javascript expert :)
     
    EddyInTheSky, Feb 27, 2008 IP
  6. Alfie87

    Alfie87 Peon

    Messages:
    40
    Likes Received:
    0
    Best Answers:
    0
    Trophy Points:
    0
    #6
    Try, not necessary maybe an other one but I'm not a professional I'm still learning it
     
    Alfie87, Feb 27, 2008 IP
  7. EddyInTheSky

    EddyInTheSky Peon

    Messages:
    5
    Likes Received:
    0
    Best Answers:
    0
    Trophy Points:
    0
    #7
    Thanks alot LogicFlux :D, I solved it by using:

    function validateForm(){
      errors = false;
      validateHTMLInputElements();
      return (!errors);
    }
    
    function validateHTMLInputElements(){
      var HTMLInputElements = document.getElementsByTagName("input");
      for(i=0; i < HTMLInputElements.length; i++){
        try {
          if(HTMLInputElements[i].attributes["onblur"].value && !(HTMLInputElements[i].attributes["onblur"].value == 'null')){
            var start = HTMLInputElements[i].attributes["onblur"].value.indexOf('(');
            var end = HTMLInputElements[i].attributes["onblur"].value.indexOf(',');
            var code = HTMLInputElements[i].attributes["onblur"].value.substring(0,start + 1)+"HTMLInputElements[i]"+HTMLInputElements[i].attributes["onblur"].value.substring(end);
            eval(code);
          }
        }catch(e){}
      }
    }
    Code (markup):
    It works like a charm, and I don't need to rewrite the code again to validate the form as a whole. Looks a little bit complex, but I just steal the code from the onblur attribute, and reuse it directly... (instead of activating the onblur event).
    So, once again, thanks alot, It took about 100 people to view it (also on other forums) before I got this decent reply from you. :cool:
     
    EddyInTheSky, Feb 28, 2008 IP
  8. lephron

    lephron Active Member

    Messages:
    204
    Likes Received:
    2
    Best Answers:
    0
    Trophy Points:
    53
    #8
    Is horrible!!! Why not:

    if(divObj.attributes["id"].value) divObj.attributes["id"].value = "errorMessage"
    else divObj.attributes["id"] = "errorMessage"

    ?
     
    lephron, Mar 2, 2008 IP
  9. MMJ

    MMJ Guest

    Messages:
    460
    Likes Received:
    12
    Best Answers:
    0
    Trophy Points:
    0
    #9
    Yup.

    Or: divObj.setAttribute("id", "errorMessage");
     
    MMJ, Mar 4, 2008 IP
  10. EddyInTheSky

    EddyInTheSky Peon

    Messages:
    5
    Likes Received:
    0
    Best Answers:
    0
    Trophy Points:
    0
    #10
    I knew it was a dirty trick to use try() catch there, but heck, didn't feel like looking any further to make it work on a 'clean' way. Thanks for the good hint there MMJ, it's realy nice to put that try catch away and replace it with this one line (even though I no longer need to set this attribute since I no longer detect errors using getElementById() ):
    divObj.setAttribute("id", "errorMessage");
     
    EddyInTheSky, Mar 11, 2008 IP