Skript, das mit HTML oder XHTML benutzt wird.
Die Technik bezieht sich auf:
Das Ziel dieser Technik ist die Anzeige einer Fehlermeldung vorzuführen, wenn die client-seitige Validierung eines Formularfeldes fehlgeschlagen ist. Anchor-Elemente werden benutzt, um die Fehlermeldungen in einer Liste anzuzeigen und werden über den zu validierenden Feldern eingefügt. Anchor-Elemente werden in den Fehlermeldungen benutzt, so dass der Fokus auf die Fehlermeldung(en) gesetzt werden kann, um damit die Aufmerksamkeit des Benutzers darauf zu ziehen. Der href
der anchor-Elemente enthält einen seiten-internen Link, der die Felder, in denen der/die Fehler gefunden wurden, referenziert.
In einer eingesetzten Anwendung tritt eine client-seitige Validierung nicht auf, wenn Javascript abgeschaltet ist. Daher wäre diese Technik nur in Situationen ausreichend, in denen man für die Konformität auf Scripting angewiesen ist oder wenn auch server-seitige Validierungstechniken benutzt werden, um jegliche Fehler zu erfassen und die Seite mit Informationen über die fehlerhaften Felder zurückzugeben.
Dieses Beispiel validiert sowohl Pflichtfelder als auch Felder, bei denen ein bestimmtes Format vorgeschrieben ist. Wenn ein Fehler erkannt wird, fügt das Skript eine Liste mit Fehlermeldungen in das DOM ein und bewegt den Fokus zu ihnen.
HTML- und Javascript-Code
Hier ist das HTML für das Beispielformular.
Code-Beispiel:
<!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>
Hier ist das Javascript, das die Validierung ausführt und die Fehlermeldungen einfügt:
Code-Beispiel:
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;
}
Hier ist ein funktionierendes Beispiel dieser Technik, das durch die Benutzung von PHP, Javascript, CSS und XHTML implementiert wurde: Form Validation Example (Beispiel zur Formular-Validierung).
Erstellen Sie Fehlermeldungen, indem Sie anchor-Tags und ein entsprechendes Scripting per oben genannter Technik benutzen.
Laden Sie die Seite.
Geben Sie einen gültigen Wert in das/die Feld(er) ein, die mit einer Fehlermeldung verknüpft sind und verifizieren Sie, dass keine Fehlermeldungen angezeigt werden.
Geben Sie einen ungültigen Wert in das/die Feld(er) ein, die mit einer Fehlermeldung verknüpft sind und verifizieren Sie, dass die korrekte Fehlermeldung für das Feld angezeigt wird.
Verifizieren Sie, dass die Fehlermeldungen den Fokus erhalten.
Geben Sie einen gültigen Wert in das/die Feld(er) ein, die mit einer Fehlermeldung verknüpft sind und verifizieren Sie, dass die Fehlermeldung entfernt wird.
Wiederholen sie dies bei allen Feldern mit verknüpften Fehlermeldungen, die über anchor-Tags erstellt wurden.
Anmerkung: Es wird empfohlen, dass Sie die oben genannte Vorgehensweise auch unter Benutzung einer assistierenden Technik durchführen.
Tests #2, #3, #4 und #5 sind alle wahr.
Wenn dies eine ausreichende Technik für ein Erfolgskriterium ist, dann bedeutet das Scheitern an diesem Testverfahren nicht zwangsläufig, dass das Erfolgskriterium nicht auf irgendeine andere Art und Weise erfüllt wurde, sondern nur, diese Technik nicht erfolgreich implementiert wurde und nicht benutzt werden kann, um die Konformität zu erklären.