function output()
 {
     $a_formElsToAdd = array();
     $a_formRulesToAdd = array();
     $this->o_form = new JsonFormBuilder($this->modx, $this->getJsonVal($this->a_json, 'id', true));
     $a_ignore = array('id', 'elements');
     foreach ($this->a_json as $key => $val) {
         if (in_array($key, $a_ignore)) {
             continue;
         }
         $methodName = 'set' . ucfirst($key);
         $this->o_form->{$methodName}($val);
     }
     $a_elements = $this->getJsonVal($this->a_json, 'elements', true);
     foreach ($a_elements as $element) {
         if (is_array($element) === false && empty($element) === false) {
             $a_formElsToAdd[] = $element;
         } else {
             $elementMethod = 'JsonFormBuilder_element' . ucfirst($this->getJsonVal($element, 'element', true));
             //required to set id and label in constructors.. all elements have id and label
             $o_el = new $elementMethod($element['id'], $element['label']);
             $a_ignore = array('element', 'rules', 'id', 'label');
             foreach ($element as $key => $val) {
                 if (in_array($key, $a_ignore)) {
                     continue;
                 }
                 $methodName = 'set' . ucfirst($key);
                 $o_el->{$methodName}($val);
             }
             $a_formElsToAdd[] = $o_el;
             //add rules if needed
             $a_rules = $this->getJsonVal($element, 'rules');
             if ($a_rules) {
                 foreach ($a_rules as $rule) {
                     if (is_array($rule)) {
                         //rule in assoc array
                         $r = new FormRule($rule['type'], $o_el, $rule['value']);
                         $a_ruleignore = array('type');
                         foreach ($rule as $key => $val) {
                             if (in_array($key, $a_ruleignore)) {
                                 continue;
                             }
                             $methodName = 'set' . ucfirst($key);
                             $r->{$methodName}($val);
                         }
                     } else {
                         //simple rule
                         $r = new FormRule($rule, $o_el);
                     }
                     $r->refresh();
                     // just in case
                     $a_formRulesToAdd[] = $r;
                 }
             }
         }
     }
     $this->o_form->addRules($a_formRulesToAdd);
     $this->o_form->addElements($a_formElsToAdd);
     return $this->o_form->output();
 }
//NOTE: Requires jQuery Validate to work.
//Conditional required rule example
$r = new FormRule(FormRuleType::required, $o_fe_dogname, NULL, 'As you have a dog, please tell us its name.');
$r->setCondition(array($o_fe_havedog, 'Yes'));
$a_formRules[] = $r;
//You can create a Show rule which will keep the field hidden, unless the value of another field is selected.
$r = new FormRule(FormRuleType::conditionShow, $o_fe_dogname);
$r->setCondition(array($o_fe_havedog, 'Yes'));
$a_formRules[] = $r;
$o_fe_havecat = new JsonFormBuilder_elementRadioGroup('havecat', 'Do you have a cat?', array('Yes' => 'Yes', 'No' => 'No'));
$o_fe_catname = new JsonFormBuilder_elementText('catname', 'Name of Cat');
//Same setup for a radio group
$r = new FormRule(FormRuleType::required, $o_fe_catname, NULL, 'As you have a cat, please tell us its name.');
$r->setCondition(array($o_fe_havecat, 'Yes'));
$a_formRules[] = $r;
$r = new FormRule(FormRuleType::conditionShow, $o_fe_catname);
$r->setCondition(array($o_fe_havecat, 'Yes'));
$a_formRules[] = $r;
$o_fe_buttSubmit = new JsonFormBuilder_elementButton('submit', 'Submit Form', 'submit');
//Set required fields
$a_formFields_required = array($o_fe_havedog, $o_fe_havecat, $o_fe_name, $o_fe_email);
foreach ($a_formFields_required as $field) {
    $a_formRules[] = new FormRule(FormRuleType::required, $field);
}
//Make email field require a valid email address
$a_formRules[] = new FormRule(FormRuleType::email, $o_fe_email, NULL, 'Please provide a valid email address');
//CREATE FORM AND SETUP
$o_form = new JsonFormBuilder($modx, 'contactForm');
$o_form->setRedirectDocument(3);
$o_form->addRules($a_formRules);
$o_form->setEmailToAddress($modx->getOption('emailsender'));
$a_formRules = array();
////////////////
//CUSTOM RULES//
////////////////
/*
There are a few parts to this if you want to add custom validation well. Firstly, if using the jQuery validate functionality,
ideally you want to have your custom rule validating before server side processing (as well as of course during server side processing).

As long as the following javascript is run after jQuery validate had been included, you can add as many validation methods as you like.
If you have a collection of common rules it would be beneficial to have them in a separate javascript file.
See docs/examples/JsonFormBuilder-template.php for an example of the customPhoneNum validation method.
*/
//Add the custom validation method to your form element by doing the following
//1. Create a custom rule.
$numBlocks = array(3, 3, 4);
$rule = new FormRule(FormRuleType::custom, $o_fe_phone, NULL, 'Phone number must be in format ' . str_repeat("#", $numBlocks[0]) . '-' . str_repeat("#", $numBlocks[1]) . '-' . str_repeat("#", $numBlocks[2]));
//2. For jQuery validate to file off we need to tell it what rule to match
$rule->setCustomRuleName('customPhoneNum');
//3. Optionally we can pass a value to it as well if the validation method needs to know a variable (e.g. minLength, or the example in the template).
$rule->setCustomRuleParam($numBlocks);
//4. Create an anonymous validate function that will be used to determine value at the server side, and specify to use this via the setCustomRuleValidateFunction method.
//$val will contain the form element value, $var will contain the contents of the param specified in step 3 above.
$func = function ($val = null, $var = null) {
    if (empty($val) === false) {
        $phoneVal = $val;
        $foundMatches = preg_match('/^\\(?(\\d{' . $var[0] . '})\\)?[- ]?(\\d{' . $var[1] . '})[- ]?(\\d{' . $var[2] . '})$/', $phoneVal);
        if ($foundMatches !== 1) {
            return false;
        }
    }
    return true;