brainstem-js 0.2.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (56) hide show
  1. data/.gitignore +8 -0
  2. data/.pairs +21 -0
  3. data/.ruby-gemset +1 -0
  4. data/.ruby-version +1 -0
  5. data/.tm_properties +1 -0
  6. data/.travis.yml +12 -0
  7. data/Assetfile +79 -0
  8. data/Gemfile +6 -0
  9. data/Gemfile.lock +50 -0
  10. data/LICENSE.txt +22 -0
  11. data/README.md +143 -0
  12. data/Rakefile +25 -0
  13. data/brainstemjs.gemspec +24 -0
  14. data/lib/brainstem/js/engine.rb +5 -0
  15. data/lib/brainstem/js/version.rb +5 -0
  16. data/lib/brainstem/js.rb +10 -0
  17. data/spec/brainstem-collection-spec.coffee +141 -0
  18. data/spec/brainstem-model-spec.coffee +283 -0
  19. data/spec/brainstem-sync-spec.coffee +22 -0
  20. data/spec/brainstem-utils-spec.coffee +12 -0
  21. data/spec/brianstem-expectation-spec.coffee +209 -0
  22. data/spec/helpers/builders.coffee +80 -0
  23. data/spec/helpers/jquery-matchers.js +137 -0
  24. data/spec/helpers/models/post.coffee +14 -0
  25. data/spec/helpers/models/project.coffee +13 -0
  26. data/spec/helpers/models/task.coffee +14 -0
  27. data/spec/helpers/models/time-entry.coffee +13 -0
  28. data/spec/helpers/models/user.coffee +8 -0
  29. data/spec/helpers/spec-helper.coffee +79 -0
  30. data/spec/storage-manager-spec.coffee +613 -0
  31. data/spec/support/.DS_Store +0 -0
  32. data/spec/support/console-runner.js +103 -0
  33. data/spec/support/headless.coffee +47 -0
  34. data/spec/support/headless.html +60 -0
  35. data/spec/support/runner.html +85 -0
  36. data/spec/vendor/backbone-factory.js +62 -0
  37. data/spec/vendor/backbone.js +1571 -0
  38. data/spec/vendor/inflection.js +448 -0
  39. data/spec/vendor/jquery-1.7.js +9300 -0
  40. data/spec/vendor/jquery.cookie.js +47 -0
  41. data/spec/vendor/minispade.js +67 -0
  42. data/spec/vendor/sinon-1.3.4.js +3561 -0
  43. data/spec/vendor/underscore.js +1221 -0
  44. data/vendor/assets/.DS_Store +0 -0
  45. data/vendor/assets/javascripts/.DS_Store +0 -0
  46. data/vendor/assets/javascripts/brainstem/brainstem-collection.coffee +53 -0
  47. data/vendor/assets/javascripts/brainstem/brainstem-expectation.coffee +65 -0
  48. data/vendor/assets/javascripts/brainstem/brainstem-inflections.js +449 -0
  49. data/vendor/assets/javascripts/brainstem/brainstem-model.coffee +141 -0
  50. data/vendor/assets/javascripts/brainstem/brainstem-sync.coffee +76 -0
  51. data/vendor/assets/javascripts/brainstem/index.js +1 -0
  52. data/vendor/assets/javascripts/brainstem/iso8601.js +41 -0
  53. data/vendor/assets/javascripts/brainstem/loading-mixin.coffee +13 -0
  54. data/vendor/assets/javascripts/brainstem/storage-manager.coffee +275 -0
  55. data/vendor/assets/javascripts/brainstem/utils.coffee +35 -0
  56. metadata +198 -0
