Understanding WCAG 2.0

Skip to Content (Press Enter)

SCR32: Kliens-oldali validálás és hibaüzenet hozzáadása a DOM-on keresztül

Alkalmazás

HTML-el vagy XHTML-el alkalmazott szkript.

Ez a technika az alábbiakra vonatkozik:

Leírás

A technika célja az, hogy az űrlapmező kliens-oldali hitelesítésének hibája esetén egy hibaüzenet kerüljön megjelenítésre. A listában megjelenő hibaüzenet esetében a szerkesztő egy horgony elemmel helyezheti el azt a hitelesítendő mező felé. A horgony elemek a hibaüzenettel együtt alkalmazhatók és így a fókusz, figyelem felhívás céljából, a hiba üzenet(ek)re helyezhető. A horgony elem href attribútuma egy lapon belülre mutató hivatkozást tartalmaz, amely a hibás mezőre mutat.

Egy olyan aktivált alkalmazásban, amelyben a JavaScript kikapcsolásra került, nem működik a kliens-oldali hitelesítés. Ennek megfelelően ez a technika csak akkor hatékony, ha a szkriptelés a megfelelőségen alapszik, vagy a szerver-oldali hitelesítés a hibák felfedésére és azok jelzésére is szolgál.

Példák

1. példa

Az alábbi példa bizonyos mezők hitelesítését, illetve bizonyos speciális formátumot igénylő mezők hitelesítését tartalmazza. Hiba előfordulása esetén a szkript hibaüzenetek sorát illeszti be a DOM-ba és a rájuk irányítja a fókuszt.

Screenshot showing the error messages for several fields that were not filled out correctly. Error messages appear as a list of links near the top of the form.

HTML és Javascript kód.

A példa űrlap HTML kódja:

Példa kód:


<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
    <head>
        <title>Form Validation</title>
        <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
        <link href="css/validate.css" rel="stylesheet" type="text/css"/>
        <script type="text/javascript" src="scripts/validate.js"/>
    </head>
    <body>
        <h1>Form Validation</h1>
        <p>The following form is validated before being submitted if scripting is available,
            otherwise the form is validated on the server. All fields are required, except those
            marked optional. If errors are found in the submission, the form is cancelled and 
            a list of errors is displayed at the top of the form.</p>
        <p> Please enter your details below. </p>
        <h2>Validating Form</h2>
        <form id="personalform" method="post" action="index.php">
            <div class="validationerrors"/>
            <fieldset>
                <legend>Personal Details</legend>
                <p>
                    <label for="forename">Please enter your forename</label>
                    <input type="text" size="20" name="forename" id="forename" class="string"
                        value=""/>
                </p>
                <p>
                    <label for="age">Please enter your age</label>
                    <input type="text" size="20" name="age" id="age" class="number" value=""/>
                </p>
                <p>
                    <label for="email">Please enter your email address</label>
                    <input type="text" size="20" name="email" id="email" class="email" value=""/>
                </p>
            </fieldset>
            <p>
                <input type="submit" name="signup" value="Sign up"/>
            </p>
        </form>
        <h2>Second Form</h2>
        <form id="secondform" method="post" action="index.php#focuspoint">
            <div class="validationerrors"/>
            <fieldset>
                <legend>Second Form Details</legend>
                <p>
                    <label for="suggestion">Enter a suggestion</label>
                    <input type="text" size="20" name="suggestion" id="suggestion" 
                      class="string" value=""/>
                </p>
                <p>
                    <label for="optemail">Please enter your email address (optional)</label>
                    <input type="text" size="20" name="optemail" id="optemail"
                        class="optional email" value=""/>
                </p>
                <p>
                    <label for="rating">Please rate this suggestion</label>
                    <input type="text" size="20" name="rating" id="rating" 
                      class="number" value=""/>
                </p>
                <p>
                    <label for="jibberish">Enter some jibberish (optional)</label>
                    <input type="text" size="20" name="jibberish" id="jibberish" value=""/>
                </p>
            </fieldset>
            <p>
                <input type="submit" name="submit" value="Add Suggestion"/>
            </p>
        </form>
    </body>
</html>                      

Az alábbiakban a hitelesítést és a hibaüzenetek beillesztését végző JavaScript szerepel:

Példa kód:


