Fixed a bug with client side validation of form fields.

Added some default error messages for rules specified in lang pack as err_{rulename} Use the default by setting the rule message to null.
This commit is contained in:
jamiesensei
2006-10-14 12:32:31 +00:00
parent f1e4c519df
commit 5bc97c9862
3 changed files with 210 additions and 12 deletions
+7 -2
View File
@@ -299,11 +299,16 @@ class course_edit_form extends moodleform {
$costgroup[]= &MoodleQuickForm::createElement('text','cost', '', 'maxlength="6" size="6"');
$costgroup[]= &MoodleQuickForm::createElement('select', 'currency', '', $currencies);
$mform->addGroup($costgroup, 'costgrp', get_string('cost'), ' ', false);
//defining a rule for a form element within a group :
$costgrprules=array();
//set the message to null to tell Moodle to use a default message
//available for most rules, fetched from language pack (err_{rulename}).
$costgrprules['cost'][]=array(null, 'numeric', null, 'client');
$mform->addGroupRule('costgrp',$costgrprules);
$mform->setHelpButton('costgrp', array('cost', get_string('cost')), true);
$mform->setDefault('cost', '');
$mform->setDefault('currency', empty($CFG->enrol_currency) ? 'USD' : $CFG->enrol_currency);
// TODO: fix rule usage and add proper error message
//$mform->addRule('cost', get_string('error'), 'numeric', null, 'client');
}
//--------------------------------------------------------------------------------
+15 -2
View File
@@ -1,6 +1,19 @@
<?php
$string['denotesreq']='$a denotes required field.';
$string['requiredelement']='Required field.';
$string['denotesreq']='$a denotes you must supply a value in this field.';
$string['requiredelement']='You must supply a value here.';
$string['nonexistentformelements']='Trying to add help buttons to nonexistent form elements : $a';
$string['nomethodforaddinghelpbutton']='There is no method for adding a help button to form element $a->name (class $a->classname)';
//error messages for standard rules
$string['err_required']='You must supply a value here.';
$string['err_maxlength']='You must enter not more than $a->format characters here.';
$string['err_minlength']='You must enter at least $a->format characters here.';
$string['err_numeric']='You must enter a number here.';
$string['err_rangelength']='You must enter between {$a->format[0]} and {$a->format[1]} characters here.';
$string['err_email']='You must enter a valid email address here.';
$string['err_lettersonly']='You must enter only letters here.';
$string['err_alphanumeric']='You must enter only letters or numbers here.';
$string['err_nopunctuation']='You must enter no punctuation characters here.';
$string['err_nonzero']='You must enter a number not starting with a 0 here.';
$string['err_numeric']='You must enter a number here.';
?>
+188 -8
View File
@@ -20,20 +20,22 @@ if ($CFG->debug >= DEBUG_ALL){
}
class moodleform {
var $_formname; // form name
var $_form; // quickform object definition
var $_customdata; // globals workaround
function moodleform($action, $customdata=null, $method='post', $target='', $attributes=null) {
$form_name = rtrim(get_class($this), '_form');
$this->_formname = rtrim(get_class($this), '_form');
$this->_customdata = $customdata;
$this->_form =& new MoodleQuickForm($form_name, $method, $action, $target, $attributes);
$this->_form =& new MoodleQuickForm($this->_formname, $method, $action, $target, $attributes);
$this->definition();
$this->_form->addElement('hidden', 'sesskey', null); // automatic sesskey protection
$this->_form->setDefault('sesskey', sesskey());
$this->_form->addElement('hidden', '_qf__', null); // form submission marker
$this->_form->setDefault('_qf__', 1);
$this->_form->addElement('hidden', '_qf__'.$this->_formname, null); // form submission marker
$this->_form->setDefault('_qf__'.$this->_formname, 1);
$this->_form->_setDefaultRuleMessages();
// we have to know all input types before processing submission ;-)
$this->_process_submission($method);
@@ -51,8 +53,8 @@ class moodleform {
}
// following trick is needed to enable proper sesskey checks when using GET forms
// the _qf__ serves as a marker that form was actually submitted
if (array_key_exists('_qf__', $submission) and $submission['_qf__'] == 1) {
// the _qf__.$this->_formname serves as a marker that form was actually submitted
if (array_key_exists('_qf__'.$this->_formname, $submission) and $submission['_qf__'.$this->_formname] == 1) {
if (!confirm_sesskey()) {
error('Incorrect sesskey submitted, form not accepted!');
}
@@ -97,6 +99,8 @@ class moodleform {
function data_submitted($slashed=true) {
if ($this->is_submitted() and $this->is_validated()) {
$data = $this->_form->exportValues(null, $slashed);
unset($data['sesskey']); // we do not need to return sesskey
unset($data['_qf__'.$this->_formname]); // we do not need the submission marker too
if (empty($data)) {
return NULL;
} else {
@@ -245,8 +249,6 @@ class MoodleQuickForm extends HTML_QuickForm_DHTMLRulesTableless {
function exportValues($elementList= null, $addslashes=true){
$unfiltered=parent::exportValues($elementList);
unset($unfiltered['sesskey']); // we do not need to return sesskey
unset($unfiltered['_qf__']); // we do not need the submission marker too
if ($addslashes){
return $this->_recursiveFilter('addslashes',$unfiltered);
@@ -254,6 +256,184 @@ class MoodleQuickForm extends HTML_QuickForm_DHTMLRulesTableless {
return $unfiltered;
}
}
/**
* Returns the client side validation script
*
* The code here was copied from HTML_QuickForm_DHTMLRulesTableless who copied it from HTML_QuickForm
* and slightly modified to run rules per-element
* Needed to override this because of an error with client side validation of grouped elements.
*
* @access public
* @return string Javascript to perform validation, empty string if no 'client' rules were added
*/
function getValidationScript()
{
if (empty($this->_rules) || empty($this->_attributes['onsubmit'])) {
return '';
}
include_once('HTML/QuickForm/RuleRegistry.php');
$registry =& HTML_QuickForm_RuleRegistry::singleton();
$test = array();
$js_escape = array(
"\r" => '\r',
"\n" => '\n',
"\t" => '\t',
"'" => "\\'",
'"' => '\"',
'\\' => '\\\\'
);
foreach ($this->_rules as $elementName => $rules) {
foreach ($rules as $rule) {
if ('client' == $rule['validation']) {
unset($element);
$dependent = isset($rule['dependent']) && is_array($rule['dependent']);
$rule['message'] = strtr($rule['message'], $js_escape);
if (isset($rule['group'])) {
$group =& $this->getElement($rule['group']);
// No JavaScript validation for frozen elements
if ($group->isFrozen()) {
continue 2;
}
$elements =& $group->getElements();
foreach (array_keys($elements) as $key) {
if ($elementName == $group->getElementName($key)) {
$element =& $elements[$key];
break;
}
}
} elseif ($dependent) {
$element = array();
$element[] =& $this->getElement($elementName);
foreach ($rule['dependent'] as $idx => $elName) {
$element[] =& $this->getElement($elName);
}
} else {
$element =& $this->getElement($elementName);
}
// No JavaScript validation for frozen elements
if (is_object($element) && $element->isFrozen()) {
continue 2;
} elseif (is_array($element)) {
foreach (array_keys($element) as $key) {
if ($element[$key]->isFrozen()) {
continue 3;
}
}
}
// Fix for bug displaying errors for elements in a group
//$test[$elementName][] = $registry->getValidationScript($element, $elementName, $rule);
$test[$elementName][0][] = $registry->getValidationScript($element, $elementName, $rule);
$test[$elementName][1]=$element;
//end of fix
}
}
}
$js = '
<script type="text/javascript">
//<![CDATA[
function qf_errorHandler(element, _qfMsg) {
div = element.parentNode;
if (_qfMsg != \'\') {
span = document.createElement("span");
span.className = "error";
span.appendChild(document.createTextNode(_qfMsg.substring(3)));
br = document.createElement("br");
var errorDiv = document.getElementById(element.name + \'_errorDiv\');
if (!errorDiv) {
errorDiv = document.createElement("div");
errorDiv.id = element.name + \'_errorDiv\';
}
while (errorDiv.firstChild) {
errorDiv.removeChild(errorDiv.firstChild);
}
errorDiv.insertBefore(br, errorDiv.firstChild);
errorDiv.insertBefore(span, errorDiv.firstChild);
element.parentNode.insertBefore(errorDiv, element.parentNode.firstChild);
if (div.className.substr(div.className.length - 6, 6) != " error"
&& div.className != "error") {
div.className += " error";
}
return false;
} else {
var errorDiv = document.getElementById(element.name + \'_errorDiv\');
if (errorDiv) {
errorDiv.parentNode.removeChild(errorDiv);
}
if (div.className.substr(div.className.length - 6, 6) == " error") {
div.className = div.className.substr(0, div.className.length - 6);
} else if (div.className == "error") {
div.className = "";
}
return true;
}
}';
$validateJS = '';
foreach ($test as $elementName => $jsandelement) {
// Fix for bug displaying errors for elements in a group
//unset($element);
list($jsArr,$element)=$jsandelement;
//end of fix
$js .= '
function validate_' . $this->_attributes['id'] . '_' . $elementName . '(element) {
var value = \'\';
var errFlag = new Array();
var _qfGroups = {};
var _qfMsg = \'\';
var frm = element.parentNode;
while (frm && frm.nodeName != "FORM") {
frm = frm.parentNode;
}
' . join("\n", $jsArr) . '
return qf_errorHandler(element, _qfMsg);
}
';
$validateJS .= '
ret = validate_' . $this->_attributes['id'] . '_' . $elementName.'(frm.elements[\''.$elementName.'\']) && ret;';
// Fix for bug displaying errors for elements in a group
//unset($element);
//$element =& $this->getElement($elementName);
//end of fix
$valFunc = 'validate_' . $this->_attributes['id'] . '_' . $elementName . '(this)';
$onBlur = $element->getAttribute('onBlur');
$onChange = $element->getAttribute('onChange');
$element->updateAttributes(array('onBlur' => $onBlur . $valFunc,
'onChange' => $onChange . $valFunc));
}
$js .= '
function validate_' . $this->_attributes['id'] . '(frm) {
var ret = true;
' . $validateJS . ';
return ret;
}
//]]>
</script>';
return $js;
} // end func getValidationScript
function _setDefaultRuleMessages(){
foreach ($this->_rules as $field => $rulesarr){
foreach ($rulesarr as $key => $rule){
if ($rule['message']===null){
$a=new object();
$a->format=$rule['format'];
$str=get_string('err_'.$rule['type'], 'form', $a);
if (strpos($str, '[[')!==0){
$this->_rules[$field][$key]['message']=$str;
}
}
}
}
}
}
/**