3  * DHTML replacement for the standard JavaScript alert window for client-side
 
   8  * Copyright (c) 2005-2007, Mark Wiesemann <wiesemann@php.net>
 
  11  * Redistribution and use in source and binary forms, with or without
 
  12  * modification, are permitted provided that the following conditions
 
  15  *    * Redistributions of source code must retain the above copyright
 
  16  *      notice, this list of conditions and the following disclaimer.
 
  17  *    * Redistributions in binary form must reproduce the above copyright
 
  18  *      notice, this list of conditions and the following disclaimer in the 
 
  19  *      documentation and/or other materials provided with the distribution.
 
  20  *    * The names of the authors may not be used to endorse or promote products 
 
  21  *      derived from this software without specific prior written permission.
 
  23  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 
  24  * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 
  25  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 
  26  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 
  27  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 
  28  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 
  29  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 
  30  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 
  31  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 
  32  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 
  33  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
  36  * @package    HTML_QuickForm_DHTMLRulesTableless
 
  37  * @author     Alexey Borzov <borz_off@cs.msu.su>
 
  38  * @author     Adam Daniel <adaniel1@eesus.jnj.com>
 
  39  * @author     Bertrand Mansion <bmansion@mamasam.com>
 
  40  * @author     Justin Patrin <papercrane@gmail.com>
 
  41  * @author     Mark Wiesemann <wiesemann@php.net>
 
  42  * @license    http://www.opensource.org/licenses/bsd-license.php New BSD License
 
  43  * @version    CVS: $Id: PageDHTMLRulesTableless.php,v 1.3 2007/10/24 20:36:11 wiesemann Exp $
 
  44  * @link       http://pear.php.net/package/HTML_QuickForm_DHTMLRulesTableless
 
  47 require_once 'HTML/QuickForm/Page.php';
 
  50  * This is a DHTML replacement for the standard JavaScript alert window for
 
  51  * client-side validation of forms built with HTML_QuickForm
 
  54  * @package    HTML_QuickForm_DHTMLRulesTableless
 
  55  * @author     Alexey Borzov <borz_off@cs.msu.su>
 
  56  * @author     Adam Daniel <adaniel1@eesus.jnj.com>
 
  57  * @author     Bertrand Mansion <bmansion@mamasam.com>
 
  58  * @author     Justin Patrin <papercrane@gmail.com>
 
  59  * @author     Mark Wiesemann <wiesemann@php.net>
 
  60  * @license    http://www.opensource.org/licenses/bsd-license.php New BSD License
 
  61  * @version    Release: 0.3.3
 
  62  * @link       http://pear.php.net/package/HTML_QuickForm_DHTMLRulesTableless
 
  64 class HTML_QuickForm_PageDHTMLRulesTableless extends HTML_QuickForm_Page
 
  71     function HTML_QuickForm_PageDHTMLRulesTableless($formName, $method = 'post',
 
  72         $target = '', $attributes = null)
 
  74         $this->HTML_QuickForm_Page($formName, $method, '', $target, $attributes);
 
  77     // {{{ getValidationScript()
 
  80      * Returns the client side validation script
 
  82      * The code here was copied from HTML_QuickForm and slightly modified to run rules per-element
 
  85      * @return    string    Javascript to perform validation, empty string if no 'client' rules were added
 
  87     function getValidationScript()
 
  89         if (empty($this->_rules) || empty($this->_attributes['onsubmit'])) {
 
  93         include_once('HTML/QuickForm/RuleRegistry.php');
 
  94         $registry =& HTML_QuickForm_RuleRegistry::singleton();
 
 105         foreach ($this->_rules as $elementName => $rules) {
 
 106             foreach ($rules as $rule) {
 
 107                 if ('client' == $rule['validation']) {
 
 110                     $dependent  = isset($rule['dependent']) && is_array($rule['dependent']);
 
 111                     $rule['message'] = strtr($rule['message'], $js_escape);
 
 113                     if (isset($rule['group'])) {
 
 114                         $group    =& $this->getElement($rule['group']);
 
 115                         // No JavaScript validation for frozen elements
 
 116                         if ($group->isFrozen()) {
 
 119                         $elements =& $group->getElements();
 
 120                         foreach (array_keys($elements) as $key) {
 
 121                             if ($elementName == $group->getElementName($key)) {
 
 122                                 $element =& $elements[$key];
 
 126                     } elseif ($dependent) {
 
 128                         $element[] =& $this->getElement($elementName);
 
 129                         foreach ($rule['dependent'] as $idx => $elName) {
 
 130                             $element[] =& $this->getElement($elName);
 
 133                         $element =& $this->getElement($elementName);
 
 135                     // No JavaScript validation for frozen elements
 
 136                     if (is_object($element) && $element->isFrozen()) {
 
 138                     } elseif (is_array($element)) {
 
 139                         foreach (array_keys($element) as $key) {
 
 140                             if ($element[$key]->isFrozen()) {
 
 146                     $test[$elementName][] = $registry->getValidationScript($element, $elementName, $rule);
 
 151 <script type="text/javascript"><!--//--><![CDATA[//><!--
 
 152 qf_errorHandler = function(element, _qfMsg) {
 
 153   div = element.parentNode;
 
 154   var elementName = element.name.replace(/\[/, "_____");
 
 155   var elementName = elementName.replace(/\]/, "_____");
 
 156   if (_qfMsg != \'\') {
 
 157     span = document.createElement("span");
 
 158     span.className = "error";
 
 159     _qfMsg = _qfMsg.substring(4);
 
 160     span.appendChild(document.createTextNode(_qfMsg));
 
 161     br = document.createElement("br");
 
 163     var errorDiv = document.getElementById(elementName + \'_errorDiv\');
 
 165       errorDiv = document.createElement("div");
 
 166       errorDiv.id = elementName + \'_errorDiv\';
 
 168       if (   div.firstChild.textContent == \'\'
 
 169           || _qfMsg == div.firstChild.textContent
 
 174     while (errorDiv.firstChild) {
 
 175       errorDiv.removeChild(errorDiv.firstChild);
 
 178     errorDiv.insertBefore(br, errorDiv.firstChild);
 
 179     errorDiv.insertBefore(span, errorDiv.firstChild);
 
 181     errorDivInserted = false;
 
 182     for (var i = element.parentNode.childNodes.length - 1; i >= 0; i--) {
 
 184       if (j >= 0 && element.parentNode.childNodes[j].nodeName == "DIV") {
 
 185         element.parentNode.insertBefore(errorDiv, element.parentNode.childNodes[i]);
 
 186         errorDivInserted = true;
 
 190     if (!errorDivInserted) {
 
 191       element.parentNode.insertBefore(errorDiv, element.parentNode.firstChild);
 
 194     if (div.className.substr(div.className.length - 6, 6) != " error"
 
 195         && div.className != "error") {
 
 196       div.className += " error";
 
 201     var errorDiv = document.getElementById(elementName + \'_errorDiv\');
 
 203       errorDiv.parentNode.removeChild(errorDiv);
 
 206     // do not remove the error style from the div tag if there is still an error
 
 208     if (div.firstChild.innerHTML != "") {
 
 212     if (div.className.substr(div.className.length - 6, 6) == " error") {
 
 213       div.className = div.className.substr(0, div.className.length - 6);
 
 214     } else if (div.className == "error") {
 
 222         foreach ($test as $elementName => $jsArr) {
 
 223             // remove group element part of the element name to avoid JS errors
 
 224             $singleElementName = $elementName;
 
 225             $shortNameForJS = str_replace(array('[', ']'), '__', $elementName);
 
 226             $bracketPos = strpos($elementName, '[');
 
 227             if ($bracketPos !== false) {
 
 228                 $singleElementName = substr($elementName, 0, $bracketPos);
 
 229                 $groupElementName = substr($elementName, $bracketPos + 1, -1);
 
 231             if ($bracketPos === false || !$this->elementExists($singleElementName)) {
 
 232                 $groupElementName = $elementName;
 
 233                 $singleElementName = $elementName;
 
 235             $id = str_replace('-', '_', $this->_attributes['id']);
 
 237 validate_' . $id . '_' . $shortNameForJS . ' = function(element) {
 
 239   var errFlag = new Array();
 
 242   var frm = element.parentNode;
 
 243   while (frm && frm.nodeName != "FORM") {
 
 244     frm = frm.parentNode;
 
 246 ' . join("\n", $jsArr) . '
 
 247   return qf_errorHandler(element, _qfMsg);
 
 251             $element =& $this->getElement($singleElementName);
 
 252             $elementNameForJS = 'frm.elements[\'' . $elementName . '\']';
 
 253             if ($element->getType() === 'group' && $singleElementName === $elementName) {
 
 254                 $elementNameForJS = 'document.getElementById(\'' . $element->_elements[0]->getAttribute('id') . '\')';
 
 257   ret = validate_' . $id . '_' . $shortNameForJS . '('. $elementNameForJS . ') && ret;';
 
 258             if ($element->getType() !== 'group') {  // not a group
 
 259                 $valFunc = 'validate_' . $id . '_' . $shortNameForJS . '(this)';
 
 260                 $onBlur = $element->getAttribute('onBlur');
 
 261                 $onChange = $element->getAttribute('onChange');
 
 262                 $element->updateAttributes(array('onBlur' => $onBlur . $valFunc,
 
 263                                                  'onChange' => $onChange . $valFunc));
 
 265                 $elements =& $element->getElements();
 
 266                 for ($i = 0; $i < count($elements); $i++) {
 
 267                     // $groupElementName is a substring of attribute name of the element
 
 268                     if (strpos($elements[$i]->getAttribute('name'), $groupElementName) === 0) {
 
 269                         $valFunc = 'validate_' . $id . '_' . $shortNameForJS . '(this)';
 
 270                         $onBlur = $elements[$i]->getAttribute('onBlur');
 
 271                         $onChange = $elements[$i]->getAttribute('onChange');
 
 272                         $elements[$i]->updateAttributes(array('onBlur'   => $onBlur . $valFunc,
 
 273                                                               'onChange' => $onChange . $valFunc));
 
 279 validate_' . $id . ' = function (frm) {
 
 284 //--><!]]></script>';
 
 286     } // end func getValidationScript
 
 291         $this->getValidationScript();
 
 292         return parent::display();