clientside_validation.module 28.7 KB
Newer Older
Peter Droogmans's avatar
Peter Droogmans committed
1
<?php
Jelle's avatar
Jelle committed
2
// $Id$
Peter Droogmans's avatar
Peter Droogmans committed
3
4
/**
 * @file
5
 * Add client side validation to forms.
Peter Droogmans's avatar
Peter Droogmans committed
6
 */
7
8
9
define('CLIENTSIDE_VALIDATION_VALIDATE_ALL', 1);
define('CLIENTSIDE_VALIDATION_VALIDATE_SPECIFIC', 0);
define('CLIENTSIDE_VALIDATION_VALIDATE_ALL_EXCEPT', 2);
10
11
12

define('CLIENTSIDE_VALIDATION_EXCLUDE_PATHS', 0); //Add validation on all paths except those specified
define('CLIENTSIDE_VALIDATION_INCLUDE_PATHS', 1); //Only add validation on specified paths
13
14
15
16
17
18
19
20

define('CLIENTSIDE_VALIDATION_JQUERY_SELECTOR', 0);
define('CLIENTSIDE_VALIDATION_TOP_OF_FORM', 1);
define('CLIENTSIDE_VALIDATION_BEFORE_LABEL', 2);
define('CLIENTSIDE_VALIDATION_AFTER_LABEL', 3);
define('CLIENTSIDE_VALIDATION_BEFORE_INPUT', 4);
define('CLIENTSIDE_VALIDATION_AFTER_INPUT', 5);
define('CLIENTSIDE_VALIDATION_TOP_OF_FIRST_FORM', 6);
21
define('CLIENTSIDE_VALIDATION_CUSTOM_ERROR_FUNCTION', 7);
22

Peter Droogmans's avatar
Peter Droogmans committed
23
24
25
26
/**
 * Implements hook_menu().
 */
function clientside_validation_menu() {
27
28
29
30
31
32
33
34
  $items['admin/config/validation'] = array(
    'title' => 'Validation',
    'description' => 'Validation settings.',
    'position' => 'right',
    'weight' => -10,
    'page callback' => 'drupal_get_form',
    'page arguments' => array('clientside_validation_admin_settings'),
    'access arguments' => array('access administration pages'),
35
    'file' => 'clientside_validation.admin.inc',
36
37
  );
  $items['admin/config/validation/clientside_validation'] = array(
Peter Droogmans's avatar
Peter Droogmans committed
38
39
40
41
42
    'title' => 'Clientside Validation',
    'description' => 'Administer clientside validation.',
    'page callback' => 'drupal_get_form',
    'page arguments' => array('clientside_validation_admin_settings'),
    'access arguments' => array('administer site configuration'),
43
    'file' => 'clientside_validation.admin.inc',
Jelle Sebreghts's avatar
Jelle Sebreghts committed
44
  );
45
  $items['clientside_validation/ajax'] = array(
Jelle Sebreghts's avatar
Jelle Sebreghts committed
46
47
48
49
    'title' => 'Clientside validation ajax callback',
    'page callback' => '_clientside_validation_ajax_call',
    'access arguments' => array('access content'),
    'type' => MENU_CALLBACK,
Peter Droogmans's avatar
Peter Droogmans committed
50
51
52
53
  );
  return $items;
}

Jelle Sebreghts's avatar
Jelle Sebreghts committed
54
function _clientside_validation_ajax_call() {
Jelle Sebreghts's avatar
Jelle Sebreghts committed
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
  $param = $_POST['param'];
  $value = $_POST['value'];
  $result = array();
  foreach ($param['expressions'] as $key => $regex) {
    if (!(bool) preg_match($regex, (string) $value)) {
      $result =  array('result' => FALSE, 'message' => $param['messages'][$key]);
      break;
    }
  }
  if (empty($result)) {
    $result = array('result' => TRUE);
  }
  drupal_json_output($result);
}

Peter Droogmans's avatar
Peter Droogmans committed
70
/**
71
 * Implementation of hook_form_alter().
Peter Droogmans's avatar
Peter Droogmans committed
72
 */
