简体   繁体   中英

Javascript alert messages in infinite loop

Alert boxes in infinite loop, here I am trying to put a popup alert message on 2 consecutive fields so they cannot be left blank, I know why it is happening - because when onblur event of 1st function is launched it gives focus to second one & when it jumps back to first one onblur of 2nd textfield is launched.

I know validation would be best when done at the form level, but this is the requirement I got.

Any help?

Javascript code

function x()
{
   if( document.getElementById("1").value.length==0)
   {
      alert('1 is required');
      document.getElementById("1").focus();
   }
}

function y()
{
   if(document.getElementById("2").value.length==0)
   {
      alert('2 is required');
      document.getElementById("2").focus();
   }
}

HTML code

<input type="text" name="City Name" id="1" onblur="javascript:x();">
<input type="text" name="Kitty Name" id="2" onblur="javascript:y();">

Instead of handling it in onblur() event, you can handle it in onchange() event.

If you still want to use onblur() , then use the focus inside setTimeout as shown below.

alert('2 is required');
setTimeout(function() { document.getElementById("2").focus(); }, 100); 

There is a fundamental problem when trying to refocus on a field on an onblur when it is invalid. If the user decides to navigate away, the simply can't. When they click away from the field, they are forcibly taken back. I have seen instances where a user is forced to kill their browser session, just to escape an over-zealous onblur validation.

I realise this might not be the exact solution you are after, but can I recommend another approach that still involves client-side validation.

I recommend you highlight the field as being invalid in some way on the onblur . Eg put a star next to it, highlight it red, etc. This way you can dispense with the alert and user still has control.

