<?php
require_once('HTML/QuickForm.php');

class 
HTML_QuickForm_DHTMLRules extends HTML_QuickForm {
    
// {{{ getValidationScript()

    /**
     * Returns the client side validation script
     *
     * The code here was copied from HTML_QuickForm and slightly modified to run rules per-element
     *
     * @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;
                            }
                        }
                    }

                    
$test[$elementName][] = $registry->getValidationScript($element$elementName$rule);
                }
            }
        }
        
$js '
<script type="text/javascript">
//<![CDATA[
function qf_errorHandler(element, _qfMsg) {
  tr = element.parentNode;
  while (tr && tr.nodeName != "TR") {
    tr = tr.parentNode;
  }
  if (_qfMsg != \'\') {
    var msgDiv = document.getElementById(element.name+\'_errorDiv\');
    if (!msgDiv) {
      msgDiv = document.createElement("DIV");
      msgDiv.id = element.name+\'_errorDiv\';
      msgDiv.className = "error";
      element.parentNode.insertBefore(msgDiv, element.parentNode.firstChild);
    }
    while (msgDiv.firstChild) {
      msgDiv.removeChild(msgDiv.firstChild);
    }
    msgDiv.appendChild(document.createTextNode(_qfMsg.substring(3)));
    if (tr.className.substr(tr.className.length - 6, 6) != " error"
        && tr.className != "error") {
      tr.className += " error";
    }
    return false;
  } else {
    var msgDiv = document.getElementById(element.name+\'_errorDiv\');
    if (msgDiv) {
      msgDiv.parentNode.removeChild(msgDiv);
    }
    if (tr.className.substr(tr.className.length - 6, 6) == " error") {
      tr.className = tr.className.substr(0, tr.className.length - 6);
    } else if (tr.className == "error") {
      tr.className = "";
    }
    return true;
  }
}'
;
        
$validateJS '';
        foreach (
$test as $elementName => $jsArr) {
            
$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;';
            unset(
$element);
            
$element =& $this->getElement($elementName);
            
$valFunc 'validate_' $this->_attributes['id'] . '_' $elementName '(this)';
            
$element->updateAttributes(array('onBlur' => $valFunc,
                                             
//'onKeyUp' => $valFunc,
                                             
'onChange' => $valFunc));
        }
        
$js .= '
function validate_' 
$this->_attributes['id'] . '(frm) {
  var ret = true;
$validateJS ';
  return ret;
}
//]]>
</script>'
;
        return 
$js;
    } 
// end func getValidationScript

    // }}}

    
function display() {
        
$this->getValidationScript();
        return 
parent::display();
    }
}

?>