73
function clientside_validation_form_alter(&$form, &$form_state, $form_id) {
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
  $page_match = TRUE;
  $path_filter = variable_get('clientside_validation_path_list', '');
  $in_or_exclude = variable_get('clientside_validation_filter_paths', CLIENTSIDE_VALIDATION_EXCLUDE_PATHS);
  if (!empty($path_filter)) {
    $path = drupal_get_path_alias($_GET['q']);
    // Compare with the internal and path alias (if any).
    $page_match = drupal_match_path($path, $path_filter);
    if ($path != $_GET['q']) {
      $page_match = $page_match || drupal_match_path($_GET['q'], $path_filter);
    }
    // When $in_or_exclude has a value of 0 (CLIENTSIDE_VALIDATION_EXCLUDE_PATHS),
    // Clientside Validation is added on all pages except those listed in $path_filter.
    // When set to 1 (CLIENTSIDE_VALIDATION_INCLUDE_PATHS), it is displayed only on
    // those pages listed in $path_filter.
    $page_match = !((bool)$in_or_exclude xor $page_match);
  }
Jelle Sebreghts's avatar
Jelle Sebreghts committed
90
  if (!$page_match) {
91
92
    return;
  }
93
94
  $validate_specific_setting = variable_get('clientside_validation_validate_specific', '');
  $validate_specific = preg_split('/(\r\n?|\n)/', $validate_specific_setting, -1, PREG_SPLIT_NO_EMPTY);
95
96
97
98
99
100
  if (variable_get('clientside_validation_validate_all', CLIENTSIDE_VALIDATION_VALIDATE_ALL) == CLIENTSIDE_VALIDATION_VALIDATE_SPECIFIC
    && !in_array($form_id, $validate_specific)) {
    return;
  }
  elseif (variable_get('clientside_validation_validate_all', CLIENTSIDE_VALIDATION_VALIDATE_ALL) == CLIENTSIDE_VALIDATION_VALIDATE_ALL_EXCEPT
    && in_array($form_id, $validate_specific)) {
101
102
    return;
  }
103
104
  if (strpos($form_id, 'webform_client_form') !== FALSE) {
    if (isset($form['actions']['previous'])) {
105
      $form['actions']['previous']['#attributes']['class'][] = 'cancel';
106
    }
107
    $form['#after_build'][] = 'clientside_validation_webform_after_build';
108
  }
109
  else {
110
111
112
    if (isset($form['actions']['delete'])) {
      $form['actions']['delete']['#attributes']['class'][] = 'cancel';
    }
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
    switch ($form['#id']) {
      case 'node-form':
      case 'webform-component-edit-form':
        $form['#after_build'][] = 'clientside_validation_form_after_build';
        break;
      default:
        $form['#after_build'][] = 'clientside_validation_form_after_build';
        break;
    }
  }
}

/**
 * Webform.
 */
function clientside_validation_webform_after_build(&$form, &$form_state) {
  $js_rules = array();
  drupal_alter("clientside_validation_webform", $form, $form_state, $js_rules);
Peter Droogmans's avatar
Peter Droogmans committed
131
  if (!empty($js_rules)) {
132
    $settings = array();
133
    _clientside_validation_add_general_settings($settings, $form['#id']);
Jelle's avatar
Jelle committed
134
    foreach ($js_rules as $key => $rule) {
Peter Droogmans's avatar
Peter Droogmans committed
135
136
137
138
139
140
141
142
143
144
145
146
147
148
      if (isset($rule['checkboxgroupminmax'])) {
        $settings['clientsideValidation']['forms'][$form['#id']]['checkboxrules'][$key] = array(
            'checkboxgroupminmax' => $rule['checkboxgroupminmax'],
            'messages' => array('checkboxgroupminmax' => $rule['messages']['checkboxgroupminmax'])
        );
        unset($rule['checkboxgroupminmax']);
        unset($rule['messages']['checkboxgroupminmax']);
        if (empty($rule['messages'])) {
          unset($rule['messages']);
        }
      }
      if (!empty($rule)) {
        $settings['clientsideValidation']['forms'][$form['#id']]['rules'][$key] = $rule;
      }
Peter Droogmans's avatar
Peter Droogmans committed
149
    }
Peter Droogmans's avatar
Peter Droogmans committed
150
151
152
153
154
155
156
    
    if (variable_get('clientside_validation_use_minified', 0) == 0) {
      drupal_add_js(drupal_get_path('module', 'clientside_validation') . '/jquery-validate/jquery.validate.js');
    }
    else {
      drupal_add_js(drupal_get_path('module', 'clientside_validation') . '/jquery-validate/jquery.validate.min.js');
    }
157
158
    //add our js file to the footer to support vertical_tabs
    drupal_add_js(drupal_get_path('module', 'clientside_validation') . '/clientside_validation.js', array('scope' => 'footer'));
Peter Droogmans's avatar
Peter Droogmans committed
159
160
161
162
163
164
    drupal_add_js($settings, 'setting');
  }
  return $form;
}

/**
165
 * Regular form.
Peter Droogmans's avatar
Peter Droogmans committed
166
167
168
 */