Binary file
Binary file
@@ -0,0 +1,53 @@
1
+ #= require ./loading-mixin
2
+
3
+ class window.Brainstem.Collection extends Backbone.Collection
4
+ constructor: ->
5
+ super
6
+ @setLoaded false
7
+
8
+ update: (models) ->
9
+ models = models.models if models.models?
10
+ for model in models
11
+ model = this.model.parse(model) if this.model.parse?
12
+ backboneModel = @_prepareModel(model)
13
+ if backboneModel
14
+ if modelInCollection = @get(backboneModel.id)
15
+ modelInCollection.set backboneModel.attributes
16
+ else
17
+ @add backboneModel
18
+ else
19
+ Brainstem.Utils.warn "Unable to update collection with invalid model", model
20
+
21
+ loadNextPage: (options) =>
22
+ oldLength = @length
23
+ success = (collection) =>
24
+ options.success(collection, collection.length == oldLength + @lastFetchOptions.perPage) if options.success?
25
+ base.data.loadCollection @lastFetchOptions.name, _.extend({}, @lastFetchOptions, options, page: @lastFetchOptions.page + 1, collection: this, success: success)
26
+
27
+ reload: (options) =>
28
+ base.data.reset()
29
+ @reset [], silent: true
30
+ @setLoaded false
31
+ base.data.loadCollection @lastFetchOptions.name, _.extend({}, @lastFetchOptions, options, page: 1, collection: this)
32
+
33
+ getWithAssocation: (id) =>
34
+ @get(id)
35
+
36
+ toServerJSON: (method) =>
37
+ @toJSON()
38
+
39
+ @getComparatorWithIdFailover: (order) ->
40
+ [field, direction] = order.split(":")
41
+ comp = @getComparator(field)
42
+ (a, b) ->
43
+ [b, a] = [a, b] if direction.toLowerCase() == "desc"
44
+ result = comp(a, b)
45
+ if result == 0
46
+ a.get('id') - b.get('id')
47
+ else
48
+ result
49
+
50
+ @getComparator: (field) ->
51
+ return (a, b) -> a.get(field) - b.get(field)
52
+
53
+ _.extend(Brainstem.Collection.prototype, Brainstem.LoadingMixin);
@@ -0,0 +1,65 @@
1
+ window.Brainstem ?= {}
2
+
3
+ class window.Brainstem.Expectation
4
+ constructor: (collectionName, options, manager) ->
5
+ @collectionName = collectionName
6
+ @manager = manager
7
+ @manager._checkPageSettings options
8
+ @options = options
9
+ @results = []
10
+ @matches = []
11
+ @triggerError = options.triggerError
12
+ @immediate = options.immediate
13
+ delete options.immediate
14
+ @associated = {}
15
+ @collections = {}
16
+ @requestQueue = []
17
+ @options.response(@) if @options.response?
18
+
19
+ remove: =>
20
+ @disabled = true
21
+
22
+ recordRequest: (collection, callOptions) =>
23
+ if @immediate
24
+ @handleRequest collection: collection, callOptions: callOptions
25
+ else
26
+ @requestQueue.push collection: collection, callOptions: callOptions
27
+
28
+ respond: =>
29
+ for request in @requestQueue
30
+ @handleRequest request
31
+ @requestQueue = []
32
+
33
+ handleRequest: (options) =>
34
+ @matches.push options.callOptions
35
+
36
+ if @triggerError?
37
+ return @manager.errorInterceptor(options.callOptions.error, options.collection, options.callOptions, @triggerError)
38
+
39
+ for key, values of @associated
40
+ values = [values] unless values instanceof Array
41
+ for value in values
42
+ @manager.storage(value.brainstemKey).update [value]
43
+
44
+ for result in @results
45
+ if result instanceof Brainstem.Model
46
+ @manager.storage(result.brainstemKey).update [result]
47
+
48
+ returnedModels = _(@results).map (result) =>
49
+ if result instanceof Brainstem.Model
50
+ @manager.storage(result.brainstemKey).get(result.id)
51
+ else
52
+ @manager.storage(result.key).get(result.id)
53
+
54
+ @manager._success(options.callOptions, options.collection, returnedModels)
55
+
56
+ optionsMatch: (name, options) =>
57
+ @manager._checkPageSettings options
58
+ if !@disabled && @collectionName == name
59
+ _(['include', 'only', 'order', 'filters', 'perPage', 'page', 'search']).all (optionType) =>
60
+ @options[optionType] == "*" || Brainstem.Utils.matches(_.compact(_.flatten([options[optionType]])), _.compact(_.flatten([@options[optionType]])))
61
+ else
62
+ false
63
+
64
+ lastMatch: ->
65
+ @matches[@matches.length - 1]
@@ -0,0 +1,449 @@
1
+ // Modified version of InflectionJS for Brainstem-js. Contains all original code, but with some methods removed
2
+ // that are not used by Brainstem-js.
3
+
4
+ /*
5
+ Copyright (c) 2010 Ryan Schuft (ryan.schuft@gmail.com)
6
+
7
+ Permission is hereby granted, free of charge, to any person obtaining a copy
8
+ of this software and associated documentation files (the "Software"), to deal
9
+ in the Software without restriction, including without limitation the rights
10
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11
+ copies of the Software, and to permit persons to whom the Software is
12
+ furnished to do so, subject to the following conditions:
13
+
14
+ The above copyright notice and this permission notice shall be included in
15
+ all copies or substantial portions of the Software.
16
+
17
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23
+ THE SOFTWARE.
24
+ */
25
+
26
+ /*
27
+ This code is based in part on the work done in Ruby to support
28
+ infection as part of Ruby on Rails in the ActiveSupport's Inflector
29
+ and Inflections classes. It was initally ported to Javascript by
30
+ Ryan Schuft (ryan.schuft@gmail.com) in 2007.
31
+
32
+ The code is available at http://code.google.com/p/inflection-js/
33
+
34
+ The basic usage is:
35
+ 1. Include this script on your web page.
36
+ 2. Call functions on any String object in Javascript
37
+
38
+ Currently implemented functions:
39
+
40
+ String.pluralize(plural) == String
41
+ renders a singular English language noun into its plural form
42
+ normal results can be overridden by passing in an alternative
43
+
44
+ String.singularize(singular) == String
45
+ renders a plural English language noun into its singular form
46
+ normal results can be overridden by passing in an alterative
47
+
48
+ String.camelize(lowFirstLetter) == String
49
+ renders a lower case underscored word into camel case
50
+ the first letter of the result will be upper case unless you pass true
51
+ also translates "/" into "::" (underscore does the opposite)
52
+
53
+ String.underscore() == String
54
+ renders a camel cased word into words seperated by underscores
55
+ also translates "::" back into "/" (camelize does the opposite)
56
+
57
+ String.capitalize() == String
58
+ renders all characters to lower case and then makes the first upper
59
+
60
+ String.titleize() == String
61
+ renders words into title casing (as for book titles)
62
+ */
63
+
64
+ /*
65
+ This sets up a container for some constants in its own namespace
66
+ We use the window (if available) to enable dynamic loading of this script
67
+ Window won't necessarily exist for non-browsers.
68
+ */
69
+ if (window && !window.InflectionJS)
70
+ {
71
+ window.InflectionJS = null;
72
+ }
73
+
74
+ /*
75
+ This sets up some constants for later use
76
+ This should use the window namespace variable if available
77
+ */
78
+ InflectionJS =
79
+ {
80
+ /*
81
+ This is a list of nouns that use the same form for both singular and plural.
82
+ This list should remain entirely in lower case to correctly match Strings.
83
+ */
84
+ uncountable_words: [
85
+ 'equipment', 'information', 'rice', 'money', 'species', 'series',
86
+ 'fish', 'sheep', 'moose', 'deer', 'news'
87
+ ],
88
+
89
+ /*
90
+ These rules translate from the singular form of a noun to its plural form.
91
+ */
92
+ plural_rules: [
93
+ [new RegExp('(m)an$', 'gi'), '$1en'],
94
+ [new RegExp('(pe)rson$', 'gi'), '$1ople'],
95
+ [new RegExp('(child)$', 'gi'), '$1ren'],
96
+ [new RegExp('^(ox)$', 'gi'), '$1en'],
97
+ [new RegExp('(ax|test)is$', 'gi'), '$1es'],
98
+ [new RegExp('(octop|vir)us$', 'gi'), '$1i'],
99
+ [new RegExp('(alias|status)$', 'gi'), '$1es'],
100
+ [new RegExp('(bu)s$', 'gi'), '$1ses'],
101
+ [new RegExp('(buffal|tomat|potat)o$', 'gi'), '$1oes'],
102
+ [new RegExp('([ti])um$', 'gi'), '$1a'],
103
+ [new RegExp('sis$', 'gi'), 'ses'],
104
+ [new RegExp('(?:([^f])fe|([lr])f)$', 'gi'), '$1$2ves'],
105
+ [new RegExp('(hive)$', 'gi'), '$1s'],
106
+ [new RegExp('([^aeiouy]|qu)y$', 'gi'), '$1ies'],
107
+ [new RegExp('(x|ch|ss|sh)$', 'gi'), '$1es'],
108
+ [new RegExp('(matr|vert|ind)ix|ex$', 'gi'), '$1ices'],
109
+ [new RegExp('([m|l])ouse$', 'gi'), '$1ice'],
110
+ [new RegExp('(quiz)$', 'gi'), '$1zes'],
111
+ [new RegExp('s$', 'gi'), 's'],
112
+ [new RegExp('$', 'gi'), 's']
113
+ ],
114
+
115
+ /*
116
+ These rules translate from the plural form of a noun to its singular form.
117
+ */
118
+ singular_rules: [
119
+ [new RegExp('(m)en$', 'gi'), '$1an'],
120
+ [new RegExp('(pe)ople$', 'gi'), '$1rson'],
121
+ [new RegExp('(child)ren$', 'gi'), '$1'],
122
+ [new RegExp('([ti])a$', 'gi'), '$1um'],
123
+ [new RegExp('((a)naly|(b)a|(d)iagno|(p)arenthe|(p)rogno|(s)ynop|(t)he)ses$','gi'), '$1$2sis'],
124
+ [new RegExp('(hive)s$', 'gi'), '$1'],
125
+ [new RegExp('(tive)s$', 'gi'), '$1'],
126
+ [new RegExp('(curve)s$', 'gi'), '$1'],
127
+ [new RegExp('([lr])ves$', 'gi'), '$1f'],
128
+ [new RegExp('([^fo])ves$', 'gi'), '$1fe'],
129
+ [new RegExp('([^aeiouy]|qu)ies$', 'gi'), '$1y'],
130
+ [new RegExp('(s)eries$', 'gi'), '$1eries'],
131
+ [new RegExp('(m)ovies$', 'gi'), '$1ovie'],
132
+ [new RegExp('(x|ch|ss|sh)es$', 'gi'), '$1'],
133
+ [new RegExp('([m|l])ice$', 'gi'), '$1ouse'],
134
+ [new RegExp('(bus)es$', 'gi'), '$1'],
135
+ [new RegExp('(o)es$', 'gi'), '$1'],
136
+ [new RegExp('(shoe)s$', 'gi'), '$1'],
137
+ [new RegExp('(cris|ax|test)es$', 'gi'), '$1is'],
138
+ [new RegExp('(octop|vir)i$', 'gi'), '$1us'],
139
+ [new RegExp('(alias|status)es$', 'gi'), '$1'],
140
+ [new RegExp('^(ox)en', 'gi'), '$1'],
141
+ [new RegExp('(vert|ind)ices$', 'gi'), '$1ex'],
142
+ [new RegExp('(matr)ices$', 'gi'), '$1ix'],
143
+ [new RegExp('(quiz)zes$', 'gi'), '$1'],
144
+ [new RegExp('s$', 'gi'), '']
145
+ ],
146
+
147
+ /*
148
+ This is a list of words that should not be capitalized for title case
149
+ */
150
+ non_titlecased_words: [
151
+ 'and', 'or', 'nor', 'a', 'an', 'the', 'so', 'but', 'to', 'of', 'at',
152
+ 'by', 'from', 'into', 'on', 'onto', 'off', 'out', 'in', 'over',
153
+ 'with', 'for'
154
+ ],
155
+
156
+ /*
157
+ These are regular expressions used for converting between String formats
158
+ */
159
+ underbar: new RegExp('_', 'g'),
160
+ space_or_underbar: new RegExp('[\ _]', 'g'),
161
+ uppercase: new RegExp('([A-Z])', 'g'),
162
+ underbar_prefix: new RegExp('^_'),
163
+
164
+ /*
165
+ This is a helper method that applies rules based replacement to a String
166
+ Signature:
167
+ InflectionJS.apply_rules(str, rules, skip, override) == String
168
+ Arguments:
169
+ str - String - String to modify and return based on the passed rules
170
+ rules - Array: [RegExp, String] - Regexp to match paired with String to use for replacement
171
+ skip - Array: [String] - Strings to skip if they match
172
+ override - String (optional) - String to return as though this method succeeded (used to conform to APIs)
173
+ Returns:
174
+ String - passed String modified by passed rules
175
+ Examples:
176
+ InflectionJS.apply_rules("cows", InflectionJs.singular_rules) === 'cow'
177
+ */
178
+ apply_rules: function(str, rules, skip, override)
179
+ {
180
+ if (override)
181
+ {
182
+ str = override;
183
+ }
184
+ else
185
+ {
186
+ var ignore = (skip.indexOf(str.toLowerCase()) > -1);
187
+ if (!ignore)
188
+ {
189
+ for (var x = 0; x < rules.length; x++)
190
+ {
191
+ if (str.match(rules[x][0]))
192
+ {
193
+ str = str.replace(rules[x][0], rules[x][1]);
194
+ break;
195
+ }
196
+ }
197
+ }
198
+ }
199
+ return str;
200
+ }
201
+ };
202
+
203
+ /*
204
+ This lets us detect if an Array contains a given element
205
+ Signature:
206
+ Array.indexOf(item, fromIndex, compareFunc) == Integer
207
+ Arguments:
208
+ item - Object - object to locate in the Array
209
+ fromIndex - Integer (optional) - starts checking from this position in the Array
210
+ compareFunc - Function (optional) - function used to compare Array item vs passed item
211
+ Returns:
212
+ Integer - index position in the Array of the passed item
213
+ Examples:
214
+ ['hi','there'].indexOf("guys") === -1
215
+ ['hi','there'].indexOf("hi") === 0
216
+ */
217
+ if (!Array.prototype.indexOf)
218
+ {
219
+ Array.prototype.indexOf = function(item, fromIndex, compareFunc)
220
+ {
221
+ if (!fromIndex)
222
+ {
223
+ fromIndex = -1;
224
+ }
225
+ var index = -1;
226
+ for (var i = fromIndex; i < this.length; i++)
227
+ {
228
+ if (this[i] === item || compareFunc && compareFunc(this[i], item))
229
+ {
230
+ index = i;
231
+ break;
232
+ }
233
+ }
234
+ return index;
235
+ };
236
+ }
237
+
238
+ /*
239
+ You can override this list for all Strings or just one depending on if you
240
+ set the new values on prototype or on a given String instance.
241
+ */
242
+ if (!String.prototype._uncountable_words)
243
+ {
244
+ String.prototype._uncountable_words = InflectionJS.uncountable_words;
245
+ }
246
+
247
+ /*
248
+ You can override this list for all Strings or just one depending on if you
249
+ set the new values on prototype or on a given String instance.
250
+ */
251
+ if (!String.prototype._plural_rules)
252
+ {
253
+ String.prototype._plural_rules = InflectionJS.plural_rules;
254
+ }
255
+
256
+ /*
257
+ You can override this list for all Strings or just one depending on if you
258
+ set the new values on prototype or on a given String instance.
259
+ */
260
+ if (!String.prototype._singular_rules)
261
+ {
262
+ String.prototype._singular_rules = InflectionJS.singular_rules;
263
+ }
264
+
265
+ /*
266
+ You can override this list for all Strings or just one depending on if you
267
+ set the new values on prototype or on a given String instance.
268
+ */
269
+ if (!String.prototype._non_titlecased_words)
270
+ {
271
+ String.prototype._non_titlecased_words = InflectionJS.non_titlecased_words;
272
+ }
273
+
274
+ /*
275
+ This function adds plurilization support to every String object
276
+ Signature:
277
+ String.pluralize(plural) == String
278
+ Arguments:
279
+ plural - String (optional) - overrides normal output with said String
280
+ Returns:
281
+ String - singular English language nouns are returned in plural form
282
+ Examples:
283
+ "person".pluralize() == "people"
284
+ "octopus".pluralize() == "octopi"
285
+ "Hat".pluralize() == "Hats"
286
+ "person".pluralize("guys") == "guys"
287
+ */
288
+ if (!String.prototype.pluralize)
289
+ {
290
+ String.prototype.pluralize = function(plural)
291
+ {
292
+ return InflectionJS.apply_rules(
293
+ this,
294
+ this._plural_rules,
295
+ this._uncountable_words,
296
+ plural
297
+ );
298
+ };
299
+ }
300
+
301
+ /*
302
+ This function adds singularization support to every String object
303
+ Signature:
304
+ String.singularize(singular) == String
305
+ Arguments:
306
+ singular - String (optional) - overrides normal output with said String
307
+ Returns:
308
+ String - plural English language nouns are returned in singular form
309
+ Examples:
310
+ "people".singularize() == "person"
311
+ "octopi".singularize() == "octopus"
312
+ "Hats".singularize() == "Hat"
313
+ "guys".singularize("person") == "person"
314
+ */
315
+ if (!String.prototype.singularize)
316
+ {
317
+ String.prototype.singularize = function(singular)
318
+ {
319
+ return InflectionJS.apply_rules(
320
+ this,
321
+ this._singular_rules,
322
+ this._uncountable_words,
323
+ singular
324
+ );
325
+ };
326
+ }
327
+
328
+ /*
329
+ This function adds camelization support to every String object
330
+ Signature:
331
+ String.camelize(lowFirstLetter) == String
332
+ Arguments:
333
+ lowFirstLetter - boolean (optional) - default is to capitalize the first
334
+ letter of the results... passing true will lowercase it
335
+ Returns:
336
+ String - lower case underscored words will be returned in camel case
337
+ additionally '/' is translated to '::'
338
+ Examples:
339
+ "message_properties".camelize() == "MessageProperties"
340
+ "message_properties".camelize(true) == "messageProperties"
341
+ */
342
+ if (!String.prototype.camelize)
343
+ {
344
+ String.prototype.camelize = function(lowFirstLetter)
345
+ {
346
+ var str = this.toLowerCase();
347
+ var str_path = str.split('/');
348
+ for (var i = 0; i < str_path.length; i++)
349
+ {
350
+ var str_arr = str_path[i].split('_');
351
+ var initX = ((lowFirstLetter && i + 1 === str_path.length) ? (1) : (0));
352
+ for (var x = initX; x < str_arr.length; x++)
353
+ {
354
+ str_arr[x] = str_arr[x].charAt(0).toUpperCase() + str_arr[x].substring(1);
355
+ }
356
+ str_path[i] = str_arr.join('');
357
+ }
358
+ str = str_path.join('::');
359
+ return str;
360
+ };
361
+ }
362
+
363
+ /*
364
+ This function adds underscore support to every String object
365
+ Signature:
366
+ String.underscore() == String
367
+ Arguments:
368
+ N/A
369
+ Returns:
370
+ String - camel cased words are returned as lower cased and underscored
371
+ additionally '::' is translated to '/'
372
+ Examples:
373
+ "MessageProperties".camelize() == "message_properties"
374
+ "messageProperties".underscore() == "message_properties"
375
+ */
376
+ if (!String.prototype.underscore)
377
+ {
378
+ String.prototype.underscore = function()
379
+ {
380
+ var str = this;
381
+ var str_path = str.split('::');
382
+ for (var i = 0; i < str_path.length; i++)
383
+ {
384
+ str_path[i] = str_path[i].replace(InflectionJS.uppercase, '_$1');
385
+ str_path[i] = str_path[i].replace(InflectionJS.underbar_prefix, '');
386
+ }
387
+ str = str_path.join('/').toLowerCase();
388
+ return str;
389
+ };
390
+ }
391
+
392
+ /*
393
+ This function adds capitalization support to every String object
394
+ Signature:
395
+ String.capitalize() == String
396
+ Arguments:
397
+ N/A
398
+ Returns:
399
+ String - all characters will be lower case and the first will be upper
400
+ Examples:
401
+ "message_properties".capitalize() == "Message_properties"
402
+ "message properties".capitalize() == "Message properties"
403
+ */
404
+ if (!String.prototype.capitalize)
405
+ {
406
+ String.prototype.capitalize = function()
407
+ {
408
+ var str = this.toLowerCase();
409
+ str = str.substring(0, 1).toUpperCase() + str.substring(1);
410
+ return str;
411
+ };
412
+ }
413
+
414
+ /*
415
+ This function adds titleize support to every String object
416
+ Signature:
417
+ String.titleize() == String
418
+ Arguments:
419
+ N/A
420
+ Returns:
421
+ String - capitalizes words as you would for a book title
422
+ Examples:
423
+ "message_properties".titleize() == "Message Properties"
424
+ "message properties to keep".titleize() == "Message Properties to Keep"
425
+ */
426
+ if (!String.prototype.titleize)
427
+ {
428
+ String.prototype.titleize = function()
429
+ {
430
+ var str = this.toLowerCase();
431
+ str = str.replace(InflectionJS.underbar, ' ');
432
+ var str_arr = str.split(' ');
433
+ for (var x = 0; x < str_arr.length; x++)
434
+ {
435
+ var d = str_arr[x].split('-');
436
+ for (var i = 0; i < d.length; i++)
437
+ {
438
+ if (this._non_titlecased_words.indexOf(d[i].toLowerCase()) < 0)
439
+ {
440
+ d[i] = d[i].capitalize();
441
+ }
442
+ }
443
+ str_arr[x] = d.join('-');
444
+ }
445
+ str = str_arr.join(' ');
446
+ str = str.substring(0, 1).toUpperCase() + str.substring(1);
447
+ return str;
448
+ };
449
+ }