chiropractor 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,7 @@
1
+ Backbone.Marionette.Renderer.render = function(template, data){
2
+ if(!JST[template]){
3
+ throw "Template '" + template + "' not found!";
4
+ }
5
+
6
+ return JST[template](data);
7
+ }
@@ -0,0 +1,75 @@
1
+ class Backbone.Marionette.Outlet extends Backbone.Events
2
+
3
+ constructor: (options = {}) ->
4
+ _.extend(this, options)
5
+
6
+ @currentView = null
7
+ throw "must specify el" unless @el.length
8
+ @$el = @el
9
+ this
10
+
11
+ show: (view) ->
12
+ view.render()
13
+ @attach(view, false)
14
+
15
+ make: (tagName) ->
16
+ jQuery(document.createElement(tagName))
17
+
18
+
19
+ attach: (view, reTriggerRender = true) ->
20
+ # need to replace this with an empty element so that we keep our place
21
+ placeholder = @make("div")
22
+
23
+ # ok, so do the replacing here
24
+ @$el.replaceWith(placeholder)
25
+
26
+ # be nice and neat, the view if there was one
27
+ @currentView?.close()
28
+
29
+ # yay, a new view
30
+ @currentView = view
31
+ return unless view
32
+
33
+ # questionable, this needs more thought but I'm leaving it in
34
+ # basically, there's no clear lifecycle defined so until there is
35
+ # this needs to be here
36
+ view.trigger("render") if reTriggerRender
37
+
38
+ # now that we've made sure it's had all the time it needs to
39
+ # render and all that, replace the placeholder
40
+ placeholder.replaceWith(view.el)
41
+ @$el = view.$el
42
+
43
+ # now do the callbacks
44
+ view.onShow() if _.isFunction(view.onShow)
45
+ view.trigger("show")
46
+
47
+ close: ->
48
+ placeHolder = @make("div")
49
+ @$el.replaceWith(placeHolder)
50
+ @$el = placeHolder
51
+
52
+ if @currentView && _.isFunction(@currentView.close)
53
+ @currentView.close()
54
+
55
+
56
+ class Backbone.Marionette.LayoutRegion extends Backbone.Marionette.Layout
57
+ constructor: (options = {}) ->
58
+ super(options)
59
+ @bindTo(this, "render", @initializeOutlets, this)
60
+
61
+ initializeOutlets: ->
62
+ return unless @outlets
63
+
64
+ @outletBindings = @outlets
65
+ @outlets = {}
66
+
67
+ _(@outletBindings).each (selector, name) =>
68
+ @outlets[name] = new Backbone.Marionette.Outlet(el: @$(selector))
69
+
70
+ close: () ->
71
+ _(@outlets).each (outlet, name) ->
72
+ outlet.close()
73
+
74
+ super()
75
+
@@ -0,0 +1,13 @@
1
+ //= require jquery
2
+ //= require jquery_ujs
3
+ //= require underscore
4
+ //= require ./underscore.string
5
+ //= require ./underscore.inflection
6
+ //= require backbone
7
+ //= require backbone.marionette
8
+ //= require ./Backbone.ModelBinder
9
+ //= require ./backbone-relational
10
+ //= require ./backbone.layoutRegion
11
+ //= require ./backbone.jst
12
+ //= require ./moment
13
+ //= require ./accounting
@@ -0,0 +1,1213 @@
1
+ // moment.js
2
+ // version : 1.7.2
3
+ // author : Tim Wood
4
+ // license : MIT
5
+ // momentjs.com
6
+
7
+ (function (undefined) {
8
+
9
+ /************************************
10
+ Constants
11
+ ************************************/
12
+
13
+ var moment,
14
+ VERSION = "1.7.2",
15
+ round = Math.round, i,
16
+ // internal storage for language config files
17
+ languages = {},
18
+ currentLanguage = 'en',
19
+
20
+ // check for nodeJS
21
+ hasModule = (typeof module !== 'undefined' && module.exports),
22
+
23
+ // Parameters to check for on the lang config. This list of properties
24
+ // will be inherited from English if not provided in a language
25
+ // definition. monthsParse is also a lang config property, but it
26
+ // cannot be inherited and as such cannot be enumerated here.
27
+ langConfigProperties = 'months|monthsShort|weekdays|weekdaysShort|weekdaysMin|longDateFormat|calendar|relativeTime|ordinal|meridiem'.split('|'),
28
+
29
+ // ASP.NET json date format regex
30
+ aspNetJsonRegex = /^\/?Date\((\-?\d+)/i,
31
+
32
+ // format tokens
33
+ formattingTokens = /(\[[^\[]*\])|(\\)?(Mo|MM?M?M?|Do|DDDo|DD?D?D?|ddd?d?|do?|w[o|w]?|YYYY|YY|a|A|hh?|HH?|mm?|ss?|SS?S?|zz?|ZZ?|.)/g,
34
+ localFormattingTokens = /(\[[^\[]*\])|(\\)?(LT|LL?L?L?)/g,
35
+
36
+ // parsing tokens
37
+ parseMultipleFormatChunker = /([0-9a-zA-Z\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]+)/gi,
38
+
39
+ // parsing token regexes
40
+ parseTokenOneOrTwoDigits = /\d\d?/, // 0 - 99
41
+ parseTokenOneToThreeDigits = /\d{1,3}/, // 0 - 999
42
+ parseTokenThreeDigits = /\d{3}/, // 000 - 999
43
+ parseTokenFourDigits = /\d{1,4}/, // 0 - 9999
44
+ parseTokenWord = /[0-9a-z\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]+/i, // any word characters or numbers
45
+ parseTokenTimezone = /Z|[\+\-]\d\d:?\d\d/i, // +00:00 -00:00 +0000 -0000 or Z
46
+ parseTokenT = /T/i, // T (ISO seperator)
47
+
48
+ // preliminary iso regex
49
+ // 0000-00-00 + T + 00 or 00:00 or 00:00:00 or 00:00:00.000 + +00:00 or +0000
50
+ isoRegex = /^\s*\d{4}-\d\d-\d\d(T(\d\d(:\d\d(:\d\d(\.\d\d?\d?)?)?)?)?([\+\-]\d\d:?\d\d)?)?/,
51
+ isoFormat = 'YYYY-MM-DDTHH:mm:ssZ',
52
+
53
+ // iso time formats and regexes
54
+ isoTimes = [
55
+ ['HH:mm:ss.S', /T\d\d:\d\d:\d\d\.\d{1,3}/],
56
+ ['HH:mm:ss', /T\d\d:\d\d:\d\d/],
57
+ ['HH:mm', /T\d\d:\d\d/],
58
+ ['HH', /T\d\d/]
59
+ ],
60
+
61
+ // timezone chunker "+10:00" > ["10", "00"] or "-1530" > ["-15", "30"]
62
+ parseTimezoneChunker = /([\+\-]|\d\d)/gi,
63
+
64
+ // getter and setter names
65
+ proxyGettersAndSetters = 'Month|Date|Hours|Minutes|Seconds|Milliseconds'.split('|'),
66
+ unitMillisecondFactors = {
67
+ 'Milliseconds' : 1,
68
+ 'Seconds' : 1e3,
69
+ 'Minutes' : 6e4,
70
+ 'Hours' : 36e5,
71
+ 'Days' : 864e5,
72
+ 'Months' : 2592e6,
73
+ 'Years' : 31536e6
74
+ },
75
+
76
+ // format function strings
77
+ formatFunctions = {},
78
+
79
+ // tokens to ordinalize and pad
80
+ ordinalizeTokens = 'DDD w M D d'.split(' '),
81
+ paddedTokens = 'M D H h m s w'.split(' '),
82
+
83
+ /*
84
+ * moment.fn.format uses new Function() to create an inlined formatting function.
85
+ * Results are a 3x speed boost
86
+ * http://jsperf.com/momentjs-cached-format-functions
87
+ *
88
+ * These strings are appended into a function using replaceFormatTokens and makeFormatFunction
89
+ */
90
+ formatTokenFunctions = {
91
+ // a = placeholder
92
+ // b = placeholder
93
+ // t = the current moment being formatted
94
+ // v = getValueAtKey function
95
+ // o = language.ordinal function
96
+ // p = leftZeroFill function
97
+ // m = language.meridiem value or function
98
+ M : function () {
99
+ return this.month() + 1;
100
+ },
101
+ MMM : function (format) {
102
+ return getValueFromArray("monthsShort", this.month(), this, format);
103
+ },
104
+ MMMM : function (format) {
105
+ return getValueFromArray("months", this.month(), this, format);
106
+ },
107
+ D : function () {
108
+ return this.date();
109
+ },
110
+ DDD : function () {
111
+ var a = new Date(this.year(), this.month(), this.date()),
112
+ b = new Date(this.year(), 0, 1);
113
+ return ~~(((a - b) / 864e5) + 1.5);
114
+ },
115
+ d : function () {
116
+ return this.day();
117
+ },
118
+ dd : function (format) {
119
+ return getValueFromArray("weekdaysMin", this.day(), this, format);
120
+ },
121
+ ddd : function (format) {
122
+ return getValueFromArray("weekdaysShort", this.day(), this, format);
123
+ },
124
+ dddd : function (format) {
125
+ return getValueFromArray("weekdays", this.day(), this, format);
126
+ },
127
+ w : function () {
128
+ var a = new Date(this.year(), this.month(), this.date() - this.day() + 5),
129
+ b = new Date(a.getFullYear(), 0, 4);
130
+ return ~~((a - b) / 864e5 / 7 + 1.5);
131
+ },
132
+ YY : function () {
133
+ return leftZeroFill(this.year() % 100, 2);
134
+ },
135
+ YYYY : function () {
136
+ return leftZeroFill(this.year(), 4);
137
+ },
138
+ a : function () {
139
+ return this.lang().meridiem(this.hours(), this.minutes(), true);
140
+ },
141
+ A : function () {
142
+ return this.lang().meridiem(this.hours(), this.minutes(), false);
143
+ },
144
+ H : function () {
145
+ return this.hours();
146
+ },
147
+ h : function () {
148
+ return this.hours() % 12 || 12;
149
+ },
150
+ m : function () {
151
+ return this.minutes();
152
+ },
153
+ s : function () {
154
+ return this.seconds();
155
+ },
156
+ S : function () {
157
+ return ~~(this.milliseconds() / 100);
158
+ },
159
+ SS : function () {
160
+ return leftZeroFill(~~(this.milliseconds() / 10), 2);
161
+ },
162
+ SSS : function () {
163
+ return leftZeroFill(this.milliseconds(), 3);
164
+ },
165
+ Z : function () {
166
+ var a = -this.zone(),
167
+ b = "+";
168
+ if (a < 0) {
169
+ a = -a;
170
+ b = "-";
171
+ }
172
+ return b + leftZeroFill(~~(a / 60), 2) + ":" + leftZeroFill(~~a % 60, 2);
173
+ },
174
+ ZZ : function () {
175
+ var a = -this.zone(),
176
+ b = "+";
177
+ if (a < 0) {
178
+ a = -a;
179
+ b = "-";
180
+ }
181
+ return b + leftZeroFill(~~(10 * a / 6), 4);
182
+ }
183
+ };
184
+
185
+ function getValueFromArray(key, index, m, format) {
186
+ var lang = m.lang();
187
+ return lang[key].call ? lang[key](m, format) : lang[key][index];
188
+ }
189
+
190
+ function padToken(func, count) {
191
+ return function (a) {
192
+ return leftZeroFill(func.call(this, a), count);
193
+ };
194
+ }
195
+ function ordinalizeToken(func) {
196
+ return function (a) {
197
+ var b = func.call(this, a);
198
+ return b + this.lang().ordinal(b);
199
+ };
200
+ }
201
+
202
+ while (ordinalizeTokens.length) {
203
+ i = ordinalizeTokens.pop();
204
+ formatTokenFunctions[i + 'o'] = ordinalizeToken(formatTokenFunctions[i]);
205
+ }
206
+ while (paddedTokens.length) {
207
+ i = paddedTokens.pop();
208
+ formatTokenFunctions[i + i] = padToken(formatTokenFunctions[i], 2);
209
+ }
210
+ formatTokenFunctions.DDDD = padToken(formatTokenFunctions.DDD, 3);
211
+
212
+
213
+ /************************************
214
+ Constructors
215
+ ************************************/
216
+
217
+
218
+ // Moment prototype object
219
+ function Moment(date, isUTC, lang) {
220
+ this._d = date;
221
+ this._isUTC = !!isUTC;
222
+ this._a = date._a || null;
223
+ this._lang = lang || false;
224
+ }
225
+
226
+ // Duration Constructor
227
+ function Duration(duration) {
228
+ var data = this._data = {},
229
+ years = duration.years || duration.y || 0,
230
+ months = duration.months || duration.M || 0,
231
+ weeks = duration.weeks || duration.w || 0,
232
+ days = duration.days || duration.d || 0,
233
+ hours = duration.hours || duration.h || 0,
234
+ minutes = duration.minutes || duration.m || 0,
235
+ seconds = duration.seconds || duration.s || 0,
236
+ milliseconds = duration.milliseconds || duration.ms || 0;
237
+
238
+ // representation for dateAddRemove
239
+ this._milliseconds = milliseconds +
240
+ seconds * 1e3 + // 1000
241
+ minutes * 6e4 + // 1000 * 60
242
+ hours * 36e5; // 1000 * 60 * 60
243
+ // Because of dateAddRemove treats 24 hours as different from a
244
+ // day when working around DST, we need to store them separately
245
+ this._days = days +
246
+ weeks * 7;
247
+ // It is impossible translate months into days without knowing
248
+ // which months you are are talking about, so we have to store
249
+ // it separately.
250
+ this._months = months +
251
+ years * 12;
252
+
253
+ // The following code bubbles up values, see the tests for
254
+ // examples of what that means.
255
+ data.milliseconds = milliseconds % 1000;
256
+ seconds += absRound(milliseconds / 1000);
257
+
258
+ data.seconds = seconds % 60;
259
+ minutes += absRound(seconds / 60);
260
+
261
+ data.minutes = minutes % 60;
262
+ hours += absRound(minutes / 60);
263
+
264
+ data.hours = hours % 24;
265
+ days += absRound(hours / 24);
266
+
267
+ days += weeks * 7;
268
+ data.days = days % 30;
269
+
270
+ months += absRound(days / 30);
271
+
272
+ data.months = months % 12;
273
+ years += absRound(months / 12);
274
+
275
+ data.years = years;
276
+
277
+ this._lang = false;
278
+ }
279
+
280
+
281
+ /************************************
282
+ Helpers
283
+ ************************************/
284
+
285
+
286
+ function absRound(number) {
287
+ if (number < 0) {
288
+ return Math.ceil(number);
289
+ } else {
290
+ return Math.floor(number);
291
+ }
292
+ }
293
+
294
+ // left zero fill a number
295
+ // see http://jsperf.com/left-zero-filling for performance comparison
296
+ function leftZeroFill(number, targetLength) {
297
+ var output = number + '';
298
+ while (output.length < targetLength) {
299
+ output = '0' + output;
300
+ }
301
+ return output;
302
+ }
303
+
304
+ // helper function for _.addTime and _.subtractTime
305
+ function addOrSubtractDurationFromMoment(mom, duration, isAdding) {
306
+ var ms = duration._milliseconds,
307
+ d = duration._days,
308
+ M = duration._months,
309
+ currentDate;
310
+
311
+ if (ms) {
312
+ mom._d.setTime(+mom + ms * isAdding);
313
+ }
314
+ if (d) {
315
+ mom.date(mom.date() + d * isAdding);
316
+ }
317
+ if (M) {
318
+ currentDate = mom.date();
319
+ mom.date(1)
320
+ .month(mom.month() + M * isAdding)
321
+ .date(Math.min(currentDate, mom.daysInMonth()));
322
+ }
323
+ }
324
+
325
+ // check if is an array
326
+ function isArray(input) {
327
+ return Object.prototype.toString.call(input) === '[object Array]';
328
+ }
329
+
330
+ // compare two arrays, return the number of differences
331
+ function compareArrays(array1, array2) {
332
+ var len = Math.min(array1.length, array2.length),
333
+ lengthDiff = Math.abs(array1.length - array2.length),
334
+ diffs = 0,
335
+ i;
336
+ for (i = 0; i < len; i++) {
337
+ if (~~array1[i] !== ~~array2[i]) {
338
+ diffs++;
339
+ }
340
+ }
341
+ return diffs + lengthDiff;
342
+ }
343
+
344
+ // convert an array to a date.
345
+ // the array should mirror the parameters below
346
+ // note: all values past the year are optional and will default to the lowest possible value.
347
+ // [year, month, day , hour, minute, second, millisecond]
348
+ function dateFromArray(input, asUTC, hoursOffset, minutesOffset) {
349
+ var i, date, forValid = [];
350
+ for (i = 0; i < 7; i++) {
351
+ forValid[i] = input[i] = (input[i] == null) ? (i === 2 ? 1 : 0) : input[i];
352
+ }
353
+ // we store whether we used utc or not in the input array
354
+ input[7] = forValid[7] = asUTC;
355
+ // if the parser flagged the input as invalid, we pass the value along
356
+ if (input[8] != null) {
357
+ forValid[8] = input[8];
358
+ }
359
+ // add the offsets to the time to be parsed so that we can have a clean array
360
+ // for checking isValid
361
+ input[3] += hoursOffset || 0;
362
+ input[4] += minutesOffset || 0;
363
+ date = new Date(0);
364
+ if (asUTC) {
365
+ date.setUTCFullYear(input[0], input[1], input[2]);
366
+ date.setUTCHours(input[3], input[4], input[5], input[6]);
367
+ } else {
368
+ date.setFullYear(input[0], input[1], input[2]);
369
+ date.setHours(input[3], input[4], input[5], input[6]);
370
+ }
371
+ date._a = forValid;
372
+ return date;
373
+ }
374
+
375
+ // Loads a language definition into the `languages` cache. The function
376
+ // takes a key and optionally values. If not in the browser and no values
377
+ // are provided, it will load the language file module. As a convenience,
378
+ // this function also returns the language values.
379
+ function loadLang(key, values) {
380
+ var i, m,
381
+ parse = [];
382
+
383
+ if (!values && hasModule) {
384
+ values = require('./lang/' + key);
385
+ }
386
+
387
+ for (i = 0; i < langConfigProperties.length; i++) {
388
+ // If a language definition does not provide a value, inherit
389
+ // from English
390
+ values[langConfigProperties[i]] = values[langConfigProperties[i]] ||
391
+ languages.en[langConfigProperties[i]];
392
+ }
393
+
394
+ for (i = 0; i < 12; i++) {
395
+ m = moment([2000, i]);
396
+ parse[i] = new RegExp('^' + (values.months[i] || values.months(m, '')) +
397
+ '|^' + (values.monthsShort[i] || values.monthsShort(m, '')).replace('.', ''), 'i');
398
+ }
399
+ values.monthsParse = values.monthsParse || parse;
400
+
401
+ languages[key] = values;
402
+
403
+ return values;
404
+ }
405
+
406
+ // Determines which language definition to use and returns it.
407
+ //
408
+ // With no parameters, it will return the global language. If you
409
+ // pass in a language key, such as 'en', it will return the
410
+ // definition for 'en', so long as 'en' has already been loaded using
411
+ // moment.lang. If you pass in a moment or duration instance, it
412
+ // will decide the language based on that, or default to the global
413
+ // language.
414
+ function getLangDefinition(m) {
415
+ var langKey = (typeof m === 'string') && m ||
416
+ m && m._lang ||
417
+ null;
418
+
419
+ return langKey ? (languages[langKey] || loadLang(langKey)) : moment;
420
+ }
421
+
422
+
423
+ /************************************
424
+ Formatting
425
+ ************************************/
426
+
427
+
428
+ function removeFormattingTokens(input) {
429
+ if (input.match(/\[.*\]/)) {
430
+ return input.replace(/^\[|\]$/g, "");
431
+ }
432
+ return input.replace(/\\/g, "");
433
+ }
434
+
435
+ function makeFormatFunction(format) {
436
+ var array = format.match(formattingTokens), i, length;
437
+
438
+ for (i = 0, length = array.length; i < length; i++) {
439
+ if (formatTokenFunctions[array[i]]) {
440
+ array[i] = formatTokenFunctions[array[i]];
441
+ } else {
442
+ array[i] = removeFormattingTokens(array[i]);
443
+ }
444
+ }
445
+
446
+ return function (mom) {
447
+ var output = "";
448
+ for (i = 0; i < length; i++) {
449
+ output += typeof array[i].call === 'function' ? array[i].call(mom, format) : array[i];
450
+ }
451
+ return output;
452
+ };
453
+ }
454
+
455
+ // format date using native date object
456
+ function formatMoment(m, format) {
457
+ var i = 5;
458
+
459
+ function replaceLongDateFormatTokens(input) {
460
+ return m.lang().longDateFormat[input] || input;
461
+ }
462
+
463
+ while (i-- && localFormattingTokens.test(format)) {
464
+ format = format.replace(localFormattingTokens, replaceLongDateFormatTokens);
465
+ }
466
+
467
+ if (!formatFunctions[format]) {
468
+ formatFunctions[format] = makeFormatFunction(format);
469
+ }
470
+
471
+ return formatFunctions[format](m);
472
+ }
473
+
474
+
475
+ /************************************
476
+ Parsing
477
+ ************************************/
478
+
479
+
480
+ // get the regex to find the next token
481
+ function getParseRegexForToken(token) {
482
+ switch (token) {
483
+ case 'DDDD':
484
+ return parseTokenThreeDigits;
485
+ case 'YYYY':
486
+ return parseTokenFourDigits;
487
+ case 'S':
488
+ case 'SS':
489
+ case 'SSS':
490
+ case 'DDD':
491
+ return parseTokenOneToThreeDigits;
492
+ case 'MMM':
493
+ case 'MMMM':
494
+ case 'dd':
495
+ case 'ddd':
496
+ case 'dddd':
497
+ case 'a':
498
+ case 'A':
499
+ return parseTokenWord;
500
+ case 'Z':
501
+ case 'ZZ':
502
+ return parseTokenTimezone;
503
+ case 'T':
504
+ return parseTokenT;
505
+ case 'MM':
506
+ case 'DD':
507
+ case 'YY':
508
+ case 'HH':
509
+ case 'hh':
510
+ case 'mm':
511
+ case 'ss':
512
+ case 'M':
513
+ case 'D':
514
+ case 'd':
515
+ case 'H':
516
+ case 'h':
517
+ case 'm':
518
+ case 's':
519
+ return parseTokenOneOrTwoDigits;
520
+ default :
521
+ return new RegExp(token.replace('\\', ''));
522
+ }
523
+ }
524
+
525
+ // function to convert string input to date
526
+ function addTimeToArrayFromToken(token, input, datePartArray, config) {
527
+ var a, b;
528
+
529
+ switch (token) {
530
+ // MONTH
531
+ case 'M' : // fall through to MM
532
+ case 'MM' :
533
+ datePartArray[1] = (input == null) ? 0 : ~~input - 1;
534
+ break;
535
+ case 'MMM' : // fall through to MMMM
536
+ case 'MMMM' :
537
+ for (a = 0; a < 12; a++) {
538
+ if (getLangDefinition().monthsParse[a].test(input)) {
539
+ datePartArray[1] = a;
540
+ b = true;
541
+ break;
542
+ }
543
+ }
544
+ // if we didn't find a month name, mark the date as invalid.
545
+ if (!b) {
546
+ datePartArray[8] = false;
547
+ }
548
+ break;
549
+ // DAY OF MONTH
550
+ case 'D' : // fall through to DDDD
551
+ case 'DD' : // fall through to DDDD
552
+ case 'DDD' : // fall through to DDDD
553
+ case 'DDDD' :
554
+ if (input != null) {
555
+ datePartArray[2] = ~~input;
556
+ }
557
+ break;
558
+ // YEAR
559
+ case 'YY' :
560
+ datePartArray[0] = ~~input + (~~input > 70 ? 1900 : 2000);
561
+ break;
562
+ case 'YYYY' :
563
+ datePartArray[0] = ~~Math.abs(input);
564
+ break;
565
+ // AM / PM
566
+ case 'a' : // fall through to A
567
+ case 'A' :
568
+ config.isPm = ((input + '').toLowerCase() === 'pm');
569
+ break;
570
+ // 24 HOUR
571
+ case 'H' : // fall through to hh
572
+ case 'HH' : // fall through to hh
573
+ case 'h' : // fall through to hh
574
+ case 'hh' :
575
+ datePartArray[3] = ~~input;
576
+ break;
577
+ // MINUTE
578
+ case 'm' : // fall through to mm
579
+ case 'mm' :
580
+ datePartArray[4] = ~~input;
581
+ break;
582
+ // SECOND
583
+ case 's' : // fall through to ss
584
+ case 'ss' :
585
+ datePartArray[5] = ~~input;
586
+ break;
587
+ // MILLISECOND
588
+ case 'S' :
589
+ case 'SS' :
590
+ case 'SSS' :
591
+ datePartArray[6] = ~~ (('0.' + input) * 1000);
592
+ break;
593
+ // TIMEZONE
594
+ case 'Z' : // fall through to ZZ
595
+ case 'ZZ' :
596
+ config.isUTC = true;
597
+ a = (input + '').match(parseTimezoneChunker);
598
+ if (a && a[1]) {
599
+ config.tzh = ~~a[1];
600
+ }
601
+ if (a && a[2]) {
602
+ config.tzm = ~~a[2];
603
+ }
604
+ // reverse offsets
605
+ if (a && a[0] === '+') {
606
+ config.tzh = -config.tzh;
607
+ config.tzm = -config.tzm;
608
+ }
609
+ break;
610
+ }
611
+
612
+ // if the input is null, the date is not valid
613
+ if (input == null) {
614
+ datePartArray[8] = false;
615
+ }
616
+ }
617
+
618
+ // date from string and format string
619
+ function makeDateFromStringAndFormat(string, format) {
620
+ // This array is used to make a Date, either with `new Date` or `Date.UTC`
621
+ // We store some additional data on the array for validation
622
+ // datePartArray[7] is true if the Date was created with `Date.UTC` and false if created with `new Date`
623
+ // datePartArray[8] is false if the Date is invalid, and undefined if the validity is unknown.
624
+ var datePartArray = [0, 0, 1, 0, 0, 0, 0],
625
+ config = {
626
+ tzh : 0, // timezone hour offset
627
+ tzm : 0 // timezone minute offset
628
+ },
629
+ tokens = format.match(formattingTokens),
630
+ i, parsedInput;
631
+
632
+ for (i = 0; i < tokens.length; i++) {
633
+ parsedInput = (getParseRegexForToken(tokens[i]).exec(string) || [])[0];
634
+ if (parsedInput) {
635
+ string = string.slice(string.indexOf(parsedInput) + parsedInput.length);
636
+ }
637
+ // don't parse if its not a known token
638
+ if (formatTokenFunctions[tokens[i]]) {
639
+ addTimeToArrayFromToken(tokens[i], parsedInput, datePartArray, config);
640
+ }
641
+ }
642
+ // handle am pm
643
+ if (config.isPm && datePartArray[3] < 12) {
644
+ datePartArray[3] += 12;
645
+ }
646
+ // if is 12 am, change hours to 0
647
+ if (config.isPm === false && datePartArray[3] === 12) {
648
+ datePartArray[3] = 0;
649
+ }
650
+ // return
651
+ return dateFromArray(datePartArray, config.isUTC, config.tzh, config.tzm);
652
+ }
653
+
654
+ // date from string and array of format strings
655
+ function makeDateFromStringAndArray(string, formats) {
656
+ var output,
657
+ inputParts = string.match(parseMultipleFormatChunker) || [],
658
+ formattedInputParts,
659
+ scoreToBeat = 99,
660
+ i,
661
+ currentDate,
662
+ currentScore;
663
+ for (i = 0; i < formats.length; i++) {
664
+ currentDate = makeDateFromStringAndFormat(string, formats[i]);
665
+ formattedInputParts = formatMoment(new Moment(currentDate), formats[i]).match(parseMultipleFormatChunker) || [];
666
+ currentScore = compareArrays(inputParts, formattedInputParts);
667
+ if (currentScore < scoreToBeat) {
668
+ scoreToBeat = currentScore;
669
+ output = currentDate;
670
+ }
671
+ }
672
+ return output;
673
+ }
674
+
675
+ // date from iso format
676
+ function makeDateFromString(string) {
677
+ var format = 'YYYY-MM-DDT',
678
+ i;
679
+ if (isoRegex.exec(string)) {
680
+ for (i = 0; i < 4; i++) {
681
+ if (isoTimes[i][1].exec(string)) {
682
+ format += isoTimes[i][0];
683
+ break;
684
+ }
685
+ }
686
+ return parseTokenTimezone.exec(string) ?
687
+ makeDateFromStringAndFormat(string, format + ' Z') :
688
+ makeDateFromStringAndFormat(string, format);
689
+ }
690
+ return new Date(string);
691
+ }
692
+
693
+
694
+ /************************************
695
+ Relative Time
696
+ ************************************/
697
+
698
+
699
+ // helper function for moment.fn.from, moment.fn.fromNow, and moment.duration.fn.humanize
700
+ function substituteTimeAgo(string, number, withoutSuffix, isFuture, lang) {
701
+ var rt = lang.relativeTime[string];
702
+ return (typeof rt === 'function') ?
703
+ rt(number || 1, !!withoutSuffix, string, isFuture) :
704
+ rt.replace(/%d/i, number || 1);
705
+ }
706
+
707
+ function relativeTime(milliseconds, withoutSuffix, lang) {
708
+ var seconds = round(Math.abs(milliseconds) / 1000),
709
+ minutes = round(seconds / 60),
710
+ hours = round(minutes / 60),
711
+ days = round(hours / 24),
712
+ years = round(days / 365),
713
+ args = seconds < 45 && ['s', seconds] ||
714
+ minutes === 1 && ['m'] ||
715
+ minutes < 45 && ['mm', minutes] ||
716
+ hours === 1 && ['h'] ||
717
+ hours < 22 && ['hh', hours] ||
718
+ days === 1 && ['d'] ||
719
+ days <= 25 && ['dd', days] ||
720
+ days <= 45 && ['M'] ||
721
+ days < 345 && ['MM', round(days / 30)] ||
722
+ years === 1 && ['y'] || ['yy', years];
723
+ args[2] = withoutSuffix;
724
+ args[3] = milliseconds > 0;
725
+ args[4] = lang;
726
+ return substituteTimeAgo.apply({}, args);
727
+ }
728
+
729
+
730
+ /************************************
731
+ Top Level Functions
732
+ ************************************/
733
+
734
+
735
+ moment = function (input, format) {
736
+ if (input === null || input === '') {
737
+ return null;
738
+ }
739
+ var date,
740
+ matched;
741
+ // parse Moment object
742
+ if (moment.isMoment(input)) {
743
+ return new Moment(new Date(+input._d), input._isUTC, input._lang);
744
+ // parse string and format
745
+ } else if (format) {
746
+ if (isArray(format)) {
747
+ date = makeDateFromStringAndArray(input, format);
748
+ } else {
749
+ date = makeDateFromStringAndFormat(input, format);
750
+ }
751
+ // evaluate it as a JSON-encoded date
752
+ } else {
753
+ matched = aspNetJsonRegex.exec(input);
754
+ date = input === undefined ? new Date() :
755
+ matched ? new Date(+matched[1]) :
756
+ input instanceof Date ? input :
757
+ isArray(input) ? dateFromArray(input) :
758
+ typeof input === 'string' ? makeDateFromString(input) :
759
+ new Date(input);
760
+ }
761
+
762
+ return new Moment(date);
763
+ };
764
+
765
+ // creating with utc
766
+ moment.utc = function (input, format) {
767
+ if (isArray(input)) {
768
+ return new Moment(dateFromArray(input, true), true);
769
+ }
770
+ // if we don't have a timezone, we need to add one to trigger parsing into utc
771
+ if (typeof input === 'string' && !parseTokenTimezone.exec(input)) {
772
+ input += ' +0000';
773
+ if (format) {
774
+ format += ' Z';
775
+ }
776
+ }
777
+ return moment(input, format).utc();
778
+ };
779
+
780
+ // creating with unix timestamp (in seconds)
781
+ moment.unix = function (input) {
782
+ return moment(input * 1000);
783
+ };
784
+
785
+ // duration
786
+ moment.duration = function (input, key) {
787
+ var isDuration = moment.isDuration(input),
788
+ isNumber = (typeof input === 'number'),
789
+ duration = (isDuration ? input._data : (isNumber ? {} : input)),
790
+ ret;
791
+
792
+ if (isNumber) {
793
+ if (key) {
794
+ duration[key] = input;
795
+ } else {
796
+ duration.milliseconds = input;
797
+ }
798
+ }
799
+
800
+ ret = new Duration(duration);
801
+
802
+ if (isDuration) {
803
+ ret._lang = input._lang;
804
+ }
805
+
806
+ return ret;
807
+ };
808
+
809
+ // humanizeDuration
810
+ // This method is deprecated in favor of the new Duration object. Please
811
+ // see the moment.duration method.
812
+ moment.humanizeDuration = function (num, type, withSuffix) {
813
+ return moment.duration(num, type === true ? null : type).humanize(type === true ? true : withSuffix);
814
+ };
815
+
816
+ // version number
817
+ moment.version = VERSION;
818
+
819
+ // default format
820
+ moment.defaultFormat = isoFormat;
821
+
822
+ // This function will load languages and then set the global language. If
823
+ // no arguments are passed in, it will simply return the current global
824
+ // language key.
825
+ moment.lang = function (key, values) {
826
+ var i;
827
+
828
+ if (!key) {
829
+ return currentLanguage;
830
+ }
831
+ if (values || !languages[key]) {
832
+ loadLang(key, values);
833
+ }
834
+ if (languages[key]) {
835
+ // deprecated, to get the language definition variables, use the
836
+ // moment.fn.lang method or the getLangDefinition function.
837
+ for (i = 0; i < langConfigProperties.length; i++) {
838
+ moment[langConfigProperties[i]] = languages[key][langConfigProperties[i]];
839
+ }
840
+ moment.monthsParse = languages[key].monthsParse;
841
+ currentLanguage = key;
842
+ }
843
+ };
844
+
845
+ // returns language data
846
+ moment.langData = getLangDefinition;
847
+
848
+ // compare moment object
849
+ moment.isMoment = function (obj) {
850
+ return obj instanceof Moment;
851
+ };
852
+
853
+ // for typechecking Duration objects
854
+ moment.isDuration = function (obj) {
855
+ return obj instanceof Duration;
856
+ };
857
+
858
+ // Set default language, other languages will inherit from English.
859
+ moment.lang('en', {
860
+ months : "January_February_March_April_May_June_July_August_September_October_November_December".split("_"),
861
+ monthsShort : "Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec".split("_"),
862
+ weekdays : "Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_"),
863
+ weekdaysShort : "Sun_Mon_Tue_Wed_Thu_Fri_Sat".split("_"),
864
+ weekdaysMin : "Su_Mo_Tu_We_Th_Fr_Sa".split("_"),
865
+ longDateFormat : {
866
+ LT : "h:mm A",
867
+ L : "MM/DD/YYYY",
868
+ LL : "MMMM D YYYY",
869
+ LLL : "MMMM D YYYY LT",
870
+ LLLL : "dddd, MMMM D YYYY LT"
871
+ },
872
+ meridiem : function (hours, minutes, isLower) {
873
+ if (hours > 11) {
874
+ return isLower ? 'pm' : 'PM';
875
+ } else {
876
+ return isLower ? 'am' : 'AM';
877
+ }
878
+ },
879
+ calendar : {
880
+ sameDay : '[Today at] LT',
881
+ nextDay : '[Tomorrow at] LT',
882
+ nextWeek : 'dddd [at] LT',
883
+ lastDay : '[Yesterday at] LT',
884
+ lastWeek : '[last] dddd [at] LT',
885
+ sameElse : 'L'
886
+ },
887
+ relativeTime : {
888
+ future : "in %s",
889
+ past : "%s ago",
890
+ s : "a few seconds",
891
+ m : "a minute",
892
+ mm : "%d minutes",
893
+ h : "an hour",
894
+ hh : "%d hours",
895
+ d : "a day",
896
+ dd : "%d days",
897
+ M : "a month",
898
+ MM : "%d months",
899
+ y : "a year",
900
+ yy : "%d years"
901
+ },
902
+ ordinal : function (number) {
903
+ var b = number % 10;
904
+ return (~~ (number % 100 / 10) === 1) ? 'th' :
905
+ (b === 1) ? 'st' :
906
+ (b === 2) ? 'nd' :
907
+ (b === 3) ? 'rd' : 'th';
908
+ }
909
+ });
910
+
911
+
912
+ /************************************
913
+ Moment Prototype
914
+ ************************************/
915
+
916
+
917
+ moment.fn = Moment.prototype = {
918
+
919
+ clone : function () {
920
+ return moment(this);
921
+ },
922
+
923
+ valueOf : function () {
924
+ return +this._d;
925
+ },
926
+
927
+ unix : function () {
928
+ return Math.floor(+this._d / 1000);
929
+ },
930
+
931
+ toString : function () {
932
+ return this._d.toString();
933
+ },
934
+
935
+ toDate : function () {
936
+ return this._d;
937
+ },
938
+
939
+ toArray : function () {
940
+ var m = this;
941
+ return [
942
+ m.year(),
943
+ m.month(),
944
+ m.date(),
945
+ m.hours(),
946
+ m.minutes(),
947
+ m.seconds(),
948
+ m.milliseconds(),
949
+ !!this._isUTC
950
+ ];
951
+ },
952
+
953
+ isValid : function () {
954
+ if (this._a) {
955
+ // if the parser finds that the input is invalid, it sets
956
+ // the eighth item in the input array to false.
957
+ if (this._a[8] != null) {
958
+ return !!this._a[8];
959
+ }
960
+ return !compareArrays(this._a, (this._a[7] ? moment.utc(this._a) : moment(this._a)).toArray());
961
+ }
962
+ return !isNaN(this._d.getTime());
963
+ },
964
+
965
+ utc : function () {
966
+ this._isUTC = true;
967
+ return this;
968
+ },
969
+
970
+ local : function () {
971
+ this._isUTC = false;
972
+ return this;
973
+ },
974
+
975
+ format : function (inputString) {
976
+ return formatMoment(this, inputString ? inputString : moment.defaultFormat);
977
+ },
978
+
979
+ add : function (input, val) {
980
+ var dur = val ? moment.duration(+val, input) : moment.duration(input);
981
+ addOrSubtractDurationFromMoment(this, dur, 1);
982
+ return this;
983
+ },
984
+
985
+ subtract : function (input, val) {
986
+ var dur = val ? moment.duration(+val, input) : moment.duration(input);
987
+ addOrSubtractDurationFromMoment(this, dur, -1);
988
+ return this;
989
+ },
990
+
991
+ diff : function (input, val, asFloat) {
992
+ var inputMoment = this._isUTC ? moment(input).utc() : moment(input).local(),
993
+ zoneDiff = (this.zone() - inputMoment.zone()) * 6e4,
994
+ diff = this._d - inputMoment._d - zoneDiff,
995
+ year = this.year() - inputMoment.year(),
996
+ month = this.month() - inputMoment.month(),
997
+ date = this.date() - inputMoment.date(),
998
+ output;
999
+ if (val === 'months') {
1000
+ output = year * 12 + month + date / 30;
1001
+ } else if (val === 'years') {
1002
+ output = year + (month + date / 30) / 12;
1003
+ } else {
1004
+ output = val === 'seconds' ? diff / 1e3 : // 1000
1005
+ val === 'minutes' ? diff / 6e4 : // 1000 * 60
1006
+ val === 'hours' ? diff / 36e5 : // 1000 * 60 * 60
1007
+ val === 'days' ? diff / 864e5 : // 1000 * 60 * 60 * 24
1008
+ val === 'weeks' ? diff / 6048e5 : // 1000 * 60 * 60 * 24 * 7
1009
+ diff;
1010
+ }
1011
+ return asFloat ? output : round(output);
1012
+ },
1013
+
1014
+ from : function (time, withoutSuffix) {
1015
+ return moment.duration(this.diff(time)).lang(this._lang).humanize(!withoutSuffix);
1016
+ },
1017
+
1018
+ fromNow : function (withoutSuffix) {
1019
+ return this.from(moment(), withoutSuffix);
1020
+ },
1021
+
1022
+ calendar : function () {
1023
+ var diff = this.diff(moment().sod(), 'days', true),
1024
+ calendar = this.lang().calendar,
1025
+ allElse = calendar.sameElse,
1026
+ format = diff < -6 ? allElse :
1027
+ diff < -1 ? calendar.lastWeek :
1028
+ diff < 0 ? calendar.lastDay :
1029
+ diff < 1 ? calendar.sameDay :
1030
+ diff < 2 ? calendar.nextDay :
1031
+ diff < 7 ? calendar.nextWeek : allElse;
1032
+ return this.format(typeof format === 'function' ? format.apply(this) : format);
1033
+ },
1034
+
1035
+ isLeapYear : function () {
1036
+ var year = this.year();
1037
+ return (year % 4 === 0 && year % 100 !== 0) || year % 400 === 0;
1038
+ },
1039
+
1040
+ isDST : function () {
1041
+ return (this.zone() < moment([this.year()]).zone() ||
1042
+ this.zone() < moment([this.year(), 5]).zone());
1043
+ },
1044
+
1045
+ day : function (input) {
1046
+ var day = this._isUTC ? this._d.getUTCDay() : this._d.getDay();
1047
+ return input == null ? day :
1048
+ this.add({ d : input - day });
1049
+ },
1050
+
1051
+ startOf: function (val) {
1052
+ // the following switch intentionally omits break keywords
1053
+ // to utilize falling through the cases.
1054
+ switch (val.replace(/s$/, '')) {
1055
+ case 'year':
1056
+ this.month(0);
1057
+ /* falls through */
1058
+ case 'month':
1059
+ this.date(1);
1060
+ /* falls through */
1061
+ case 'day':
1062
+ this.hours(0);
1063
+ /* falls through */
1064
+ case 'hour':
1065
+ this.minutes(0);
1066
+ /* falls through */
1067
+ case 'minute':
1068
+ this.seconds(0);
1069
+ /* falls through */
1070
+ case 'second':
1071
+ this.milliseconds(0);
1072
+ /* falls through */
1073
+ }
1074
+ return this;
1075
+ },
1076
+
1077
+ endOf: function (val) {
1078
+ return this.startOf(val).add(val.replace(/s?$/, 's'), 1).subtract('ms', 1);
1079
+ },
1080
+
1081
+ sod: function () {
1082
+ return this.clone().startOf('day');
1083
+ },
1084
+
1085
+ eod: function () {
1086
+ // end of day = start of day plus 1 day, minus 1 millisecond
1087
+ return this.clone().endOf('day');
1088
+ },
1089
+
1090
+ zone : function () {
1091
+ return this._isUTC ? 0 : this._d.getTimezoneOffset();
1092
+ },
1093
+
1094
+ daysInMonth : function () {
1095
+ return moment.utc([this.year(), this.month() + 1, 0]).date();
1096
+ },
1097
+
1098
+ // If passed a language key, it will set the language for this
1099
+ // instance. Otherwise, it will return the language configuration
1100
+ // variables for this instance.
1101
+ lang : function (lang) {
1102
+ if (lang === undefined) {
1103
+ return getLangDefinition(this);
1104
+ } else {
1105
+ this._lang = lang;
1106
+ return this;
1107
+ }
1108
+ }
1109
+ };
1110
+
1111
+ // helper for adding shortcuts
1112
+ function makeGetterAndSetter(name, key) {
1113
+ moment.fn[name] = function (input) {
1114
+ var utc = this._isUTC ? 'UTC' : '';
1115
+ if (input != null) {
1116
+ this._d['set' + utc + key](input);
1117
+ return this;
1118
+ } else {
1119
+ return this._d['get' + utc + key]();
1120
+ }
1121
+ };
1122
+ }
1123
+
1124
+ // loop through and add shortcuts (Month, Date, Hours, Minutes, Seconds, Milliseconds)
1125
+ for (i = 0; i < proxyGettersAndSetters.length; i ++) {
1126
+ makeGetterAndSetter(proxyGettersAndSetters[i].toLowerCase(), proxyGettersAndSetters[i]);
1127
+ }
1128
+
1129
+ // add shortcut for year (uses different syntax than the getter/setter 'year' == 'FullYear')
1130
+ makeGetterAndSetter('year', 'FullYear');
1131
+
1132
+
1133
+ /************************************
1134
+ Duration Prototype
1135
+ ************************************/
1136
+
1137
+
1138
+ moment.duration.fn = Duration.prototype = {
1139
+ weeks : function () {
1140
+ return absRound(this.days() / 7);
1141
+ },
1142
+
1143
+ valueOf : function () {
1144
+ return this._milliseconds +
1145
+ this._days * 864e5 +
1146
+ this._months * 2592e6;
1147
+ },
1148
+
1149
+ humanize : function (withSuffix) {
1150
+ var difference = +this,
1151
+ rel = this.lang().relativeTime,
1152
+ output = relativeTime(difference, !withSuffix, this.lang()),
1153
+ fromNow = difference <= 0 ? rel.past : rel.future;
1154
+
1155
+ if (withSuffix) {
1156
+ if (typeof fromNow === 'function') {
1157
+ output = fromNow(output);
1158
+ } else {
1159
+ output = fromNow.replace(/%s/i, output);
1160
+ }
1161
+ }
1162
+
1163
+ return output;
1164
+ },
1165
+
1166
+ lang : moment.fn.lang
1167
+ };
1168
+
1169
+ function makeDurationGetter(name) {
1170
+ moment.duration.fn[name] = function () {
1171
+ return this._data[name];
1172
+ };
1173
+ }
1174
+
1175
+ function makeDurationAsGetter(name, factor) {
1176
+ moment.duration.fn['as' + name] = function () {
1177
+ return +this / factor;
1178
+ };
1179
+ }
1180
+
1181
+ for (i in unitMillisecondFactors) {
1182
+ if (unitMillisecondFactors.hasOwnProperty(i)) {
1183
+ makeDurationAsGetter(i, unitMillisecondFactors[i]);
1184
+ makeDurationGetter(i.toLowerCase());
1185
+ }
1186
+ }
1187
+
1188
+ makeDurationAsGetter('Weeks', 6048e5);
1189
+
1190
+
1191
+ /************************************
1192
+ Exposing Moment
1193
+ ************************************/
1194
+
1195
+
1196
+ // CommonJS module is defined
1197
+ if (hasModule) {
1198
+ module.exports = moment;
1199
+ }
1200
+ /*global ender:false */
1201
+ if (typeof ender === 'undefined') {
1202
+ // here, `this` means `window` in the browser, or `global` on the server
1203
+ // add `moment` as a global object via a string identifier,
1204
+ // for Closure Compiler "advanced" mode
1205
+ this['moment'] = moment;
1206
+ }
1207
+ /*global define:false */
1208
+ if (typeof define === "function" && define.amd) {
1209
+ define("moment", [], function () {
1210
+ return moment;
1211
+ });
1212
+ }
1213
+ }).call(this);