joosy 0.1.0.alpha → 1.0.0.RC1
Sign up to get free protection for your applications and to get access to all the features.
- data/.codoopts +5 -0
- data/.gitignore +2 -0
- data/Gemfile +15 -2
- data/Gemfile.lock +102 -81
- data/Guardfile +16 -16
- data/LICENSE +22 -0
- data/MIT-LICENSE +2 -2
- data/README.md +118 -0
- data/app/assets/javascripts/joosy/core/application.js.coffee +53 -0
- data/app/assets/javascripts/joosy/core/form.js.coffee +338 -0
- data/app/assets/javascripts/joosy/core/helpers/form.js.coffee +72 -0
- data/app/assets/javascripts/joosy/core/helpers/view.js.coffee +42 -0
- data/app/assets/javascripts/joosy/core/helpers/widgets.js.coffee +14 -0
- data/app/assets/javascripts/joosy/core/joosy.js.coffee +184 -0
- data/app/assets/javascripts/joosy/core/layout.js.coffee +168 -0
- data/app/assets/javascripts/joosy/core/modules/container.js.coffee +124 -0
- data/app/assets/javascripts/joosy/core/modules/events.js.coffee +122 -0
- data/app/assets/javascripts/joosy/core/modules/filters.js.coffee +39 -0
- data/app/assets/javascripts/joosy/core/modules/log.js.coffee +36 -0
- data/app/assets/javascripts/joosy/core/modules/module.js.coffee +117 -0
- data/app/assets/javascripts/joosy/core/modules/renderer.js.coffee +200 -0
- data/app/assets/javascripts/joosy/core/modules/time_manager.js.coffee +46 -0
- data/app/assets/javascripts/joosy/core/modules/widgets_manager.js.coffee +87 -0
- data/app/assets/javascripts/joosy/core/page.js.coffee +387 -0
- data/app/assets/javascripts/joosy/core/preloader.js.coffee +13 -0
- data/app/assets/javascripts/joosy/core/resource/collection.js.coffee +175 -0
- data/app/assets/javascripts/joosy/core/resource/generic.js.coffee +303 -0
- data/app/assets/javascripts/joosy/core/resource/rest.js.coffee +244 -0
- data/app/assets/javascripts/joosy/core/resource/rest_collection.js.coffee +24 -0
- data/app/assets/javascripts/joosy/core/router.js.coffee +201 -0
- data/app/assets/javascripts/joosy/core/templaters/rails_jst.js.coffee +37 -0
- data/app/assets/javascripts/joosy/core/widget.js.coffee +85 -0
- data/app/assets/javascripts/joosy/preloaders/caching.js.coffee +169 -0
- data/app/assets/javascripts/joosy/preloaders/inline.js.coffee +56 -0
- data/{vendor → app}/assets/javascripts/joosy.js.coffee +0 -1
- data/app/helpers/joosy/sprockets_helper.rb +39 -12
- data/joosy.gemspec +4 -3
- data/lib/joosy/rails/engine.rb +12 -1
- data/lib/joosy/rails/version.rb +2 -2
- data/lib/joosy.rb +9 -0
- data/lib/rails/generators/joosy/application_generator.rb +15 -3
- data/lib/rails/generators/joosy/joosy_base.rb +2 -2
- data/lib/rails/generators/joosy/layout_generator.rb +8 -1
- data/lib/rails/generators/joosy/page_generator.rb +21 -6
- data/lib/rails/generators/joosy/preloader_generator.rb +14 -7
- data/lib/rails/generators/joosy/resource_generator.rb +29 -0
- data/lib/rails/generators/joosy/templates/app/helpers/application.js.coffee +4 -0
- data/lib/rails/generators/joosy/templates/app/layouts/application.js.coffee +1 -0
- data/lib/rails/generators/joosy/templates/app/layouts/template.js.coffee +1 -1
- data/lib/rails/generators/joosy/templates/app/pages/application.js.coffee +1 -1
- data/lib/rails/generators/joosy/templates/app/pages/template.js.coffee +3 -3
- data/lib/rails/generators/joosy/templates/app/pages/welcome/index.js.coffee +22 -0
- data/lib/rails/generators/joosy/templates/app/resources/template.js.coffee +2 -0
- data/lib/rails/generators/joosy/templates/app/routes.js.coffee +7 -1
- data/lib/rails/generators/joosy/templates/app/templates/layouts/application.jst.hamlc +2 -0
- data/lib/rails/generators/joosy/templates/app/templates/pages/welcome/index.jst.hamlc +7 -0
- data/lib/rails/generators/joosy/templates/app/widgets/template.js.coffee +2 -2
- data/lib/rails/generators/joosy/templates/app.js.coffee +4 -0
- data/lib/rails/generators/joosy/templates/app_preloader.js.coffee.erb +9 -12
- data/lib/rails/generators/joosy/templates/app_resources_predefiner.js.coffee.erb +11 -0
- data/lib/rails/generators/joosy/templates/preload.html.erb +5 -6
- data/lib/rails/generators/joosy/templates/preload.html.haml +3 -5
- data/lib/rails/generators/joosy/widget_generator.rb +8 -1
- data/lib/rails/resources_with_joosy.rb +11 -0
- data/spec/javascripts/helpers/spec_helper.js.coffee +25 -0
- data/spec/javascripts/joosy/core/application_spec.js.coffee +40 -0
- data/spec/javascripts/joosy/core/form_spec.js.coffee +200 -0
- data/spec/javascripts/joosy/core/helpers/forms_spec.js.coffee +103 -0
- data/spec/javascripts/joosy/core/helpers/view_spec.js.coffee +10 -0
- data/spec/javascripts/joosy/core/joosy_spec.js.coffee +97 -0
- data/spec/javascripts/joosy/core/layout_spec.js.coffee +50 -0
- data/spec/javascripts/joosy/core/modules/container_spec.js.coffee +32 -27
- data/spec/javascripts/joosy/core/modules/events_spec.js.coffee +55 -18
- data/spec/javascripts/joosy/core/modules/filters_spec.js.coffee +28 -27
- data/spec/javascripts/joosy/core/modules/log_spec.js.coffee +3 -3
- data/spec/javascripts/joosy/core/modules/module_spec.js.coffee +6 -15
- data/spec/javascripts/joosy/core/modules/renderer_spec.js.coffee +203 -0
- data/spec/javascripts/joosy/core/modules/time_manager_spec.js.coffee +12 -7
- data/spec/javascripts/joosy/core/modules/widget_manager_spec.js.coffee +31 -17
- data/spec/javascripts/joosy/core/page_spec.js.coffee +178 -0
- data/spec/javascripts/joosy/core/resource/collection_spec.js.coffee +84 -0
- data/spec/javascripts/joosy/core/resource/generic_spec.js.coffee +149 -0
- data/spec/javascripts/joosy/core/resource/rest_collection_spec.js.coffee +31 -0
- data/spec/javascripts/joosy/core/resource/rest_spec.js.coffee +171 -0
- data/spec/javascripts/joosy/core/router_spec.js.coffee +143 -0
- data/spec/javascripts/joosy/core/templaters/rails_jst_spec.js.coffee +25 -0
- data/spec/javascripts/joosy/core/widget_spec.js.coffee +40 -0
- data/spec/javascripts/joosy/preloaders/caching_spec.js.coffee +36 -0
- data/spec/javascripts/joosy/preloaders/inline_spec.js.coffee +16 -0
- data/spec/javascripts/support/assets/coolface.jpg +0 -0
- data/spec/javascripts/support/assets/okay.jpg +0 -0
- data/spec/javascripts/support/assets/test.js +1 -0
- data/spec/javascripts/support/sinon-ie-1.3.1.js +82 -0
- data/vendor/assets/javascripts/jquery.form.js +978 -963
- data/vendor/assets/javascripts/metamorph.js +409 -0
- data/vendor/assets/javascripts/sugar.js +1057 -366
- metadata +95 -50
- data/README.rdoc +0 -3
- data/lib/joosy/forms.rb +0 -47
- data/lib/joosy-rails.rb +0 -5
- data/lib/rails/generators/joosy/templates/preload.html.slim +0 -21
- data/tmp/javascripts/.gitignore +0 -1
- data/tmp/spec/javascripts/helpers/.gitignore +0 -1
- data/vendor/assets/javascripts/base64.js +0 -135
- data/vendor/assets/javascripts/inflection.js +0 -656
- data/vendor/assets/javascripts/joosy/core/application.js.coffee +0 -26
- data/vendor/assets/javascripts/joosy/core/form.js.coffee +0 -87
- data/vendor/assets/javascripts/joosy/core/joosy.js.coffee +0 -62
- data/vendor/assets/javascripts/joosy/core/layout.js.coffee +0 -38
- data/vendor/assets/javascripts/joosy/core/modules/container.js.coffee +0 -51
- data/vendor/assets/javascripts/joosy/core/modules/events.js.coffee +0 -17
- data/vendor/assets/javascripts/joosy/core/modules/filters.js.coffee +0 -39
- data/vendor/assets/javascripts/joosy/core/modules/log.js.coffee +0 -12
- data/vendor/assets/javascripts/joosy/core/modules/module.js.coffee +0 -28
- data/vendor/assets/javascripts/joosy/core/modules/time_manager.js.coffee +0 -23
- data/vendor/assets/javascripts/joosy/core/modules/widgets_manager.js.coffee +0 -45
- data/vendor/assets/javascripts/joosy/core/page.js.coffee +0 -136
- data/vendor/assets/javascripts/joosy/core/resource/rest.js.coffee +0 -69
- data/vendor/assets/javascripts/joosy/core/resource/rest_collection.js.coffee +0 -42
- data/vendor/assets/javascripts/joosy/core/router.js.coffee +0 -75
- data/vendor/assets/javascripts/joosy/core/widget.js.coffee +0 -35
- data/vendor/assets/javascripts/joosy/preloader/development.js.coffee +0 -27
- data/vendor/assets/javascripts/joosy/preloader/production.js.coffee +0 -84
@@ -8,36 +8,42 @@
|
|
8
8
|
// native objects. IE8 does not have defineProperies, however, so this check saves a try/catch block.
|
9
9
|
var definePropertySupport = object.defineProperty && object.defineProperties;
|
10
10
|
|
11
|
+
// Class extending methods
|
12
|
+
|
11
13
|
function extend(klass, instance, override, methods) {
|
12
|
-
var extendee = instance ? klass.prototype : klass;
|
14
|
+
var extendee = instance ? klass.prototype : klass, original;
|
13
15
|
initializeClass(klass, instance, methods);
|
14
16
|
iterateOverObject(methods, function(name, method) {
|
17
|
+
original = extendee[name];
|
15
18
|
if(typeof override === 'function') {
|
16
|
-
|
17
|
-
}
|
19
|
+
method = wrapNative(extendee[name], method, override);
|
20
|
+
}
|
21
|
+
if(override !== false || !extendee[name]) {
|
18
22
|
defineProperty(extendee, name, method);
|
19
23
|
}
|
20
24
|
// If the method is internal to Sugar, then store a reference so it can be restored later.
|
21
|
-
klass['SugarMethods'][name] = { instance: instance, method: method };
|
25
|
+
klass['SugarMethods'][name] = { instance: instance, method: method, original: original };
|
22
26
|
});
|
23
27
|
}
|
24
28
|
|
25
29
|
function initializeClass(klass) {
|
26
30
|
if(klass.SugarMethods) return;
|
27
31
|
defineProperty(klass, 'SugarMethods', {});
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
32
|
+
extend(klass, false, false, {
|
33
|
+
'restore': function() {
|
34
|
+
var all = arguments.length === 0, methods = multiArgs(arguments);
|
35
|
+
iterateOverObject(klass['SugarMethods'], function(name, m) {
|
36
|
+
if(all || methods.has(name)) {
|
37
|
+
defineProperty(m.instance ? klass.prototype : klass, name, m.method);
|
38
|
+
}
|
39
|
+
});
|
40
|
+
},
|
41
|
+
'extend': function(methods, override, instance) {
|
42
|
+
if(klass === object && arguments.length === 0) {
|
43
|
+
mapObjectPrototypeMethods();
|
44
|
+
} else {
|
45
|
+
extend(klass, instance !== false, override, methods);
|
33
46
|
}
|
34
|
-
});
|
35
|
-
});
|
36
|
-
defineProperty(klass, 'extend', function(methods, override, instance) {
|
37
|
-
if(klass === object && arguments.length === 0) {
|
38
|
-
mapObjectPrototypeMethods();
|
39
|
-
} else {
|
40
|
-
extend(klass, instance !== false, override, methods);
|
41
47
|
}
|
42
48
|
});
|
43
49
|
}
|
@@ -60,48 +66,18 @@
|
|
60
66
|
}
|
61
67
|
}
|
62
68
|
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
fn.call(obj, key, obj[key], count);
|
68
|
-
count++;
|
69
|
-
}
|
69
|
+
// Object helpers
|
70
|
+
|
71
|
+
function hasOwnProperty(obj, key) {
|
72
|
+
return object.prototype.hasOwnProperty.call(obj, key);
|
70
73
|
}
|
71
74
|
|
72
|
-
function
|
73
|
-
var
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
} else if(primitive == 'RegExp') {
|
79
|
-
return a.ignoreCase == b.ignoreCase &&
|
80
|
-
a.multiline == b.multiline &&
|
81
|
-
a.source == b.source &&
|
82
|
-
a.global == b.global;
|
83
|
-
} else if(primitive == 'Array' || primitive == 'Object') {
|
84
|
-
// This method for checking for cyclic structures was egregiously stolen from
|
85
|
-
// the ingenious method by @kitcambridge from the Underscore script... ref:
|
86
|
-
// https://github.com/documentcloud/underscore/issues/240
|
87
|
-
var length = stack.length;
|
88
|
-
while (length--) {
|
89
|
-
if (stack[length] == a) return true;
|
90
|
-
}
|
91
|
-
stack.push(a);
|
92
|
-
for(var key in a) {
|
93
|
-
if(!a.hasOwnProperty(key)) continue;
|
94
|
-
if(!b.hasOwnProperty(key) || !equal(a[key], b[key], stack)) {
|
95
|
-
return false;
|
96
|
-
}
|
97
|
-
}
|
98
|
-
stack.pop();
|
99
|
-
return object.keys(a).length === object.keys(b).length &&
|
100
|
-
a.constructor === b.constructor &&
|
101
|
-
a.length === b.length;
|
102
|
-
} else {
|
103
|
-
return isClass(b, primitive) && a.valueOf() === b.valueOf();
|
104
|
-
}
|
75
|
+
function iterateOverObject(obj, fn) {
|
76
|
+
var key;
|
77
|
+
for(key in obj) {
|
78
|
+
if(!hasOwnProperty(obj, key)) continue;
|
79
|
+
fn.call(obj, key, obj[key]);
|
80
|
+
}
|
105
81
|
}
|
106
82
|
|
107
83
|
function multiMatch(el, match, scope, params) {
|
@@ -128,6 +104,52 @@
|
|
128
104
|
}
|
129
105
|
}
|
130
106
|
|
107
|
+
function stringify(thing, stack) {
|
108
|
+
var value, klass, isObject, isArray, arr, i, key, type = typeof thing;
|
109
|
+
|
110
|
+
// Return quickly if string to save cycles
|
111
|
+
if(type === 'string') return thing;
|
112
|
+
|
113
|
+
klass = object.prototype.toString.call(thing)
|
114
|
+
isObject = klass === '[object Object]';
|
115
|
+
isArray = klass === '[object Array]';
|
116
|
+
|
117
|
+
if(thing != null && isObject || isArray) {
|
118
|
+
// This method for checking for cyclic structures was egregiously stolen from
|
119
|
+
// the ingenious method by @kitcambridge from the Underscore script:
|
120
|
+
// https://github.com/documentcloud/underscore/issues/240
|
121
|
+
if(!stack) stack = [];
|
122
|
+
// Allowing a step into the structure before triggering this
|
123
|
+
// script to save cycles on standard JSON structures and also to
|
124
|
+
// try as hard as possible to catch basic properties that may have
|
125
|
+
// been modified.
|
126
|
+
if(stack.length > 1) {
|
127
|
+
i = stack.length;
|
128
|
+
while (i--) {
|
129
|
+
if (stack[i] === thing) {
|
130
|
+
return 'CYC';
|
131
|
+
}
|
132
|
+
}
|
133
|
+
}
|
134
|
+
stack.push(thing);
|
135
|
+
value = string(thing.constructor);
|
136
|
+
arr = isArray ? thing : object.keys(thing).sort();
|
137
|
+
for(i = 0; i < arr.length; i++) {
|
138
|
+
key = isArray ? i : arr[i];
|
139
|
+
value += key + stringify(thing[key], stack);
|
140
|
+
}
|
141
|
+
stack.pop();
|
142
|
+
} else if(1 / thing === -Infinity) {
|
143
|
+
value = '-0';
|
144
|
+
} else {
|
145
|
+
value = string(thing);
|
146
|
+
}
|
147
|
+
return type + klass + value;
|
148
|
+
}
|
149
|
+
|
150
|
+
|
151
|
+
// Argument helpers
|
152
|
+
|
131
153
|
function transformArgument(el, map, context, mapArgs) {
|
132
154
|
if(isUndefined(map)) {
|
133
155
|
return el;
|
@@ -146,11 +168,12 @@
|
|
146
168
|
|
147
169
|
function multiArgs(args, fn, flatten, index) {
|
148
170
|
args = getArgs(args);
|
149
|
-
if(flatten
|
171
|
+
if(flatten === true) args = arrayFlatten(args, 1);
|
150
172
|
arrayEach(args, fn || function(){}, index);
|
151
173
|
return args;
|
152
174
|
}
|
153
175
|
|
176
|
+
|
154
177
|
// Used for both arrays and strings
|
155
178
|
|
156
179
|
function entryAtIndex(arr, args, str) {
|
@@ -179,40 +202,10 @@
|
|
179
202
|
return object.prototype.toString.call(obj) === '[object '+str+']';
|
180
203
|
}
|
181
204
|
|
182
|
-
function isObjectPrimitive(o) {
|
183
|
-
return typeof o == 'object';
|
184
|
-
}
|
185
|
-
|
186
|
-
function isNull(o) {
|
187
|
-
return o === null;
|
188
|
-
}
|
189
|
-
|
190
205
|
function isUndefined(o) {
|
191
206
|
return o === Undefined;
|
192
207
|
}
|
193
208
|
|
194
|
-
function isDefined(o) {
|
195
|
-
return o !== Undefined;
|
196
|
-
}
|
197
|
-
|
198
|
-
function mergeObject(target, source, deep, resolve) {
|
199
|
-
if(isObjectPrimitive(source)) {
|
200
|
-
iterateOverObject(source, function(key, val) {
|
201
|
-
var prop = target[key], conflict = isDefined(prop), isArray = object.isArray(val);
|
202
|
-
if(deep === true && (isArray || object.isObject(val))) {
|
203
|
-
if(!prop) prop = isArray ? [] : {};
|
204
|
-
mergeObject(prop, val, deep);
|
205
|
-
} else if(conflict && object.isFunction(resolve)) {
|
206
|
-
prop = resolve.call(source, key, target[key], source[key])
|
207
|
-
} else if(!conflict || (conflict && resolve !== false)) {
|
208
|
-
prop = source[key];
|
209
|
-
}
|
210
|
-
target[key] = prop;
|
211
|
-
});
|
212
|
-
}
|
213
|
-
return target;
|
214
|
-
}
|
215
|
-
|
216
209
|
function setParamsObject(obj, param, value, deep) {
|
217
210
|
var reg = /^(.+?)(\[.*\])$/, isArray, match, allKeys, key;
|
218
211
|
if(deep !== false && (match = param.match(reg))) {
|
@@ -247,13 +240,11 @@
|
|
247
240
|
});
|
248
241
|
}
|
249
242
|
|
250
|
-
Hash.prototype.constructor = object;
|
251
|
-
|
252
243
|
/***
|
253
244
|
* @method is[Type](<obj>)
|
254
245
|
* @returns Boolean
|
255
246
|
* @short Returns true if <obj> is an object of that type.
|
256
|
-
* @extra %isObject% will return false on anything that is not an object literal, including instances of inherited classes. Note also that %isNaN% will ONLY return true if the object IS %NaN%. It does not mean the same as browser native %isNaN%, which returns true for anything that is "not a number". Type methods are available as instance methods on extended objects
|
247
|
+
* @extra %isObject% will return false on anything that is not an object literal, including instances of inherited classes. Note also that %isNaN% will ONLY return true if the object IS %NaN%. It does not mean the same as browser native %isNaN%, which returns true for anything that is "not a number". Type methods are available as instance methods on extended objects.
|
257
248
|
* @example
|
258
249
|
*
|
259
250
|
* Object.isArray([1,2,3]) -> true
|
@@ -285,10 +276,15 @@
|
|
285
276
|
***/
|
286
277
|
|
287
278
|
|
279
|
+
var ObjectTypeMethods = ['isObject','isNaN'];
|
280
|
+
var ObjectHashMethods = ['keys','values','each','merge','isEmpty','clone','equal','watch','tap','has']
|
281
|
+
|
288
282
|
function buildTypeMethods() {
|
289
|
-
var methods = {};
|
283
|
+
var methods = {}, name;
|
290
284
|
arrayEach(['Array','Boolean','Date','Function','Number','String','RegExp'], function(type) {
|
291
|
-
|
285
|
+
name = 'is' + type;
|
286
|
+
ObjectTypeMethods.push(name);
|
287
|
+
methods[name] = function(obj) {
|
292
288
|
return isClass(obj, type);
|
293
289
|
}
|
294
290
|
});
|
@@ -307,11 +303,11 @@
|
|
307
303
|
|
308
304
|
function buildObject() {
|
309
305
|
buildTypeMethods();
|
310
|
-
buildInstanceMethods(
|
306
|
+
buildInstanceMethods(ObjectHashMethods, Hash);
|
311
307
|
}
|
312
308
|
|
313
309
|
function mapObjectPrototypeMethods() {
|
314
|
-
buildInstanceMethods(
|
310
|
+
buildInstanceMethods(ObjectTypeMethods.concat(ObjectHashMethods), Object);
|
315
311
|
}
|
316
312
|
|
317
313
|
extend(object, false, true, {
|
@@ -319,7 +315,7 @@
|
|
319
315
|
* @method watch(<obj>, <prop>, <fn>)
|
320
316
|
* @returns Nothing
|
321
317
|
* @short Watches a property of <obj> and runs <fn> when it changes.
|
322
|
-
* @extra <fn> is passed three arguments: the property <prop>, the old value, and the new value. The return value of [fn] will be set as the new value. This method is useful for things such as validating or cleaning the value when it is set. Warning: this method WILL NOT work in browsers that don't support %Object.defineProperty%. This notably includes IE 8 and below, and Opera. This is the only method in Sugar that is not fully compatible with all browsers. %watch% is available as an instance method on extended objects
|
318
|
+
* @extra <fn> is passed three arguments: the property <prop>, the old value, and the new value. The return value of [fn] will be set as the new value. This method is useful for things such as validating or cleaning the value when it is set. Warning: this method WILL NOT work in browsers that don't support %Object.defineProperty%. This notably includes IE 8 and below, and Opera. This is the only method in Sugar that is not fully compatible with all browsers. %watch% is available as an instance method on extended objects.
|
323
319
|
* @example
|
324
320
|
*
|
325
321
|
* Object.watch({ foo: 'bar' }, 'foo', function(prop, oldVal, newVal) {
|
@@ -369,10 +365,11 @@
|
|
369
365
|
* @set isType
|
370
366
|
***/
|
371
367
|
'isObject': function(obj) {
|
372
|
-
if(
|
368
|
+
if(obj == null) {
|
373
369
|
return false;
|
374
370
|
} else {
|
375
|
-
|
371
|
+
// === on the constructor is not safe across iframes
|
372
|
+
return isClass(obj, 'Object') && string(obj.constructor) === string(object) || obj.constructor === Hash;
|
376
373
|
}
|
377
374
|
},
|
378
375
|
|
@@ -389,7 +386,7 @@
|
|
389
386
|
* @method each(<obj>, [fn])
|
390
387
|
* @returns Object
|
391
388
|
* @short Iterates over each property in <obj> calling [fn] on each iteration.
|
392
|
-
* @extra %each% is available as an instance method on extended objects
|
389
|
+
* @extra %each% is available as an instance method on extended objects.
|
393
390
|
* @example
|
394
391
|
*
|
395
392
|
* Object.each({ broken:'wear' }, function(key, value) {
|
@@ -410,29 +407,62 @@
|
|
410
407
|
},
|
411
408
|
|
412
409
|
/***
|
413
|
-
* @method merge(<target>, <source>, [resolve] = true)
|
410
|
+
* @method merge(<target>, <source>, [deep] = false, [resolve] = true)
|
414
411
|
* @returns Merged object
|
415
412
|
* @short Merges all the properties of <source> into <target>.
|
416
|
-
* @extra Properties of <source> will win in the case of conflicts, unless [resolve] is %false%. [resolve] can also be a function that resolves the conflict. In this case it will be passed 3 arguments, %key%, %targetVal%, and %sourceVal%, with the context set to <source>. This will allow you to solve conflict any way you want, ie. adding two numbers together, etc. %merge% is available as an instance method on extended objects
|
413
|
+
* @extra Merges are shallow unless [deep] is %true%. Properties of <source> will win in the case of conflicts, unless [resolve] is %false%. [resolve] can also be a function that resolves the conflict. In this case it will be passed 3 arguments, %key%, %targetVal%, and %sourceVal%, with the context set to <source>. This will allow you to solve conflict any way you want, ie. adding two numbers together, etc. %merge% is available as an instance method on extended objects.
|
417
414
|
* @example
|
418
415
|
*
|
419
416
|
* Object.merge({a:1},{b:2}) -> { a:1, b:2 }
|
420
|
-
* Object.merge({a:1},{a:2}, false) -> { a:1 }
|
421
|
-
+ Object.merge({a:1},{a:2}, function(key, a, b) {
|
417
|
+
* Object.merge({a:1},{a:2}, false, false) -> { a:1 }
|
418
|
+
+ Object.merge({a:1},{a:2}, false, function(key, a, b) {
|
422
419
|
* return a + b;
|
423
420
|
* }); -> { a:3 }
|
424
421
|
* Object.extended({a:1}).merge({b:2}) -> { a:1, b:2 }
|
425
422
|
*
|
426
423
|
***/
|
427
|
-
'merge': function(target,
|
428
|
-
|
424
|
+
'merge': function(target, source, deep, resolve) {
|
425
|
+
var key, val;
|
426
|
+
// Strings cannot be reliably merged thanks to
|
427
|
+
// their properties not being enumerable in < IE8.
|
428
|
+
if(target && typeof source != 'string') {
|
429
|
+
for(key in source) {
|
430
|
+
if(!hasOwnProperty(source, key) || !target) continue;
|
431
|
+
val = source[key];
|
432
|
+
// Conflict!
|
433
|
+
if(target[key] !== Undefined) {
|
434
|
+
// Do not merge.
|
435
|
+
if(resolve === false) {
|
436
|
+
continue;
|
437
|
+
}
|
438
|
+
// Use the result of the callback as the result.
|
439
|
+
if(object.isFunction(resolve)) {
|
440
|
+
val = resolve.call(source, key, target[key], source[key])
|
441
|
+
}
|
442
|
+
}
|
443
|
+
// Deep merging.
|
444
|
+
if(deep === true && val && typeof val === 'object') {
|
445
|
+
if(object.isDate(val)) {
|
446
|
+
val = new Date(val.getTime());
|
447
|
+
} else if(object.isRegExp(val)) {
|
448
|
+
val = new RegExp(val.source, val.getFlags());
|
449
|
+
} else {
|
450
|
+
if(!target[key]) target[key] = array.isArray(val) ? [] : {};
|
451
|
+
Object.merge(target[key], source[key], deep, resolve);
|
452
|
+
continue;
|
453
|
+
}
|
454
|
+
}
|
455
|
+
target[key] = val;
|
456
|
+
}
|
457
|
+
}
|
458
|
+
return target;
|
429
459
|
},
|
430
460
|
|
431
461
|
/***
|
432
462
|
* @method isEmpty(<obj>)
|
433
463
|
* @returns Boolean
|
434
464
|
* @short Returns true if <obj> is empty.
|
435
|
-
* @extra %isEmpty% is available as an instance method on extended objects
|
465
|
+
* @extra %isEmpty% is available as an instance method on extended objects.
|
436
466
|
* @example
|
437
467
|
*
|
438
468
|
* Object.isEmpty({}) -> true
|
@@ -441,7 +471,7 @@
|
|
441
471
|
*
|
442
472
|
***/
|
443
473
|
'isEmpty': function(obj) {
|
444
|
-
if(
|
474
|
+
if(obj == null || typeof obj != 'object') return !(obj && obj.length > 0);
|
445
475
|
return object.keys(obj).length == 0;
|
446
476
|
},
|
447
477
|
|
@@ -449,7 +479,7 @@
|
|
449
479
|
* @method equal(<a>, <b>)
|
450
480
|
* @returns Boolean
|
451
481
|
* @short Returns true if <a> and <b> are equal.
|
452
|
-
* @extra %
|
482
|
+
* @extra %equal% in Sugar is "egal", meaning the values are equal if they are "not observably distinguishable". Note that on extended objects the name is %equals% for readability.
|
453
483
|
* @example
|
454
484
|
*
|
455
485
|
* Object.equal({a:2}, {a:2}) -> true
|
@@ -458,14 +488,14 @@
|
|
458
488
|
*
|
459
489
|
***/
|
460
490
|
'equal': function(a, b) {
|
461
|
-
return
|
491
|
+
return stringify(a) === stringify(b);
|
462
492
|
},
|
463
493
|
|
464
494
|
/***
|
465
495
|
* @method values(<obj>, [fn])
|
466
496
|
* @returns Array
|
467
497
|
* @short Returns an array containing the values in <obj>. Optionally calls [fn] for each value.
|
468
|
-
* @extra Returned values are in no particular order. %values% is available as an instance method on extended objects
|
498
|
+
* @extra Returned values are in no particular order. %values% is available as an instance method on extended objects.
|
469
499
|
* @example
|
470
500
|
*
|
471
501
|
* Object.values({ broken: 'wear' }) -> ['wear']
|
@@ -488,7 +518,7 @@
|
|
488
518
|
* @method clone(<obj> = {}, [deep] = false)
|
489
519
|
* @returns Cloned object
|
490
520
|
* @short Creates a clone (copy) of <obj>.
|
491
|
-
* @extra Default is a shallow clone, unless [deep] is true. %clone% is available as an instance method on extended objects
|
521
|
+
* @extra Default is a shallow clone, unless [deep] is true. %clone% is available as an instance method on extended objects.
|
492
522
|
* @example
|
493
523
|
*
|
494
524
|
* Object.clone({foo:'bar'}) -> { foo: 'bar' }
|
@@ -497,9 +527,10 @@
|
|
497
527
|
*
|
498
528
|
***/
|
499
529
|
'clone': function(obj, deep) {
|
500
|
-
if(
|
501
|
-
|
502
|
-
|
530
|
+
if(obj == null || typeof obj !== 'object') return obj;
|
531
|
+
if(array.isArray(obj)) return obj.clone();
|
532
|
+
var target = obj.constructor === Hash ? new Hash() : {};
|
533
|
+
return object.merge(target, obj, deep);
|
503
534
|
},
|
504
535
|
|
505
536
|
/***
|
@@ -539,6 +570,21 @@
|
|
539
570
|
'tap': function(obj, fn) {
|
540
571
|
transformArgument(obj, fn, obj, [obj]);
|
541
572
|
return obj;
|
573
|
+
},
|
574
|
+
|
575
|
+
/***
|
576
|
+
* @method has(<obj>, <key>)
|
577
|
+
* @returns Boolean
|
578
|
+
* @short Checks if <obj> has <key> using hasOwnProperty from Object.prototype.
|
579
|
+
* @extra This method is considered safer than %Object#hasOwnProperty% when using objects as hashes. See %http://www.devthought.com/2012/01/18/an-object-is-not-a-hash/% for more.
|
580
|
+
* @example
|
581
|
+
*
|
582
|
+
* Object.has({ foo: 'bar' }, 'foo') -> true
|
583
|
+
* Object.has({ foo: 'bar' }, 'baz') -> false
|
584
|
+
* Object.has({ hasOwnProperty: true }, 'foo') -> false
|
585
|
+
***/
|
586
|
+
'has': function (obj, key) {
|
587
|
+
return hasOwnProperty(obj, key);
|
542
588
|
}
|
543
589
|
|
544
590
|
});
|
@@ -550,7 +596,7 @@
|
|
550
596
|
* @method keys(<obj>, [fn])
|
551
597
|
* @returns Array
|
552
598
|
* @short Returns an array containing the keys in <obj>. Optionally calls [fn] for each key.
|
553
|
-
* @extra This method is provided for browsers that don't support it natively, and additionally is enhanced to accept the callback [fn]. Returned keys are in no particular order. %keys% is available as an instance method on extended objects
|
599
|
+
* @extra This method is provided for browsers that don't support it natively, and additionally is enhanced to accept the callback [fn]. Returned keys are in no particular order. %keys% is available as an instance method on extended objects.
|
554
600
|
* @example
|
555
601
|
*
|
556
602
|
* Object.keys({ broken: 'wear' }) -> ['broken']
|
@@ -561,7 +607,7 @@
|
|
561
607
|
*
|
562
608
|
***/
|
563
609
|
'keys': function(obj, fn) {
|
564
|
-
if(
|
610
|
+
if(obj == null || typeof obj != 'object' && !object.isRegExp(obj) && !object.isFunction(obj)) {
|
565
611
|
throw new TypeError('Object required');
|
566
612
|
}
|
567
613
|
var keys = [];
|
@@ -587,7 +633,6 @@
|
|
587
633
|
***/
|
588
634
|
|
589
635
|
|
590
|
-
|
591
636
|
// Basic array internal methods
|
592
637
|
|
593
638
|
function arrayEach(arr, fn, startIndex, loop, sparse) {
|
@@ -619,19 +664,17 @@
|
|
619
664
|
return returnIndex ? index : result;
|
620
665
|
}
|
621
666
|
|
622
|
-
function existsInArray(arr, obj) {
|
623
|
-
return arr.any(function(el) {
|
624
|
-
return object.equal(obj, el);
|
625
|
-
});
|
626
|
-
}
|
627
|
-
|
628
667
|
function arrayUnique(arr, map) {
|
629
|
-
var
|
630
|
-
|
631
|
-
|
632
|
-
|
633
|
-
|
634
|
-
|
668
|
+
var result = [], o = {}, stringified, transformed;
|
669
|
+
arrayEach(arr, function(el, i) {
|
670
|
+
transformed = map ? transformArgument(el, map, arr, [el, i, arr]) : el;
|
671
|
+
stringified = stringify(transformed);
|
672
|
+
if(!arrayObjectExists(o, stringified, el)) {
|
673
|
+
o[stringified] = transformed;
|
674
|
+
result.push(el);
|
675
|
+
}
|
676
|
+
})
|
677
|
+
return result;
|
635
678
|
}
|
636
679
|
|
637
680
|
function arrayFlatten(arr, level, current) {
|
@@ -649,18 +692,27 @@
|
|
649
692
|
}
|
650
693
|
|
651
694
|
function arrayIntersect(arr1, arr2, subtract) {
|
652
|
-
var result = [];
|
695
|
+
var result = [], o = {};
|
696
|
+
arr2.each(function(el) {
|
697
|
+
o[stringify(el)] = el;
|
698
|
+
});
|
653
699
|
arr1.each(function(el) {
|
700
|
+
var stringified = stringify(el), exists = arrayObjectExists(o, stringified, el);
|
654
701
|
// Add the result to the array if:
|
655
702
|
// 1. We're subtracting intersections or it doesn't already exist in the result and
|
656
703
|
// 2. It exists in the compared array and we're adding, or it doesn't exist and we're removing.
|
657
|
-
if(
|
704
|
+
if(exists != subtract) {
|
705
|
+
delete o[stringified];
|
658
706
|
result.push(el);
|
659
707
|
}
|
660
708
|
});
|
661
709
|
return result;
|
662
710
|
}
|
663
711
|
|
712
|
+
function arrayObjectExists(hash, stringified, obj) {
|
713
|
+
return stringified in hash && (typeof obj !== 'function' || obj === hash[stringified]);
|
714
|
+
}
|
715
|
+
|
664
716
|
// ECMA5 methods
|
665
717
|
|
666
718
|
function arrayIndexOf(arr, search, fromIndex, increment) {
|
@@ -684,7 +736,7 @@
|
|
684
736
|
}
|
685
737
|
|
686
738
|
function arrayReduce(arr, fn, initialValue, fromRight) {
|
687
|
-
var length = arr.length, count = 0, defined =
|
739
|
+
var length = arr.length, count = 0, defined = initialValue !== Undefined, result, index;
|
688
740
|
checkCallback(fn);
|
689
741
|
if(length == 0 && !defined) {
|
690
742
|
throw new TypeError('Reduce called on empty array with no initial value');
|
@@ -754,9 +806,7 @@
|
|
754
806
|
iterateOverObject(obj, function(key) {
|
755
807
|
var entry = obj[key];
|
756
808
|
var test = transformArgument(entry, map, obj, isArray? [entry, key.toNumber(), obj] : []);
|
757
|
-
if(
|
758
|
-
return;
|
759
|
-
} else if(test === edge) {
|
809
|
+
if(test === edge) {
|
760
810
|
result.push(entry);
|
761
811
|
} else if((max && test > edge) || (min && test < edge)) {
|
762
812
|
result = [entry];
|
@@ -767,6 +817,74 @@
|
|
767
817
|
}
|
768
818
|
|
769
819
|
|
820
|
+
// Alphanumeric collation helpers
|
821
|
+
|
822
|
+
function collateStrings(a, b) {
|
823
|
+
var aValue, bValue, aChar, bChar, aEquiv, bEquiv, index = 0, tiebreaker = 0;
|
824
|
+
a = getCollationReadyString(a);
|
825
|
+
b = getCollationReadyString(b);
|
826
|
+
do {
|
827
|
+
aChar = getCollationCharacter(a, index);
|
828
|
+
bChar = getCollationCharacter(b, index);
|
829
|
+
aValue = getCollationValue(aChar);
|
830
|
+
bValue = getCollationValue(bChar);
|
831
|
+
if(aValue === -1 || bValue === -1) {
|
832
|
+
aValue = a.charCodeAt(index) || null;
|
833
|
+
bValue = b.charCodeAt(index) || null;
|
834
|
+
}
|
835
|
+
aEquiv = aChar !== a.charAt(index);
|
836
|
+
bEquiv = bChar !== b.charAt(index);
|
837
|
+
if(aEquiv !== bEquiv && tiebreaker === 0) {
|
838
|
+
tiebreaker = aEquiv - bEquiv;
|
839
|
+
}
|
840
|
+
index += 1;
|
841
|
+
} while(aValue != null && bValue != null && aValue === bValue);
|
842
|
+
if(aValue === bValue) return tiebreaker;
|
843
|
+
return aValue < bValue ? -1 : 1;
|
844
|
+
}
|
845
|
+
|
846
|
+
function getCollationReadyString(str) {
|
847
|
+
if(array[AlphanumericSortIgnoreCase]) {
|
848
|
+
str = str.toLowerCase();
|
849
|
+
}
|
850
|
+
return str.remove(array[AlphanumericSortIgnore]);
|
851
|
+
}
|
852
|
+
|
853
|
+
function getCollationCharacter(str, index) {
|
854
|
+
var chr = str.charAt(index), eq = array[AlphanumericSortEquivalents] || {};
|
855
|
+
return eq[chr] || chr;
|
856
|
+
}
|
857
|
+
|
858
|
+
function getCollationValue(chr) {
|
859
|
+
if(!chr) {
|
860
|
+
return null;
|
861
|
+
} else {
|
862
|
+
return array[AlphanumericSortOrder].indexOf(chr);
|
863
|
+
}
|
864
|
+
}
|
865
|
+
|
866
|
+
var AlphanumericSortOrder = 'AlphanumericSortOrder';
|
867
|
+
var AlphanumericSortIgnore = 'AlphanumericSortIgnore';
|
868
|
+
var AlphanumericSortIgnoreCase = 'AlphanumericSortIgnoreCase';
|
869
|
+
var AlphanumericSortEquivalents = 'AlphanumericSortEquivalents';
|
870
|
+
|
871
|
+
function buildArray() {
|
872
|
+
var order = 'AÁÀÂÃĄBCĆČÇDĎÐEÉÈĚÊËĘFGĞHıIÍÌİÎÏJKLŁMNŃŇÑOÓÒÔPQRŘSŚŠŞTŤUÚÙŮÛÜVWXYÝZŹŻŽÞÆŒØÕÅÄÖ';
|
873
|
+
var equiv = 'AÁÀÂÃÄ,CÇ,EÉÈÊË,IÍÌİÎÏ,OÓÒÔÕÖ,Sß,UÚÙÛÜ';
|
874
|
+
array[AlphanumericSortOrder] = order.split('').map(function(str) {
|
875
|
+
return str + str.toLowerCase();
|
876
|
+
}).join('');
|
877
|
+
var equivalents = {};
|
878
|
+
equiv.split(',').each(function(set) {
|
879
|
+
var equivalent = set.charAt(0);
|
880
|
+
set.slice(1).chars(function(chr) {
|
881
|
+
equivalents[chr] = equivalent;
|
882
|
+
equivalents[chr.toLowerCase()] = equivalent.toLowerCase();
|
883
|
+
});
|
884
|
+
});
|
885
|
+
array[AlphanumericSortIgnoreCase] = true;
|
886
|
+
array[AlphanumericSortEquivalents] = equivalents;
|
887
|
+
}
|
770
888
|
|
771
889
|
extend(array, false, false, {
|
772
890
|
|
@@ -1099,7 +1217,7 @@
|
|
1099
1217
|
***/
|
1100
1218
|
'findIndex': function(f, startIndex, loop) {
|
1101
1219
|
var index = arrayFind(this, f, startIndex, loop, true);
|
1102
|
-
return
|
1220
|
+
return isUndefined(index) ? -1 : index;
|
1103
1221
|
},
|
1104
1222
|
|
1105
1223
|
/***
|
@@ -1164,7 +1282,7 @@
|
|
1164
1282
|
i++;
|
1165
1283
|
}
|
1166
1284
|
}
|
1167
|
-
}
|
1285
|
+
});
|
1168
1286
|
return arr;
|
1169
1287
|
},
|
1170
1288
|
|
@@ -1250,7 +1368,7 @@
|
|
1250
1368
|
*
|
1251
1369
|
***/
|
1252
1370
|
'clone': function() {
|
1253
|
-
return
|
1371
|
+
return object.merge([], this);
|
1254
1372
|
},
|
1255
1373
|
|
1256
1374
|
/***
|
@@ -1284,8 +1402,8 @@
|
|
1284
1402
|
***/
|
1285
1403
|
'union': function() {
|
1286
1404
|
var arr = this;
|
1287
|
-
multiArgs(arguments, function(
|
1288
|
-
arr = arr.concat(
|
1405
|
+
multiArgs(arguments, function(arg) {
|
1406
|
+
arr = arr.concat(arg);
|
1289
1407
|
});
|
1290
1408
|
return arrayUnique(arr);
|
1291
1409
|
},
|
@@ -1301,7 +1419,7 @@
|
|
1301
1419
|
*
|
1302
1420
|
***/
|
1303
1421
|
'intersect': function() {
|
1304
|
-
return arrayIntersect(this, multiArgs(arguments), false);
|
1422
|
+
return arrayIntersect(this, multiArgs(arguments, null, true), false);
|
1305
1423
|
},
|
1306
1424
|
|
1307
1425
|
/***
|
@@ -1316,7 +1434,7 @@
|
|
1316
1434
|
*
|
1317
1435
|
***/
|
1318
1436
|
'subtract': function(a) {
|
1319
|
-
return arrayIntersect(this, multiArgs(arguments), true);
|
1437
|
+
return arrayIntersect(this, multiArgs(arguments, null, true), true);
|
1320
1438
|
},
|
1321
1439
|
|
1322
1440
|
/***
|
@@ -1623,7 +1741,7 @@
|
|
1623
1741
|
result.push(el.compact());
|
1624
1742
|
} else if(all && el) {
|
1625
1743
|
result.push(el);
|
1626
|
-
} else if(!all &&
|
1744
|
+
} else if(!all && el != null && !object.isNaN(el)) {
|
1627
1745
|
result.push(el);
|
1628
1746
|
}
|
1629
1747
|
});
|
@@ -1664,7 +1782,7 @@
|
|
1664
1782
|
* @method sortBy(<map>, [desc] = false)
|
1665
1783
|
* @returns Array
|
1666
1784
|
* @short Sorts the array by <map>.
|
1667
|
-
* @extra <map> may be a function
|
1785
|
+
* @extra <map> may be a function, a string acting as a shortcut, or blank (direct comparison of array values). [desc] will sort the array in descending order. When the field being sorted on is a string, the resulting order will be determined by an internal algorithm that is optimized for major Western languages, but can be customized. For more information see @array_sorting.
|
1668
1786
|
* @example
|
1669
1787
|
*
|
1670
1788
|
* ['world','a','new'].sortBy('length') -> ['a','new','world']
|
@@ -1680,10 +1798,14 @@
|
|
1680
1798
|
var aProperty, bProperty, comp;
|
1681
1799
|
aProperty = transformArgument(a, map, arr, [a]);
|
1682
1800
|
bProperty = transformArgument(b, map, arr, [b]);
|
1683
|
-
if(aProperty &&
|
1684
|
-
comp = aProperty
|
1801
|
+
if(object.isString(aProperty) && object.isString(bProperty)) {
|
1802
|
+
comp = collateStrings(aProperty, bProperty);
|
1803
|
+
} else if(aProperty < bProperty) {
|
1804
|
+
comp = -1;
|
1805
|
+
} else if(aProperty > bProperty) {
|
1806
|
+
comp = 1;
|
1685
1807
|
} else {
|
1686
|
-
comp =
|
1808
|
+
comp = 0;
|
1687
1809
|
}
|
1688
1810
|
return comp * (desc ? -1 : 1);
|
1689
1811
|
});
|
@@ -1749,7 +1871,6 @@
|
|
1749
1871
|
return arguments.length > 0 ? result : result[0];
|
1750
1872
|
}
|
1751
1873
|
|
1752
|
-
|
1753
1874
|
});
|
1754
1875
|
|
1755
1876
|
|
@@ -1855,8 +1976,8 @@
|
|
1855
1976
|
'random': function(n1, n2) {
|
1856
1977
|
var min, max;
|
1857
1978
|
if(arguments.length == 1) n2 = n1, n1 = 0;
|
1858
|
-
min = Math.min(n1 || 0,
|
1859
|
-
max = Math.max(n1 || 0,
|
1979
|
+
min = Math.min(n1 || 0, isUndefined(n2) ? 1 : n2);
|
1980
|
+
max = Math.max(n1 || 0, isUndefined(n2) ? 1 : n2);
|
1860
1981
|
return round((Math.random() * (max - min)) + min);
|
1861
1982
|
}
|
1862
1983
|
|
@@ -1908,7 +2029,7 @@
|
|
1908
2029
|
*
|
1909
2030
|
***/
|
1910
2031
|
'metric': function(precision, limit) {
|
1911
|
-
return abbreviateNumber(this, precision, 'nμm kMGTPE', 4,
|
2032
|
+
return abbreviateNumber(this, precision, 'nμm kMGTPE', 4, isUndefined(limit) ? 1 : limit);
|
1912
2033
|
},
|
1913
2034
|
|
1914
2035
|
/***
|
@@ -1925,7 +2046,7 @@
|
|
1925
2046
|
*
|
1926
2047
|
***/
|
1927
2048
|
'bytes': function(precision, limit) {
|
1928
|
-
return abbreviateNumber(this, precision, 'kMGTPE', 0,
|
2049
|
+
return abbreviateNumber(this, precision, 'kMGTPE', 0, isUndefined(limit) ? 4 : limit, true) + 'B';
|
1929
2050
|
},
|
1930
2051
|
|
1931
2052
|
/***
|
@@ -2231,22 +2352,6 @@
|
|
2231
2352
|
***/
|
2232
2353
|
'hex': function(pad) {
|
2233
2354
|
return this.pad(pad || 1, false, 16);
|
2234
|
-
},
|
2235
|
-
|
2236
|
-
/***
|
2237
|
-
* @method compare(<num>)
|
2238
|
-
* @returns Number
|
2239
|
-
* @short Performs a numeric comparison against the number.
|
2240
|
-
* @extra This method is also defined on %String% and %Date%, and is useful when performing complex sort operations where the type isn't known.
|
2241
|
-
* @example
|
2242
|
-
*
|
2243
|
-
* (255).compare(254) -> 1;
|
2244
|
-
* (245).compare(254) -> -9;
|
2245
|
-
* (0).compare(0) -> 0;
|
2246
|
-
*
|
2247
|
-
***/
|
2248
|
-
'compare': function(num) {
|
2249
|
-
return this - Number(num);
|
2250
2355
|
}
|
2251
2356
|
|
2252
2357
|
});
|
@@ -2473,8 +2578,13 @@
|
|
2473
2578
|
return string.Inflector && string.Inflector.acronyms && string.Inflector.acronyms[word];
|
2474
2579
|
}
|
2475
2580
|
|
2581
|
+
var btoa, atob;
|
2582
|
+
|
2476
2583
|
function buildBase64(key) {
|
2477
|
-
if(
|
2584
|
+
if(this.btoa) {
|
2585
|
+
btoa = this.btoa;
|
2586
|
+
atob = this.atob;
|
2587
|
+
}
|
2478
2588
|
var base64reg = /[^A-Za-z0-9\+\/\=]/g;
|
2479
2589
|
btoa = function(str) {
|
2480
2590
|
var output = '';
|
@@ -2531,8 +2641,6 @@
|
|
2531
2641
|
}
|
2532
2642
|
}
|
2533
2643
|
|
2534
|
-
|
2535
|
-
|
2536
2644
|
function buildTrim() {
|
2537
2645
|
var support = getTrimmableCharacters().match(/^\s+$/);
|
2538
2646
|
try { string.prototype.trim.call([1]); } catch(e) { support = false; }
|
@@ -2705,7 +2813,7 @@
|
|
2705
2813
|
*
|
2706
2814
|
***/
|
2707
2815
|
'capitalize': function(all) {
|
2708
|
-
var reg = all ?
|
2816
|
+
var reg = all ? /^\S|\s\S/g : /^\S/;
|
2709
2817
|
return this.toLowerCase().replace(reg, function(letter) {
|
2710
2818
|
return letter.toUpperCase();
|
2711
2819
|
});
|
@@ -2769,7 +2877,7 @@
|
|
2769
2877
|
},
|
2770
2878
|
|
2771
2879
|
/***
|
2772
|
-
* @method each([search] =
|
2880
|
+
* @method each([search] = single character, [fn])
|
2773
2881
|
* @returns Array
|
2774
2882
|
* @short Runs callback [fn] against each occurence of [search].
|
2775
2883
|
* @extra Returns an array of matches. [search] may be either a string or regex, and defaults to every character in the string.
|
@@ -2785,9 +2893,9 @@
|
|
2785
2893
|
'each': function(search, fn) {
|
2786
2894
|
if(object.isFunction(search)) {
|
2787
2895
|
fn = search;
|
2788
|
-
search =
|
2896
|
+
search = /[\s\S]/g;
|
2789
2897
|
} else if(!search) {
|
2790
|
-
search =
|
2898
|
+
search = /[\s\S]/g
|
2791
2899
|
} else if(object.isString(search)) {
|
2792
2900
|
search = regexp(regexp.escape(search), 'gi');
|
2793
2901
|
} else if(object.isRegExp(search)) {
|
@@ -2856,7 +2964,7 @@
|
|
2856
2964
|
*
|
2857
2965
|
***/
|
2858
2966
|
'chars': function(fn) {
|
2859
|
-
return this.
|
2967
|
+
return this.each(fn);
|
2860
2968
|
},
|
2861
2969
|
|
2862
2970
|
/***
|
@@ -2980,7 +3088,7 @@
|
|
2980
3088
|
*
|
2981
3089
|
***/
|
2982
3090
|
'has': function(find) {
|
2983
|
-
return this.search(find) !== -1;
|
3091
|
+
return this.search(object.isRegExp(find) ? find : RegExp.escape(find)) !== -1;
|
2984
3092
|
},
|
2985
3093
|
|
2986
3094
|
|
@@ -3137,8 +3245,9 @@
|
|
3137
3245
|
*
|
3138
3246
|
***/
|
3139
3247
|
'compact': function() {
|
3140
|
-
|
3141
|
-
|
3248
|
+
return this.trim().replace(/([\r\n\s ])+/g, function(match, whitespace){
|
3249
|
+
return whitespace === ' ' ? whitespace : ' ';
|
3250
|
+
});
|
3142
3251
|
},
|
3143
3252
|
|
3144
3253
|
/***
|
@@ -3171,7 +3280,7 @@
|
|
3171
3280
|
*
|
3172
3281
|
***/
|
3173
3282
|
'first': function(num) {
|
3174
|
-
|
3283
|
+
if(isUndefined(num)) num = 1;
|
3175
3284
|
return this.substr(0, num);
|
3176
3285
|
},
|
3177
3286
|
|
@@ -3186,7 +3295,7 @@
|
|
3186
3295
|
*
|
3187
3296
|
***/
|
3188
3297
|
'last': function(num) {
|
3189
|
-
|
3298
|
+
if(isUndefined(num)) num = 1;
|
3190
3299
|
var start = this.length - num < 0 ? 0 : this.length - num;
|
3191
3300
|
return this.substr(start);
|
3192
3301
|
},
|
@@ -3346,28 +3455,51 @@
|
|
3346
3455
|
},
|
3347
3456
|
|
3348
3457
|
/***
|
3349
|
-
* @method truncate(<length>, [
|
3458
|
+
* @method truncate(<length>, [split] = true, from = 'right', [ellipsis] = '...')
|
3350
3459
|
* @returns Object
|
3351
3460
|
* @short Truncates a string.
|
3352
|
-
* @extra
|
3353
|
-
* @example
|
3354
|
-
*
|
3355
|
-
* 'just sittin on the dock of the bay'.truncate(20)
|
3356
|
-
* 'just sittin on the dock of the bay'.truncate(20,
|
3357
|
-
* 'just sittin on the dock of the bay'.truncate(20,
|
3358
|
-
*
|
3359
|
-
|
3360
|
-
|
3361
|
-
|
3362
|
-
|
3363
|
-
|
3364
|
-
|
3365
|
-
|
3366
|
-
|
3367
|
-
|
3368
|
-
|
3461
|
+
* @extra If [split] is %false%, will not split words up, and instead discard the word where the truncation occurred. [from] can also be %"middle"% or %"left"%.
|
3462
|
+
* @example
|
3463
|
+
*
|
3464
|
+
* 'just sittin on the dock of the bay'.truncate(20) -> 'just sittin on the do...'
|
3465
|
+
* 'just sittin on the dock of the bay'.truncate(20, false) -> 'just sittin on the...'
|
3466
|
+
* 'just sittin on the dock of the bay'.truncate(20, true, 'middle') -> 'just sitt...of the bay'
|
3467
|
+
* 'just sittin on the dock of the bay'.truncate(20, true, 'middle') -> '...the dock of the bay'
|
3468
|
+
*
|
3469
|
+
***/
|
3470
|
+
'truncate': function(length, split, from, ellipsis) {
|
3471
|
+
var pos,
|
3472
|
+
prepend = '',
|
3473
|
+
append = '',
|
3474
|
+
str = this.toString(),
|
3475
|
+
chars = '[' + getTrimmableCharacters() + ']+',
|
3476
|
+
space = '[^' + getTrimmableCharacters() + ']*',
|
3477
|
+
reg = regexp(chars + space + '$');
|
3478
|
+
ellipsis = isUndefined(ellipsis) ? '...' : string(ellipsis);
|
3479
|
+
if(str.length <= length) {
|
3480
|
+
return str;
|
3481
|
+
}
|
3482
|
+
switch(from) {
|
3483
|
+
case 'left':
|
3484
|
+
pos = str.length - length;
|
3485
|
+
prepend = ellipsis;
|
3486
|
+
str = str.slice(pos);
|
3487
|
+
reg = regexp('^' + space + chars);
|
3488
|
+
break;
|
3489
|
+
case 'middle':
|
3490
|
+
pos = Math.floor(length / 2);
|
3491
|
+
append = ellipsis + str.slice(str.length - pos).trimLeft();
|
3492
|
+
str = str.slice(0, pos);
|
3493
|
+
break;
|
3494
|
+
default:
|
3495
|
+
pos = length;
|
3496
|
+
append = ellipsis;
|
3497
|
+
str = str.slice(0, pos);
|
3498
|
+
}
|
3499
|
+
if(split === false && this.slice(pos, pos + 1).match(/\S/)) {
|
3500
|
+
str = str.remove(reg);
|
3369
3501
|
}
|
3370
|
-
return
|
3502
|
+
return prepend + str + append;
|
3371
3503
|
},
|
3372
3504
|
|
3373
3505
|
/***
|
@@ -3392,32 +3524,8 @@
|
|
3392
3524
|
}
|
3393
3525
|
});
|
3394
3526
|
return this.replace(/\{(.+?)\}/g, function(m, key) {
|
3395
|
-
return
|
3527
|
+
return hasOwnProperty(assign, key) ? assign[key] : m;
|
3396
3528
|
});
|
3397
|
-
},
|
3398
|
-
|
3399
|
-
/***
|
3400
|
-
* @method compare(<str>, [ignore] = false)
|
3401
|
-
* @returns Number
|
3402
|
-
* @short Performs a lexical (alphabetic) comparison against the number.
|
3403
|
-
* @extra This method is also defined on %Number% and %Date%, and is useful when performing complex sort operations where the type isn't known. If [ignore] is %true%, will ignore any non-alphanumeric character when performing comparison. [ignore] can also be a regexp.
|
3404
|
-
* @example
|
3405
|
-
*
|
3406
|
-
* ('a').compare('b') -> -1;
|
3407
|
-
* ('b').compare('a') -> 1;
|
3408
|
-
* ('a').compare('a') -> 0;
|
3409
|
-
* ('a').compare('@a', true) -> 0;
|
3410
|
-
*
|
3411
|
-
***/
|
3412
|
-
'compare': function(cmp, ignore) {
|
3413
|
-
var str = this, cmp = String(cmp);
|
3414
|
-
if(ignore === true) ignore = /\W/g;
|
3415
|
-
if(ignore) {
|
3416
|
-
cmp = cmp.remove(ignore);
|
3417
|
-
str = str.remove(ignore);
|
3418
|
-
}
|
3419
|
-
if(str == cmp) return 0;
|
3420
|
-
else return str < cmp ? -1 : 1;
|
3421
3529
|
}
|
3422
3530
|
|
3423
3531
|
});
|
@@ -3548,7 +3656,7 @@
|
|
3548
3656
|
***/
|
3549
3657
|
'escape': function(str) {
|
3550
3658
|
if(!object.isString(str)) str = String(str);
|
3551
|
-
return str.replace(/([
|
3659
|
+
return str.replace(/([\\/'*+?|()\[\]{}.^$])/g,'\\$1');
|
3552
3660
|
}
|
3553
3661
|
|
3554
3662
|
});
|
@@ -3619,6 +3727,7 @@
|
|
3619
3727
|
|
3620
3728
|
function setDelay(fn, ms, after, scope, args) {
|
3621
3729
|
if(!fn.timers) fn.timers = [];
|
3730
|
+
if(!object.isNumber(ms)) ms = 0;
|
3622
3731
|
fn.timers.push(setTimeout(function(){
|
3623
3732
|
fn.timers.removeAt(index);
|
3624
3733
|
after.apply(scope, args || []);
|
@@ -3696,12 +3805,12 @@
|
|
3696
3805
|
*
|
3697
3806
|
***/
|
3698
3807
|
'lazy': function(ms, limit) {
|
3699
|
-
var fn = this, queue = [], lock = false, rounded, perExecution;
|
3808
|
+
var fn = this, queue = [], lock = false, execute, rounded, perExecution;
|
3700
3809
|
ms = ms || 1;
|
3701
3810
|
limit = limit || Infinity;
|
3702
3811
|
rounded = ms.ceil();
|
3703
3812
|
perExecution = round(rounded / ms);
|
3704
|
-
|
3813
|
+
execute = function() {
|
3705
3814
|
if(lock || queue.length == 0) return;
|
3706
3815
|
var max = Math.max(queue.length - perExecution, 0);
|
3707
3816
|
while(queue.length > max) {
|
@@ -3738,36 +3847,43 @@
|
|
3738
3847
|
***/
|
3739
3848
|
'delay': function(ms) {
|
3740
3849
|
var fn = this;
|
3741
|
-
if(!object.isNumber(ms)) ms = 0;
|
3742
3850
|
var args = getArgs(arguments, 1);
|
3743
3851
|
setDelay(fn, ms, fn, fn, args);
|
3744
3852
|
return fn;
|
3745
3853
|
},
|
3746
3854
|
|
3747
3855
|
/***
|
3748
|
-
* @method
|
3856
|
+
* @method throttle(<ms>)
|
3749
3857
|
* @returns Function
|
3750
|
-
* @short
|
3751
|
-
* @
|
3858
|
+
* @short Creates a throttled version of the function that will only be executed once per <ms> milliseconds.
|
3859
|
+
* @example
|
3860
|
+
*
|
3861
|
+
* var fn = (function(arg1) {
|
3862
|
+
* // called immediately and will wait 50ms until it responds again
|
3863
|
+
* }).throttle(50); fn() fn() fn();
|
3864
|
+
*
|
3865
|
+
***/
|
3866
|
+
'throttle': function(ms) {
|
3867
|
+
return this.lazy(ms, 1);
|
3868
|
+
},
|
3869
|
+
|
3870
|
+
/***
|
3871
|
+
* @method debounce(<ms>)
|
3872
|
+
* @returns Function
|
3873
|
+
* @short Creates a "debounced" function that postpones its execution until after <ms> milliseconds have passed.
|
3874
|
+
* @extra This method is useful to execute a function after things have "settled down". A good example of this is when a user tabs quickly through form fields, execution of a heavy operation should happen after a few milliseconds when they have "settled" on a field.
|
3752
3875
|
* @example
|
3753
3876
|
*
|
3754
3877
|
* var fn = (function(arg1) {
|
3755
3878
|
* // called once 50ms later
|
3756
3879
|
* }).debounce(50); fn() fn() fn();
|
3757
|
-
* var fn = (function(arg1) {
|
3758
|
-
* // called immediately and will wait 50ms until it responds again
|
3759
|
-
* }).debounce(50, false); fn() fn() fn();
|
3760
3880
|
*
|
3761
3881
|
***/
|
3762
|
-
'debounce': function(ms
|
3882
|
+
'debounce': function(ms) {
|
3763
3883
|
var fn = this;
|
3764
|
-
|
3765
|
-
|
3766
|
-
|
3767
|
-
return function() {
|
3768
|
-
fn.cancel();
|
3769
|
-
setDelay(fn, ms, fn, this, arguments);
|
3770
|
-
}
|
3884
|
+
return function() {
|
3885
|
+
fn.cancel();
|
3886
|
+
setDelay(fn, ms, fn, this, arguments);
|
3771
3887
|
}
|
3772
3888
|
},
|
3773
3889
|
|
@@ -3840,7 +3956,7 @@
|
|
3840
3956
|
'once': function() {
|
3841
3957
|
var fn = this;
|
3842
3958
|
return function() {
|
3843
|
-
return
|
3959
|
+
return hasOwnProperty(fn, 'memo') ? fn['memo'] : fn['memo'] = fn.apply(this, arguments);
|
3844
3960
|
}
|
3845
3961
|
},
|
3846
3962
|
|
@@ -3862,7 +3978,7 @@
|
|
3862
3978
|
return function() {
|
3863
3979
|
var args = getArgs(arguments);
|
3864
3980
|
arrayEach(curried, function(arg, index) {
|
3865
|
-
if(
|
3981
|
+
if(arg != null || index >= args.length) args.splice(index, 0, arg);
|
3866
3982
|
});
|
3867
3983
|
return fn.apply(this, args);
|
3868
3984
|
}
|
@@ -3876,13 +3992,18 @@
|
|
3876
3992
|
buildObject();
|
3877
3993
|
buildString();
|
3878
3994
|
buildFunction();
|
3995
|
+
buildArray();
|
3879
3996
|
initializeClass(date);
|
3880
3997
|
|
3998
|
+
Object.initializeClass = initializeClass;
|
3999
|
+
|
4000
|
+
|
3881
4001
|
})();
|
4002
|
+
// Google Closure Compiler will output a wrapping function here.
|
3882
4003
|
(function() {
|
3883
4004
|
|
3884
|
-
|
3885
|
-
var regexp = RegExp, object = Object, date = Date, number = Number, Undefined;
|
4005
|
+
// A few optimizations for Google Closure Compiler will save us a couple kb in the release script.
|
4006
|
+
var regexp = RegExp, object = Object, date = Date, number = Number, Undefined, English;
|
3886
4007
|
|
3887
4008
|
function isDefined(o) {
|
3888
4009
|
return o !== Undefined;
|
@@ -3898,9 +4019,11 @@
|
|
3898
4019
|
*
|
3899
4020
|
***/
|
3900
4021
|
|
3901
|
-
var TimeFormat = ['hour','minute','second','
|
3902
|
-
var
|
4022
|
+
var TimeFormat = ['hour','minute','second','meridian','utc','offset_sign','offset_hours','offset_minutes']
|
4023
|
+
var FloatReg = '\\d{1,2}(?:[,.]\\d+)?';
|
4024
|
+
var RequiredTime = '('+FloatReg+'):?('+FloatReg+')?:?('+FloatReg+')?(am|pm)?(?:(Z)|(?:([+-])(\\d{2})(?::?(\\d{2}))?)?)?';
|
3903
4025
|
var OptionalTime = '\\s*(?:(?:t|at |\\s+)' + RequiredTime + ')?';
|
4026
|
+
|
3904
4027
|
var LowerAsianDigits = '一二三四五六七八九';
|
3905
4028
|
var UpperAsianDigits = '十百千万';
|
3906
4029
|
var AsianDigitReg = regexp('[' + LowerAsianDigits + UpperAsianDigits + ']', 'g');
|
@@ -4106,80 +4229,55 @@
|
|
4106
4229
|
|
4107
4230
|
var CommonLocales = {
|
4108
4231
|
|
4109
|
-
'en': '2;;January,February,March,April,May,June,July,August,September,October,November,December;Sunday,Monday,Tuesday,Wednesday,Thursday,Friday,Saturday;millisecond:|s,second:|s,minute:|s,hour:|s,day:|s,week:|s,month:|s,year:|s;one,two,three,four,five,six,seven,eight,nine,ten;a,an,the;the,st|nd|rd|th,of;{num} {unit} {sign},{num} {unit=4-5} {sign} {day},{weekday?} {month} {date}{
|
4232
|
+
'en': '2;;January,February,March,April,May,June,July,August,September,October,November,December;Sunday,Monday,Tuesday,Wednesday,Thursday,Friday,Saturday;millisecond:|s,second:|s,minute:|s,hour:|s,day:|s,week:|s,month:|s,year:|s;one,two,three,four,five,six,seven,eight,nine,ten;a,an,the;the,st|nd|rd|th,of;{num} {unit} {sign},{num} {unit=4-5} {sign} {day},{weekday?} {month} {date}{1} {year?} {time?},{date} {month} {year},{month} {year},{shift?} {weekday} {time?},{shift} week {weekday} {time?},{shift} {unit=5-7},{0} {edge} of {shift?} {unit=4-7?}{month?}{year?},{weekday} {2} {shift} week,{0} {date}{1} of {month},{0}{month?} {date?}{1} of {shift} {unit=6-7},{day} at {time?},{time} {day};{Month} {d}, {yyyy};,yesterday,today,tomorrow;,ago|before,,from now|after|from;,last,the|this,next;last day,end,,first day|beginning',
|
4110
4233
|
|
4111
4234
|
'ja': '1;月;;日曜日,月曜日,火曜日,水曜日,木曜日,金曜日,土曜日;ミリ秒,秒,分,時間,日,週間|週,ヶ月|ヵ月|月,年;;;;{num}{unit}{sign},{shift}{unit=5-7}{weekday?},{year}年{month?}月?{date?}日?,{month}月{date?}日?,{date}日;{yyyy}年{M}月{d}日;一昨日,昨日,今日,明日,明後日;,前,,後;,去|先,,来',
|
4112
4235
|
|
4113
4236
|
'ko': '1;월;;일요일,월요일,화요일,수요일,목요일,금요일,토요일;밀리초,초,분,시간,일,주,개월|달,년;일|한,이,삼,사,오,육,칠,팔,구,십;;;{num}{unit} {sign},{shift} {unit=5-7},{shift} {unit=5?} {weekday},{year}년{month?}월?{date?}일?,{month}월{date?}일?,{date}일;{yyyy}년{M}월{d}일;그저께,어제,오늘,내일,모레;,전,,후;,지난|작,이번,다음|내',
|
4114
4237
|
|
4115
|
-
'ru': '4;;Январ:я|ь,Феврал:я|ь,Март:а|,Апрел:я|ь,Ма:я|й,Июн:я|ь,Июл:я|ь,Август:а|,Сентябр:я|ь,Октябр:я|ь,Ноябр:я|ь,Декабр:я|ь;Воскресенье,Понедельник,Вторник,Среда,Четверг,Пятница,Суббота;миллисекунд:а|у|ы|,секунд:а|у|ы|,минут:а|у|ы|,час:||а|ов,день|день|дня|дней,недел:я|ю|и|ь|е,месяц:||а|ев|е,год|год|года|лет|году;од:ин|ну,дв:а|е,три,четыре,пять,шесть,семь,восемь,девять,десять;;в|на,года;{num} {unit} {sign},{sign} {num} {unit},{date} {month} {year?} {
|
4238
|
+
'ru': '4;;Январ:я|ь,Феврал:я|ь,Март:а|,Апрел:я|ь,Ма:я|й,Июн:я|ь,Июл:я|ь,Август:а|,Сентябр:я|ь,Октябр:я|ь,Ноябр:я|ь,Декабр:я|ь;Воскресенье,Понедельник,Вторник,Среда,Четверг,Пятница,Суббота;миллисекунд:а|у|ы|,секунд:а|у|ы|,минут:а|у|ы|,час:||а|ов,день|день|дня|дней,недел:я|ю|и|ь|е,месяц:||а|ев|е,год|год|года|лет|году;од:ин|ну,дв:а|е,три,четыре,пять,шесть,семь,восемь,девять,десять;;в|на,года;{num} {unit} {sign},{sign} {num} {unit},{date} {month} {year?} {1},{month} {year},{0} {shift} {unit=5-7};{d} {month} {yyyy} года;позавчера,вчера,сегодня,завтра,послезавтра;,назад,,через;,прошло:й|м,,следующе:й|м',
|
4116
4239
|
|
4117
|
-
'es': '6;;enero,febrero,marzo,abril,mayo,junio,julio,agosto,septiembre,octubre,noviembre,diciembre;domingo,lunes,martes,miércoles|miercoles,jueves,viernes,sábado|sabado;milisegundo:|s,segundo:|s,minuto:|s,hora:|s,día|días|dia|dias,semana:|s,mes:|es,año|años|ano|anos;uno,dos,tres,cuatro,cinco,seis,siete,ocho,nueve,diez;;el,de;{sign} {num} {unit},{num} {unit} {sign},{date?} {
|
4240
|
+
'es': '6;;enero,febrero,marzo,abril,mayo,junio,julio,agosto,septiembre,octubre,noviembre,diciembre;domingo,lunes,martes,miércoles|miercoles,jueves,viernes,sábado|sabado;milisegundo:|s,segundo:|s,minuto:|s,hora:|s,día|días|dia|dias,semana:|s,mes:|es,año|años|ano|anos;uno,dos,tres,cuatro,cinco,seis,siete,ocho,nueve,diez;;el,de;{sign} {num} {unit},{num} {unit} {sign},{date?} {1} {month} {1} {year?},{0} {unit=5-7} {shift},{0} {shift} {unit=5-7};{d} de {month} de {yyyy};anteayer,ayer,hoy,mañana|manana;,hace,,de ahora;,pasad:o|a,,próximo|próxima|proximo|proxima',
|
4118
4241
|
|
4119
|
-
'pt': '6;;janeiro,fevereiro,março,abril,maio,junho,julho,agosto,setembro,outubro,novembro,dezembro;domingo,segunda-feira,terça-feira,quarta-feira,quinta-feira,sexta-feira,sábado|sabado;milisegundo:|s,segundo:|s,minuto:|s,hora:|s,dia:|s,semana:|s,mês|mêses|mes|meses,ano:|s;um,dois,três|tres,quatro,cinco,seis,sete,oito,nove,dez,uma,duas;;a,de;{num} {unit} {sign},{sign} {num} {unit},{date?} {
|
4242
|
+
'pt': '6;;janeiro,fevereiro,março,abril,maio,junho,julho,agosto,setembro,outubro,novembro,dezembro;domingo,segunda-feira,terça-feira,quarta-feira,quinta-feira,sexta-feira,sábado|sabado;milisegundo:|s,segundo:|s,minuto:|s,hora:|s,dia:|s,semana:|s,mês|mêses|mes|meses,ano:|s;um,dois,três|tres,quatro,cinco,seis,sete,oito,nove,dez,uma,duas;;a,de;{num} {unit} {sign},{sign} {num} {unit},{date?} {1} {month} {1} {year?},{0} {unit=5-7} {shift},{0} {shift} {unit=5-7};{d} de {month} de {yyyy};anteontem,ontem,hoje,amanh:ã|a;,atrás|atras|há|ha,,daqui a;,passad:o|a,,próximo|próxima|proximo|proxima',
|
4120
4243
|
|
4121
|
-
'fr': '2;;janvier,février|fevrier,mars,avril,mai,juin,juillet,août,septembre,octobre,novembre,décembre|decembre;dimanche,lundi,mardi,mercredi,jeudi,vendredi,samedi;milliseconde:|s,seconde:|s,minute:|s,heure:|s,jour:|s,semaine:|s,mois,an:|s|née|nee;un:|e,deux,trois,quatre,cinq,six,sept,huit,neuf,dix;;l\'|la|le;{sign} {num} {unit},{sign} {num} {unit},{
|
4244
|
+
'fr': '2;;janvier,février|fevrier,mars,avril,mai,juin,juillet,août,septembre,octobre,novembre,décembre|decembre;dimanche,lundi,mardi,mercredi,jeudi,vendredi,samedi;milliseconde:|s,seconde:|s,minute:|s,heure:|s,jour:|s,semaine:|s,mois,an:|s|née|nee;un:|e,deux,trois,quatre,cinq,six,sept,huit,neuf,dix;;l\'|la|le;{sign} {num} {unit},{sign} {num} {unit},{0} {date?} {month} {year?},{0} {unit=5-7} {shift};{d} {month} {yyyy};,hier,aujourd\'hui,demain;,il y a,,dans|d\'ici;,derni:er|ère|ere,,prochain:|e',
|
4122
4245
|
|
4123
|
-
'it': '2;;Gennaio,Febbraio,Marzo,Aprile,Maggio,Giugno,Luglio,Agosto,Settembre,Ottobre,Novembre,Dicembre;Domenica,Luned:ì|i,Marted:ì|i,Mercoled:ì|i,Gioved:ì|i,Venerd:ì|i,Sabato;millisecond:o|i,second:o|i,minut:o|i,or:a|e,giorn:o|i,settiman:a|e,mes:e|i,ann:o|i;un:|\'|a|o,due,tre,quattro,cinque,sei,sette,otto,nove,dieci;;l\'|la|il;{num} {unit} {sign},{weekday?} {date?} {month} {year?},{
|
4246
|
+
'it': '2;;Gennaio,Febbraio,Marzo,Aprile,Maggio,Giugno,Luglio,Agosto,Settembre,Ottobre,Novembre,Dicembre;Domenica,Luned:ì|i,Marted:ì|i,Mercoled:ì|i,Gioved:ì|i,Venerd:ì|i,Sabato;millisecond:o|i,second:o|i,minut:o|i,or:a|e,giorn:o|i,settiman:a|e,mes:e|i,ann:o|i;un:|\'|a|o,due,tre,quattro,cinque,sei,sette,otto,nove,dieci;;l\'|la|il;{num} {unit} {sign},{weekday?} {date?} {month} {year?},{0} {unit=5-7} {shift},{0} {shift} {unit=5-7};{d} {month} {yyyy};,ieri,oggi,domani,dopodomani;,fa,,da adesso;,scors:o|a,,prossim:o|a',
|
4124
4247
|
|
4125
4248
|
'de': '2;;Januar,Februar,März|Marz,April,Mai,Juni,Juli,August,September,Oktober,November,Dezember;Sonntag,Montag,Dienstag,Mittwoch,Donnerstag,Freitag,Samstag;Millisekunde:|n,Sekunde:|n,Minute:|n,Stunde:|n,Tag:|en,Woche:|n,Monat:|en,Jahr:|en;ein:|e|er|em|en,zwei,drei,vier,fuenf,sechs,sieben,acht,neun,zehn;;der;{sign} {num} {unit},{num} {unit} {sign},{num} {unit} {sign},{sign} {num} {unit},{weekday?} {date?} {month} {year?},{shift} {unit=5-7};{d}. {Month} {yyyy};vorgestern,gestern,heute,morgen,übermorgen|ubermorgen|uebermorgen;,vor:|her,,in;,letzte:|r|n|s,,nächste:|r|n|s+naechste:|r|n|s',
|
4126
4249
|
|
4127
|
-
'zh-TW': '1;月;;日,一,二,三,四,五,六;毫秒,秒鐘,分鐘,小時,天,個星期|週,個月,年;;;日|號;{num}{unit}{sign},星期{weekday},{shift}{unit=5-7},{shift}{unit=5}{weekday},{year}年{month?}月?{date?}{
|
4250
|
+
'zh-TW': '1;月;;日,一,二,三,四,五,六;毫秒,秒鐘,分鐘,小時,天,個星期|週,個月,年;;;日|號;{num}{unit}{sign},星期{weekday},{shift}{unit=5-7},{shift}{unit=5}{weekday},{year}年{month?}月?{date?}{0},{month}月{date?}{0},{date}{0};{yyyy}年{M}月{d}日;前天,昨天,今天,明天,後天;,前,,後;,上|去,這,下|明',
|
4128
4251
|
|
4129
|
-
'zh-CN': '1;月;;日,一,二,三,四,五,六;毫秒,秒钟,分钟,小时,天,个星期|周,个月,年;;;日|号;{num}{unit}{sign},星期{weekday},{shift}{unit=5-7},{shift}{unit=5}{weekday},{year}年{month?}月?{date?}{
|
4252
|
+
'zh-CN': '1;月;;日,一,二,三,四,五,六;毫秒,秒钟,分钟,小时,天,个星期|周,个月,年;;;日|号;{num}{unit}{sign},星期{weekday},{shift}{unit=5-7},{shift}{unit=5}{weekday},{year}年{month?}月?{date?}{0},{month}月{date?}{0},{date}{0};{yyyy}年{M}月{d}日;前天,昨天,今天,明天,后天;,前,,后;,上|去,这,下|明'
|
4130
4253
|
|
4131
4254
|
}
|
4132
4255
|
|
4133
4256
|
function checkLocaleFormatsAdded(loc) {
|
4134
|
-
var
|
4257
|
+
var code = loc['code'];
|
4135
4258
|
if(loc.formatsAdded) return;
|
4136
|
-
|
4137
|
-
|
4138
|
-
|
4259
|
+
addDateInputFormat('(' + loc['months'].compact().join('|') + ')', ['month'], code);
|
4260
|
+
addDateInputFormat('(' + loc['weekdays'].compact().join('|') + ')', ['weekday'], code);
|
4261
|
+
addDateInputFormat('(' + loc['modifiers'].filter(function(m){ return m.name === 'day'; }).map('src').join('|') + ')', ['day'], code);
|
4139
4262
|
loc['formats'].each(function(src) {
|
4140
|
-
|
4141
|
-
src = src.replace(/\s+/g, '[-,. ]*');
|
4142
|
-
src = src.replace(/\{(.+?)\}/g, function(all, k) {
|
4143
|
-
var opt = k.match(/\?$/), slice = k.match(/(\d)(?:-(\d))?/), nc = k.match(/^\d+$/), key = k.replace(/[^a-z]+$/, ''), value, arr;
|
4144
|
-
if(key === 'time') {
|
4145
|
-
to = to.concat(TimeFormat);
|
4146
|
-
return opt ? OptionalTime : RequiredTime;
|
4147
|
-
}
|
4148
|
-
if(nc) {
|
4149
|
-
value = loc['optionals'][nc[0] - 1];
|
4150
|
-
} else if(loc[key]) {
|
4151
|
-
value = loc[key];
|
4152
|
-
} else if(loc[key + 's']) {
|
4153
|
-
value = loc[key + 's'];
|
4154
|
-
if(slice) {
|
4155
|
-
// Can't use filter here as Prototype hijacks the method and doesn't
|
4156
|
-
// pass an index, so use a simple loop instead!
|
4157
|
-
arr = [];
|
4158
|
-
value.each(function(m,i) {
|
4159
|
-
var mod = i % (loc['units'] ? 8 : value.length);
|
4160
|
-
if(mod >= slice[1] && mod <= (slice[2] || slice[1])) {
|
4161
|
-
arr.push(m);
|
4162
|
-
}
|
4163
|
-
});
|
4164
|
-
value = arr;
|
4165
|
-
}
|
4166
|
-
value = value.compact().join('|');
|
4167
|
-
}
|
4168
|
-
if(nc) {
|
4169
|
-
return '(?:' + value + ')?';
|
4170
|
-
} else {
|
4171
|
-
to.push(key);
|
4172
|
-
return '(' + value + ')' + (opt ? '?' : '');
|
4173
|
-
}
|
4174
|
-
});
|
4175
|
-
addFormat(src, to, code);
|
4263
|
+
loc.addFormat(src, code, false);
|
4176
4264
|
});
|
4177
4265
|
loc.formatsAdded = true;
|
4178
4266
|
}
|
4179
4267
|
|
4268
|
+
function addDateInputFormat(format, match, locale, variant, method) {
|
4269
|
+
method = method || 'push';
|
4270
|
+
DateInputFormats[method]({
|
4271
|
+
variant: variant,
|
4272
|
+
locale: locale,
|
4273
|
+
reg: regexp('^' + format + '$', 'i'),
|
4274
|
+
to: match
|
4275
|
+
});
|
4276
|
+
}
|
4277
|
+
|
4180
4278
|
function getLocalization(code, fallback, set) {
|
4181
4279
|
if(fallback && (!object.isString(code) || !code)) code = Date['currentLocale'];
|
4182
|
-
if(code && !Localizations[code]) initializeLocalization(code, set);
|
4280
|
+
if(code && !Localizations[code] || set) initializeLocalization(code, set);
|
4183
4281
|
return Localizations[code];
|
4184
4282
|
}
|
4185
4283
|
|
@@ -4203,7 +4301,7 @@
|
|
4203
4301
|
function setArray(name, abbreviate, multiple) {
|
4204
4302
|
var arr = [];
|
4205
4303
|
if(!set[name]) return;
|
4206
|
-
set[name].
|
4304
|
+
set[name].forEach(function(el, i) {
|
4207
4305
|
eachAlternate(el, function(str, j) {
|
4208
4306
|
arr[j * multiple + i] = str.toLowerCase();
|
4209
4307
|
});
|
@@ -4230,13 +4328,13 @@
|
|
4230
4328
|
var arr = [];
|
4231
4329
|
set.modifiersByName = {};
|
4232
4330
|
set['modifiers'].each(function(modifier) {
|
4233
|
-
eachAlternate(modifier.
|
4331
|
+
eachAlternate(modifier.src, function(t) {
|
4234
4332
|
set.modifiersByName[t] = modifier;
|
4235
|
-
arr.push({ name: modifier.name,
|
4333
|
+
arr.push({ name: modifier.name, src: t, value: modifier.value });
|
4236
4334
|
});
|
4237
4335
|
});
|
4238
4336
|
arr.groupBy('name', function(name, group) {
|
4239
|
-
group = group.map('
|
4337
|
+
group = group.map('src');
|
4240
4338
|
if(name === 'day') group = group.concat(set['weekdays']);
|
4241
4339
|
set[name] = group.join('|');
|
4242
4340
|
});
|
@@ -4276,7 +4374,7 @@
|
|
4276
4374
|
['day','sign','shift','edge'].each(function(name, i) {
|
4277
4375
|
if(!pre[i + 10]) return;
|
4278
4376
|
pre[i + 10].split(',').each(function(t, j) {
|
4279
|
-
if(t) set['modifiers'].push({ name: name,
|
4377
|
+
if(t) set['modifiers'].push({ name: name, src: t, value: j - 2 });
|
4280
4378
|
});
|
4281
4379
|
});
|
4282
4380
|
if(bool(1)) {
|
@@ -4292,6 +4390,7 @@
|
|
4292
4390
|
set['hasPlural'] = bool(2);
|
4293
4391
|
set['pastRelativeFormat'] = set['formats'][0];
|
4294
4392
|
set['futureRelativeFormat'] = set['formats'][bool(3) ? 1 : 0];
|
4393
|
+
set['durationFormat'] = set['formats'][0].replace(/\s*\{sign\}\s*/, '');
|
4295
4394
|
return set;
|
4296
4395
|
}
|
4297
4396
|
|
@@ -4340,9 +4439,16 @@
|
|
4340
4439
|
return English['units'][this['units'].indexOf(n) % 8];
|
4341
4440
|
},
|
4342
4441
|
|
4343
|
-
relative: function(
|
4344
|
-
|
4345
|
-
|
4442
|
+
relative: function(adu) {
|
4443
|
+
return this.convertAdjustedToFormat(adu, adu[2] > 0 ? 'futureRelativeFormat' : 'pastRelativeFormat');
|
4444
|
+
},
|
4445
|
+
|
4446
|
+
duration: function(ms) {
|
4447
|
+
return this.convertAdjustedToFormat(getAdjustedUnit(ms), 'durationFormat');
|
4448
|
+
},
|
4449
|
+
|
4450
|
+
convertAdjustedToFormat: function(adu, format) {
|
4451
|
+
var num = adu[0], u = adu[1], ms = adu[2], sign, unit, last, mult;
|
4346
4452
|
if(this['code'] == 'ru') {
|
4347
4453
|
last = num.toString().from(-1);
|
4348
4454
|
switch(true) {
|
@@ -4356,7 +4462,47 @@
|
|
4356
4462
|
unit = this['units'][mult * 8 + u] || this['units'][u];
|
4357
4463
|
if(this['capitalizeUnit']) unit = unit.capitalize();
|
4358
4464
|
sign = this['modifiers'].find(function(m) { return m.name == 'sign' && m.value == (ms > 0 ? 1 : -1); });
|
4359
|
-
return format.assign({ 'num': num, 'unit': unit, 'sign': sign.
|
4465
|
+
return this[format].assign({ 'num': num, 'unit': unit, 'sign': sign.src });
|
4466
|
+
},
|
4467
|
+
|
4468
|
+
addFormat: function(src, code, add) {
|
4469
|
+
var to = [], loc = this;
|
4470
|
+
if(add !== false) loc.formats.push(src);
|
4471
|
+
src = src.replace(/\s+/g, '[-,. ]*');
|
4472
|
+
src = src.replace(/\{(.+?)\}/g, function(all, k) {
|
4473
|
+
var opt = k.match(/\?$/), slice = k.match(/(\d)(?:-(\d))?/), nc = k.match(/^\d+$/), key = k.replace(/[^a-z]+$/, ''), value, arr;
|
4474
|
+
if(key === 'time') {
|
4475
|
+
to = to.concat(TimeFormat);
|
4476
|
+
return opt ? OptionalTime : RequiredTime;
|
4477
|
+
}
|
4478
|
+
if(nc) {
|
4479
|
+
value = loc['optionals'][nc[0]];
|
4480
|
+
} else if(loc[key]) {
|
4481
|
+
value = loc[key];
|
4482
|
+
} else if(loc[key + 's']) {
|
4483
|
+
value = loc[key + 's'];
|
4484
|
+
if(slice) {
|
4485
|
+
// Can't use filter here as Prototype hijacks the method and doesn't
|
4486
|
+
// pass an index, so use a simple loop instead!
|
4487
|
+
arr = [];
|
4488
|
+
value.forEach(function(m, i) {
|
4489
|
+
var mod = i % (loc['units'] ? 8 : value.length);
|
4490
|
+
if(mod >= slice[1] && mod <= (slice[2] || slice[1])) {
|
4491
|
+
arr.push(m);
|
4492
|
+
}
|
4493
|
+
});
|
4494
|
+
value = arr;
|
4495
|
+
}
|
4496
|
+
value = value.compact().join('|');
|
4497
|
+
}
|
4498
|
+
if(nc) {
|
4499
|
+
return '(?:' + value + ')?';
|
4500
|
+
} else {
|
4501
|
+
to.push(key);
|
4502
|
+
return '(' + value + ')' + (opt ? '?' : '');
|
4503
|
+
}
|
4504
|
+
});
|
4505
|
+
addDateInputFormat(src, to, code);
|
4360
4506
|
}
|
4361
4507
|
|
4362
4508
|
});
|
@@ -4390,8 +4536,7 @@
|
|
4390
4536
|
if(isUndefined(value) || value === '') return;
|
4391
4537
|
value = convertAsianDigits(value.hankaku('n'), key);
|
4392
4538
|
if(key === 'year') obj.yearAsString = value;
|
4393
|
-
|
4394
|
-
num = parseFloat(value);
|
4539
|
+
num = parseFloat(value.replace(/,/, '.'));
|
4395
4540
|
obj[key] = !isNaN(num) ? num : value.toLowerCase();
|
4396
4541
|
});
|
4397
4542
|
return obj;
|
@@ -4473,7 +4618,7 @@
|
|
4473
4618
|
}
|
4474
4619
|
|
4475
4620
|
// Adjust for timezone offset
|
4476
|
-
if(
|
4621
|
+
if('offset_hours' in set || 'offset_minutes' in set) {
|
4477
4622
|
set['utc'] = true;
|
4478
4623
|
set['offset_minutes'] = set['offset_minutes'] || 0;
|
4479
4624
|
set['offset_minutes'] += set['offset_hours'] * 60;
|
@@ -4521,9 +4666,18 @@
|
|
4521
4666
|
// Finally shift the unit.
|
4522
4667
|
set[unit] = (set[unit] || 0) + num;
|
4523
4668
|
}
|
4669
|
+
|
4524
4670
|
if(set['year_sign'] === '-') {
|
4525
4671
|
set['year'] *= -1;
|
4526
4672
|
}
|
4673
|
+
|
4674
|
+
DateUnitsReversed.slice(1,4).each(function(u, i) {
|
4675
|
+
var value = set[u.unit], fraction = value % 1;
|
4676
|
+
if(fraction) {
|
4677
|
+
set[DateUnitsReversed[i].unit] = (fraction * (u.unit === 'second' ? 1000 : 60)).round();
|
4678
|
+
set[u.unit] = value | 0;
|
4679
|
+
}
|
4680
|
+
});
|
4527
4681
|
return false;
|
4528
4682
|
}
|
4529
4683
|
});
|
@@ -4534,6 +4688,9 @@
|
|
4534
4688
|
} else if(relative) {
|
4535
4689
|
d.advance(set);
|
4536
4690
|
} else if(set['utc']) {
|
4691
|
+
// UTC times can traverse into other days or even months,
|
4692
|
+
// so preemtively reset the time here to prevent this.
|
4693
|
+
d.resetTime();
|
4537
4694
|
d.setUTC(set, true);
|
4538
4695
|
} else {
|
4539
4696
|
d.set(set, true);
|
@@ -4569,20 +4726,20 @@
|
|
4569
4726
|
} else if(Date[f]) {
|
4570
4727
|
f = Date[f];
|
4571
4728
|
} else if(object.isFunction(f)) {
|
4572
|
-
adu =
|
4729
|
+
adu = getAdjustedUnit(date.millisecondsFromNow());
|
4573
4730
|
f = f.apply(date, adu.concat(loc));
|
4574
4731
|
}
|
4575
4732
|
if(!f && !relative) {
|
4576
4733
|
f = loc['outputFormat'];
|
4577
4734
|
} else if(!f && relative) {
|
4578
|
-
adu = adu ||
|
4735
|
+
adu = adu || getAdjustedUnit(date.millisecondsFromNow());
|
4579
4736
|
// Adjust up if time is in ms, as this doesn't
|
4580
4737
|
// look very good for a standard relative date.
|
4581
4738
|
if(adu[1] === 0) {
|
4582
4739
|
adu[1] = 1;
|
4583
4740
|
adu[0] = 1;
|
4584
4741
|
}
|
4585
|
-
return loc.relative(adu
|
4742
|
+
return loc.relative(adu);
|
4586
4743
|
}
|
4587
4744
|
DateOutputFormats.each(function(dof) {
|
4588
4745
|
f = f.replace(regexp('\\{('+dof.token+')(\\d)?\\}', dof.word ? 'i' : ''), function(m,t,d) {
|
@@ -4626,7 +4783,7 @@
|
|
4626
4783
|
var min = p.date.getTime();
|
4627
4784
|
var max = min + accuracy;
|
4628
4785
|
if(p.set && p.set.specificity == 'week' && new Date(max + 1).getHours() != 0) {
|
4629
|
-
max
|
4786
|
+
max += date['DSTOffset'];
|
4630
4787
|
}
|
4631
4788
|
return t >= (min - loBuffer) && t <= (max + hiBuffer);
|
4632
4789
|
}
|
@@ -4710,10 +4867,10 @@
|
|
4710
4867
|
return 1 + (date.daysSince(date.clone().beginningOfYear()) / 7 | 0);
|
4711
4868
|
}
|
4712
4869
|
|
4713
|
-
function
|
4714
|
-
var next,
|
4870
|
+
function getAdjustedUnit(ms) {
|
4871
|
+
var next, ams = ms.abs(), value = ams, unit = 0;
|
4715
4872
|
DateUnitsReversed.from(1).each(function(u, i) {
|
4716
|
-
next = (ams / u.multiplier()).round(
|
4873
|
+
next = (ams / u.multiplier() * 10).round() / 10 | 0;
|
4717
4874
|
if(next >= 1) {
|
4718
4875
|
value = next;
|
4719
4876
|
unit = i + 1;
|
@@ -5087,9 +5244,9 @@
|
|
5087
5244
|
DateUnitsReversed = DateUnits.clone().reverse();
|
5088
5245
|
var monthReg = '\\d{1,2}|' + English['months'].join('|');
|
5089
5246
|
StaticInputFormats.each(function(f) {
|
5090
|
-
|
5247
|
+
addDateInputFormat(f.src.replace(/\{month\}/, monthReg) + (f.time === false ? '' : OptionalTime), f.to.concat(TimeFormat), 'en', f.variant);
|
5091
5248
|
});
|
5092
|
-
|
5249
|
+
addDateInputFormat(RequiredTime, TimeFormat);
|
5093
5250
|
}
|
5094
5251
|
|
5095
5252
|
/***
|
@@ -5493,11 +5650,41 @@
|
|
5493
5650
|
}
|
5494
5651
|
|
5495
5652
|
|
5653
|
+
/***
|
5654
|
+
* @method toISOString()
|
5655
|
+
* @returns String
|
5656
|
+
* @short Formats the string to ISO8601 format.
|
5657
|
+
* @extra This will always format as UTC time. Provided for browsers that do not support this method.
|
5658
|
+
* @example
|
5659
|
+
*
|
5660
|
+
* Date.create().toISOString() -> ex. 2011-07-05 12:24:55.528Z
|
5661
|
+
*
|
5662
|
+
***
|
5663
|
+
* @method toJSON()
|
5664
|
+
* @returns String
|
5665
|
+
* @short Returns a JSON representation of the date.
|
5666
|
+
* @extra This is effectively an alias for %toISOString%. Will always return the date in UTC time. Implemented for browsers that do not support it.
|
5667
|
+
* @example
|
5668
|
+
*
|
5669
|
+
* Date.create().toJSON() -> ex. 2011-07-05 12:24:55.528Z
|
5670
|
+
*
|
5671
|
+
***/
|
5672
|
+
|
5673
|
+
function buildISOString(name) {
|
5674
|
+
var d = new date(date.UTC(1999, 11, 31)), target = '1999-12-31T00:00:00.000Z', methods = {};
|
5675
|
+
if(!d[name] || d[name]() !== target) {
|
5676
|
+
methods[name] = function() { return formatDate(this.toUTC(), date['ISO8601_DATETIME']); }
|
5677
|
+
date.extend(methods, true);
|
5678
|
+
}
|
5679
|
+
}
|
5680
|
+
|
5496
5681
|
function buildDate() {
|
5497
5682
|
English = date.setLocale('en');
|
5498
5683
|
buildDateMethods();
|
5499
5684
|
buildDateInputFormats();
|
5500
5685
|
buildRelativeAliases();
|
5686
|
+
buildISOString('toISOString');
|
5687
|
+
buildISOString('toJSON');
|
5501
5688
|
setDateProperties();
|
5502
5689
|
}
|
5503
5690
|
|
@@ -5574,32 +5761,13 @@
|
|
5574
5761
|
*
|
5575
5762
|
***/
|
5576
5763
|
'addFormat': function(format, match, locale, variant) {
|
5577
|
-
|
5578
|
-
variant: variant,
|
5579
|
-
locale: locale,
|
5580
|
-
reg: regexp('^' + format + '$', 'i'),
|
5581
|
-
to: match
|
5582
|
-
});
|
5764
|
+
addDateInputFormat(format, match, locale, variant, 'unshift');
|
5583
5765
|
}
|
5584
5766
|
|
5585
5767
|
}, false, false);
|
5586
5768
|
|
5587
5769
|
date.extend({
|
5588
5770
|
|
5589
|
-
/***
|
5590
|
-
* @method toISOString()
|
5591
|
-
* @returns String
|
5592
|
-
* @short Formats the string to ISO8601 format.
|
5593
|
-
* @extra This will always format as UTC time. Provided for browsers that do not support this method.
|
5594
|
-
* @example
|
5595
|
-
*
|
5596
|
-
* Date.create().toISOString() -> ex. 2011-07-05 12:24:55.528Z
|
5597
|
-
*
|
5598
|
-
***/
|
5599
|
-
'toISOString': function() {
|
5600
|
-
return formatDate(this.toUTC(), date['ISO8601_DATETIME']);
|
5601
|
-
},
|
5602
|
-
|
5603
5771
|
/***
|
5604
5772
|
* @method set(<set>, [reset] = false)
|
5605
5773
|
* @returns Date
|
@@ -5887,7 +6055,7 @@
|
|
5887
6055
|
* Date.create().format('{Weekday} {d} {Month}, {yyyy}') -> ex. Monday July 4, 2003
|
5888
6056
|
* Date.create().format('{hh}:{mm}') -> ex. 15:57
|
5889
6057
|
* Date.create().format('{12hr}:{mm}{tt}') -> ex. 3:57pm
|
5890
|
-
* Date.create().format(Date.
|
6058
|
+
* Date.create().format(Date.ISO8601_DATETIME) -> ex. 2011-07-05 12:24:55.528Z
|
5891
6059
|
* Date.create('last week').format('', 'ja') -> ex. 先週
|
5892
6060
|
* Date.create('yesterday').format(function(value,unit,ms,loc) {
|
5893
6061
|
* // value = 1, unit = 3, ms = -86400000, loc = [current locale object]
|
@@ -5977,20 +6145,6 @@
|
|
5977
6145
|
***/
|
5978
6146
|
'clone': function() {
|
5979
6147
|
return new date(this.getTime());
|
5980
|
-
},
|
5981
|
-
|
5982
|
-
/***
|
5983
|
-
* @method compare(<obj>)
|
5984
|
-
* @returns Number
|
5985
|
-
* @short Performs a numeric comparison against the date.
|
5986
|
-
* @extra This method is also defined on %String% and %Number%, and is useful when performing complex sort operations where the type isn't known.
|
5987
|
-
* @example
|
5988
|
-
*
|
5989
|
-
* Date.create('1 day ago').compare('today') -> -864000;
|
5990
|
-
*
|
5991
|
-
***/
|
5992
|
-
'compare': function(obj) {
|
5993
|
-
return this - createDate(arguments);
|
5994
6148
|
}
|
5995
6149
|
|
5996
6150
|
});
|
@@ -5999,24 +6153,14 @@
|
|
5999
6153
|
// Instance aliases
|
6000
6154
|
date.extend({
|
6001
6155
|
|
6002
|
-
/***
|
6003
|
-
* @method toJSON()
|
6004
|
-
* @returns String
|
6005
|
-
* @short Returns a JSON representation of the date.
|
6006
|
-
* @extra This is effectively an alias for %toISOString%. Will always return the date in UTC time. Implemented for browsers that do not support it.
|
6007
|
-
* @example
|
6008
|
-
*
|
6009
|
-
* Date.create().toJSON() -> ex. 2011-07-05 12:24:55.528Z
|
6010
|
-
*
|
6011
|
-
***/
|
6012
|
-
'toJSON': date.prototype.toISOString,
|
6013
|
-
|
6014
6156
|
/***
|
6015
6157
|
* @method iso()
|
6016
6158
|
* @alias toISOString
|
6017
6159
|
*
|
6018
6160
|
***/
|
6019
|
-
'iso':
|
6161
|
+
'iso': function() {
|
6162
|
+
return this.toISOString();
|
6163
|
+
},
|
6020
6164
|
|
6021
6165
|
/***
|
6022
6166
|
* @method getWeekday()
|
@@ -6035,6 +6179,553 @@
|
|
6035
6179
|
});
|
6036
6180
|
|
6037
6181
|
|
6182
|
+
|
6183
|
+
/***
|
6184
|
+
* Number module
|
6185
|
+
*
|
6186
|
+
***/
|
6187
|
+
|
6188
|
+
number.extend({
|
6189
|
+
|
6190
|
+
/***
|
6191
|
+
* @method duration([locale] = currentLocale)
|
6192
|
+
* @returns String
|
6193
|
+
* @short Takes the number as milliseconds and returns a unit-adjusted localized string.
|
6194
|
+
* @extra This method is the same as %Date#relative% without the localized equivalent of "from now" or "ago". [locale] can be passed as the first (and only) parameter. Note that this method is only available when the dates package is included.
|
6195
|
+
* @example
|
6196
|
+
*
|
6197
|
+
* (500).duration() -> '500 milliseconds'
|
6198
|
+
* (1200).duration() -> '1 second'
|
6199
|
+
* (75).minutes().duration() -> '1 hour'
|
6200
|
+
* (75).minutes().duration('es') -> '1 hora'
|
6201
|
+
*
|
6202
|
+
***/
|
6203
|
+
'duration': function(code) {
|
6204
|
+
return Date.getLocale(code).duration(this);
|
6205
|
+
}
|
6206
|
+
|
6207
|
+
});
|
6208
|
+
|
6038
6209
|
buildDate();
|
6039
6210
|
|
6040
6211
|
})();
|
6212
|
+
(function(context) {
|
6213
|
+
|
6214
|
+
/***
|
6215
|
+
* String module
|
6216
|
+
*
|
6217
|
+
***/
|
6218
|
+
|
6219
|
+
|
6220
|
+
var globalContext,
|
6221
|
+
plurals = [],
|
6222
|
+
singulars = [],
|
6223
|
+
uncountables = [],
|
6224
|
+
humans = [],
|
6225
|
+
acronyms = {},
|
6226
|
+
Downcased,
|
6227
|
+
Normalize,
|
6228
|
+
Inflector;
|
6229
|
+
|
6230
|
+
globalContext = typeof global !== 'undefined' ? global : context;
|
6231
|
+
|
6232
|
+
function removeFromUncountablesAndAddTo(arr, rule, replacement) {
|
6233
|
+
if(Object.isString(rule)) {
|
6234
|
+
uncountables.remove(rule);
|
6235
|
+
}
|
6236
|
+
uncountables.remove(replacement)
|
6237
|
+
arr.unshift({ rule: rule, replacement: replacement })
|
6238
|
+
}
|
6239
|
+
|
6240
|
+
function paramMatchesType(param, type) {
|
6241
|
+
return param == type || param == 'all' || !param;
|
6242
|
+
}
|
6243
|
+
|
6244
|
+
function isUncountable(word) {
|
6245
|
+
return uncountables.any(function(uncountable) {
|
6246
|
+
return new RegExp('\\b' + uncountable + '$', 'i').test(word);
|
6247
|
+
});
|
6248
|
+
}
|
6249
|
+
|
6250
|
+
function inflect(word, pluralize) {
|
6251
|
+
word = Object.isString(word) ? word.toString() : '';
|
6252
|
+
if(word.isBlank() || isUncountable(word)) {
|
6253
|
+
return word;
|
6254
|
+
} else {
|
6255
|
+
return runReplacements(word, pluralize ? plurals : singulars);
|
6256
|
+
}
|
6257
|
+
}
|
6258
|
+
|
6259
|
+
function runReplacements(word, table) {
|
6260
|
+
table.each(function(inflection) {
|
6261
|
+
if(word.match(inflection.rule)) {
|
6262
|
+
word = word.replace(inflection.rule, inflection.replacement);
|
6263
|
+
return false;
|
6264
|
+
}
|
6265
|
+
});
|
6266
|
+
return word;
|
6267
|
+
}
|
6268
|
+
|
6269
|
+
function capitalize(word) {
|
6270
|
+
return word.replace(/^\W*[a-z]/, function(w){
|
6271
|
+
return w.toUpperCase();
|
6272
|
+
});
|
6273
|
+
}
|
6274
|
+
|
6275
|
+
Inflector = {
|
6276
|
+
|
6277
|
+
/*
|
6278
|
+
* Specifies a new acronym. An acronym must be specified as it will appear in a camelized string. An underscore
|
6279
|
+
* string that contains the acronym will retain the acronym when passed to %camelize%, %humanize%, or %titleize%.
|
6280
|
+
* A camelized string that contains the acronym will maintain the acronym when titleized or humanized, and will
|
6281
|
+
* convert the acronym into a non-delimited single lowercase word when passed to String#underscore.
|
6282
|
+
*
|
6283
|
+
* Examples:
|
6284
|
+
* String.Inflector.acronym('HTML')
|
6285
|
+
* 'html'.titleize() -> 'HTML'
|
6286
|
+
* 'html'.camelize() -> 'HTML'
|
6287
|
+
* 'MyHTML'.underscore() -> 'my_html'
|
6288
|
+
*
|
6289
|
+
* The acronym, however, must occur as a delimited unit and not be part of another word for conversions to recognize it:
|
6290
|
+
*
|
6291
|
+
* String.Inflector.acronym('HTTP')
|
6292
|
+
* 'my_http_delimited'.camelize() -> 'MyHTTPDelimited'
|
6293
|
+
* 'https'.camelize() -> 'Https', not 'HTTPs'
|
6294
|
+
* 'HTTPS'.underscore() -> 'http_s', not 'https'
|
6295
|
+
*
|
6296
|
+
* String.Inflector.acronym('HTTPS')
|
6297
|
+
* 'https'.camelize() -> 'HTTPS'
|
6298
|
+
* 'HTTPS'.underscore() -> 'https'
|
6299
|
+
*
|
6300
|
+
* Note: Acronyms that are passed to %pluralize% will no longer be recognized, since the acronym will not occur as
|
6301
|
+
* a delimited unit in the pluralized result. To work around this, you must specify the pluralized form as an
|
6302
|
+
* acronym as well:
|
6303
|
+
*
|
6304
|
+
* String.Inflector.acronym('API')
|
6305
|
+
* 'api'.pluralize().camelize() -> 'Apis'
|
6306
|
+
*
|
6307
|
+
* String.Inflector.acronym('APIs')
|
6308
|
+
* 'api'.pluralize().camelize() -> 'APIs'
|
6309
|
+
*
|
6310
|
+
* %acronym% may be used to specify any word that contains an acronym or otherwise needs to maintain a non-standard
|
6311
|
+
* capitalization. The only restriction is that the word must begin with a capital letter.
|
6312
|
+
*
|
6313
|
+
* Examples:
|
6314
|
+
* String.Inflector.acronym('RESTful')
|
6315
|
+
* 'RESTful'.underscore() -> 'restful'
|
6316
|
+
* 'RESTfulController'.underscore() -> 'restful_controller'
|
6317
|
+
* 'RESTfulController'.titleize() -> 'RESTful Controller'
|
6318
|
+
* 'restful'.camelize() -> 'RESTful'
|
6319
|
+
* 'restful_controller'.camelize() -> 'RESTfulController'
|
6320
|
+
*
|
6321
|
+
* String.Inflector.acronym('McDonald')
|
6322
|
+
* 'McDonald'.underscore() -> 'mcdonald'
|
6323
|
+
* 'mcdonald'.camelize() -> 'McDonald'
|
6324
|
+
*/
|
6325
|
+
'acronym': function(word) {
|
6326
|
+
acronyms[word.toLowerCase()] = word;
|
6327
|
+
Inflector.acronymRegExp = new RegExp(Object.values(acronyms).join('|'), 'g');
|
6328
|
+
},
|
6329
|
+
|
6330
|
+
/*
|
6331
|
+
* Specifies a new pluralization rule and its replacement. The rule can either be a string or a regular expression.
|
6332
|
+
* The replacement should always be a string that may include references to the matched data from the rule.
|
6333
|
+
*/
|
6334
|
+
'plural': function(rule, replacement) {
|
6335
|
+
removeFromUncountablesAndAddTo(plurals, rule, replacement);
|
6336
|
+
},
|
6337
|
+
|
6338
|
+
/*
|
6339
|
+
* Specifies a new singularization rule and its replacement. The rule can either be a string or a regular expression.
|
6340
|
+
* The replacement should always be a string that may include references to the matched data from the rule.
|
6341
|
+
*/
|
6342
|
+
'singular': function(rule, replacement) {
|
6343
|
+
removeFromUncountablesAndAddTo(singulars, rule, replacement);
|
6344
|
+
},
|
6345
|
+
|
6346
|
+
/*
|
6347
|
+
* Specifies a new irregular that applies to both pluralization and singularization at the same time. This can only be used
|
6348
|
+
* for strings, not regular expressions. You simply pass the irregular in singular and plural form.
|
6349
|
+
*
|
6350
|
+
* Examples:
|
6351
|
+
* String.Inflector.irregular('octopus', 'octopi')
|
6352
|
+
* String.Inflector.irregular('person', 'people')
|
6353
|
+
*/
|
6354
|
+
'irregular': function(singular, plural) {
|
6355
|
+
var singularFirst = singular.first(),
|
6356
|
+
singularRest = singular.from(1),
|
6357
|
+
pluralFirst = plural.first(),
|
6358
|
+
pluralRest = plural.from(1),
|
6359
|
+
pluralFirstUpper = pluralFirst.toUpperCase(),
|
6360
|
+
pluralFirstLower = pluralFirst.toLowerCase(),
|
6361
|
+
singularFirstUpper = singularFirst.toUpperCase(),
|
6362
|
+
singularFirstLower = singularFirst.toLowerCase();
|
6363
|
+
uncountables.remove(singular)
|
6364
|
+
uncountables.remove(plural)
|
6365
|
+
if(singularFirstUpper == pluralFirstUpper) {
|
6366
|
+
Inflector.plural(new RegExp('({1}){2}$'.assign(singularFirst, singularRest), 'i'), '$1' + pluralRest);
|
6367
|
+
Inflector.plural(new RegExp('({1}){2}$'.assign(pluralFirst, pluralRest), 'i'), '$1' + pluralRest);
|
6368
|
+
Inflector.singular(new RegExp('({1}){2}$'.assign(pluralFirst, pluralRest), 'i'), '$1' + singularRest);
|
6369
|
+
} else {
|
6370
|
+
Inflector.plural(new RegExp('{1}{2}$'.assign(singularFirstUpper, singularRest)), pluralFirstUpper + pluralRest);
|
6371
|
+
Inflector.plural(new RegExp('{1}{2}$'.assign(singularFirstLower, singularRest)), pluralFirstLower + pluralRest);
|
6372
|
+
Inflector.plural(new RegExp('{1}{2}$'.assign(pluralFirstUpper, pluralRest)), pluralFirstUpper + pluralRest);
|
6373
|
+
Inflector.plural(new RegExp('{1}{2}$'.assign(pluralFirstLower, pluralRest)), pluralFirstLower + pluralRest);
|
6374
|
+
Inflector.singular(new RegExp('{1}{2}$'.assign(pluralFirstUpper, pluralRest)), singularFirstUpper + singularRest);
|
6375
|
+
Inflector.singular(new RegExp('{1}{2}$'.assign(pluralFirstLower, pluralRest)), singularFirstLower + singularRest);
|
6376
|
+
}
|
6377
|
+
},
|
6378
|
+
|
6379
|
+
/*
|
6380
|
+
* Add uncountable words that shouldn't be attempted inflected.
|
6381
|
+
*
|
6382
|
+
* Examples:
|
6383
|
+
* String.Inflector.uncountable('money')
|
6384
|
+
* String.Inflector.uncountable('money', 'information')
|
6385
|
+
* String.Inflector.uncountable(['money', 'information', 'rice'])
|
6386
|
+
*/
|
6387
|
+
'uncountable': function() {
|
6388
|
+
uncountables.add(Array.create(arguments).flatten());
|
6389
|
+
},
|
6390
|
+
|
6391
|
+
/*
|
6392
|
+
* Specifies a humanized form of a string by a regular expression rule or by a string mapping.
|
6393
|
+
* When using a regular expression based replacement, the normal humanize formatting is called after the replacement.
|
6394
|
+
* When a string is used, the human form should be specified as desired (example: 'The name', not 'the_name')
|
6395
|
+
*
|
6396
|
+
* Examples:
|
6397
|
+
* String.Inflector.human(/_cnt$/i, '_count')
|
6398
|
+
* String.Inflector.human('legacy_col_person_name', 'Name')
|
6399
|
+
*/
|
6400
|
+
'human': function(rule, replacement) {
|
6401
|
+
humans.unshift({ rule: rule, replacement: replacement })
|
6402
|
+
},
|
6403
|
+
|
6404
|
+
|
6405
|
+
/*
|
6406
|
+
* Clears the loaded inflections within a given scope (default is 'all').
|
6407
|
+
* Options are: 'all', 'plurals', 'singulars', 'uncountables', 'humans'.
|
6408
|
+
*
|
6409
|
+
* Examples:
|
6410
|
+
* String.Inflector.clear('all')
|
6411
|
+
* String.Inflector.clear('plurals')
|
6412
|
+
*/
|
6413
|
+
'clear': function(type) {
|
6414
|
+
if(paramMatchesType(type, 'singulars')) singulars = [];
|
6415
|
+
if(paramMatchesType(type, 'plurals')) plurals = [];
|
6416
|
+
if(paramMatchesType(type, 'uncountables')) uncountables = [];
|
6417
|
+
if(paramMatchesType(type, 'humans')) humans = [];
|
6418
|
+
if(paramMatchesType(type, 'acronyms')) acronyms = {};
|
6419
|
+
}
|
6420
|
+
|
6421
|
+
};
|
6422
|
+
|
6423
|
+
Downcased = [
|
6424
|
+
'and', 'or', 'nor', 'a', 'an', 'the', 'so', 'but', 'to', 'of', 'at',
|
6425
|
+
'by', 'from', 'into', 'on', 'onto', 'off', 'out', 'in', 'over',
|
6426
|
+
'with', 'for'
|
6427
|
+
];
|
6428
|
+
|
6429
|
+
Normalize = {
|
6430
|
+
'A': /[AⒶAÀÁÂẦẤẪẨÃĀĂẰẮẴẲȦǠÄǞẢÅǺǍȀȂẠẬẶḀĄȺⱯ]/g,
|
6431
|
+
'B': /[BⒷBḂḄḆɃƂƁ]/g,
|
6432
|
+
'C': /[CⒸCĆĈĊČÇḈƇȻꜾ]/g,
|
6433
|
+
'D': /[DⒹDḊĎḌḐḒḎĐƋƊƉꝹ]/g,
|
6434
|
+
'E': /[EⒺEÈÉÊỀẾỄỂẼĒḔḖĔĖËẺĚȄȆẸỆȨḜĘḘḚƐƎ]/g,
|
6435
|
+
'F': /[FⒻFḞƑꝻ]/g,
|
6436
|
+
'G': /[GⒼGǴĜḠĞĠǦĢǤƓꞠꝽꝾ]/g,
|
6437
|
+
'H': /[HⒽHĤḢḦȞḤḨḪĦⱧⱵꞍ]/g,
|
6438
|
+
'I': /[IⒾIÌÍÎĨĪĬİÏḮỈǏȈȊỊĮḬƗ]/g,
|
6439
|
+
'J': /[JⒿJĴɈ]/g,
|
6440
|
+
'K': /[KⓀKḰǨḲĶḴƘⱩꝀꝂꝄꞢ]/g,
|
6441
|
+
'L': /[LⓁLĿĹĽḶḸĻḼḺŁȽⱢⱠꝈꝆꞀ]/g,
|
6442
|
+
'M': /[MⓂMḾṀṂⱮƜ]/g,
|
6443
|
+
'N': /[NⓃNǸŃÑṄŇṆŅṊṈȠƝꞐꞤ]/g,
|
6444
|
+
'O': /[OⓄOÒÓÔỒỐỖỔÕṌȬṎŌṐṒŎȮȰÖȪỎŐǑȌȎƠỜỚỠỞỢỌỘǪǬØǾƆƟꝊꝌ]/g,
|
6445
|
+
'P': /[PⓅPṔṖƤⱣꝐꝒꝔ]/g,
|
6446
|
+
'Q': /[QⓆQꝖꝘɊ]/g,
|
6447
|
+
'R': /[RⓇRŔṘŘȐȒṚṜŖṞɌⱤꝚꞦꞂ]/g,
|
6448
|
+
'S': /[SⓈSẞŚṤŜṠŠṦṢṨȘŞⱾꞨꞄ]/g,
|
6449
|
+
'T': /[TⓉTṪŤṬȚŢṰṮŦƬƮȾꞆ]/g,
|
6450
|
+
'U': /[UⓊUÙÚÛŨṸŪṺŬÜǛǗǕǙỦŮŰǓȔȖƯỪỨỮỬỰỤṲŲṶṴɄ]/g,
|
6451
|
+
'V': /[VⓋVṼṾƲꝞɅ]/g,
|
6452
|
+
'W': /[WⓌWẀẂŴẆẄẈⱲ]/g,
|
6453
|
+
'X': /[XⓍXẊẌ]/g,
|
6454
|
+
'Y': /[YⓎYỲÝŶỸȲẎŸỶỴƳɎỾ]/g,
|
6455
|
+
'Z': /[ZⓏZŹẐŻŽẒẔƵȤⱿⱫꝢ]/g,
|
6456
|
+
'a': /[aⓐaẚàáâầấẫẩãāăằắẵẳȧǡäǟảåǻǎȁȃạậặḁąⱥɐ]/g,
|
6457
|
+
'b': /[bⓑbḃḅḇƀƃɓ]/g,
|
6458
|
+
'c': /[cⓒcćĉċčçḉƈȼꜿↄ]/g,
|
6459
|
+
'd': /[dⓓdḋďḍḑḓḏđƌɖɗꝺ]/g,
|
6460
|
+
'e': /[eⓔeèéêềếễểẽēḕḗĕėëẻěȅȇẹệȩḝęḙḛɇɛǝ]/g,
|
6461
|
+
'f': /[fⓕfḟƒꝼ]/g,
|
6462
|
+
'g': /[gⓖgǵĝḡğġǧģǥɠꞡᵹꝿ]/g,
|
6463
|
+
'h': /[hⓗhĥḣḧȟḥḩḫẖħⱨⱶɥ]/g,
|
6464
|
+
'i': /[iⓘiìíîĩīĭïḯỉǐȉȋịįḭɨı]/g,
|
6465
|
+
'j': /[jⓙjĵǰɉ]/g,
|
6466
|
+
'k': /[kⓚkḱǩḳķḵƙⱪꝁꝃꝅꞣ]/g,
|
6467
|
+
'l': /[lⓛlŀĺľḷḹļḽḻſłƚɫⱡꝉꞁꝇ]/g,
|
6468
|
+
'm': /[mⓜmḿṁṃɱɯ]/g,
|
6469
|
+
'n': /[nⓝnǹńñṅňṇņṋṉƞɲʼnꞑꞥ]/g,
|
6470
|
+
'o': /[oⓞoòóôồốỗổõṍȭṏōṑṓŏȯȱöȫỏőǒȍȏơờớỡởợọộǫǭøǿɔꝋꝍɵ]/g,
|
6471
|
+
'p': /[pⓟpṕṗƥᵽꝑꝓꝕ]/g,
|
6472
|
+
'q': /[qⓠqɋꝗꝙ]/g,
|
6473
|
+
'r': /[rⓡrŕṙřȑȓṛṝŗṟɍɽꝛꞧꞃ]/g,
|
6474
|
+
's': /[sⓢsśṥŝṡšṧṣṩșşȿꞩꞅẛ]/g,
|
6475
|
+
't': /[tⓣtṫẗťṭțţṱṯŧƭʈⱦꞇ]/g,
|
6476
|
+
'u': /[uⓤuùúûũṹūṻŭüǜǘǖǚủůűǔȕȗưừứữửựụṳųṷṵʉ]/g,
|
6477
|
+
'v': /[vⓥvṽṿʋꝟʌ]/g,
|
6478
|
+
'w': /[wⓦwẁẃŵẇẅẘẉⱳ]/g,
|
6479
|
+
'x': /[xⓧxẋẍ]/g,
|
6480
|
+
'y': /[yⓨyỳýŷỹȳẏÿỷẙỵƴɏỿ]/g,
|
6481
|
+
'z': /[zⓩzźẑżžẓẕƶȥɀⱬꝣ]/g,
|
6482
|
+
'AA': /[Ꜳ]/g,
|
6483
|
+
'AE': /[ÆǼǢ]/g,
|
6484
|
+
'AO': /[Ꜵ]/g,
|
6485
|
+
'AU': /[Ꜷ]/g,
|
6486
|
+
'AV': /[ꜸꜺ]/g,
|
6487
|
+
'AY': /[Ꜽ]/g,
|
6488
|
+
'DZ': /[DZDŽ]/g,
|
6489
|
+
'Dz': /[DzDž]/g,
|
6490
|
+
'LJ': /[LJ]/g,
|
6491
|
+
'Lj': /[Lj]/g,
|
6492
|
+
'NJ': /[NJ]/g,
|
6493
|
+
'Nj': /[Nj]/g,
|
6494
|
+
'OI': /[Ƣ]/g,
|
6495
|
+
'OO': /[Ꝏ]/g,
|
6496
|
+
'OU': /[Ȣ]/g,
|
6497
|
+
'TZ': /[Ꜩ]/g,
|
6498
|
+
'VY': /[Ꝡ]/g,
|
6499
|
+
'aa': /[ꜳ]/g,
|
6500
|
+
'ae': /[æǽǣ]/g,
|
6501
|
+
'ao': /[ꜵ]/g,
|
6502
|
+
'au': /[ꜷ]/g,
|
6503
|
+
'av': /[ꜹꜻ]/g,
|
6504
|
+
'ay': /[ꜽ]/g,
|
6505
|
+
'dz': /[dzdž]/g,
|
6506
|
+
'hv': /[ƕ]/g,
|
6507
|
+
'lj': /[lj]/g,
|
6508
|
+
'nj': /[nj]/g,
|
6509
|
+
'oi': /[ƣ]/g,
|
6510
|
+
'ou': /[ȣ]/g,
|
6511
|
+
'oo': /[ꝏ]/g,
|
6512
|
+
'ss': /[ß]/g,
|
6513
|
+
'tz': /[ꜩ]/g,
|
6514
|
+
'vy': /[ꝡ]/
|
6515
|
+
};
|
6516
|
+
|
6517
|
+
|
6518
|
+
Inflector.plural(/$/, 's');
|
6519
|
+
Inflector.plural(/s$/gi, 's');
|
6520
|
+
Inflector.plural(/(ax|test)is$/gi, '$1es');
|
6521
|
+
Inflector.plural(/(octop|vir|fung|foc|radi|alumn)(i|us)$/gi, '$1i');
|
6522
|
+
Inflector.plural(/(census|alias|status)$/gi, '$1es');
|
6523
|
+
Inflector.plural(/(bu)s$/gi, '$1ses');
|
6524
|
+
Inflector.plural(/(buffal|tomat)o$/gi, '$1oes');
|
6525
|
+
Inflector.plural(/([ti])um$/gi, '$1a');
|
6526
|
+
Inflector.plural(/([ti])a$/gi, '$1a');
|
6527
|
+
Inflector.plural(/sis$/gi, 'ses');
|
6528
|
+
Inflector.plural(/f+e?$/gi, 'ves');
|
6529
|
+
Inflector.plural(/(cuff|roof)$/gi, '$1s');
|
6530
|
+
Inflector.plural(/([ht]ive)$/gi, '$1s');
|
6531
|
+
Inflector.plural(/([^aeiouy]o)$/gi, '$1es');
|
6532
|
+
Inflector.plural(/([^aeiouy]|qu)y$/gi, '$1ies');
|
6533
|
+
Inflector.plural(/(x|ch|ss|sh)$/gi, '$1es');
|
6534
|
+
Inflector.plural(/(matr|vert|ind)(?:ix|ex)$/gi, '$1ices');
|
6535
|
+
Inflector.plural(/([ml])ouse$/gi, '$1ice');
|
6536
|
+
Inflector.plural(/([ml])ice$/gi, '$1ice');
|
6537
|
+
Inflector.plural(/^(ox)$/gi, '$1en');
|
6538
|
+
Inflector.plural(/^(oxen)$/gi, '$1');
|
6539
|
+
Inflector.plural(/(quiz)$/gi, '$1zes');
|
6540
|
+
Inflector.plural(/(phot|cant|hom|zer|pian|portic|pr|quart|kimon)o$/gi, '$1os');
|
6541
|
+
Inflector.plural(/(craft)$/gi, '$1');
|
6542
|
+
Inflector.plural(/[eo]{2}(th?)$/gi, 'ee$1');
|
6543
|
+
|
6544
|
+
Inflector.singular(/s$/gi, '');
|
6545
|
+
Inflector.singular(/([pst][aiu]s)$/gi, '$1');
|
6546
|
+
Inflector.singular(/([aeiouy])ss$/gi, '$1ss');
|
6547
|
+
Inflector.singular(/(n)ews$/gi, '$1ews');
|
6548
|
+
Inflector.singular(/([ti])a$/gi, '$1um');
|
6549
|
+
Inflector.singular(/((a)naly|(b)a|(d)iagno|(p)arenthe|(p)rogno|(s)ynop|(t)he)ses$/gi, '$1$2sis');
|
6550
|
+
Inflector.singular(/(^analy)ses$/gi, '$1sis');
|
6551
|
+
Inflector.singular(/(i)(f|ves)$/i, '$1fe');
|
6552
|
+
Inflector.singular(/([aeolr]f?)(f|ves)$/i, '$1f');
|
6553
|
+
Inflector.singular(/([ht]ive)s$/gi, '$1');
|
6554
|
+
Inflector.singular(/([^aeiouy]|qu)ies$/gi, '$1y');
|
6555
|
+
Inflector.singular(/(s)eries$/gi, '$1eries');
|
6556
|
+
Inflector.singular(/(m)ovies$/gi, '$1ovie');
|
6557
|
+
Inflector.singular(/(x|ch|ss|sh)es$/gi, '$1');
|
6558
|
+
Inflector.singular(/([ml])(ous|ic)e$/gi, '$1ouse');
|
6559
|
+
Inflector.singular(/(bus)(es)?$/gi, '$1');
|
6560
|
+
Inflector.singular(/(o)es$/gi, '$1');
|
6561
|
+
Inflector.singular(/(shoe)s?$/gi, '$1');
|
6562
|
+
Inflector.singular(/(cris|ax|test)[ie]s$/gi, '$1is');
|
6563
|
+
Inflector.singular(/(octop|vir|fung|foc|radi|alumn)(i|us)$/gi, '$1us');
|
6564
|
+
Inflector.singular(/(census|alias|status)(es)?$/gi, '$1');
|
6565
|
+
Inflector.singular(/^(ox)(en)?/gi, '$1');
|
6566
|
+
Inflector.singular(/(vert|ind)(ex|ices)$/gi, '$1ex');
|
6567
|
+
Inflector.singular(/(matr)(ix|ices)$/gi, '$1ix');
|
6568
|
+
Inflector.singular(/(quiz)(zes)?$/gi, '$1');
|
6569
|
+
Inflector.singular(/(database)s?$/gi, '$1');
|
6570
|
+
Inflector.singular(/ee(th?)$/gi, 'oo$1');
|
6571
|
+
|
6572
|
+
Inflector.irregular('person', 'people');
|
6573
|
+
Inflector.irregular('man', 'men');
|
6574
|
+
Inflector.irregular('child', 'children');
|
6575
|
+
Inflector.irregular('sex', 'sexes');
|
6576
|
+
Inflector.irregular('move', 'moves');
|
6577
|
+
Inflector.irregular('save', 'saves');
|
6578
|
+
Inflector.irregular('save', 'saves');
|
6579
|
+
Inflector.irregular('cow', 'kine');
|
6580
|
+
Inflector.irregular('goose', 'geese');
|
6581
|
+
Inflector.irregular('zombie', 'zombies');
|
6582
|
+
|
6583
|
+
Inflector.uncountable('equipment,information,rice,money,species,series,fish,sheep,jeans'.split(','));
|
6584
|
+
|
6585
|
+
|
6586
|
+
String.extend({
|
6587
|
+
|
6588
|
+
/***
|
6589
|
+
* @method pluralize()
|
6590
|
+
* @returns String
|
6591
|
+
* @short Returns the plural form of the word in the string.
|
6592
|
+
* @example
|
6593
|
+
*
|
6594
|
+
* 'post'.pluralize() -> 'posts'
|
6595
|
+
* 'octopus'.pluralize() -> 'octopi'
|
6596
|
+
* 'sheep'.pluralize() -> 'sheep'
|
6597
|
+
* 'words'.pluralize() -> 'words'
|
6598
|
+
* 'CamelOctopus'.pluralize() -> 'CamelOctopi'
|
6599
|
+
*
|
6600
|
+
***/
|
6601
|
+
'pluralize': function() {
|
6602
|
+
return inflect(this, true);
|
6603
|
+
},
|
6604
|
+
|
6605
|
+
/***
|
6606
|
+
* @method singularize()
|
6607
|
+
* @returns String
|
6608
|
+
* @short The reverse of String#pluralize. Returns the singular form of a word in a string.
|
6609
|
+
* @example
|
6610
|
+
*
|
6611
|
+
* 'posts'.singularize() -> 'post'
|
6612
|
+
* 'octopi'.singularize() -> 'octopus'
|
6613
|
+
* 'sheep'.singularize() -> 'sheep'
|
6614
|
+
* 'word'.singularize() -> 'word'
|
6615
|
+
* 'CamelOctopi'.singularize() -> 'CamelOctopus'
|
6616
|
+
*
|
6617
|
+
***/
|
6618
|
+
'singularize': function() {
|
6619
|
+
return inflect(this, false);
|
6620
|
+
},
|
6621
|
+
|
6622
|
+
/***
|
6623
|
+
* @method humanize()
|
6624
|
+
* @returns String
|
6625
|
+
* @short Creates a human readable string.
|
6626
|
+
* @extra Capitalizes the first word and turns underscores into spaces and strips a trailing '_id', if any. Like String#titleize, this is meant for creating pretty output.
|
6627
|
+
* @example
|
6628
|
+
*
|
6629
|
+
* 'employee_salary'.humanize() -> 'Employee salary'
|
6630
|
+
* 'author_id'.humanize() -> 'Author'
|
6631
|
+
*
|
6632
|
+
***/
|
6633
|
+
'humanize': function() {
|
6634
|
+
var str = runReplacements(this, humans);
|
6635
|
+
str = str.replace(/_id$/g, '');
|
6636
|
+
str = str.replace(/(_)?([a-z\d]*)/gi, function(match, _, word){
|
6637
|
+
return (_ ? ' ' : '') + (acronyms[word] || word.toLowerCase());
|
6638
|
+
});
|
6639
|
+
return capitalize(str);
|
6640
|
+
},
|
6641
|
+
|
6642
|
+
/***
|
6643
|
+
* @method titleize()
|
6644
|
+
* @returns String
|
6645
|
+
* @short Creates a title version of the string.
|
6646
|
+
* @extra Capitalizes all the words and replaces some characters in the string to create a nicer looking title. String#titleize is meant for creating pretty output.
|
6647
|
+
* @example
|
6648
|
+
*
|
6649
|
+
* 'man from the boondocks'.titleize() -> 'Man from the Boondocks'
|
6650
|
+
* 'x-men: the last stand'.titleize() -> 'X Men: The Last Stand'
|
6651
|
+
* 'TheManWithoutAPast'.titleize() -> 'The Man Without a Past'
|
6652
|
+
* 'raiders_of_the_lost_ark'.titleize() -> 'Raiders of the Lost Ark'
|
6653
|
+
*
|
6654
|
+
***/
|
6655
|
+
'titleize': function() {
|
6656
|
+
var fullStopPunctuation = /[.:;!]$/, hasPunctuation, lastHadPunctuation, isFirstOrLast;
|
6657
|
+
return this.spacify().humanize().words(function(word, index, words) {
|
6658
|
+
hasPunctuation = fullStopPunctuation.test(word);
|
6659
|
+
isFirstOrLast = index == 0 || index == words.length - 1 || hasPunctuation || lastHadPunctuation;
|
6660
|
+
lastHadPunctuation = hasPunctuation;
|
6661
|
+
if(isFirstOrLast || !Downcased.any(word)) {
|
6662
|
+
return capitalize(word);
|
6663
|
+
} else {
|
6664
|
+
return word;
|
6665
|
+
}
|
6666
|
+
}).join(' ');
|
6667
|
+
},
|
6668
|
+
|
6669
|
+
/***
|
6670
|
+
* @method namespace()
|
6671
|
+
* @returns Mixed
|
6672
|
+
* @short Tries to find the namespace or property with the name specified in the string.
|
6673
|
+
* @extra Namespacing begins at the global level and operates on every "." in the string. If any level returns %undefined% the result will be %undefined%.
|
6674
|
+
* @example
|
6675
|
+
*
|
6676
|
+
* 'Path.To.Namespace'.namespace() -> Path.To.Namespace
|
6677
|
+
*
|
6678
|
+
***/
|
6679
|
+
'namespace': function() {
|
6680
|
+
var spaces = this.split('.'), scope = globalContext;
|
6681
|
+
spaces.each(function(s) {
|
6682
|
+
return !!(scope = scope[s]);
|
6683
|
+
});
|
6684
|
+
return scope;
|
6685
|
+
},
|
6686
|
+
|
6687
|
+
/***
|
6688
|
+
* @method parameterize()
|
6689
|
+
* @returns String
|
6690
|
+
* @short Replaces special characters in a string so that it may be used as part of a pretty URL.
|
6691
|
+
* @example
|
6692
|
+
*
|
6693
|
+
* 'hell, no!'.parameterize() -> 'hell-no'
|
6694
|
+
*
|
6695
|
+
***/
|
6696
|
+
'parameterize': function(separator) {
|
6697
|
+
if(separator === undefined) separator = '-';
|
6698
|
+
var str = this.normalize();
|
6699
|
+
str = str.replace(/[^a-z0-9\-_]+/gi, separator)
|
6700
|
+
if(separator) {
|
6701
|
+
str = str.replace(new RegExp('^{sep}+|{sep}+$|({sep}){sep}+'.assign({ 'sep': RegExp.escape(separator) }), 'g'), '$1');
|
6702
|
+
}
|
6703
|
+
return str.toLowerCase();
|
6704
|
+
},
|
6705
|
+
|
6706
|
+
/***
|
6707
|
+
* @method normalize()
|
6708
|
+
* @returns String
|
6709
|
+
* @short Returns the string with accented and non-standard Latin-based characters converted into ASCII approximate equivalents.
|
6710
|
+
* @example
|
6711
|
+
*
|
6712
|
+
* 'á'.normalize() -> 'a'
|
6713
|
+
* 'Ménage à trois'.normalize() -> 'Menage a trois'
|
6714
|
+
* 'Volkswagen'.normalize() -> 'Volkswagen'
|
6715
|
+
* 'FULLWIDTH'.normalize() -> 'FULLWIDTH'
|
6716
|
+
*
|
6717
|
+
***/
|
6718
|
+
'normalize': function() {
|
6719
|
+
var str = this.toString();
|
6720
|
+
Object.each(Normalize, function(base, reg) {
|
6721
|
+
str = str.replace(reg, base);
|
6722
|
+
});
|
6723
|
+
return str;
|
6724
|
+
}
|
6725
|
+
|
6726
|
+
});
|
6727
|
+
|
6728
|
+
String.Inflector = Inflector;
|
6729
|
+
String.Inflector.acronyms = acronyms;
|
6730
|
+
|
6731
|
+
})(this);
|