User login

How Clientside Validation's JavaScript Works

Everything added as a method only exists elsewhere as a type of rule (in PHP). See for example these searches.

ben@Onyx:~/workspace/dfm/sites/all/modules/contrib$ gp digits_negative clientside_validation/
clientside_validation/clientside_validation.module:328:  $js_rules[$name]['digits_negative'] = TRUE;
clientside_validation/clientside_validation.module:344:  $js_rules[$name]['messages']['digits_negative'] = theme('clientside_error', $variables);
clientside_validation/clientside_validation.js:460:    jQuery.validator.addMethod("digits_negative", function(value, element, param) {

ben@Onyx:~/workspace/dfm/sites/all/modules/contrib$ gp oneOf  clientside_validation/
clientside_validation/clientside_validation.module:698:  $js_rules[$name]['oneOf'] = $value;
clientside_validation/clientside_validation.module:716:  $js_rules[$name]['messages']['oneOf'] = $message;
clientside_validation/clientside_validation.js:465:    jQuery.validator.addMethod("oneOf", function(value, element, param) {

Let's walk through how the "is required" gets added to the Title on a node form.

In clientside_validation_form.module, the function _clientside_validation_set_required($el_name, $el_title, $element['#required'], $js_rules, $required_error);
is called like that, being given the element name, element title, and whether the element is required in

This all takes place in the context of a hook form alter after build function.

The _clientside_validation_set_required() function is defined in clientside_validation.module itself. What it does is put a lot of information into the $js_rules array:

If it is indeed a required field (otherwise it does nothing), the $js_rules array gets a namespace named after the element, with one entry for the error itself, namespaced as the error type. So in this example the error type is 'required' so a value is stored in $js_rules['title']['required']. For required this value is simply TRUE, but it could be a string or even an array for other error types. The messages namespace, also under the element name namespace, gets an additional namespace of the error type and is assigned the value of the message, which can be constructed from variables like the field title (redundantly 'Title' in this case) passed in immediately.

The rules are then snuck into the $settings variable in the function _clientside_validation_add_special_rules(). The general case is handled by the lines:

<?php
   
if (!empty($rule)) {
     
$settings['clientsideValidation']['forms'][$form['#id']]['rules'][$key] = $rule;
    }
?>

Where $key in our case is 'title' -- the name of the element (so for the tags field, field_tags[und], and for the image alt text, field_image[und][0][alt] ).

In clientside_validation.js, the key line appears to be this:

          $("#" + formid + " :input[name='" + r + "']").rules("add", self.forms[formid]['rules'][r]);

where r equals 'title', for us.

The relevant part of jquery.validate.js that receives this is:

            case "add":
                $.extend(existingRules, $.validator.normalizeRule(argument));
                staticRules[element.name] = existingRules;
                if (argument.messages)
                    settings.messages[element.name] = $.extend( settings.messages[element.name], argument.messages );
                break;

Um, ok, for something a little more complicated than 'required' (which is handled entirely by jquery.validate it seems) you can simply use the name in JavaScript with jQuery.validator.addMethod.

A very rough early example, but it works in the part that the value of the title field gets sent to it when you make changes to it and tab or mouse away:

(function ($) {
  Drupal.behaviors.ajaxFormMsgs = {
    attach: function (context) {
      $(document).bind('clientsideValidationAddCustomRules', function(event){
        jQuery.validator.addMethod("ajaxFormMessage", function(value, element, param) {
          if ( typeof this.oldvalue != 'undefined' && this.oldvalue == value ) {
            // Don't do anything if the value hasn't changed.
            return;
          }
          // Save old value to prevent any action unless value changes.
          this.oldvalue = value;
console.log(element);
console.log(param);
console.log(this);

          var result = false;
          jQuery.ajax({
            'url': Drupal.settings.basePath + 'formmsgsajax/' + param['callback'],
            'type': 'POST',
            'data': {
              'value': value,
              'param': param
            },
            'dataType': 'json',
            'async': false,
            'success': function(res){
              result = res;
            }
          });
          if (result['result'] === false) {
            if (result['message'].length) {
              jQuery.extend(jQuery.validator.messages, {
                "ajaxFormMessage": result['message']
              });
            }
          }
          return result['result'];
        });

      });
    }
  }
})(jQuery);

NOTE: You have to actually change something over there in the form to see the function called!!!

Performance note: It seems to always trigger itself twice for each change event. That is, the code within "jQuery.validator.addMethod("ajaxFormMessage", function(value, element, param) {" runs two times, immediately, when tabbing out of the Title field.

Comments

Post new comment

The content of this field is kept private and will not be shown publicly.
  • You may post code using <code>...</code> (generic) or <?php ... ?> (highlighted PHP) tags.
  • You can use Markdown syntax to format and style the text. Also see Markdown Extra for tables, footnotes, and more.
  • Web page addresses and e-mail addresses turn into links automatically.
  • Allowed HTML tags: <a> <em> <strong> <cite> <code> <ul> <ol> <li> <dl> <dt> <dd> <img> <blockquote> <small> <h2> <h3> <h4> <h5> <h6> <sub> <sup> <p> <br> <strike> <table> <tr> <td> <thead> <th> <tbody> <tt> <output>
  • Lines and paragraphs break automatically.

More information about formatting options

By submitting this form, you accept the Mollom privacy policy.