backbone-validation-rails 0.6.2.1 → 0.7.1.1

Sign up to get free protection for your applications and to get access to all the features.
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