When the user comes to submit the form, you perform your client-side checks and display alert to them then (see @Phill Sacre's answer)

My suggestion: consolidate your validation into one method, and check each sequentially in it.

So (pseudo-code):

function validate() {
     for (field in fieldlist) {
         if (document.getElementById(field).value.length == 0) {
              displayerror();
              document.getElementById(field).focus();
         }
     }
}

This way you will only ever display one error at a time.

If you modify your code like this. It can be solved.

<html>
<head>
<title>break alert infinite loop </title>
<script>
var e = function( _id ){
    return document.getElementById(_id);
};
window.onload = function(){
    e("test").onblur = function(){
        if( e("test").value != "11" ){
            Msg("Number[11] is only allow");
            e("test").focus();
        }
    };
};

/* fix start */
var beforeMsg = "";
/* fix end */

function Msg( msg ){
    /* fix start */
    if( msg == beforeMsg ){
        return;
    }
    beforeMsg = msg;
    /* fix end */

    alert(msg);

    /* fix start */
    setTimeout(function(){
        beforeMsg = "";
    },1000);
    /* fix end */
}

</script>
</head>
<body>
    <p>only 11 is allow</p>
    <input type="text" id="test"/>
</body>
</html>

other code

common.js

if( window.COMMON_JS == undefined ){
    window.COMMON_JS = "common.js ver:1.0.0.1";

    window.AletMessage = "";
    MessageAlert = function( msg ){
        if( window.AletMessage == msg  ){
            return;
        }
        window.AletMessage = msg;
        alert(msg);
        setTimeout(function(){
            window.AletMessage = "";    
        },1000);
    };
}

test.html

<html>
<head>
<script type="text/javascript" src="common.js"></script>
<script>
var e = function( _id ){
    return document.getElementById(_id);
};
window.onload = function(){
    e("test").onblur = function(){
        if( e("test").value != "11" ){
            MessageAlert("Number[11] is only allow");
            e("test").focus();
        }
    };
};
</script>
</head>
<body>
    <p>Only 11 allowed.</p>
    <input type="text" id="test"/>
</body>
</html>

I have one JS and have one function which is called onblur event of textbox and onblur that event is in Infinite loop.

After that, I have declared one global variable (On the top of JS and outside the function Var Isvalid = true; )

In function, Performing validation code.

if (IsValid == true)
{   
    if validation is false.
    giving alert message.
    and updating the IsValid = false;
}

If the validation is true then updating the global variable. Isvalid = true;

In second recursion it will not execute the loop. If in next phase if blur event occurred then variable automatically set to True .

Try Below Js Code. It will solve your problem.

function x()
{
   if( document.getElementById("1").value.length==0)
   {
      if(alert('1 is required')){
          document.getElementById("1").focus();
      }
      else
          document.activeElement.blur();
   }
}


function y()
{
   if(document.getElementById("2").value.length==0)
   {
      if(alert('2 is required')){
           document.getElementById("2").focus();
      }
      else
          document.activeElement.blur();
   }
}

With the use of timeouts you can disable the onBlur event on the "target" element and go back to the source element. This works in IE.

function focusWithoutEvents(object) {
    // Small timeout so that the active element will be the "next" element
    setTimeout(function() {
        var activeElement = document.activeElement;

        // Save the current onblur()
        var activeOnblur = activeElement.onblur;

        // Disable the onblur event
        activeElement.onblur = null;

        // Now we can focus without triggering onblur event
        object.focus();

        // With a small delay, put back the onblur code.
        setTimeout(function() {
            activeElement.onblur = activeOnblur
        }, 100);
    }, 100);
}

My recommendation is to temporarily disable the blur handler during the execution of the other input's handler.

I've also replaced your HTML onblur with a proper Javascript solution, removed the blank lines and added code indentation.

I've also changed the element IDs, which are not allowed to start with numbers; your script would not have worked at all on compliant browsers.

<html>
<body>

<script type="text/javascript">
window.onload = function() {
   document.getElementById("input1").onblur = x;
   document.getElementById("input2").onblur = y;
};

function x() {
   if (document.getElementById("input1").value.length == 0) {
     alert('1 is required');

     // temporarily disable binding
     document.getElementById("input2").onblur = function() {};

     document.getElementById("input1").focus();

     // re-bind
     document.getElementById("input2").onblur = y;
   }
}

function y() {
   if (document.getElementById("input2").value.length == 0) {
     alert('2 is required');

     // temporarily disable binding
     document.getElementById("input1").onblur = function() {};

     document.getElementById("input2").focus();

     // re-bind
     document.getElementById("input1").onblur = x;
   }
}
</script>

<input type="text" name="City Name" id="input1" onblur="javascript:x();">
<input type="text" name="Kitty Name" id="input2" onblur="javascript:y();">

</body>
</html>

Now, this script is rather verbose and carries a lot of code duplication. But in the interests of staying on-topic, I'll leave further improvements for another day.

I would also suggest not doing this at all; as James said, it's irritating .

My be you have to change your way of comparison from

document.getElementById("1").value.length==0

to

document.getElementById("1").value != ''

it seems to me that length is always not equal zero

Try this

<html>
    <head>
    <script>

function x() {
   if (document.getElementById("input1").value.length == 0 ) {
     alert('1 is required');
     document.getElementById("input1").focus();

   }
   else  if (document.getElementById("input2").value.length == 0 ) {
     alert('2 is required');
     document.getElementById("input2").focus(); 
   }

}

</script>
    </head>
    <body >
    cityname:
    <input type="text" name="City Name" id="input1" onblur="javascript:x();">
    <br/>
    KittyName:
<input type="text" name="Kitty Name" id="input2" onblur="javascript:x();">

    </body>
</html>

Here is my solution:

function x()
{
   if( document.getElementById("1").value.length==0)
   {
      alert('1 is required');
      document.getElementById("1").focus();
      return false;
   }
   return true
}

function y()
{
   if(x() && document.getElementById("2").value.length==0)
   {
      alert('2 is required');
      document.getElementById("2").focus();
   }
}

So, if 1 is required, the y function won't be evaluated

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM