another newbie question - onblur / focus

Discussion in 'Javascript' started by please-answer-here, Jun 4, 2005.

  1. What is wrong with this code?

    When I only assign the onblur call to one of the input fields everythings
    work, but when I as belove use it on both fields I'll get an endless loop
    with the alert messages repeating/replacing each other. I'll guess that the
    problem/error must be somewhere in the focus expression but where is it?

    ******************* code ******************
    <html>
    <head>
    <title>Test1</title>

    <script>
    function needed(fieldid) {
    var form = document.form1;
    if (fieldid.value.length == 0) {
    alert('Field must not be empty '+ fieldid.name);
    form.elements[fieldid.name].focus();
    }
    }
    </script>

    </head>
    <body>
    <form name="form1" action="cgi.asp" method="Post">
    <input name="field1" type="text" onblur="needed(this) ">
    <input name="field2" type="text" onblur="needed(this) ">
    <input type="submit" name="sendit" value="push me">
    </form>
    </body>
    </html>
    ****************** code ******************
     
    please-answer-here, Jun 4, 2005
    #1
    1. Advertisements

  2. It is well-known that using validation code in onblur handlers that
    calls alert can trigger an endless loop of focus/blur events and thus
    you should not use that. If you want to validate use the onsubmit
    handler of the <form> element or if you really see a need to validate
    each control after the user has input something then use the onchange
    handler.
     
    Martin Honnen, Jun 4, 2005
    #2
    1. Advertisements

  3. please-answer-here wrote:
    In the long run validating your HTML will save you many headaches while
    trying to script the resulting DOM. For valid HTML 4 a SCRIPT element
    requires a TYPE attribute.
    Using the 'shortcut' property accessor - document.form1 -, while
    practical and generally successful in HTML DOM implementations, is a bad
    habit. The shortcuts are not necessarily available in XHTML DOMs, and
    are often taken as implying that all sorts of non-form elements will be
    available as named properties of the - document - object, while that
    type of shortcut is quite inconstantly implemented.

    Given a need to reference a form in a document by name or ID the W3C
    HTML DOM standardised/formalised - document.forms - collection is the
    place to make such a reference (not the document itself).

    As the 'fieldid' parameter contains a reference to a form control a
    reference to a containing form object is available as a property of the
    form control called 'form' (I.E.:- var form = fieldid.form; -). This
    allows the form object to be referenced anonymously, and so the writing
    of more general code.
    Think about what this line of code is doing. You are passed a reference
    to the form control as the misnamed 'fieldid' parameter (misnamed
    because an ID would be expected to be a string value not an object
    reference). You then read the - name - properly of the object referred
    to by - fieldid - and use that name value to look-up a reference to a
    form control in the form's - elements - collection. If that operation is
    successful (as calling a focus method on the result must
    (optimistically) assume) the result would be a form control with a -
    name - property that corresponds with the - name - property of the form
    control passed as a parameter. That is; the result of -
    form.elements[fieldid.name] - must be a reference to the _same_ form
    control that - fieldid - refers to (unless multiple controls share the
    same name, in which case the result of - form.elements[fieldid.name] -
    is a collection and the script errors when the collection's
    non-existent - focus - method is called).
    <snip>

    A blur event is fired when another element gains focus (or it leave the
    document entirely). even when an onblur handler tries to focus another
    element the element to which focus was being transferred, to trigger the
    initial blur event, will be focused, and so the scripted transfer of
    focus will trigger an onblur handler in that second element. Validating
    onblur is strongly discouraged because it has a strong tendency to
    produce this type of looping.

    Richard.
     
    Richard Cornford, Jun 4, 2005
    #3
  4. Thanks for the information which for me as a newbie wasn't "well-known". If
    I somehow want's to hold on to the logic which is that the user should be
    informed on the error when leaving the field is there any options at all.
    The onchange event I'll guess would not not trigger when leaving an
    initially empty field.
     
    please-answer-here, Jun 4, 2005
    #4
  5. If I understand you right it is wrong to use fieldid.name in the
    elements.[] reference. But how can I pas it as a string?

    You then read the - name - properly of the object referred to by - fieldid -
    and use that name value to look-up a
    reference to a form control in the form's - elements - collection. If that
    operation is successful the result would be a form control
    with a - name - property that corresponds with the - name - property of the
    form control passed as a parameter.

    I've read the above statement several times without fully grasping the
    essense. Could you by chance explain this in a another way which makes
    better understanding to a newbie in javascript/html .

    Thanks for this very deep and informative information.Nice to see things
    explained a litte "deeper" than those "intro/teach yourself" etc. books I've
    stumpled upon.

    So if I wan't to test the validity/nonemptiness of input fields before
    submitting the entire form do I have any options at all.
     
    please-answer-here, Jun 4, 2005
    #5
  6. It is correct that onchange is not fired when the user enters and leaves
    a field that is empty.
    If you insist on using onblur then you can of course in modern browsers
    dynamically create and insert the validation error message directly in
    the HTML document itself, next to the field, here is a simple example to
    outline how that could work:

    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
    "http://www.w3.org/TR/html4/strict.dtd">
    <html lang="en">
    <head>
    <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
    <title>inline validation messages</title>
    <style type="text/css">
    span.validationError {
    color: red;
    font-weight: bold;
    }
    </style>
    <script type="text/javascript">
    function setInnerText (element, text) {
    if (typeof element.innerText != 'undefined') {
    element.innerText = text;
    }
    else if (element.hasChildNodes && element.appendChild) {
    while (element.hasChildNodes()) {
    element.removeChild(element.lastChild);
    }
    element.appendChild(document.createTextNode(text));
    }
    }

    function createErrorMessage (control, message) {
    var errorElement = control.errorElement;
    if (!errorElement && document.createElement) {
    errorElement = document.createElement('span');
    errorElement.className = 'validationError';
    control.parentNode.appendChild(errorElement, control.nextSibling);
    control.errorElement = errorElement;
    }
    if (errorElement) {
    setInnerText(errorElement, message);
    }
    }

    function checkError (control) {
    if (control.value == '') {
    createErrorMessage(control, 'You need to enter a value here.');
    }
    }

    function clearError (control) {
    if (control.errorElement) {
    setInnerText(control.errorElement, '');
    }
    }
    </script>
    <script type="text/javascript">
    function output (tagName, text) {
    var element = document.createElement(tagName);
    element.appendChild(document.createTextNode(text));
    document.body.appendChild(element);
    }
    </script>
    </head>
    <body>

    <form action="whatever.asp">
    <div>
    <label>
    field 1
    <input type="text" name="field1"
    onfocus="clearError(this);"
    onblur="checkError(this);">
    </label>
    </div>
    <div>
    <label>
    field 2
    <input type="text" name="field2"
    onfocus="clearError(this);"
    onblur="checkError(this);">
    </label>
    </div>
    <div>
    <input type="submit">
    </div>
    </form>

    </body>
    </html>
     
    Martin Honnen, Jun 4, 2005
    #6
  7. In that particular sentence, Richard is just referring to the name of
    the identifier, fieldid. Identifiers should be meaningful and help make
    code easier to understand. It is clear that fieldid doesn't contain the
    id of a field, but a reference, therefore field would be more appropriate.
    You don't need to, as the next part of Richard's post said.

    [snipped somewhat obscure explanation :p]
    The reason you were trying:

    form.elements[fieldid.name]

    was to get a reference to a field so you could call its focus method.
    However, fieldid /is/ a reference to that field, so it's a waste of
    time. Instead, use:

    if(field.focus) {
    field.focus();
    }

    assuming the identifier change fieldid->field suggested above.

    [snip]
    If you want to validate form controls prior to the submit event, you can
    use the change event. This is preferable not only because it can't form
    never ending loops, but that it only fires when a value is changed so
    users won't be bugged constantly.

    Mike
     
    Michael Winter, Jun 4, 2005
    #7
  8. Point taken. Actually the "error" is mainly due to a quick translation from
    danish.
    Oooh that makes sense
    Point taken, but still leaves me with the problem about how to test for
    whether a user left an initially blank field blank. I will take a deeper
    look at Martin Honnens suggestions if its the only way to do it.
     
    please-answer-here, Jun 4, 2005
    #8
  9. On 04/06/2005 17:08, please-answer-here wrote:

    [MW: Using the change event]
    There's no reason why you can't combine per-field validation with
    validation of the entire form. With the latter, you can perform a sanity
    check for all input.

    Of course, if you're validating server-side too (and I hope you are),
    then client-side validation is just a convenience and not something to
    get too worried about.

    Mike
     
    Michael Winter, Jun 4, 2005
    #9
  10. please-answer-here

    RobG Guest

    Don't get too hung up on validation. If the user never puts focus on
    the empty field, onblur wont run either.

    A user may not want to fill in that field just yet, or may wish to
    leave it for a moment to do something else. Constant alerts annoy the
    hell out of people, the form only needs to be valid when submitted, not
    before.

    Offer good on-screen assistance so users know what's needed, put
    warnings in the HTML rather than alerts and do a final validation on
    submit - remembering that none of your client-side validation will have
    run for users with JavaScript disabled (or a JS-less UA).
     
    RobG, Jun 5, 2005
    #10
    1. Advertisements

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments (here). After that, you can post your question and our members will help you out.