function clientside_validation_form_after_build(&$form, &$form_state) {
  static $js_rules = array();
169
170
171
172
  static $form_ids = array();
  if (isset($form_ids[$form['#id']])) {
    return $form;
  }
173
  
174
  drupal_alter("clientside_validation_form", $form, $form_state, $js_rules);
Peter Droogmans's avatar
Peter Droogmans committed
175
  if (!empty($js_rules)) {
176
    $settings = array();
177
    _clientside_validation_add_general_settings($settings, $form['#id']);
Jelle's avatar
Jelle committed
178
    foreach ($js_rules as $key => $rule) {
Jelle Sebreghts's avatar
Jelle Sebreghts committed
179
180
181
182
183
184
185
186
187
188
189
190
191
192
      if (isset($rule['checkboxgroupminmax'])) {
        $settings['clientsideValidation']['forms'][$form['#id']]['checkboxrules'][$key] = array(
            'checkboxgroupminmax' => $rule['checkboxgroupminmax'],
            'messages' => array('checkboxgroupminmax' => $rule['messages']['checkboxgroupminmax'])
        );
        unset($rule['checkboxgroupminmax']);
        unset($rule['messages']['checkboxgroupminmax']);
        if (empty($rule['messages'])) {
          unset($rule['messages']);
        }
      }
      if (!empty($rule)) {
        $settings['clientsideValidation']['forms'][$form['#id']]['rules'][$key] = $rule;
      }
Peter Droogmans's avatar
Peter Droogmans committed
193
    }
Peter Droogmans's avatar
Peter Droogmans committed
194
195
196
197
198
199
    if (variable_get('clientside_validation_use_minified', 0) == 0) {
      drupal_add_js(drupal_get_path('module', 'clientside_validation') . '/jquery-validate/jquery.validate.js');
    }
    else {
      drupal_add_js(drupal_get_path('module', 'clientside_validation') . '/jquery-validate/jquery.validate.min.js');
    }
200
201
    //add our js file to the footer to support vertical_tabs
    drupal_add_js(drupal_get_path('module', 'clientside_validation') . '/clientside_validation.js', array('scope' => 'footer'));
Peter Droogmans's avatar
Peter Droogmans committed
202
    drupal_add_js($settings, 'setting');
203
    $form_ids[$form['#id']] = TRUE;
Peter Droogmans's avatar
Peter Droogmans committed
204
205
  }

206
  return $form;
Peter Droogmans's avatar
Peter Droogmans committed
207
208
}

209
210
211
212
213
214
215
216
217
218
219
220
221
function _clientside_validation_add_general_settings(&$settings, $form_id) {
  // Add a setting for this form if the hidden elements should still be validated
  $include_hidden_setting = variable_get('clientside_validation_include_hidden', '');
  $include_hidden = preg_split('/(\r\n?|\n)/', $include_hidden_setting, -1, PREG_SPLIT_NO_EMPTY);
  if (in_array(str_replace('-', '_', $form_id), $include_hidden)) {
    $setting['clientsideValidation']['forms'][$form_id]['includeHidden'] = TRUE;
  }

  $jquery = preg_split('/(\r\n?|\n)/', variable_get('clientside_validation_error_placement_jquery', ''), -1, PREG_SPLIT_NO_EMPTY);
  $top_of_form = preg_split('/(\r\n?|\n)/', variable_get('clientside_validation_error_placement_top_of_form', ''), -1, PREG_SPLIT_NO_EMPTY);
  $before_label = preg_split('/(\r\n?|\n)/', variable_get('clientside_validation_error_placement_before_label', ''), -1, PREG_SPLIT_NO_EMPTY);
  $after_label = preg_split('/(\r\n?|\n)/', variable_get('clientside_validation_error_placement_after_label', ''), -1, PREG_SPLIT_NO_EMPTY);
  $before_input = preg_split('/(\r\n?|\n)/', variable_get('clientside_validation_error_placement_before_input', ''), -1, PREG_SPLIT_NO_EMPTY);
222
  $custom_function = preg_split('/(\r\n?|\n)/', variable_get('clientside_validation_error_placement_custom_function', ''), -1, PREG_SPLIT_NO_EMPTY);
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
  $after_input = preg_split('/(\r\n?|\n)/', variable_get('clientside_validation_error_placement_after_input', ''), -1, PREG_SPLIT_NO_EMPTY);
  $jquery_selector = variable_get('clientside_validation_jquery_selector', '');

  if (in_array(str_replace('-', '_', $form_id), $jquery) && !empty($jquery_selector)) {
    $settings['clientsideValidation']['forms'][$form_id]['errorPlacement'] = CLIENTSIDE_VALIDATION_JQUERY_SELECTOR;
    $settings['clientsideValidation']['forms'][$form_id]['errorJquerySelector'] = $jquery_selector;
  }
  elseif (in_array(str_replace('-', '_', $form_id), $top_of_form)) {
    $settings['clientsideValidation']['forms'][$form_id]['errorPlacement'] = CLIENTSIDE_VALIDATION_TOP_OF_FORM;
  }
  elseif (in_array(str_replace('-', '_', $form_id), $before_label)) {
    $settings['clientsideValidation']['forms'][$form_id]['errorPlacement'] = CLIENTSIDE_VALIDATION_BEFORE_LABEL;
  }
  elseif (in_array(str_replace('-', '_', $form_id), $after_label)) {
    $settings['clientsideValidation']['forms'][$form_id]['errorPlacement'] = CLIENTSIDE_VALIDATION_AFTER_LABEL;
  }
  elseif (in_array(str_replace('-', '_', $form_id), $before_input)) {
    $settings['clientsideValidation']['forms'][$form_id]['errorPlacement'] = CLIENTSIDE_VALIDATION_BEFORE_INPUT;
  }
  elseif (in_array(str_replace('-', '_', $form_id), $after_input)) {
    $settings['clientsideValidation']['forms'][$form_id]['errorPlacement'] = CLIENTSIDE_VALIDATION_AFTER_INPUT;
  }
245
246
247
248
  elseif (in_array(str_replace('-', '_', $form_id), $custom_function)) {
    $settings['clientsideValidation']['forms'][$form_id]['errorPlacement'] = CLIENTSIDE_VALIDATION_CUSTOM_ERROR_FUNCTION;
    $settings['clientsideValidation']['forms'][$form_id]['customErrorFunction'] = variable_get('clientside_validation_custom_error_function', '');
  }
249
250
251
252
253
254
255
256
  else {
    if (variable_get('clientside_validation_error_placement_default', CLIENTSIDE_VALIDATION_TOP_OF_FIRST_FORM) == CLIENTSIDE_VALIDATION_JQUERY_SELECTOR
        && empty($jquery_selector)) {
      $settings['clientsideValidation']['forms'][$form_id]['errorPlacement'] = CLIENTSIDE_VALIDATION_TOP_OF_FIRST_FORM;
    }
    else {
      $settings['clientsideValidation']['forms'][$form_id]['errorPlacement'] = variable_get('clientside_validation_error_placement_default', CLIENTSIDE_VALIDATION_TOP_OF_FIRST_FORM);
      $settings['clientsideValidation']['forms'][$form_id]['errorJquerySelector'] = $jquery_selector;
257
      $settings['clientsideValidation']['forms'][$form_id]['customErrorFunction'] = variable_get('clientside_validation_custom_error_function', '');
258
259
260
    }
  }
  $form_settings_added[] = str_replace('-', '_', $form_id);
261
262
263
264
265
266
267
268
269
270
271
272
273
  $settings['clientsideValidation']['general'] = array(
    "errorClass" => "error",
    "wrapper" => "li",
    "validateTabs" =>  variable_get('clientside_validation_validate_tabs', 1),
    "scrollTo" => variable_get('clientside_validation_scrollto_errormessage', 1),
    "scrollSpeed" => (int)variable_get('clientside_validation_scroll_speed', 1000),
    "disableHtml5Validation" => variable_get('clientside_validation_disable_html5', 1),
    "validateOnBlur" => variable_get('clientside_validation_validate_onblur', 1),
    "validateOnKeyUp" => variable_get('clientside_validation_validate_onkeyup', 1),
    "validateOnSubmit" => variable_get('clientside_validation_validate_onsubmit', 1),
  );
}

274
275
276
/**
 * Set validation rule for required fields.
 */
Jelle's avatar
Jelle committed
277
function _clientside_validation_set_required($name, $title, $required, &$js_rules, $message = '') {
Jelle Sebreghts's avatar
Jelle Sebreghts committed
278
  $title = variable_get('clientside_validation_prefix', '') . $title . variable_get('clientside_validation_suffix', '');
Peter Droogmans's avatar
Peter Droogmans committed
279
280
  if ($required) {
    $js_rules[$name]['required'] = TRUE;
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
    if (empty($message)) {
      $variables = array(
        'message' => '!title field is required.',
        'placeholders' => array('!title' => $title),
        'error_type' => 'required',
        'element_name' => $name,
      );
    }
    else {
      $variables = array(
        'message' => $message,
        'error_type' => 'required',
        'element_name' => $name,
      );
    }
    $js_rules[$name]['messages']['required'] = theme('clientside_error', $variables);
Peter Droogmans's avatar
Peter Droogmans committed
297
298
299
  }
}

300
301
302
/**
 * Set validation rule for number fields.
 */
303
function _clientside_validation_set_number($name, $title, &$js_rules) {
Jelle Sebreghts's avatar
Jelle Sebreghts committed
304
  $title = variable_get('clientside_validation_prefix', '') . $title . variable_get('clientside_validation_suffix', '');
Peter Droogmans's avatar
Peter Droogmans committed
305
  $js_rules[$name]['digits_negative'] = TRUE;
306
307
308
309
310
311
312
  $variables = array(
    'message' => '!title field accepts only numbers.',
    'placeholders' => array('!title' => $title),
    'error_type' => 'number',
    'element_name' => $name,
  );
  $js_rules[$name]['messages']['digits_negative'] = theme('clientside_error', $variables);
Peter Droogmans's avatar
Peter Droogmans committed
313
314
}

315
316
317
/**
 * Set validation rule for decimal fields.
 */
318
function _clientside_validation_set_number_decimal($name, $title, $decimalpoint, &$js_rules) {
Jelle Sebreghts's avatar
Jelle Sebreghts committed
319
  $title = variable_get('clientside_validation_prefix', '') . $title . variable_get('clientside_validation_suffix', '');
Peter Droogmans's avatar
Peter Droogmans committed
320
321
  if ($decimalpoint == '.') {
    $js_rules[$name]['number'] = TRUE;
322
323
324
325
326
327
328
    $variables = array(
      'message' => '!title field accepts only numbers (use a \'.\' as decimal point).',
      'placeholders' => array('!title' => $title),
      'error_type' => 'number',
      'element_name' => $name,
    );
    $js_rules[$name]['messages']['number'] = theme('clientside_error', $variables);
Peter Droogmans's avatar
Peter Droogmans committed
329
330
331
  }
  else {
    $js_rules[$name]['numberDE'] = TRUE;
332
333
334
335
336
337
338
    $variables = array(
      'message' => '!title field accepts only numbers (use a \',\' as decimal point).',
      'placeholers' => array('!title' => $title),
      'error_type' => 'number',
      'element_name' => $name,
    );
    $js_rules[$name]['messages']['numberDE'] = theme('clientside_error', $variables);
Peter Droogmans's avatar
Peter Droogmans committed
339
340
341
  }
}

342
343
344
/**
 * Set validation rule for fields with a minimum and/or a maximum value.
 */
Jelle's avatar
Jelle committed
345
function _clientside_validation_set_minmax($name, $title, $min, $max, &$js_rules, $message = '') {
Jelle Sebreghts's avatar
Jelle Sebreghts committed
346
  $title = variable_get('clientside_validation_prefix', '') . $title . variable_get('clientside_validation_suffix', '');
347
  if (isset($min) && $min !== '' && isset($max) && $max !== '') {
Peter Droogmans's avatar
Peter Droogmans committed
348
    $js_rules[$name]['range'] = array($min, $max);
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
    if (empty($message)) {
      $variables = array(
        'message' => '!title field has to be between !min and !max.',
        'placeholders' => array('!title' => $title, '!min' => $min, '!max' => $max),
        'error_type' => 'range',
        'element_name' => $name,
      );
    }
    else {
      $variables = array(
        'message' => $message,
        'error_type' => 'range',
        'element_name' => $name,
      );
    }
    $js_rules[$name]['messages']['range'] = theme('clientside_error', $variables);
Peter Droogmans's avatar
Peter Droogmans committed
365
  }
366
  elseif (isset($min) && $min !== '') {
Peter Droogmans's avatar
Peter Droogmans committed
367
    $js_rules[$name]['min'] = $min;
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
    if (empty($message)) {
      $variables = array(
        'message' => '!title field has to be greater than !min.',
        'placeholders' => array('!title' => $title, '!min' => $min),
        'error_type' => 'min',
        'element_name' => $name,
      );
    }
    else {
      $variables = array(
        'message' => $message,
        'error_type' => 'min',
        'element_name' => $name,
      );
    }
    $js_rules[$name]['messages']['min'] = theme('clientside_error', $variables);
Peter Droogmans's avatar
Peter Droogmans committed
384
  }
385
  elseif (isset($max) && $max !== '') {
Peter Droogmans's avatar
Peter Droogmans committed
386
    $js_rules[$name]['max'] = $max;
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
    if (empty($message)) {
      $variables = array(
        'message' => '!title field has to be smaller than !max.',
        'placeholders' => array('!title' => $title, '!max' => $max),
        'error_type' => 'max',
        'element_name' => $name,
      );
    }
    else {
      $variables = array(
        'message' => $message,
        'error_type' => 'max',
        'element_name' => $name,
      );
    }
    $js_rules[$name]['messages']['max'] = theme('clientside_error', $variables);
Peter Droogmans's avatar
Peter Droogmans committed
403
404
405
  }
}

406
407
408
/**
 * Set validation rule for fields with a minimum and/or maximum length.
 */
Jelle's avatar
Jelle committed
409
function _clientside_validation_set_minmaxlength($name, $title, $min, $max, &$js_rules, $message = '') {
Jelle Sebreghts's avatar
Jelle Sebreghts committed
410
  $title = variable_get('clientside_validation_prefix', '') . $title . variable_get('clientside_validation_suffix', '');
Jelle Sebreghts's avatar
Jelle Sebreghts committed
411
  if ($max == 1) {
412
413
    $max = '';
  }
414
  if (isset($min) && $min !== '' && isset($max) && $max !== '') {
Peter Droogmans's avatar
Peter Droogmans committed
415
    $js_rules[$name]['rangelength'] = array($min, $max);
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
    if (empty($message)) {
      $variables = array(
        'message' => '!title field has to have between !min and !max values.',
        'placeholders' => array('!title' => $title, '!min' => $min, '!max' => $max),
        'error_type' => 'rangelength',
        'element_name' => $name,
      );
    }
    else {
      $variables = array(
        'message' => $message,
        'error_type' => 'rangelength',
        'element_name' => $name,
      );
    }
    $js_rules[$name]['messages']['rangelength'] = theme('clientside_error', $variables);
Peter Droogmans's avatar
Peter Droogmans committed
432
  }
433
  elseif (isset($min) && $min !== '') {
Peter Droogmans's avatar
Peter Droogmans committed
434
    $js_rules[$name]['minlength'] = $min;
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
    if (empty($message)) {
      $variables = array(
        'message' => '!title field has to have minimal !min values.',
        'placeholders' => array('!title' => $title, '!min' => $min),
        'error_type' => 'minlength',
        'element_name' => $name,
      );
    }
    else {
      $variables = array(
        'message' => $message,
        'error_type' => 'minlength',
        'element_name' => $name,
      );
    }
    $js_rules[$name]['messages']['minlength'] = theme('clientside_error', $variables);
Peter Droogmans's avatar
Peter Droogmans committed
451
  }
452
  elseif (isset($max) && $max !== '') {
Peter Droogmans's avatar
Peter Droogmans committed
453
    $js_rules[$name]['maxlength'] = $max;
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
    if (empty($message)) {
      $variables = array(
        'message' => '!title field has to have maximum !max values.',
        'placeholders' => array('!title' => $title, '!max' => $max),
        'error_type' => 'maxlength',
        'element_name' => $name,
      );
    }
    else {
      $variables = array(
        'message' => $message,
        'error_type' => 'maxlength',
        'element_name' => $name,
      );
    }
    $js_rules[$name]['messages']['maxlength'] = theme('clientside_error', $variables);
Peter Droogmans's avatar
Peter Droogmans committed
470
471
472
  }
}

473
474
475
/**
 * Set validation rule for required fields that must equal a value from an other field.
 */
Jelle's avatar
Jelle committed
476
function _clientside_validation_set_equal($name, $title, $value, &$js_rules) {
Jelle Sebreghts's avatar
Jelle Sebreghts committed
477
  $title = variable_get('clientside_validation_prefix', '') . $title . variable_get('clientside_validation_suffix', '');
478
  $js_rules[$name]['equalTo'] = ':input[name=\'submitted[' . $value['form_key'] . ']\']';
479
480
481
482
483
484
485
  $variables = array(
    'message' => '!title field has to be equal to !firstone.',
    'placeholders' => array('!title' => $title, '!firstone' => $value['name']),
    'error_type' => 'equalto',
    'element_name' => $name,
  );
  $js_rules[$name]['messages']['equalTo'] = theme('clientside_error', $variables);
486
487
488
489
490
}

/**
 * Set validation rule for fields that can not be equal to a value from an other field.
 */
Jelle's avatar
Jelle committed
491
function _clientside_validation_set_not_equal($name, $title, $value, &$js_rules, $message = '') {
492
  $js_rules[$name]['notEqualTo'] = ':input[name=\'submitted[' . $value['form_key'] . ']\']';
Jelle Sebreghts's avatar
Jelle Sebreghts committed
493
  $title = variable_get('clientside_validation_prefix', '') . $title . variable_get('clientside_validation_suffix', '');
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
  if (empty($message)) {
    $variables = array(
      'message' => '!title field has to different from !firstone.',
      'placeholders' => array('!title' => $title, '!firstone' => $value['name']),
      'error_type' => 'notequalto',
      'element_name' => $name,
    );
  }
  else {
    $variables = array(
      'message' => $message,
      'error_type' => 'notequalto',
      'element_name' => $name,
    );
  }
  $message = theme('clientside_error', $variables);
510
511
512
513
514
515
  $js_rules[$name]['messages']['notEqualTo'] = $message;
}

/**
 * Set validation rule for fields that must be equal to a specific value.
 */
Jelle's avatar
Jelle committed
516
function _clientside_validation_set_specific_value($name, $title, $value, &$js_rules, $message = '') {
517
  $js_rules[$name]['oneOf'] = $value;
Jelle Sebreghts's avatar
Jelle Sebreghts committed
518
  $title = variable_get('clientside_validation_prefix', '') . $title . variable_get('clientside_validation_suffix', '');
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
  if (empty($message)) {
    $variables = array(
      'message' => '!title field has to different from !firstone.',
      'placeholders' => array('!title' => $title, '!firstone' => $value['name']),
      'error_type' => 'specific value',
      'element_name' => $name
    );
  }
  else{
    $variables = array(
      'message' => $message,
      'error_type' => 'specific value',
      'element_name' => $name
    );
  }
  $message = theme('clientside_error', $variables);
535
536
537
  $js_rules[$name]['messages']['oneOf'] = $message;
}

538
539
540
541
542
543
/**
 * Set validation rule for fields that consist of one or more of specific values (e.g. string with only a, b and c in it).
 */
function _clientside_validation_set_specific_values($name, $title, $values, &$js_rules, $message = '') {
  $js_rules[$name]['specificVals'] = $values;
  $title = variable_get('clientside_validation_prefix', '') . $title . variable_get('clientside_validation_suffix', '');
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
  if (empty($message)) {
    $variables = array(
      'message' => '!title field must consist of following elements only: !elements.',
      'placeholders' => array('!title' => $title, '!elements' => implode(', ', $values)),
      'error_type' => 'specific values',
      'element_name' => $name
    );
  }
  else {
    $variables = array(
      'message' => $message,
      'error_type' => 'specific values',
      'element_name' => $name
    );
  }
  $message = theme('clientside_error', $variables);
560
561
562
  $js_rules[$name]['messages']['specificVals'] = $message;
}

563
564
565
/**
 * Set validation rule for ean number fields.
 */
Jelle's avatar
Jelle committed
566
function _clientside_validation_set_ean($name, $title, &$js_rules, $message = '') {
Jelle Sebreghts's avatar
Jelle Sebreghts committed
567
  $title = variable_get('clientside_validation_prefix', '') . $title . variable_get('clientside_validation_suffix', '');
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
  if (empty($message)) {
    $variables = array(
      'message' => '!title field is not a valid EAN number.',
      'placeholders' => array('!title' => $title),
      'error_type' => 'ean',
      'element_name' => $name
     );
  }
  else {
    $variables = array(
      'message' => $message,
      'error_type' => 'ean',
      'element_name' => $name
    );
  }
  $message = theme('clientside_error', $variables);
584
  $js_rules[$name]['validEAN'] = TRUE;
Peter Droogmans's avatar
Peter Droogmans committed
585
  $js_rules[$name]['messages']['validEAN'] = $message;
Peter Droogmans's avatar
Peter Droogmans committed
586
587
}

588
589
590
/**
 * Set validation rule for fields with regex validation from webform_validation
 */
591
function _clientside_validation_set_regex($name, $title, &$js_rules, $expression, $message = '', $modifiers = "", $type = 'regex') {
592
  $title = variable_get('clientside_validation_prefix', '') . $title . variable_get('clientside_validation_suffix', '');
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
   if (empty($message)) {
    $variables = array(
      'message' => '!title field does not match the required pattern.',
      'placeholders' => array('!title' => $title),
      'error_type' => $type,
      'element_name' => $name
    );
  }
  else {
    $variables = array(
      'message' => $message,
      'error_type' => $type,
      'element_name' => $name
    );
  }
  $message = theme('clientside_error', $variables);
609
  $js_rules[$name]['regexMatch'] = array($expression);
Jelle Sebreghts's avatar
Jelle Sebreghts committed
610
  if (!empty($modifiers)) {
611
612
    $js_rules[$name]['regexMatch'][] = $modifiers;
  }
613
614
615
  $js_rules[$name]['messages']['regexMatch'] = $message;
}

Jelle Sebreghts's avatar
Jelle Sebreghts committed
616
617
618
/**
 * Set validation rule for fields with regex validation from webform_validation
 */
619
function _clientside_validation_set_regex_pcre($name, $title, &$js_rules, $expression, $message = '', $type = 'regex pcre') {
Jelle Sebreghts's avatar
Jelle Sebreghts committed
620
  $title = variable_get('clientside_validation_prefix', '') . $title . variable_get('clientside_validation_suffix', '');
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
  if (empty($message)) {
    $variables = array(
      'message' => '!title field does not match the required pattern.',
      'placeholders' => array('!title' => $title),
      'error_type' => $type,
      'element_name' => $name
    );
  }
  else {
    $variables = array(
      'message' => $message,
      'error_type' => $type,
      'element_name' => $name
    );
  }
  $message = theme('clientside_error', $variables);
Jelle Sebreghts's avatar
Jelle Sebreghts committed
637
  $js_rules[$name]['regexMatchPCRE']['expressions'][] = $expression;
638
  $js_rules[$name]['regexMatchPCRE']['messages'][] = $message;
Jelle Sebreghts's avatar
Jelle Sebreghts committed
639
640
}

641
642
643
/**
 * Set validation rule for file fields that must have a certain extension.
 */
Jelle's avatar
Jelle committed
644
function _clientside_validation_set_extensions($name, $extensions, &$js_rules) {
645
646
  $extension_list = preg_replace('#,(?![^,]+,)#', ' or', implode(', ', $extensions));
  $js_rules[$name]['accept'] = implode('|', $extensions);
647
648
649
650
651
652
653
  $variables = array(
    'message' => "Only files with a %exts extension are allowed.",
    'placeholders' => array('%exts' => $extension_list),
    'error_type' => 'extensions',
    'element_name' => $name
  );
  $js_rules[$name]['messages']['accept'] = theme('clientside_error', $variables);
654
655
656
657
658
}

/**
 * Set validation rule for checkboxes.
 */
659
function _clientside_validation_set_checkboxgroup_minmax($name, $title, $id, &$js_rules, $message = '', $min = 1, $max = 99) {
Jelle Sebreghts's avatar
Jelle Sebreghts committed
660
  $title = variable_get('clientside_validation_prefix', '') . $title . variable_get('clientside_validation_suffix', '');
661
  $js_rules[$name]['checkboxgroupminmax'] = array($min, $max, $id);
662
663
664
665
666
667
668
    $variables = array(
    'message' => '!title field is required.',
    'placeholders' => array('!title' => $title),
    'error_type' => 'required',
    'element_name' => $name
  );
  $js_rules[$name]['messages']['checkboxgroupminmax'] = theme('clientside_error', $variables);
669
670
671
672
673
}

/**
 * Set validation rule for email fields.
 */
Jelle's avatar
Jelle committed
674
function _clientside_validation_set_email($name, $title, &$js_rules) {
Jelle Sebreghts's avatar
Jelle Sebreghts committed
675
  $title = variable_get('clientside_validation_prefix', '') . $title . variable_get('clientside_validation_suffix', '');
676
  $js_rules[$name]['email'] = TRUE;
677
678
679
680
681
682
683
  $variables = array(
    'message' => 'The value in !title is not a valid email address.',
    'placeholders' => array('!title' => $title),
    'error_type' => 'email',
    'element_name' => $name
  );
  $js_rules[$name]['messages']['email'] = theme('clientside_error', $variables);
684
685
}

686
687
688
/**
 * Set validation rule for url fields.
 */
Jelle Sebreghts's avatar
Jelle Sebreghts committed
689
function _clientside_validation_set_url($name, $title, &$js_rules) {
690
691
  $title = variable_get('clientside_validation_prefix', '') . $title . variable_get('clientside_validation_suffix', '');
  $js_rules[$name]['url'] = TRUE;
692
693
694
695
696
697
  $variables = array(
    'message' => 'The value in !title is not a valid url.', 'placeholders' => array('!title' => $title),
    'error_type' => 'url',
    'element_name' => $name
  );
  $js_rules[$name]['messages']['url'] = theme('clientside_error', $variables);
698
699
}

700
701
function clientside_validation_drupal_json_encode($var) {
  return str_replace(array('<', '>', '&'), array('\u003c', '\u003e', '\u0026'), json_encode($var));
702
}
703
704
705
706
707
708
709
710
711
712

/**
 * Implements hook_theme().
 */
function clientside_validation_theme($existing, $type, $theme, $path) {
   return array(
    'clientside_error' => array(
      'variables' => array(
        'message' => '',
        'placeholders' => array(),
713
714
        'error_type' => '',
        'element_name' => '',
715
716
717
718
719
720
721
      )
    )
  );
}

/**
 * Theme callback function.
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
 * @param array $variables
 * An array with the following keys:
 *  'message':
 *  A string containing the error message
 *  'placeholders':
 *  An associative array of replacements to make after translation.
 *  Incidences of any key in this array are replaced with the corresponding value.
 *  Based on the first character of the key, the value is escaped and/or themed:
 *    !variable: inserted as is
 *    @variable: escape plain text to HTML (check_plain)
 *    %variable: escape text and theme as a placeholder for user-submitted content (check_plain + theme_placeholder)
 *  'error_type':
 *  The error type of this error message (e.g. 'required', 'min', 'max', 'range', 'decimal', 'number', ...)
 *  'element_name':
 *  The name attribute of the element the error is for.
737
738
739
740
741
742
 *
 * @return string
 */
function theme_clientside_error($variables) {
  return t($variables['message'], $variables['placeholders']);
}