public function validate()
 {
     //prepare can be called multiple times for simplicity, but should only run once.
     if ($this->b_validated === true) {
         return;
     } else {
         $this->b_validated = true;
     }
     //if security field has been filled, kill script with a false thankyou.
     $secVar = $this->postVal($this->_id . '_fke' . date('Y') . 'Sp' . date('m') . 'Blk');
     //This vields value is set with javascript. If the field does not equal the secredvalue
     $secVar2 = $this->postVal($this->_id . '_fke' . date('Y') . 'Sp' . date('m') . 'Blk2');
     if (strlen($secVar) > 0) {
         $this->spamDetectExit(1);
     }
     if ($secVar2 !== false && $secVar2 != '1962') {
         $this->spamDetectExit(2);
     }
     $this->setIsSubmitted(false);
     $s_submittedVal = $this->postVal('submitVar_' . $this->_id);
     if (empty($s_submittedVal) === false) {
         $this->setIsSubmitted(true);
     }
     //process and add form rules
     $a_fieldProps_jqValidate = array();
     $a_fieldProps_jqValidateGroups = array();
     $a_fieldProps_errstringJq = array();
     $a_footJavascript = array();
     //Keep tally of all validation errors. If posted and 0, form will continue.
     foreach ($this->_rules as $rule) {
         $o_elFull = $rule->getElement();
         //verify this element is actually in the form
         $b_found = false;
         foreach ($this->_formElements as $o_el) {
             if ($o_elFull === $o_el) {
                 $b_found = true;
                 break;
             }
         }
         if ($b_found === false) {
             JsonFormBuilder::throwError('Rule "' . $rule->getType() . '" for element "' . $o_elFull->getId() . '" specified, but element is not in form.');
         }
         if (is_array($o_elFull) === true) {
             $o_el = $o_elFull[0];
         } else {
             $o_el = $o_elFull;
         }
         $elId = $o_el->getId();
         //used to test simple single post values
         $s_postedValue = $this->postVal($o_el->getId());
         $elName = $o_el->getName();
         if (isset($a_fieldProps_jqValidate[$elId]) === false) {
             $a_fieldProps_jqValidate[$elId] = array();
         }
         if (isset($a_fieldProps_errstringJq[$elId]) === false) {
             $a_fieldProps_errstringJq[$elId] = array();
         }
         $s_validationMessage = $rule->getValidationMessage();
         switch ($rule->getType()) {
             case FormRuleType::email:
                 $a_fieldProps_jqValidate[$elName][] = 'email:true';
                 $a_fieldProps_errstringJq[$elName][] = 'email:' . json_encode($s_validationMessage);
                 if (!empty($s_postedValue)) {
                     if (filter_var($s_postedValue, FILTER_VALIDATE_EMAIL) === false) {
                         $this->_invalidElements[] = $o_el;
                         $o_el->errorMessages[] = $s_validationMessage;
                     }
                 }
                 break;
             case FormRuleType::url:
                 $a_fieldProps_jqValidate[$elName][] = 'url:true';
                 $a_fieldProps_errstringJq[$elName][] = 'url:' . json_encode($s_validationMessage);
                 if (!empty($s_postedValue)) {
                     if (filter_var($s_postedValue, FILTER_VALIDATE_URL) === false) {
                         $this->_invalidElements[] = $o_el;
                         $o_el->errorMessages[] = $s_validationMessage;
                     }
                 }
                 break;
             case FormRuleType::fieldMatch:
                 $val = $rule->getValue();
                 if (is_a($val, 'JsonFormBuilder_baseElement') === false) {
                     $val = $this->getElementById($val);
                 }
                 if (is_a($val, 'JsonFormBuilder_baseElement') === false) {
                     JsonFormBuilder::throwError('Element for fieldMatch not found for "' . htmlspecialchars($elName) . '" rule. Specify a valid ID or Element Object');
                 }
                 $a_fieldProps_jqValidate[$elName][] = 'equalTo:"#' . $val->getId() . '"';
                 $a_fieldProps_errstringJq[$elName][] = 'equalTo:' . json_encode($s_validationMessage);
                 //validation check
                 $val1 = $this->postVal($o_elFull->getId());
                 $val2 = $this->postVal($val->getId());
                 if ($val1 !== $val2) {
                     $this->_invalidElements[] = $o_el;
                     $o_el->errorMessages[] = $s_validationMessage;
                 }
                 break;
             case FormRuleType::maximumLength:
                 $val = (int) $rule->getValue();
                 $a_fieldProps_jqValidate[$elName][] = 'maxlength:' . $val;
                 $a_fieldProps_errstringJq[$elName][] = 'maxlength:' . json_encode($s_validationMessage);
                 if (is_a($o_el, 'JsonFormBuilder_elementCheckboxGroup')) {
                     //validation check
                     $a_elementsSelected = $this->postVal($o_el->getId());
                     if (is_array($a_elementsSelected) === true && count($a_elementsSelected) > 0) {
                         //ignore if not selected at all as "required" should pick this up.
                         if (is_array($a_elementsSelected) === false || count($a_elementsSelected) > $val) {
                             $this->_invalidElements[] = $o_el;
                             $o_el->errorMessages[] = $s_validationMessage;
                         }
                     }
                 } else {
                     //validation check
                     if (strlen($s_postedValue) > $val) {
                         $this->_invalidElements[] = $o_el;
                         $o_el->errorMessages[] = $s_validationMessage;
                     }
                 }
                 break;
             case FormRuleType::maximumValue:
                 $val = (int) $rule->getValue();
                 $a_fieldProps_jqValidate[$elName][] = 'max:' . $val;
                 $a_fieldProps_errstringJq[$elName][] = 'max:' . json_encode($s_validationMessage);
                 //validation check
                 if ($s_postedValue != '' && (int) $s_postedValue > $val) {
                     $this->_invalidElements[] = $o_el;
                     $o_el->errorMessages[] = $s_validationMessage;
                 }
                 break;
             case FormRuleType::minimumLength:
                 $val = (int) $rule->getValue();
                 $a_fieldProps_jqValidate[$elName][] = 'minlength:' . $val;
                 $a_fieldProps_errstringJq[$elName][] = 'minlength:' . json_encode($s_validationMessage);
                 if (is_a($o_el, 'JsonFormBuilder_elementCheckboxGroup')) {
                     //validation check
                     $a_elementsSelected = $this->postVal($o_el->getId());
                     if (is_array($a_elementsSelected) === true && count($a_elementsSelected) > 0) {
                         //ignore if not selected at all as "required" should pick this up.
                         if (is_array($a_elementsSelected) === false || count($a_elementsSelected) < $val) {
                             $this->_invalidElements[] = $o_el;
                             $o_el->errorMessages[] = $s_validationMessage;
                         }
                     }
                 } else {
                     //validation check
                     if (strlen($s_postedValue) < $val) {
                         $this->_invalidElements[] = $o_el;
                         $o_el->errorMessages[] = $s_validationMessage;
                     }
                 }
                 break;
             case FormRuleType::minimumValue:
                 $val = (int) $rule->getValue();
                 $a_fieldProps_jqValidate[$elName][] = 'min:' . $val;
                 $a_fieldProps_errstringJq[$elName][] = 'min:' . json_encode($s_validationMessage);
                 //validation check
                 if ($s_postedValue != '' && (int) $s_postedValue < $val) {
                     $this->_invalidElements[] = $o_el;
                     $o_el->errorMessages[] = $s_validationMessage;
                 }
                 break;
             case FormRuleType::numeric:
                 $a_fieldProps_jqValidate[$elName][] = 'digits:true';
                 $a_fieldProps_errstringJq[$elName][] = 'digits:' . json_encode($s_validationMessage);
                 //validation check
                 if ($s_postedValue != '' && ctype_digit($s_postedValue) === false) {
                     $this->_invalidElements[] = $o_el;
                     $o_el->errorMessages[] = $s_validationMessage;
                 }
                 break;
             case FormRuleType::required:
                 $jqRequiredVal = 'true';
                 $ruleCondition = $rule->getCondition();
                 if (!empty($ruleCondition) && is_a($ruleCondition[0], 'JsonFormBuilder_baseElement') === false) {
                     $ruleCondition[0] = $this->getElementById($ruleCondition[0]);
                 }
                 $b_validateRequiredPost = true;
                 if (!empty($ruleCondition)) {
                     $this_elID = $ruleCondition[0]->getId();
                     if (is_a($ruleCondition[0], 'JsonFormBuilder_elementRadioGroup')) {
                         $s_valJq = 'jQuery("input[type=radio][name=' . $this_elID . ']")';
                     } else {
                         $s_valJq = 'jQuery("#' . $this_elID . '")';
                     }
                     $jqRequiredVal = '{depends:function(element){var v=' . $s_valJq . '.val(); return (v=="' . rawurlencode($ruleCondition[1]) . '"?true:false); }}';
                     $b_validateRequiredPost = false;
                     if ($this->postVal($this_elID) == $ruleCondition[1]) {
                         $b_validateRequiredPost = true;
                     }
                 }
                 if (is_a($o_el, 'JsonFormBuilder_elementMatrix')) {
                     $s_type = $o_el->getType();
                     $a_rows = $o_el->getRows();
                     $a_columns = $o_el->getColumns();
                     $a_namesForGroup = array();
                     switch ($s_type) {
                         case 'text':
                             for ($row_cnt = 0; $row_cnt < count($a_rows); $row_cnt++) {
                                 for ($col_cnt = 0; $col_cnt < count($a_columns); $col_cnt++) {
                                     $a_namesForGroup[] = $elName . '_' . $row_cnt . '_' . $col_cnt;
                                     $a_fieldProps_jqValidate[$elName . '_' . $row_cnt . '_' . $col_cnt][] = 'required:' . $jqRequiredVal;
                                     $a_fieldProps_errstringJq[$elName . '_' . $row_cnt . '_' . $col_cnt][] = 'required:' . json_encode($s_validationMessage);
                                 }
                             }
                             break;
                         case 'radio':
                             for ($row_cnt = 0; $row_cnt < count($a_rows); $row_cnt++) {
                                 $a_namesForGroup[] = $elName . '_' . $row_cnt;
                                 $a_fieldProps_jqValidate[$elName . '_' . $row_cnt][] = 'required:' . $jqRequiredVal;
                                 $a_fieldProps_errstringJq[$elName . '_' . $row_cnt][] = 'required:' . json_encode($s_validationMessage);
                             }
                             break;
                         case 'check':
                             for ($row_cnt = 0; $row_cnt < count($a_rows); $row_cnt++) {
                                 $s_fieldName = $elName . '_' . $row_cnt . '[]';
                                 $a_namesForGroup[] = $s_fieldName;
                                 $a_fieldProps_jqValidate[$s_fieldName][] = 'required:' . $jqRequiredVal;
                                 $a_fieldProps_errstringJq[$s_fieldName][] = 'required:' . json_encode($s_validationMessage);
                             }
                             break;
                     }
                     $a_fieldProps_jqValidateGroups[$elName] = implode(' ', $a_namesForGroup);
                     //validation check
                     $b_isMatrixValid = JsonFormBuilder::is_matrix_required_valid($o_el);
                     if ($b_validateRequiredPost && $b_isMatrixValid === false) {
                         $this->_invalidElements[] = $o_el;
                         $o_el->errorMessages[] = $s_validationMessage;
                     }
                 } else {
                     if (is_a($o_el, 'JsonFormBuilder_elementCheckboxGroup')) {
                         //validation check
                         $a_elementsSelected = $this->postVal($o_el->getId());
                         if ($b_validateRequiredPost && (is_array($a_elementsSelected) === false || count($a_elementsSelected) === 0)) {
                             $this->_invalidElements[] = $o_el;
                             $o_el->errorMessages[] = $s_validationMessage;
                         }
                     } else {
                         if (is_a($o_el, 'JsonFormBuilder_elementFile')) {
                             //validation check
                             if (isset($_FILES[$o_el->getId()]) === true && $_FILES[$o_el->getId()]['size'] != 0) {
                                 //file is uploaded
                             } else {
                                 if ($b_validateRequiredPost) {
                                     $this->_invalidElements[] = $o_el;
                                     $o_el->errorMessages[] = $s_validationMessage;
                                 }
                             }
                         } else {
                             if (is_a($o_el, 'JsonFormBuilder_elementDate')) {
                                 $a_fieldProps_jqValidate[$elName . '_0'][] = 'required:' . $jqRequiredVal . ',dateElementRequired:true';
                                 $a_fieldProps_errstringJq[$elName . '_0'][] = 'required:' . json_encode($s_validationMessage) . ',dateElementRequired:' . json_encode($s_validationMessage);
                                 //validation check
                                 $elID = $o_el->getId();
                                 $postVal0 = $this->postVal($elID . '_0');
                                 $postVal1 = $this->postVal($elID . '_1');
                                 $postVal2 = $this->postVal($elID . '_2');
                                 if (empty($postVal0) === false && empty($postVal1) === false && empty($postVal2) === false) {
                                     //all three date elements must be selected
                                 } else {
                                     if ($b_validateRequiredPost) {
                                         $this->_invalidElements[] = $o_el;
                                         $o_el->errorMessages[] = $s_validationMessage;
                                     }
                                 }
                             } else {
                                 $a_fieldProps_jqValidate[$elName][] = 'required:' . $jqRequiredVal;
                                 $a_fieldProps_errstringJq[$elName][] = 'required:' . json_encode($s_validationMessage);
                                 //validation check
                                 if ($b_validateRequiredPost && strlen($s_postedValue) < 1) {
                                     $this->_invalidElements[] = $o_el;
                                     $o_el->errorMessages[] = $s_validationMessage;
                                 }
                             }
                         }
                     }
                 }
                 break;
             case FormRuleType::date:
                 $s_thisVal = $rule->getValue();
                 $s_thisErrorMsg = str_replace('===dateformat===', $s_thisVal, $s_validationMessage);
                 $a_fieldProps_jqValidate[$elName][] = 'dateFormat:\'' . $s_thisVal . '\'';
                 $a_fieldProps_errstringJq[$elName][] = 'dateFormat:' . json_encode($s_thisErrorMsg);
                 //validation check
                 $a_formatInfo = JsonFormBuilder::is_valid_date($s_postedValue, $s_thisVal);
                 if ($b_validateRequiredPost && $a_formatInfo['status'] === false) {
                     $this->_invalidElements[] = $o_el;
                     $o_el->errorMessages[] = $s_thisErrorMsg;
                 }
                 break;
             case FormRuleType::custom:
                 $custRuleName = $rule->getCustomRuleName();
                 if (empty($custRuleName)) {
                     JsonFormBuilder::throwError('CustomRuleName for custom rule not set (Element "' . htmlspecialchars($elName) . '" ' . self::fieldMatch . '").');
                 } else {
                     $custval = 'true';
                     $custRuleParam = $rule->getCustomRuleParam();
                     if (!empty($custRuleParam)) {
                         $custval = json_encode($custRuleParam);
                     }
                     $a_fieldProps_jqValidate[$elName][] = $custRuleName . ':' . $custval;
                     $a_fieldProps_errstringJq[$elName][] = $custRuleName . ':' . json_encode($s_validationMessage);
                     //validation check
                     $func = $rule->getCustomRuleValidateFunction();
                     if (!empty($func)) {
                         //validate server side
                         if (!empty($custRuleParam)) {
                             $valid = $func($s_postedValue, $custRuleParam);
                         } else {
                             $valid = $func($s_postedValue);
                         }
                         if ($valid !== true) {
                             $this->_invalidElements[] = $o_el;
                             $o_el->errorMessages[] = $s_validationMessage;
                         }
                     }
                 }
                 break;
             case FormRuleType::conditionShow:
                 $jqRequiredVal = 'true';
                 $ruleCondition = $rule->getCondition();
                 if (!empty($ruleCondition) && is_a($ruleCondition[0], 'JsonFormBuilder_baseElement') === false) {
                     $ruleCondition[0] = $this->getElementById($ruleCondition[0]);
                 }
                 $b_validateRequiredPost = true;
                 if (!empty($ruleCondition)) {
                     $this_elID = $ruleCondition[0]->getId();
                     if (count($a_footJavascript) == 0) {
                         $a_footJavascript[] = 'var a; var e; var v; var b_s; var w;';
                     }
                     //input[type=radio][name=bedStatus]
                     $a_footJavascript[] = '' . 'b_v=false;' . (is_a($ruleCondition[0], 'JsonFormBuilder_elementRadioGroup') ? 'a=jQuery("input[type=radio][name=' . $this_elID . ']"); if(a.is(":checked")===false){v="";}else{v=a.val();}' : 'a=jQuery("#' . $this_elID . '"); v=a.val();') . 'if(v=="' . rawurlencode($ruleCondition[1]) . '"){ b_v=true; }' . 'e=jQuery("#' . $o_elFull->getId() . '");' . 'w=e.parents(".formSegWrap");' . 'if(b_v){w.show();}else{ w.hide(); }' . 'a.change(function(){ var e=jQuery("#' . $o_elFull->getId() . '"); var w=e.parents(".formSegWrap"); if(jQuery(this).val()=="' . rawurlencode($ruleCondition[1]) . '"){ w.show(); }else{ w.hide(); } });' . '';
                 }
                 break;
         }
     }
     //validate on elements themselves
     foreach ($this->_formElements as $o_el) {
         if (is_object($o_el) === false) {
             //
         } else {
             $s_elClass = get_class($o_el);
             $s_postedValue = $this->postVal($o_el->getId());
             if ($s_elClass == 'JsonFormBuilder_elementFile') {
                 $this->_attachmentIncluded = true;
                 $id = $o_el->getId();
                 $a_allowedExtenstions = $o_el->getAllowedExtensions();
                 $i_maxSize = $o_el->getMaxFilesize();
                 if ($a_allowedExtenstions) {
                     $s_extInvalidMessage = 'Only ' . strtoupper(implode(', ', $a_allowedExtenstions)) . ' files allowed.';
                     $a_fieldProps_jqValidate[$id][] = 'fileExtValid:' . json_encode($a_allowedExtenstions);
                     $a_fieldProps_errstringJq[$id][] = 'fileExtValid:"' . $s_extInvalidMessage . '"';
                 }
                 if ($i_maxSize) {
                     $mbOrkb = 'mb';
                     $size = round($i_maxSize / 1024 / 1024, 2);
                     if ($size < 1) {
                         $size = round($i_maxSize / 1024);
                         $mbOrkb = 'kb';
                     }
                     $s_sizeInvalidMessage = 'File exceeds size limit (' . $size . $mbOrkb . ').';
                     $a_fieldProps_jqValidate[$id][] = 'fileSizeValid:' . $i_maxSize;
                     $a_fieldProps_errstringJq[$id][] = 'fileSizeValid:"' . $s_sizeInvalidMessage . '"';
                 }
                 //validation
                 if (isset($_FILES[$id]['size']) === true && $_FILES[$id]['size'] > 0) {
                     if ($o_el->isAllowedFilename($_FILES[$id]['name']) === false) {
                         $this->_invalidElements[] = $o_el;
                         $o_el->errorMessages[] = $s_extInvalidMessage;
                     }
                     if ($o_el->isAllowedSize($_FILES[$id]['size']) === false) {
                         $this->_invalidElements[] = $o_el;
                         $o_el->errorMessages[] = $s_sizeInvalidMessage;
                     }
                 }
             }
         }
     }
     $this->_fieldProps_jqValidate = $a_fieldProps_jqValidate;
     $this->_fieldProps_jqValidateGroups = $a_fieldProps_jqValidateGroups;
     $this->_fieldProps_errstringJq = $a_fieldProps_errstringJq;
     $this->_footJavascript = $a_footJavascript;
 }