window.onload = initialise;
function initialise()
{
   var objForms = document.getElementsByTagName('form');
   var iCounter;
   // Attach an event handler for each form
   for (iCounter=0; iCounter<objForms.length; iCounter++)
   {
      objForms[iCounter].onsubmit = function(){return validateForm(this);};
   }
}

// Event handler for the form
function validateForm(objForm)
{
   var arClass = [];
   var iErrors = 0;
   var objField = objForm.getElementsByTagName('input');
   var objLabel = objForm.getElementsByTagName('label');
   var objList = document.createElement('ol');
   var objError, objExisting, objNew, objTitle, objParagraph, objAnchor, objPosition;
   var strLinkID, iFieldCounter, iClassCounter, iCounter;
   // Get the id or name of the form, to make a unique
   // fragment identifier
   if (objForm.id)
   {
      strLinkID = objForm.id + 'ErrorID';
   }
   else
   {
      strLinkID = objForm.name + 'ErrorID';
   }
   // Iterate through input form controls, looking for validation classes
   for (iFieldCounter=0; iFieldCounter<objField.length; iFieldCounter++)
   {
      // Get the class for the field, and look for the appropriate class
      arClass = objField[iFieldCounter].className.split(' ');
      for (iClassCounter=0; iClassCounter<arClass.length; iClassCounter++)
      {
         switch (arClass[iClassCounter])
         {
            case 'string':
               if (!isString(objField[iFieldCounter].value, arClass))
               {
                  if (iErrors === 0)
                  {
                     logError(objField[iFieldCounter], objLabel, objList, strLinkID);
                  }
                  else
                  {
                     logError(objField[iFieldCounter], objLabel, objList, '');
                  }
                  iErrors++;
               }
               break;
            case 'number':
               if (!isNumber(objField[iFieldCounter].value, arClass))
               {
                  if (iErrors === 0)
                  {
                     logError(objField[iFieldCounter], objLabel, objList, strLinkID);
                  }
                  else
                  {
                     logError(objField[iFieldCounter], objLabel, objList, '');
                  }
                  iErrors++;
               }
               break;
            case 'email' :
               if (!isEmail(objField[iFieldCounter].value, arClass))
               {
                  if (iErrors === 0)
                  {
                     logError(objField[iFieldCounter], objLabel, objList, strLinkID);
                  }
                  else
                  {
                     logError(objField[iFieldCounter], objLabel, objList, '');
                  }
                  iErrors++;
               }
               break;
         }
      }
   }
   if (iErrors > 0)
   {
      // If not valid, display error messages
      objError = objForm.getElementsByTagName('div');
      
      // Look for existing errors
      for (iCounter=0; iCounter<objError.length; iCounter++)
      {
         if (objError[iCounter].className == 'validationerrors')
         {
            objExisting = objError[iCounter];
         }
      }
      objNew = document.createElement('div');
      objTitle = document.createElement('h2');
      objParagraph = document.createElement('p');
      objAnchor = document.createElement('a');
      if (iErrors == 1)
      {
         objAnchor.appendChild(document.createTextNode('1 Error in Submission'));
      }
      else
      {
         objAnchor.appendChild(document.createTextNode(iErrors + ' Errors in Submission'));
      }
      objAnchor.href = '#' + strLinkID;
      objAnchor.className = 'submissionerror';
      objTitle.appendChild(objAnchor);
      objParagraph.appendChild(document.createTextNode('Please review the following'));
      objNew.className = 'validationerrors';
      objNew.appendChild(objTitle);
      objNew.appendChild(objParagraph);
      objNew.appendChild(objList);
      
      // If there were existing error, replace them with the new lot,
      // otherwise add the new errors to the start of the form
      if (objExisting)
      {
         objExisting.parentNode.replaceChild(objNew, objExisting);
      }
      else
      {
         objPosition = objForm.firstChild;
         objForm.insertBefore(objNew, objPosition);
      }
      // Allow for latency
      setTimeout(function() { objAnchor.focus(); }, 50);
      
      // Don't submit the form
      objForm.submitAllowed = false;
      return false;
   }
   // Submit the form
   return true;
}
// Function to add a link in a list item that points to problematic field control
function addError(objList, strError, strID, strErrorID)
{
   var objListItem = document.createElement('li');
   var objAnchor = document.createElement('a');
   
   // Fragment identifier to the form control
   objAnchor.href='#' + strID;
   // Make this the target for the error heading
   if (strErrorID.length > 0)
   {
      objAnchor.id = strErrorID;
   }
   // Use the label prompt for the error message
   objAnchor.appendChild(document.createTextNode(strError));
   // Add keyboard and mouse events to set focus to the form control
   objAnchor.onclick = function(event){return focusFormField(this, event);};
   objAnchor.onkeypress = function(event){return focusFormField(this, event);};
   objListItem.appendChild(objAnchor);
   objList.appendChild(objListItem);
}
function focusFormField(objAnchor, objEvent)
{
   var strFormField, objForm;
   // Allow keyboard navigation over links
   if (objEvent && objEvent.type == 'keypress')
   {
      if (objEvent.keyCode != 13 && objEvent.keyCode != 32)
      {
         return true;
      }
   }
   // set focus to the form control
   strFormField = objAnchor.href.match(/[^#]\w*$/);
   objForm = getForm(strFormField);
   objForm[strFormField].focus();
   return false;
}
// Function to return the form element from a given form field name
function getForm(strField)
{
   var objElement = document.getElementById(strField);
   // Find the appropriate form
   do
   {
      objElement = objElement.parentNode;
   } while (!objElement.tagName.match(/form/i) && objElement.parentNode);
   return objElement;
}
// Function to log the error in a list
function logError(objField, objLabel, objList, strErrorID)
{
   var iCounter, strError;
   // Search the label for the error prompt
   for (iCounter=0; iCounter<objLabel.length; iCounter++)
   {
      if (objLabel[iCounter].htmlFor == objField.id)
      {
         strError = objLabel[iCounter].firstChild.nodeValue;
      }
   }
   addError(objList, strError, objField.id, strErrorID);
}
// Validation routines - add as required
function isString(strValue, arClass)
{
   var bValid = (typeof strValue == 'string' && strValue.replace(/^\s*|\s*$/g, '') 
     !== '' && isNaN(strValue));
   return checkOptional(bValid, strValue, arClass);
}
function isEmail(strValue, arClass)
{
   var objRE = /^[\w-\.\']{1,}\@([\da-zA-Z\-]{1,}\.){1,}[\da-zA-Z\-]{2,}$/;
   var bValid = objRE.test(strValue);
   return checkOptional(bValid, strValue, arClass);
}
function isNumber(strValue, arClass)
{
   var bValid = (!isNaN(strValue) && strValue.replace(/^\s*|\s*$/g, '') !== '');
   return checkOptional(bValid, strValue, arClass);
}
function checkOptional(bValid, strValue, arClass)
{
   var bOptional = false;
   var iCounter;
   // Check if optional
   for (iCounter=0; iCounter<arClass.length; iCounter++)
   {
      if (arClass[iCounter] == 'optional')
      {
         bOptional = true;
      }
   }
   if (bOptional && strValue.replace(/^\s*|\s*$/g, '') === '')
   {
      return true;
   }
   return bValid;
   }
   

A Form Validation Example című részben megtalálható a PHP-t, JavaScriptet, CSS-t és XHTML-t alkalmazó technika működő példája..

Ellenőrzések

Folyamat

A fenti technika segítségével készítsen horgony elemeket és megfelelő szkriptet alkalmazó hibaüzeneteket.

  1. Töltse be az oldalt.

  2. Írjon be egy érvényes értéket a hibaüzenettel társított mezőbe és ellenőrizze, hogy a hibaüzenetek nem kerülnek megjelenítésre.

  3. Írjon be egy helytelen értéket a hibaüzenettel társított mezőbe és ellenőrizze, hogy a mezőnek megfelelő hibaüzenet jelenik-e meg.

  4. Ellenőrizze, hogy a hibaüzenet fókuszba kerül-e.

  5. Írjon egy helyes értéket a hibaüzenettel társított mezőbe és ellenőrizze, hogy a hibaüzenet eltűnik-e.

  6. Ismételje meg a fenti lépéseket az összes horgony elemmel és hibaüzenettel ellátott mezővel.

Megjegyzés: A fentieket a segítő technológiák alkalmazásával együtt is ajánlatos elvégezni.

Elvárható eredmények
  • A 2.,3.,4.,és 5. pontok igazak.


Teljesítési feltételek: