backbone-validation-rails 0.6.2.1 → 0.7.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/README.md CHANGED
@@ -5,7 +5,7 @@ A wrapper for the [Backbone.Validation](https://github.com/thedersen/backbone.va
5
5
  ## Version
6
6
  The version of this gem follows that of the associated Backbone.Validation version
7
7
 
8
- Currently: **0.6.2**
8
+ Currently: **v0.7.1**
9
9
 
10
10
  ## Installation
11
11
 
@@ -1,7 +1,7 @@
1
1
  module Backbone
2
2
  module Validation
3
3
  module Rails
4
- VERSION = "0.6.2.1"
4
+ VERSION = "0.7.1.1"
5
5
  end
6
6
  end
7
7
  end
@@ -1,11 +1,10 @@
1
- // Backbone.Validation v0.6.2
1
+ // Backbone.Validation v0.7.1
2
2
  //
3
3
  // Copyright (c) 2011-2012 Thomas Pedersen
4
4
  // Distributed under MIT License
5
5
  //
6
6
  // Documentation and full license available at:
7
7
  // http://thedersen.com/projects/backbone-validation
8
-
9
8
  Backbone.Validation = (function(_){
10
9
  'use strict';
11
10
 
@@ -13,13 +12,69 @@ Backbone.Validation = (function(_){
13
12
  // ---------------
14
13
 
15
14
  var defaultOptions = {
16
- forceUpdate: false,
17
- selector: 'name',
18
- labelFormatter: 'sentenceCase',
19
- valid: Function.prototype,
20
- invalid: Function.prototype
15
+ forceUpdate: false,
16
+ selector: 'name',
17
+ labelFormatter: 'sentenceCase',
18
+ valid: Function.prototype,
19
+ invalid: Function.prototype
20
+ };
21
+
22
+
23
+ // Helper functions
24
+ // ----------------
25
+
26
+ // Formatting functions used for formatting error messages
27
+ var formatFunctions = {
28
+ // Uses the configured label formatter to format the attribute name
29
+ // to make it more readable for the user
30
+ formatLabel: function(attrName, model) {
31
+ return defaultLabelFormatters[defaultOptions.labelFormatter](attrName, model);
32
+ },
33
+
34
+ // Replaces nummeric placeholders like {0} in a string with arguments
35
+ // passed to the function
36
+ format: function() {
37
+ var args = Array.prototype.slice.call(arguments),
38
+ text = args.shift();
39
+ return text.replace(/\{(\d+)\}/g, function(match, number) {
40
+ return typeof args[number] !== 'undefined' ? args[number] : match;
41
+ });
42
+ }
21
43
  };
22
44
 
45
+ // Flattens an object
46
+ // eg:
47
+ //
48
+ // var o = {
49
+ // address: {
50
+ // street: 'Street',
51
+ // zip: 1234
52
+ // }
53
+ // };
54
+ //
55
+ // becomes:
56
+ //
57
+ // var o = {
58
+ // 'address.street': 'Street',
59
+ // 'address.zip': 1234
60
+ // };
61
+ var flatten = function (obj, into, prefix) {
62
+ into = into || {};
63
+ prefix = prefix || '';
64
+
65
+ _.each(obj, function(val, key) {
66
+ if(obj.hasOwnProperty(key)) {
67
+ if (val && typeof val === 'object' && !(val instanceof Date || val instanceof RegExp)) {
68
+ flatten(val, into, prefix + key + '.');
69
+ }
70
+ else {
71
+ into[prefix + key] = val;
72
+ }
73
+ }
74
+ });
75
+
76
+ return into;
77
+ };
23
78
 
24
79
  // Validation
25
80
  // ----------
@@ -78,7 +133,11 @@ Backbone.Validation = (function(_){
78
133
  // applying all the validators and returning the first error
79
134
  // message, if any.
80
135
  return _.reduce(getValidators(model, attr), function(memo, validator){
81
- var result = validator.fn.call(defaultValidators, value, attr, validator.val, model, computed);
136
+ // Pass the format functions plus the default
137
+ // validators as the context to the validator
138
+ var ctx = _.extend({}, formatFunctions, defaultValidators),
139
+ result = validator.fn.call(ctx, value, attr, validator.val, model, computed);
140
+
82
141
  if(result === false || memo === false) {
83
142
  return false;
84
143
  }
@@ -93,18 +152,19 @@ Backbone.Validation = (function(_){
93
152
  // Returns and object containing names of invalid attributes
94
153
  // as well as error messages.
95
154
  var validateModel = function(model, attrs) {
96
- var error, attr,
155
+ var error,
97
156
  invalidAttrs = {},
98
157
  isValid = true,
99
- computed = _.clone(attrs);
158
+ computed = _.clone(attrs),
159
+ flattened = flatten(attrs);
100
160
 
101
- for (attr in attrs) {
102
- error = validateAttr(model, attr, attrs[attr], computed);
161
+ _.each(flattened, function(val, attr) {
162
+ error = validateAttr(model, attr, val, computed);
103
163
  if (error) {
104
164
  invalidAttrs[attr] = error;
105
165
  isValid = false;
106
166
  }
107
- }
167
+ });
108
168
 
109
169
  return {
110
170
  invalidAttrs: invalidAttrs,
@@ -126,16 +186,15 @@ Backbone.Validation = (function(_){
126
186
  // entire model is valid. Passing true will force a validation
127
187
  // of the model.
128
188
  isValid: function(option) {
189
+ var flattened = flatten(this.attributes);
190
+
129
191
  if(_.isString(option)){
130
- return !validateAttr(this, option, this.get(option), _.extend({}, this.attributes));
192
+ return !validateAttr(this, option, flattened[option], _.extend({}, this.attributes));
131
193
  }
132
194
  if(_.isArray(option)){
133
- for (var i = 0; i < option.length; i++) {
134
- if(validateAttr(this, option[i], this.get(option[i]), _.extend({}, this.attributes))){
135
- return false;
136
- }
137
- }
138
- return true;
195
+ return _.reduce(option, function(memo, attr) {
196
+ return memo && !validateAttr(this, attr, flattened[attr], _.extend({}, this.attributes));
197
+ }, true, this);
139
198
  }
140
199
  if(option === true) {
141
200
  this.validate();
@@ -150,24 +209,33 @@ Backbone.Validation = (function(_){
150
209
  var model = this,
151
210
  validateAll = !attrs,
152
211
  opt = _.extend({}, options, setOptions),
153
- allAttrs = _.extend(getValidatedAttrs(model), model.attributes, attrs),
154
- changedAttrs = attrs || allAttrs,
212
+ validatedAttrs = getValidatedAttrs(model),
213
+ allAttrs = _.extend({}, validatedAttrs, model.attributes, attrs),
214
+ changedAttrs = flatten(attrs || allAttrs),
215
+
155
216
  result = validateModel(model, allAttrs);
156
217
 
157
218
  model._isValid = result.isValid;
158
219
 
159
220
  // After validation is performed, loop through all changed attributes
160
- // and call either the valid or invalid callback so the view is updated.
161
- for(var attr in allAttrs) {
221
+ // and call the valid callbacks so the view is updated.
222
+ _.each(validatedAttrs, function(val, attr){
223
+ var invalid = result.invalidAttrs.hasOwnProperty(attr);
224
+ if(!invalid){
225
+ opt.valid(view, attr, opt.selector);
226
+ }
227
+ });
228
+
229
+ // After validation is performed, loop through all changed attributes
230
+ // and call the invalid callback so the view is updated.
231
+ _.each(validatedAttrs, function(val, attr){
162
232
  var invalid = result.invalidAttrs.hasOwnProperty(attr),
163
233
  changed = changedAttrs.hasOwnProperty(attr);
234
+
164
235
  if(invalid && (changed || validateAll)){
165
236
  opt.invalid(view, attr, result.invalidAttrs[attr], opt.selector);
166
237
  }
167
- if(!invalid){
168
- opt.valid(view, attr, opt.selector);
169
- }
170
- }
238
+ });
171
239
 
172
240
  // Trigger validated events.
173
241
  // Need to defer this so the model is actually updated before
@@ -215,7 +283,7 @@ Backbone.Validation = (function(_){
215
283
  return {
216
284
 
217
285
  // Current version of the library
218
- version: '0.6.2',
286
+ version: '0.7.1',
219
287
 
220
288
  // Called to configure the default options
221
289
  configure: function(options) {
@@ -227,6 +295,7 @@ Backbone.Validation = (function(_){
227
295
  bind: function(view, options) {
228
296
  var model = view.model,
229
297
  collection = view.collection;
298
+
230
299
  options = _.extend({}, defaultOptions, defaultCallbacks, options);
231
300
 
232
301
  if(typeof model === 'undefined' && typeof collection === 'undefined'){
@@ -237,7 +306,7 @@ Backbone.Validation = (function(_){
237
306
  if(model) {
238
307
  bindModel(view, model, options);
239
308
  }
240
- if(collection) {
309
+ else if(collection) {
241
310
  collection.each(function(model){
242
311
  bindModel(view, model, options);
243
312
  });
@@ -280,7 +349,7 @@ Backbone.Validation = (function(_){
280
349
  // view becomes valid. Removes any error message.
281
350
  // Should be overridden with custom functionality.
282
351
  valid: function(view, attr, selector) {
283
- view.$('[' + selector + '~=' + attr + ']')
352
+ view.$('[' + selector + '~="' + attr + '"]')
284
353
  .removeClass('invalid')
285
354
  .removeAttr('data-error');
286
355
  },
@@ -289,7 +358,7 @@ Backbone.Validation = (function(_){
289
358
  // Adds a error message.
290
359
  // Should be overridden with custom functionality.
291
360
  invalid: function(view, attr, error, selector) {
292
- view.$('[' + selector + '~=' + attr + ']')
361
+ view.$('[' + selector + '~="' + attr + '"]')
293
362
  .addClass('invalid')
294
363
  .attr('data-error', error);
295
364
  }
@@ -373,41 +442,26 @@ Backbone.Validation = (function(_){
373
442
  // }
374
443
  // });
375
444
  label: function(attrName, model) {
376
- return model.labels[attrName] || defaultLabelFormatters.sentenceCase(attrName, model);
445
+ return (model.labels && model.labels[attrName]) || defaultLabelFormatters.sentenceCase(attrName, model);
377
446
  }
378
447
  };
379
448
 
449
+
380
450
  // Built in validators
381
451
  // -------------------
382
452
 
383
453
  var defaultValidators = Validation.validators = (function(){
384
454
  // Use native trim when defined
385
455
  var trim = String.prototype.trim ?
386
- function(text) {
387
- return text === null ? '' : String.prototype.trim.call(text);
388
- } :
389
- function(text) {
390
- var trimLeft = /^\s+/,
391
- trimRight = /\s+$/;
392
-
393
- return text === null ? '' : text.toString().replace(trimLeft, '').replace(trimRight, '');
394
- };
395
-
396
- // Uses the configured label formatter to format the attribute name
397
- // to make it more readable for the user
398
- var formatLabel = function(attrName, model) {
399
- return defaultLabelFormatters[defaultOptions.labelFormatter](attrName, model);
400
- };
401
-
402
- // Replaces nummeric placeholders like {0} in a string with arguments
403
- // passed to the function
404
- var format = function() {
405
- var args = Array.prototype.slice.call(arguments);
406
- var text = args.shift();
407
- return text.replace(/\{(\d+)\}/g, function(match, number) {
408
- return typeof args[number] !== 'undefined' ? args[number] : match;
409
- });
410
- };
456
+ function(text) {
457
+ return text === null ? '' : String.prototype.trim.call(text);
458
+ } :
459
+ function(text) {
460
+ var trimLeft = /^\s+/,
461
+ trimRight = /\s+$/;
462
+
463
+ return text === null ? '' : text.toString().replace(trimLeft, '').replace(trimRight, '');
464
+ };
411
465
 
412
466
  // Determines whether or not a value is a number
413
467
  var isNumber = function(value){
@@ -437,7 +491,7 @@ Backbone.Validation = (function(_){
437
491
  return false; // overrides all other validators
438
492
  }
439
493
  if (isRequired && !hasValue(value)) {
440
- return format(defaultMessages.required, formatLabel(attr, model));
494
+ return this.format(defaultMessages.required, this.formatLabel(attr, model));
441
495
  }
442
496
  },
443
497
 
@@ -446,7 +500,7 @@ Backbone.Validation = (function(_){
446
500
  // `true` or 'true' are valid
447
501
  acceptance: function(value, attr, accept, model) {
448
502
  if(value !== 'true' && (!_.isBoolean(value) || value === false)) {
449
- return format(defaultMessages.acceptance, formatLabel(attr, model));
503
+ return this.format(defaultMessages.acceptance, this.formatLabel(attr, model));
450
504
  }
451
505
  },
452
506
 
@@ -455,7 +509,7 @@ Backbone.Validation = (function(_){
455
509
  // the min value specified
456
510
  min: function(value, attr, minValue, model) {
457
511
  if (!isNumber(value) || value < minValue) {
458
- return format(defaultMessages.min, formatLabel(attr, model), minValue);
512
+ return this.format(defaultMessages.min, this.formatLabel(attr, model), minValue);
459
513
  }
460
514
  },
461
515
 
@@ -464,7 +518,7 @@ Backbone.Validation = (function(_){
464
518
  // the max value specified
465
519
  max: function(value, attr, maxValue, model) {
466
520
  if (!isNumber(value) || value > maxValue) {
467
- return format(defaultMessages.max, formatLabel(attr, model), maxValue);
521
+ return this.format(defaultMessages.max, this.formatLabel(attr, model), maxValue);
468
522
  }
469
523
  },
470
524
 
@@ -473,7 +527,7 @@ Backbone.Validation = (function(_){
473
527
  // the two numbers specified
474
528
  range: function(value, attr, range, model) {
475
529
  if(!isNumber(value) || value < range[0] || value > range[1]) {
476
- return format(defaultMessages.range, formatLabel(attr, model), range[0], range[1]);
530
+ return this.format(defaultMessages.range, this.formatLabel(attr, model), range[0], range[1]);
477
531
  }
478
532
  },
479
533
 
@@ -482,7 +536,7 @@ Backbone.Validation = (function(_){
482
536
  // the length value specified
483
537
  length: function(value, attr, length, model) {
484
538
  if (!hasValue(value) || trim(value).length !== length) {
485
- return format(defaultMessages.length, formatLabel(attr, model), length);
539
+ return this.format(defaultMessages.length, this.formatLabel(attr, model), length);
486
540
  }
487
541
  },
488
542
 
@@ -491,7 +545,7 @@ Backbone.Validation = (function(_){
491
545
  // the min length value specified
492
546
  minLength: function(value, attr, minLength, model) {
493
547
  if (!hasValue(value) || trim(value).length < minLength) {
494
- return format(defaultMessages.minLength, formatLabel(attr, model), minLength);
548
+ return this.format(defaultMessages.minLength, this.formatLabel(attr, model), minLength);
495
549
  }
496
550
  },
497
551
 
@@ -500,7 +554,7 @@ Backbone.Validation = (function(_){
500
554
  // the max length value specified
501
555
  maxLength: function(value, attr, maxLength, model) {
502
556
  if (!hasValue(value) || trim(value).length > maxLength) {
503
- return format(defaultMessages.maxLength, formatLabel(attr, model), maxLength);
557
+ return this.format(defaultMessages.maxLength, this.formatLabel(attr, model), maxLength);
504
558
  }
505
559
  },
506
560
 
@@ -509,7 +563,7 @@ Backbone.Validation = (function(_){
509
563
  // the two numbers specified
510
564
  rangeLength: function(value, attr, range, model) {
511
565
  if(!hasValue(value) || trim(value).length < range[0] || trim(value).length > range[1]) {
512
- return format(defaultMessages.rangeLength, formatLabel(attr, model), range[0], range[1]);
566
+ return this.format(defaultMessages.rangeLength, this.formatLabel(attr, model), range[0], range[1]);
513
567
  }
514
568
  },
515
569
 
@@ -518,7 +572,7 @@ Backbone.Validation = (function(_){
518
572
  // the specified array. Case sensitive matching
519
573
  oneOf: function(value, attr, values, model) {
520
574
  if(!_.include(values, value)){
521
- return format(defaultMessages.oneOf, formatLabel(attr, model), values.join(', '));
575
+ return this.format(defaultMessages.oneOf, this.formatLabel(attr, model), values.join(', '));
522
576
  }
523
577
  },
524
578
 
@@ -527,7 +581,7 @@ Backbone.Validation = (function(_){
527
581
  // with the name specified
528
582
  equalTo: function(value, attr, equalTo, model, computed) {
529
583
  if(value !== computed[equalTo]) {
530
- return format(defaultMessages.equalTo, formatLabel(attr, model), formatLabel(equalTo, model));
584
+ return this.format(defaultMessages.equalTo, this.formatLabel(attr, model), this.formatLabel(equalTo, model));
531
585
  }
532
586
  },
533
587
 
@@ -536,11 +590,11 @@ Backbone.Validation = (function(_){
536
590
  // Can be a regular expression or the name of one of the built in patterns
537
591
  pattern: function(value, attr, pattern, model) {
538
592
  if (!hasValue(value) || !value.toString().match(defaultPatterns[pattern] || pattern)) {
539
- return format(defaultMessages.pattern, formatLabel(attr, model), pattern);
593
+ return this.format(defaultMessages.pattern, this.formatLabel(attr, model), pattern);
540
594
  }
541
595
  }
542
596
  };
543
597
  }());
544
598
 
545
599
  return Validation;
546
- }(_));
600
+ }(_));
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: backbone-validation-rails
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.2.1
4
+ version: 0.7.1.1
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-11-01 00:00:00.000000000 Z
12
+ date: 2013-01-29 00:00:00.000000000 Z
13
13
  dependencies: []
14
14
  description: A wrapper for backbone.validation in the Rails asset pipeline
15
15
  email:
@@ -43,7 +43,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
43
43
  version: '0'
44
44
  requirements: []
45
45
  rubyforge_project:
46
- rubygems_version: 1.8.24
46
+ rubygems_version: 1.8.23
47
47
  signing_key:
48
48
  specification_version: 3
49
49
  summary: Backbone Validation for Rails >= 3.1