]> git.mjollnir.org Git - moodle.git/commitdiff
Fixed a bug with client side validation of form fields.
authorjamiesensei <jamiesensei>
Sat, 14 Oct 2006 12:32:31 +0000 (12:32 +0000)
committerjamiesensei <jamiesensei>
Sat, 14 Oct 2006 12:32:31 +0000 (12:32 +0000)
Added some default error messages for rules specified in lang pack as err_{rulename} Use the default by setting the rule message to null.

course/edit_form.php
lang/en_utf8/form.php
lib/formslib.php

index e3bf67d30cb6ea579996b42ffd4eeb888703e974..da3884348a863c8f8613c0b348082754b488982d 100644 (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'), '&nbsp;', 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');
+            
         }
 
 //--------------------------------------------------------------------------------
index 7b1754790b2f705f72ea782c7a2c71bdb3321c7c..5688ace98c464a4cd7554c3b38bc692473f80213 100644 (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.';
+
 ?>
\ No newline at end of file
index bd20f64a6179958364e6612b96db539ca5d34371..489269dcae26c6482d153446e9a6c7ff04526002 100644 (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;
+                    }    
+                }
+            }
+        }
+    }
+
 }
 
 /**