rails-bootstrap-daterangepicker 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 5f32030c9a517bea393dc826dfde913b8858d053
4
+ data.tar.gz: e242e160057cf2a4ab0b42071d55da6c87974eb2
5
+ SHA512:
6
+ metadata.gz: 2d7cf3b447eb291869d66c15e3b1fea3d475b3ff6fd7697ab999adb7d8053ac749d4345de56782d2aaacdc9cd767a4207a26145d8e52c6a8ade954a65a347a84
7
+ data.tar.gz: 6f66842b2d9fdab40440ee3183452749c51835a6e6f6bda92e86136c07fd08f11b2a106507f0f5c459880f09145edc074d2c35194992032fd87fd56bd10fde78
@@ -0,0 +1,19 @@
1
+ *.rbc
2
+ *.sassc
3
+ .sass-cache
4
+ capybara-*.html
5
+ .rspec
6
+ .rvmrc
7
+ /.bundle
8
+ /vendor/bundle
9
+ /log/*
10
+ /tmp/*
11
+ /db/*.sqlite3
12
+ /public/system/*
13
+ /coverage/
14
+ /spec/tmp/*
15
+ **.orig
16
+ rerun.txt
17
+ pickle-email-*.html
18
+ .project
19
+ config/initializers/secret_token.rb
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "https://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in rails-bootstrap-daterangepicker.gemspec
4
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) <2014> <cc>
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
@@ -0,0 +1,44 @@
1
+ #rails-bootstrap-daterangepicker
2
+
3
+ ![Improvely.com](http://i.imgur.com/LbAMf3D.png)
4
+
5
+ The `rails-bootstrap-daterangepicker` gem integrates the [bootstrap-daterangepicker](https://github.com/dangrossman/bootstrap-daterangepicker) jQuery plugin with the Rails asset pipeline.
6
+
7
+
8
+ ## Usage
9
+
10
+ [![GitHub version](https://badge.fury.io/gh/chilian%2Frails-bootstrap-daterangepicker.png)](http://badge.fury.io/gh/chilian%2Frails-bootstrap-daterangepicker)
11
+
12
+ ### Install the rails-bootstrap-daterangepicker gem
13
+
14
+ Add `rails-bootstrap-daterangepicker` to your Gemfile and run `bundle install`:
15
+
16
+ gem "rails-bootstrap-daterangepicker"
17
+
18
+ ### Include rails-bootstrap-daterangepicker javascript assets
19
+
20
+ Add the following to your `app/assets/javascripts/application.js`:
21
+
22
+ //= require bootstrap-daterangepicker
23
+
24
+ ### Include rails-bootstrap-daterangepicker stylesheet assets
25
+
26
+ Add to your `app/assets/stylesheets/application.css`:
27
+
28
+ *= require bootstrap-daterangepicker-3
29
+
30
+ Or if you are using Twitter Boostrap 2 you need to require the following file instead:
31
+
32
+ *= require bootstrap-daterangepicker-2
33
+
34
+ ## Contributions
35
+
36
+ If you want to contribute, please:
37
+
38
+ * Fork the project.
39
+ * Make your feature addition or bug fix.
40
+ * Send me a pull request on Github.
41
+
42
+ ## License
43
+
44
+ rails-bootstrap-daterangepicker is released under the [MIT License](http://www.opensource.org/licenses/MIT).
@@ -0,0 +1,9 @@
1
+ #!/usr/bin/env rake
2
+ require "bundler/gem_tasks"
3
+ #require File.expand_path('../lib/rails-bootstrap-daterangepicker/source_file', __FILE__)
4
+
5
+ # TODO
6
+ # desc "Update with dangrossman's bootstrap-daterangepicker library"
7
+ # task "update-bootstrap-daterangepicker" do
8
+
9
+ # end
@@ -0,0 +1,3407 @@
1
+ //! moment.js
2
+ //! version : 2.5.1
3
+ //! authors : Tim Wood, Iskren Chernev, Moment.js contributors
4
+ //! license : MIT
5
+ //! momentjs.com
6
+
7
+ (function (undefined) {
8
+
9
+ /************************************
10
+ Constants
11
+ ************************************/
12
+
13
+ var moment,
14
+ VERSION = "2.5.1",
15
+ global = this,
16
+ round = Math.round,
17
+ i,
18
+
19
+ YEAR = 0,
20
+ MONTH = 1,
21
+ DATE = 2,
22
+ HOUR = 3,
23
+ MINUTE = 4,
24
+ SECOND = 5,
25
+ MILLISECOND = 6,
26
+
27
+ // internal storage for language config files
28
+ languages = {},
29
+
30
+ // moment internal properties
31
+ momentProperties = {
32
+ _isAMomentObject: null,
33
+ _i : null,
34
+ _f : null,
35
+ _l : null,
36
+ _strict : null,
37
+ _isUTC : null,
38
+ _offset : null, // optional. Combine with _isUTC
39
+ _pf : null,
40
+ _lang : null // optional
41
+ },
42
+
43
+ // check for nodeJS
44
+ hasModule = (typeof module !== 'undefined' && module.exports && typeof require !== 'undefined'),
45
+
46
+ // ASP.NET json date format regex
47
+ aspNetJsonRegex = /^\/?Date\((\-?\d+)/i,
48
+ aspNetTimeSpanJsonRegex = /(\-)?(?:(\d*)\.)?(\d+)\:(\d+)(?:\:(\d+)\.?(\d{3})?)?/,
49
+
50
+ // from http://docs.closure-library.googlecode.com/git/closure_goog_date_date.js.source.html
51
+ // somewhat more in line with 4.4.3.2 2004 spec, but allows decimal anywhere
52
+ isoDurationRegex = /^(-)?P(?:(?:([0-9,.]*)Y)?(?:([0-9,.]*)M)?(?:([0-9,.]*)D)?(?:T(?:([0-9,.]*)H)?(?:([0-9,.]*)M)?(?:([0-9,.]*)S)?)?|([0-9,.]*)W)$/,
53
+
54
+ // format tokens
55
+ formattingTokens = /(\[[^\[]*\])|(\\)?(Mo|MM?M?M?|Do|DDDo|DD?D?D?|ddd?d?|do?|w[o|w]?|W[o|W]?|YYYYYY|YYYYY|YYYY|YY|gg(ggg?)?|GG(GGG?)?|e|E|a|A|hh?|HH?|mm?|ss?|S{1,4}|X|zz?|ZZ?|.)/g,
56
+ localFormattingTokens = /(\[[^\[]*\])|(\\)?(LT|LL?L?L?|l{1,4})/g,
57
+
58
+ // parsing token regexes
59
+ parseTokenOneOrTwoDigits = /\d\d?/, // 0 - 99
60
+ parseTokenOneToThreeDigits = /\d{1,3}/, // 0 - 999
61
+ parseTokenOneToFourDigits = /\d{1,4}/, // 0 - 9999
62
+ parseTokenOneToSixDigits = /[+\-]?\d{1,6}/, // -999,999 - 999,999
63
+ parseTokenDigits = /\d+/, // nonzero number of digits
64
+ parseTokenWord = /[0-9]*['a-z\u00A0-\u05FF\u0700-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]+|[\u0600-\u06FF\/]+(\s*?[\u0600-\u06FF]+){1,2}/i, // any word (or two) characters or numbers including two/three word month in arabic.
65
+ parseTokenTimezone = /Z|[\+\-]\d\d:?\d\d/gi, // +00:00 -00:00 +0000 -0000 or Z
66
+ parseTokenT = /T/i, // T (ISO separator)
67
+ parseTokenTimestampMs = /[\+\-]?\d+(\.\d{1,3})?/, // 123456789 123456789.123
68
+
69
+ //strict parsing regexes
70
+ parseTokenOneDigit = /\d/, // 0 - 9
71
+ parseTokenTwoDigits = /\d\d/, // 00 - 99
72
+ parseTokenThreeDigits = /\d{3}/, // 000 - 999
73
+ parseTokenFourDigits = /\d{4}/, // 0000 - 9999
74
+ parseTokenSixDigits = /[+-]?\d{6}/, // -999,999 - 999,999
75
+ parseTokenSignedNumber = /[+-]?\d+/, // -inf - inf
76
+
77
+ // iso 8601 regex
78
+ // 0000-00-00 0000-W00 or 0000-W00-0 + T + 00 or 00:00 or 00:00:00 or 00:00:00.000 + +00:00 or +0000 or +00)
79
+ isoRegex = /^\s*(?:[+-]\d{6}|\d{4})-(?:(\d\d-\d\d)|(W\d\d$)|(W\d\d-\d)|(\d\d\d))((T| )(\d\d(:\d\d(:\d\d(\.\d+)?)?)?)?([\+\-]\d\d(?::?\d\d)?|\s*Z)?)?$/,
80
+
81
+ isoFormat = 'YYYY-MM-DDTHH:mm:ssZ',
82
+
83
+ isoDates = [
84
+ ['YYYYYY-MM-DD', /[+-]\d{6}-\d{2}-\d{2}/],
85
+ ['YYYY-MM-DD', /\d{4}-\d{2}-\d{2}/],
86
+ ['GGGG-[W]WW-E', /\d{4}-W\d{2}-\d/],
87
+ ['GGGG-[W]WW', /\d{4}-W\d{2}/],
88
+ ['YYYY-DDD', /\d{4}-\d{3}/]
89
+ ],
90
+
91
+ // iso time formats and regexes
92
+ isoTimes = [
93
+ ['HH:mm:ss.SSSS', /(T| )\d\d:\d\d:\d\d\.\d{1,3}/],
94
+ ['HH:mm:ss', /(T| )\d\d:\d\d:\d\d/],
95
+ ['HH:mm', /(T| )\d\d:\d\d/],
96
+ ['HH', /(T| )\d\d/]
97
+ ],
98
+
99
+ // timezone chunker "+10:00" > ["10", "00"] or "-1530" > ["-15", "30"]
100
+ parseTimezoneChunker = /([\+\-]|\d\d)/gi,
101
+
102
+ // getter and setter names
103
+ proxyGettersAndSetters = 'Date|Hours|Minutes|Seconds|Milliseconds'.split('|'),
104
+ unitMillisecondFactors = {
105
+ 'Milliseconds' : 1,
106
+ 'Seconds' : 1e3,
107
+ 'Minutes' : 6e4,
108
+ 'Hours' : 36e5,
109
+ 'Days' : 864e5,
110
+ 'Months' : 2592e6,
111
+ 'Years' : 31536e6
112
+ },
113
+
114
+ unitAliases = {
115
+ ms : 'millisecond',
116
+ s : 'second',
117
+ m : 'minute',
118
+ h : 'hour',
119
+ d : 'day',
120
+ D : 'date',
121
+ w : 'week',
122
+ W : 'isoWeek',
123
+ M : 'month',
124
+ y : 'year',
125
+ DDD : 'dayOfYear',
126
+ e : 'weekday',
127
+ E : 'isoWeekday',
128
+ gg: 'weekYear',
129
+ GG: 'isoWeekYear'
130
+ },
131
+
132
+ camelFunctions = {
133
+ dayofyear : 'dayOfYear',
134
+ isoweekday : 'isoWeekday',
135
+ isoweek : 'isoWeek',
136
+ weekyear : 'weekYear',
137
+ isoweekyear : 'isoWeekYear'
138
+ },
139
+
140
+ // format function strings
141
+ formatFunctions = {},
142
+
143
+ // tokens to ordinalize and pad
144
+ ordinalizeTokens = 'DDD w W M D d'.split(' '),
145
+ paddedTokens = 'M D H h m s w W'.split(' '),
146
+
147
+ formatTokenFunctions = {
148
+ M : function () {
149
+ return this.month() + 1;
150
+ },
151
+ MMM : function (format) {
152
+ return this.lang().monthsShort(this, format);
153
+ },
154
+ MMMM : function (format) {
155
+ return this.lang().months(this, format);
156
+ },
157
+ D : function () {
158
+ return this.date();
159
+ },
160
+ DDD : function () {
161
+ return this.dayOfYear();
162
+ },
163
+ d : function () {
164
+ return this.day();
165
+ },
166
+ dd : function (format) {
167
+ return this.lang().weekdaysMin(this, format);
168
+ },
169
+ ddd : function (format) {
170
+ return this.lang().weekdaysShort(this, format);
171
+ },
172
+ dddd : function (format) {
173
+ return this.lang().weekdays(this, format);
174
+ },
175
+ w : function () {
176
+ return this.week();
177
+ },
178
+ W : function () {
179
+ return this.isoWeek();
180
+ },
181
+ YY : function () {
182
+ return leftZeroFill(this.year() % 100, 2);
183
+ },
184
+ YYYY : function () {
185
+ return leftZeroFill(this.year(), 4);
186
+ },
187
+ YYYYY : function () {
188
+ return leftZeroFill(this.year(), 5);
189
+ },
190
+ YYYYYY : function () {
191
+ var y = this.year(), sign = y >= 0 ? '+' : '-';
192
+ return sign + leftZeroFill(Math.abs(y), 6);
193
+ },
194
+ gg : function () {
195
+ return leftZeroFill(this.weekYear() % 100, 2);
196
+ },
197
+ gggg : function () {
198
+ return leftZeroFill(this.weekYear(), 4);
199
+ },
200
+ ggggg : function () {
201
+ return leftZeroFill(this.weekYear(), 5);
202
+ },
203
+ GG : function () {
204
+ return leftZeroFill(this.isoWeekYear() % 100, 2);
205
+ },
206
+ GGGG : function () {
207
+ return leftZeroFill(this.isoWeekYear(), 4);
208
+ },
209
+ GGGGG : function () {
210
+ return leftZeroFill(this.isoWeekYear(), 5);
211
+ },
212
+ e : function () {
213
+ return this.weekday();
214
+ },
215
+ E : function () {
216
+ return this.isoWeekday();
217
+ },
218
+ a : function () {
219
+ return this.lang().meridiem(this.hours(), this.minutes(), true);
220
+ },
221
+ A : function () {
222
+ return this.lang().meridiem(this.hours(), this.minutes(), false);
223
+ },
224
+ H : function () {
225
+ return this.hours();
226
+ },
227
+ h : function () {
228
+ return this.hours() % 12 || 12;
229
+ },
230
+ m : function () {
231
+ return this.minutes();
232
+ },
233
+ s : function () {
234
+ return this.seconds();
235
+ },
236
+ S : function () {
237
+ return toInt(this.milliseconds() / 100);
238
+ },
239
+ SS : function () {
240
+ return leftZeroFill(toInt(this.milliseconds() / 10), 2);
241
+ },
242
+ SSS : function () {
243
+ return leftZeroFill(this.milliseconds(), 3);
244
+ },
245
+ SSSS : function () {
246
+ return leftZeroFill(this.milliseconds(), 3);
247
+ },
248
+ Z : function () {
249
+ var a = -this.zone(),
250
+ b = "+";
251
+ if (a < 0) {
252
+ a = -a;
253
+ b = "-";
254
+ }
255
+ return b + leftZeroFill(toInt(a / 60), 2) + ":" + leftZeroFill(toInt(a) % 60, 2);
256
+ },
257
+ ZZ : function () {
258
+ var a = -this.zone(),
259
+ b = "+";
260
+ if (a < 0) {
261
+ a = -a;
262
+ b = "-";
263
+ }
264
+ return b + leftZeroFill(toInt(a / 60), 2) + leftZeroFill(toInt(a) % 60, 2);
265
+ },
266
+ z : function () {
267
+ return this.zoneAbbr();
268
+ },
269
+ zz : function () {
270
+ return this.zoneName();
271
+ },
272
+ X : function () {
273
+ return this.unix();
274
+ },
275
+ Q : function () {
276
+ return this.quarter();
277
+ }
278
+ },
279
+
280
+ lists = ['months', 'monthsShort', 'weekdays', 'weekdaysShort', 'weekdaysMin'];
281
+
282
+ function defaultParsingFlags() {
283
+ // We need to deep clone this object, and es5 standard is not very
284
+ // helpful.
285
+ return {
286
+ empty : false,
287
+ unusedTokens : [],
288
+ unusedInput : [],
289
+ overflow : -2,
290
+ charsLeftOver : 0,
291
+ nullInput : false,
292
+ invalidMonth : null,
293
+ invalidFormat : false,
294
+ userInvalidated : false,
295
+ iso: false
296
+ };
297
+ }
298
+
299
+ function padToken(func, count) {
300
+ return function (a) {
301
+ return leftZeroFill(func.call(this, a), count);
302
+ };
303
+ }
304
+ function ordinalizeToken(func, period) {
305
+ return function (a) {
306
+ return this.lang().ordinal(func.call(this, a), period);
307
+ };
308
+ }
309
+
310
+ while (ordinalizeTokens.length) {
311
+ i = ordinalizeTokens.pop();
312
+ formatTokenFunctions[i + 'o'] = ordinalizeToken(formatTokenFunctions[i], i);
313
+ }
314
+ while (paddedTokens.length) {
315
+ i = paddedTokens.pop();
316
+ formatTokenFunctions[i + i] = padToken(formatTokenFunctions[i], 2);
317
+ }
318
+ formatTokenFunctions.DDDD = padToken(formatTokenFunctions.DDD, 3);
319
+
320
+
321
+ /************************************
322
+ Constructors
323
+ ************************************/
324
+
325
+ function Language() {
326
+
327
+ }
328
+
329
+ // Moment prototype object
330
+ function Moment(config) {
331
+ checkOverflow(config);
332
+ extend(this, config);
333
+ }
334
+
335
+ // Duration Constructor
336
+ function Duration(duration) {
337
+ var normalizedInput = normalizeObjectUnits(duration),
338
+ years = normalizedInput.year || 0,
339
+ months = normalizedInput.month || 0,
340
+ weeks = normalizedInput.week || 0,
341
+ days = normalizedInput.day || 0,
342
+ hours = normalizedInput.hour || 0,
343
+ minutes = normalizedInput.minute || 0,
344
+ seconds = normalizedInput.second || 0,
345
+ milliseconds = normalizedInput.millisecond || 0;
346
+
347
+ // representation for dateAddRemove
348
+ this._milliseconds = +milliseconds +
349
+ seconds * 1e3 + // 1000
350
+ minutes * 6e4 + // 1000 * 60
351
+ hours * 36e5; // 1000 * 60 * 60
352
+ // Because of dateAddRemove treats 24 hours as different from a
353
+ // day when working around DST, we need to store them separately
354
+ this._days = +days +
355
+ weeks * 7;
356
+ // It is impossible translate months into days without knowing
357
+ // which months you are are talking about, so we have to store
358
+ // it separately.
359
+ this._months = +months +
360
+ years * 12;
361
+
362
+ this._data = {};
363
+
364
+ this._bubble();
365
+ }
366
+
367
+ /************************************
368
+ Helpers
369
+ ************************************/
370
+
371
+
372
+ function extend(a, b) {
373
+ for (var i in b) {
374
+ if (b.hasOwnProperty(i)) {
375
+ a[i] = b[i];
376
+ }
377
+ }
378
+
379
+ if (b.hasOwnProperty("toString")) {
380
+ a.toString = b.toString;
381
+ }
382
+
383
+ if (b.hasOwnProperty("valueOf")) {
384
+ a.valueOf = b.valueOf;
385
+ }
386
+
387
+ return a;
388
+ }
389
+
390
+ function cloneMoment(m) {
391
+ var result = {}, i;
392
+ for (i in m) {
393
+ if (m.hasOwnProperty(i) && momentProperties.hasOwnProperty(i)) {
394
+ result[i] = m[i];
395
+ }
396
+ }
397
+
398
+ return result;
399
+ }
400
+
401
+ function absRound(number) {
402
+ if (number < 0) {
403
+ return Math.ceil(number);
404
+ } else {
405
+ return Math.floor(number);
406
+ }
407
+ }
408
+
409
+ // left zero fill a number
410
+ // see http://jsperf.com/left-zero-filling for performance comparison
411
+ function leftZeroFill(number, targetLength, forceSign) {
412
+ var output = '' + Math.abs(number),
413
+ sign = number >= 0;
414
+
415
+ while (output.length < targetLength) {
416
+ output = '0' + output;
417
+ }
418
+ return (sign ? (forceSign ? '+' : '') : '-') + output;
419
+ }
420
+
421
+ // helper function for _.addTime and _.subtractTime
422
+ function addOrSubtractDurationFromMoment(mom, duration, isAdding, ignoreUpdateOffset) {
423
+ var milliseconds = duration._milliseconds,
424
+ days = duration._days,
425
+ months = duration._months,
426
+ minutes,
427
+ hours;
428
+
429
+ if (milliseconds) {
430
+ mom._d.setTime(+mom._d + milliseconds * isAdding);
431
+ }
432
+ // store the minutes and hours so we can restore them
433
+ if (days || months) {
434
+ minutes = mom.minute();
435
+ hours = mom.hour();
436
+ }
437
+ if (days) {
438
+ mom.date(mom.date() + days * isAdding);
439
+ }
440
+ if (months) {
441
+ mom.month(mom.month() + months * isAdding);
442
+ }
443
+ if (milliseconds && !ignoreUpdateOffset) {
444
+ moment.updateOffset(mom);
445
+ }
446
+ // restore the minutes and hours after possibly changing dst
447
+ if (days || months) {
448
+ mom.minute(minutes);
449
+ mom.hour(hours);
450
+ }
451
+ }
452
+
453
+ // check if is an array
454
+ function isArray(input) {
455
+ return Object.prototype.toString.call(input) === '[object Array]';
456
+ }
457
+
458
+ function isDate(input) {
459
+ return Object.prototype.toString.call(input) === '[object Date]' ||
460
+ input instanceof Date;
461
+ }
462
+
463
+ // compare two arrays, return the number of differences
464
+ function compareArrays(array1, array2, dontConvert) {
465
+ var len = Math.min(array1.length, array2.length),
466
+ lengthDiff = Math.abs(array1.length - array2.length),
467
+ diffs = 0,
468
+ i;
469
+ for (i = 0; i < len; i++) {
470
+ if ((dontConvert && array1[i] !== array2[i]) ||
471
+ (!dontConvert && toInt(array1[i]) !== toInt(array2[i]))) {
472
+ diffs++;
473
+ }
474
+ }
475
+ return diffs + lengthDiff;
476
+ }
477
+
478
+ function normalizeUnits(units) {
479
+ if (units) {
480
+ var lowered = units.toLowerCase().replace(/(.)s$/, '$1');
481
+ units = unitAliases[units] || camelFunctions[lowered] || lowered;
482
+ }
483
+ return units;
484
+ }
485
+
486
+ function normalizeObjectUnits(inputObject) {
487
+ var normalizedInput = {},
488
+ normalizedProp,
489
+ prop;
490
+
491
+ for (prop in inputObject) {
492
+ if (inputObject.hasOwnProperty(prop)) {
493
+ normalizedProp = normalizeUnits(prop);
494
+ if (normalizedProp) {
495
+ normalizedInput[normalizedProp] = inputObject[prop];
496
+ }
497
+ }
498
+ }
499
+
500
+ return normalizedInput;
501
+ }
502
+
503
+ function makeList(field) {
504
+ var count, setter;
505
+
506
+ if (field.indexOf('week') === 0) {
507
+ count = 7;
508
+ setter = 'day';
509
+ }
510
+ else if (field.indexOf('month') === 0) {
511
+ count = 12;
512
+ setter = 'month';
513
+ }
514
+ else {
515
+ return;
516
+ }
517
+
518
+ moment[field] = function (format, index) {
519
+ var i, getter,
520
+ method = moment.fn._lang[field],
521
+ results = [];
522
+
523
+ if (typeof format === 'number') {
524
+ index = format;
525
+ format = undefined;
526
+ }
527
+
528
+ getter = function (i) {
529
+ var m = moment().utc().set(setter, i);
530
+ return method.call(moment.fn._lang, m, format || '');
531
+ };
532
+
533
+ if (index != null) {
534
+ return getter(index);
535
+ }
536
+ else {
537
+ for (i = 0; i < count; i++) {
538
+ results.push(getter(i));
539
+ }
540
+ return results;
541
+ }
542
+ };
543
+ }
544
+
545
+ function toInt(argumentForCoercion) {
546
+ var coercedNumber = +argumentForCoercion,
547
+ value = 0;
548
+
549
+ if (coercedNumber !== 0 && isFinite(coercedNumber)) {
550
+ if (coercedNumber >= 0) {
551
+ value = Math.floor(coercedNumber);
552
+ } else {
553
+ value = Math.ceil(coercedNumber);
554
+ }
555
+ }
556
+
557
+ return value;
558
+ }
559
+
560
+ function daysInMonth(year, month) {
561
+ return new Date(Date.UTC(year, month + 1, 0)).getUTCDate();
562
+ }
563
+
564
+ function daysInYear(year) {
565
+ return isLeapYear(year) ? 366 : 365;
566
+ }
567
+
568
+ function isLeapYear(year) {
569
+ return (year % 4 === 0 && year % 100 !== 0) || year % 400 === 0;
570
+ }
571
+
572
+ function checkOverflow(m) {
573
+ var overflow;
574
+ if (m._a && m._pf.overflow === -2) {
575
+ overflow =
576
+ m._a[MONTH] < 0 || m._a[MONTH] > 11 ? MONTH :
577
+ m._a[DATE] < 1 || m._a[DATE] > daysInMonth(m._a[YEAR], m._a[MONTH]) ? DATE :
578
+ m._a[HOUR] < 0 || m._a[HOUR] > 23 ? HOUR :
579
+ m._a[MINUTE] < 0 || m._a[MINUTE] > 59 ? MINUTE :
580
+ m._a[SECOND] < 0 || m._a[SECOND] > 59 ? SECOND :
581
+ m._a[MILLISECOND] < 0 || m._a[MILLISECOND] > 999 ? MILLISECOND :
582
+ -1;
583
+
584
+ if (m._pf._overflowDayOfYear && (overflow < YEAR || overflow > DATE)) {
585
+ overflow = DATE;
586
+ }
587
+
588
+ m._pf.overflow = overflow;
589
+ }
590
+ }
591
+
592
+ function isValid(m) {
593
+ if (m._isValid == null) {
594
+ m._isValid = !isNaN(m._d.getTime()) &&
595
+ m._pf.overflow < 0 &&
596
+ !m._pf.empty &&
597
+ !m._pf.invalidMonth &&
598
+ !m._pf.nullInput &&
599
+ !m._pf.invalidFormat &&
600
+ !m._pf.userInvalidated;
601
+
602
+ if (m._strict) {
603
+ m._isValid = m._isValid &&
604
+ m._pf.charsLeftOver === 0 &&
605
+ m._pf.unusedTokens.length === 0;
606
+ }
607
+ }
608
+ return m._isValid;
609
+ }
610
+
611
+ function normalizeLanguage(key) {
612
+ return key ? key.toLowerCase().replace('_', '-') : key;
613
+ }
614
+
615
+ // Return a moment from input, that is local/utc/zone equivalent to model.
616
+ function makeAs(input, model) {
617
+ return model._isUTC ? moment(input).zone(model._offset || 0) :
618
+ moment(input).local();
619
+ }
620
+
621
+ /************************************
622
+ Languages
623
+ ************************************/
624
+
625
+
626
+ extend(Language.prototype, {
627
+
628
+ set : function (config) {
629
+ var prop, i;
630
+ for (i in config) {
631
+ prop = config[i];
632
+ if (typeof prop === 'function') {
633
+ this[i] = prop;
634
+ } else {
635
+ this['_' + i] = prop;
636
+ }
637
+ }
638
+ },
639
+
640
+ _months : "January_February_March_April_May_June_July_August_September_October_November_December".split("_"),
641
+ months : function (m) {
642
+ return this._months[m.month()];
643
+ },
644
+
645
+ _monthsShort : "Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec".split("_"),
646
+ monthsShort : function (m) {
647
+ return this._monthsShort[m.month()];
648
+ },
649
+
650
+ monthsParse : function (monthName) {
651
+ var i, mom, regex;
652
+
653
+ if (!this._monthsParse) {
654
+ this._monthsParse = [];
655
+ }
656
+
657
+ for (i = 0; i < 12; i++) {
658
+ // make the regex if we don't have it already
659
+ if (!this._monthsParse[i]) {
660
+ mom = moment.utc([2000, i]);
661
+ regex = '^' + this.months(mom, '') + '|^' + this.monthsShort(mom, '');
662
+ this._monthsParse[i] = new RegExp(regex.replace('.', ''), 'i');
663
+ }
664
+ // test the regex
665
+ if (this._monthsParse[i].test(monthName)) {
666
+ return i;
667
+ }
668
+ }
669
+ },
670
+
671
+ _weekdays : "Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_"),
672
+ weekdays : function (m) {
673
+ return this._weekdays[m.day()];
674
+ },
675
+
676
+ _weekdaysShort : "Sun_Mon_Tue_Wed_Thu_Fri_Sat".split("_"),
677
+ weekdaysShort : function (m) {
678
+ return this._weekdaysShort[m.day()];
679
+ },
680
+
681
+ _weekdaysMin : "Su_Mo_Tu_We_Th_Fr_Sa".split("_"),
682
+ weekdaysMin : function (m) {
683
+ return this._weekdaysMin[m.day()];
684
+ },
685
+
686
+ weekdaysParse : function (weekdayName) {
687
+ var i, mom, regex;
688
+
689
+ if (!this._weekdaysParse) {
690
+ this._weekdaysParse = [];
691
+ }
692
+
693
+ for (i = 0; i < 7; i++) {
694
+ // make the regex if we don't have it already
695
+ if (!this._weekdaysParse[i]) {
696
+ mom = moment([2000, 1]).day(i);
697
+ regex = '^' + this.weekdays(mom, '') + '|^' + this.weekdaysShort(mom, '') + '|^' + this.weekdaysMin(mom, '');
698
+ this._weekdaysParse[i] = new RegExp(regex.replace('.', ''), 'i');
699
+ }
700
+ // test the regex
701
+ if (this._weekdaysParse[i].test(weekdayName)) {
702
+ return i;
703
+ }
704
+ }
705
+ },
706
+
707
+ _longDateFormat : {
708
+ LT : "h:mm A",
709
+ L : "MM/DD/YYYY",
710
+ LL : "MMMM D YYYY",
711
+ LLL : "MMMM D YYYY LT",
712
+ LLLL : "dddd, MMMM D YYYY LT"
713
+ },
714
+ longDateFormat : function (key) {
715
+ var output = this._longDateFormat[key];
716
+ if (!output && this._longDateFormat[key.toUpperCase()]) {
717
+ output = this._longDateFormat[key.toUpperCase()].replace(/MMMM|MM|DD|dddd/g, function (val) {
718
+ return val.slice(1);
719
+ });
720
+ this._longDateFormat[key] = output;
721
+ }
722
+ return output;
723
+ },
724
+
725
+ isPM : function (input) {
726
+ // IE8 Quirks Mode & IE7 Standards Mode do not allow accessing strings like arrays
727
+ // Using charAt should be more compatible.
728
+ return ((input + '').toLowerCase().charAt(0) === 'p');
729
+ },
730
+
731
+ _meridiemParse : /[ap]\.?m?\.?/i,
732
+ meridiem : function (hours, minutes, isLower) {
733
+ if (hours > 11) {
734
+ return isLower ? 'pm' : 'PM';
735
+ } else {
736
+ return isLower ? 'am' : 'AM';
737
+ }
738
+ },
739
+
740
+ _calendar : {
741
+ sameDay : '[Today at] LT',
742
+ nextDay : '[Tomorrow at] LT',
743
+ nextWeek : 'dddd [at] LT',
744
+ lastDay : '[Yesterday at] LT',
745
+ lastWeek : '[Last] dddd [at] LT',
746
+ sameElse : 'L'
747
+ },
748
+ calendar : function (key, mom) {
749
+ var output = this._calendar[key];
750
+ return typeof output === 'function' ? output.apply(mom) : output;
751
+ },
752
+
753
+ _relativeTime : {
754
+ future : "in %s",
755
+ past : "%s ago",
756
+ s : "a few seconds",
757
+ m : "a minute",
758
+ mm : "%d minutes",
759
+ h : "an hour",
760
+ hh : "%d hours",
761
+ d : "a day",
762
+ dd : "%d days",
763
+ M : "a month",
764
+ MM : "%d months",
765
+ y : "a year",
766
+ yy : "%d years"
767
+ },
768
+ relativeTime : function (number, withoutSuffix, string, isFuture) {
769
+ var output = this._relativeTime[string];
770
+ return (typeof output === 'function') ?
771
+ output(number, withoutSuffix, string, isFuture) :
772
+ output.replace(/%d/i, number);
773
+ },
774
+ pastFuture : function (diff, output) {
775
+ var format = this._relativeTime[diff > 0 ? 'future' : 'past'];
776
+ return typeof format === 'function' ? format(output) : format.replace(/%s/i, output);
777
+ },
778
+
779
+ ordinal : function (number) {
780
+ return this._ordinal.replace("%d", number);
781
+ },
782
+ _ordinal : "%d",
783
+
784
+ preparse : function (string) {
785
+ return string;
786
+ },
787
+
788
+ postformat : function (string) {
789
+ return string;
790
+ },
791
+
792
+ week : function (mom) {
793
+ return weekOfYear(mom, this._week.dow, this._week.doy).week;
794
+ },
795
+
796
+ _week : {
797
+ dow : 0, // Sunday is the first day of the week.
798
+ doy : 6 // The week that contains Jan 1st is the first week of the year.
799
+ },
800
+
801
+ _invalidDate: 'Invalid date',
802
+ invalidDate: function () {
803
+ return this._invalidDate;
804
+ }
805
+ });
806
+
807
+ // Loads a language definition into the `languages` cache. The function
808
+ // takes a key and optionally values. If not in the browser and no values
809
+ // are provided, it will load the language file module. As a convenience,
810
+ // this function also returns the language values.
811
+ function loadLang(key, values) {
812
+ values.abbr = key;
813
+ if (!languages[key]) {
814
+ languages[key] = new Language();
815
+ }
816
+ languages[key].set(values);
817
+ return languages[key];
818
+ }
819
+
820
+ // Remove a language from the `languages` cache. Mostly useful in tests.
821
+ function unloadLang(key) {
822
+ delete languages[key];
823
+ }
824
+
825
+ // Determines which language definition to use and returns it.
826
+ //
827
+ // With no parameters, it will return the global language. If you
828
+ // pass in a language key, such as 'en', it will return the
829
+ // definition for 'en', so long as 'en' has already been loaded using
830
+ // moment.lang.
831
+ function getLangDefinition(key) {
832
+ var i = 0, j, lang, next, split,
833
+ get = function (k) {
834
+ if (!languages[k] && hasModule) {
835
+ try {
836
+ require('./lang/' + k);
837
+ } catch (e) { }
838
+ }
839
+ return languages[k];
840
+ };
841
+
842
+ if (!key) {
843
+ return moment.fn._lang;
844
+ }
845
+
846
+ if (!isArray(key)) {
847
+ //short-circuit everything else
848
+ lang = get(key);
849
+ if (lang) {
850
+ return lang;
851
+ }
852
+ key = [key];
853
+ }
854
+
855
+ //pick the language from the array
856
+ //try ['en-au', 'en-gb'] as 'en-au', 'en-gb', 'en', as in move through the list trying each
857
+ //substring from most specific to least, but move to the next array item if it's a more specific variant than the current root
858
+ while (i < key.length) {
859
+ split = normalizeLanguage(key[i]).split('-');
860
+ j = split.length;
861
+ next = normalizeLanguage(key[i + 1]);
862
+ next = next ? next.split('-') : null;
863
+ while (j > 0) {
864
+ lang = get(split.slice(0, j).join('-'));
865
+ if (lang) {
866
+ return lang;
867
+ }
868
+ if (next && next.length >= j && compareArrays(split, next, true) >= j - 1) {
869
+ //the next array item is better than a shallower substring of this one
870
+ break;
871
+ }
872
+ j--;
873
+ }
874
+ i++;
875
+ }
876
+ return moment.fn._lang;
877
+ }
878
+
879
+ /************************************
880
+ Formatting
881
+ ************************************/
882
+
883
+
884
+ function removeFormattingTokens(input) {
885
+ if (input.match(/\[[\s\S]/)) {
886
+ return input.replace(/^\[|\]$/g, "");
887
+ }
888
+ return input.replace(/\\/g, "");
889
+ }
890
+
891
+ function makeFormatFunction(format) {
892
+ var array = format.match(formattingTokens), i, length;
893
+
894
+ for (i = 0, length = array.length; i < length; i++) {
895
+ if (formatTokenFunctions[array[i]]) {
896
+ array[i] = formatTokenFunctions[array[i]];
897
+ } else {
898
+ array[i] = removeFormattingTokens(array[i]);
899
+ }
900
+ }
901
+
902
+ return function (mom) {
903
+ var output = "";
904
+ for (i = 0; i < length; i++) {
905
+ output += array[i] instanceof Function ? array[i].call(mom, format) : array[i];
906
+ }
907
+ return output;
908
+ };
909
+ }
910
+
911
+ // format date using native date object
912
+ function formatMoment(m, format) {
913
+
914
+ if (!m.isValid()) {
915
+ return m.lang().invalidDate();
916
+ }
917
+
918
+ format = expandFormat(format, m.lang());
919
+
920
+ if (!formatFunctions[format]) {
921
+ formatFunctions[format] = makeFormatFunction(format);
922
+ }
923
+
924
+ return formatFunctions[format](m);
925
+ }
926
+
927
+ function expandFormat(format, lang) {
928
+ var i = 5;
929
+
930
+ function replaceLongDateFormatTokens(input) {
931
+ return lang.longDateFormat(input) || input;
932
+ }
933
+
934
+ localFormattingTokens.lastIndex = 0;
935
+ while (i >= 0 && localFormattingTokens.test(format)) {
936
+ format = format.replace(localFormattingTokens, replaceLongDateFormatTokens);
937
+ localFormattingTokens.lastIndex = 0;
938
+ i -= 1;
939
+ }
940
+
941
+ return format;
942
+ }
943
+
944
+
945
+ /************************************
946
+ Parsing
947
+ ************************************/
948
+
949
+
950
+ // get the regex to find the next token
951
+ function getParseRegexForToken(token, config) {
952
+ var a, strict = config._strict;
953
+ switch (token) {
954
+ case 'DDDD':
955
+ return parseTokenThreeDigits;
956
+ case 'YYYY':
957
+ case 'GGGG':
958
+ case 'gggg':
959
+ return strict ? parseTokenFourDigits : parseTokenOneToFourDigits;
960
+ case 'Y':
961
+ case 'G':
962
+ case 'g':
963
+ return parseTokenSignedNumber;
964
+ case 'YYYYYY':
965
+ case 'YYYYY':
966
+ case 'GGGGG':
967
+ case 'ggggg':
968
+ return strict ? parseTokenSixDigits : parseTokenOneToSixDigits;
969
+ case 'S':
970
+ if (strict) { return parseTokenOneDigit; }
971
+ /* falls through */
972
+ case 'SS':
973
+ if (strict) { return parseTokenTwoDigits; }
974
+ /* falls through */
975
+ case 'SSS':
976
+ if (strict) { return parseTokenThreeDigits; }
977
+ /* falls through */
978
+ case 'DDD':
979
+ return parseTokenOneToThreeDigits;
980
+ case 'MMM':
981
+ case 'MMMM':
982
+ case 'dd':
983
+ case 'ddd':
984
+ case 'dddd':
985
+ return parseTokenWord;
986
+ case 'a':
987
+ case 'A':
988
+ return getLangDefinition(config._l)._meridiemParse;
989
+ case 'X':
990
+ return parseTokenTimestampMs;
991
+ case 'Z':
992
+ case 'ZZ':
993
+ return parseTokenTimezone;
994
+ case 'T':
995
+ return parseTokenT;
996
+ case 'SSSS':
997
+ return parseTokenDigits;
998
+ case 'MM':
999
+ case 'DD':
1000
+ case 'YY':
1001
+ case 'GG':
1002
+ case 'gg':
1003
+ case 'HH':
1004
+ case 'hh':
1005
+ case 'mm':
1006
+ case 'ss':
1007
+ case 'ww':
1008
+ case 'WW':
1009
+ return strict ? parseTokenTwoDigits : parseTokenOneOrTwoDigits;
1010
+ case 'M':
1011
+ case 'D':
1012
+ case 'd':
1013
+ case 'H':
1014
+ case 'h':
1015
+ case 'm':
1016
+ case 's':
1017
+ case 'w':
1018
+ case 'W':
1019
+ case 'e':
1020
+ case 'E':
1021
+ return parseTokenOneOrTwoDigits;
1022
+ default :
1023
+ a = new RegExp(regexpEscape(unescapeFormat(token.replace('\\', '')), "i"));
1024
+ return a;
1025
+ }
1026
+ }
1027
+
1028
+ function timezoneMinutesFromString(string) {
1029
+ string = string || "";
1030
+ var possibleTzMatches = (string.match(parseTokenTimezone) || []),
1031
+ tzChunk = possibleTzMatches[possibleTzMatches.length - 1] || [],
1032
+ parts = (tzChunk + '').match(parseTimezoneChunker) || ['-', 0, 0],
1033
+ minutes = +(parts[1] * 60) + toInt(parts[2]);
1034
+
1035
+ return parts[0] === '+' ? -minutes : minutes;
1036
+ }
1037
+
1038
+ // function to convert string input to date
1039
+ function addTimeToArrayFromToken(token, input, config) {
1040
+ var a, datePartArray = config._a;
1041
+
1042
+ switch (token) {
1043
+ // MONTH
1044
+ case 'M' : // fall through to MM
1045
+ case 'MM' :
1046
+ if (input != null) {
1047
+ datePartArray[MONTH] = toInt(input) - 1;
1048
+ }
1049
+ break;
1050
+ case 'MMM' : // fall through to MMMM
1051
+ case 'MMMM' :
1052
+ a = getLangDefinition(config._l).monthsParse(input);
1053
+ // if we didn't find a month name, mark the date as invalid.
1054
+ if (a != null) {
1055
+ datePartArray[MONTH] = a;
1056
+ } else {
1057
+ config._pf.invalidMonth = input;
1058
+ }
1059
+ break;
1060
+ // DAY OF MONTH
1061
+ case 'D' : // fall through to DD
1062
+ case 'DD' :
1063
+ if (input != null) {
1064
+ datePartArray[DATE] = toInt(input);
1065
+ }
1066
+ break;
1067
+ // DAY OF YEAR
1068
+ case 'DDD' : // fall through to DDDD
1069
+ case 'DDDD' :
1070
+ if (input != null) {
1071
+ config._dayOfYear = toInt(input);
1072
+ }
1073
+
1074
+ break;
1075
+ // YEAR
1076
+ case 'YY' :
1077
+ datePartArray[YEAR] = toInt(input) + (toInt(input) > 68 ? 1900 : 2000);
1078
+ break;
1079
+ case 'YYYY' :
1080
+ case 'YYYYY' :
1081
+ case 'YYYYYY' :
1082
+ datePartArray[YEAR] = toInt(input);
1083
+ break;
1084
+ // AM / PM
1085
+ case 'a' : // fall through to A
1086
+ case 'A' :
1087
+ config._isPm = getLangDefinition(config._l).isPM(input);
1088
+ break;
1089
+ // 24 HOUR
1090
+ case 'H' : // fall through to hh
1091
+ case 'HH' : // fall through to hh
1092
+ case 'h' : // fall through to hh
1093
+ case 'hh' :
1094
+ datePartArray[HOUR] = toInt(input);
1095
+ break;
1096
+ // MINUTE
1097
+ case 'm' : // fall through to mm
1098
+ case 'mm' :
1099
+ datePartArray[MINUTE] = toInt(input);
1100
+ break;
1101
+ // SECOND
1102
+ case 's' : // fall through to ss
1103
+ case 'ss' :
1104
+ datePartArray[SECOND] = toInt(input);
1105
+ break;
1106
+ // MILLISECOND
1107
+ case 'S' :
1108
+ case 'SS' :
1109
+ case 'SSS' :
1110
+ case 'SSSS' :
1111
+ datePartArray[MILLISECOND] = toInt(('0.' + input) * 1000);
1112
+ break;
1113
+ // UNIX TIMESTAMP WITH MS
1114
+ case 'X':
1115
+ config._d = new Date(parseFloat(input) * 1000);
1116
+ break;
1117
+ // TIMEZONE
1118
+ case 'Z' : // fall through to ZZ
1119
+ case 'ZZ' :
1120
+ config._useUTC = true;
1121
+ config._tzm = timezoneMinutesFromString(input);
1122
+ break;
1123
+ case 'w':
1124
+ case 'ww':
1125
+ case 'W':
1126
+ case 'WW':
1127
+ case 'd':
1128
+ case 'dd':
1129
+ case 'ddd':
1130
+ case 'dddd':
1131
+ case 'e':
1132
+ case 'E':
1133
+ token = token.substr(0, 1);
1134
+ /* falls through */
1135
+ case 'gg':
1136
+ case 'gggg':
1137
+ case 'GG':
1138
+ case 'GGGG':
1139
+ case 'GGGGG':
1140
+ token = token.substr(0, 2);
1141
+ if (input) {
1142
+ config._w = config._w || {};
1143
+ config._w[token] = input;
1144
+ }
1145
+ break;
1146
+ }
1147
+ }
1148
+
1149
+ // convert an array to a date.
1150
+ // the array should mirror the parameters below
1151
+ // note: all values past the year are optional and will default to the lowest possible value.
1152
+ // [year, month, day , hour, minute, second, millisecond]
1153
+ function dateFromConfig(config) {
1154
+ var i, date, input = [], currentDate,
1155
+ yearToUse, fixYear, w, temp, lang, weekday, week;
1156
+
1157
+ if (config._d) {
1158
+ return;
1159
+ }
1160
+
1161
+ currentDate = currentDateArray(config);
1162
+
1163
+ //compute day of the year from weeks and weekdays
1164
+ if (config._w && config._a[DATE] == null && config._a[MONTH] == null) {
1165
+ fixYear = function (val) {
1166
+ var int_val = parseInt(val, 10);
1167
+ return val ?
1168
+ (val.length < 3 ? (int_val > 68 ? 1900 + int_val : 2000 + int_val) : int_val) :
1169
+ (config._a[YEAR] == null ? moment().weekYear() : config._a[YEAR]);
1170
+ };
1171
+
1172
+ w = config._w;
1173
+ if (w.GG != null || w.W != null || w.E != null) {
1174
+ temp = dayOfYearFromWeeks(fixYear(w.GG), w.W || 1, w.E, 4, 1);
1175
+ }
1176
+ else {
1177
+ lang = getLangDefinition(config._l);
1178
+ weekday = w.d != null ? parseWeekday(w.d, lang) :
1179
+ (w.e != null ? parseInt(w.e, 10) + lang._week.dow : 0);
1180
+
1181
+ week = parseInt(w.w, 10) || 1;
1182
+
1183
+ //if we're parsing 'd', then the low day numbers may be next week
1184
+ if (w.d != null && weekday < lang._week.dow) {
1185
+ week++;
1186
+ }
1187
+
1188
+ temp = dayOfYearFromWeeks(fixYear(w.gg), week, weekday, lang._week.doy, lang._week.dow);
1189
+ }
1190
+
1191
+ config._a[YEAR] = temp.year;
1192
+ config._dayOfYear = temp.dayOfYear;
1193
+ }
1194
+
1195
+ //if the day of the year is set, figure out what it is
1196
+ if (config._dayOfYear) {
1197
+ yearToUse = config._a[YEAR] == null ? currentDate[YEAR] : config._a[YEAR];
1198
+
1199
+ if (config._dayOfYear > daysInYear(yearToUse)) {
1200
+ config._pf._overflowDayOfYear = true;
1201
+ }
1202
+
1203
+ date = makeUTCDate(yearToUse, 0, config._dayOfYear);
1204
+ config._a[MONTH] = date.getUTCMonth();
1205
+ config._a[DATE] = date.getUTCDate();
1206
+ }
1207
+
1208
+ // Default to current date.
1209
+ // * if no year, month, day of month are given, default to today
1210
+ // * if day of month is given, default month and year
1211
+ // * if month is given, default only year
1212
+ // * if year is given, don't default anything
1213
+ for (i = 0; i < 3 && config._a[i] == null; ++i) {
1214
+ config._a[i] = input[i] = currentDate[i];
1215
+ }
1216
+
1217
+ // Zero out whatever was not defaulted, including time
1218
+ for (; i < 7; i++) {
1219
+ config._a[i] = input[i] = (config._a[i] == null) ? (i === 2 ? 1 : 0) : config._a[i];
1220
+ }
1221
+
1222
+ // add the offsets to the time to be parsed so that we can have a clean array for checking isValid
1223
+ input[HOUR] += toInt((config._tzm || 0) / 60);
1224
+ input[MINUTE] += toInt((config._tzm || 0) % 60);
1225
+
1226
+ config._d = (config._useUTC ? makeUTCDate : makeDate).apply(null, input);
1227
+ }
1228
+
1229
+ function dateFromObject(config) {
1230
+ var normalizedInput;
1231
+
1232
+ if (config._d) {
1233
+ return;
1234
+ }
1235
+
1236
+ normalizedInput = normalizeObjectUnits(config._i);
1237
+ config._a = [
1238
+ normalizedInput.year,
1239
+ normalizedInput.month,
1240
+ normalizedInput.day,
1241
+ normalizedInput.hour,
1242
+ normalizedInput.minute,
1243
+ normalizedInput.second,
1244
+ normalizedInput.millisecond
1245
+ ];
1246
+
1247
+ dateFromConfig(config);
1248
+ }
1249
+
1250
+ function currentDateArray(config) {
1251
+ var now = new Date();
1252
+ if (config._useUTC) {
1253
+ return [
1254
+ now.getUTCFullYear(),
1255
+ now.getUTCMonth(),
1256
+ now.getUTCDate()
1257
+ ];
1258
+ } else {
1259
+ return [now.getFullYear(), now.getMonth(), now.getDate()];
1260
+ }
1261
+ }
1262
+
1263
+ // date from string and format string
1264
+ function makeDateFromStringAndFormat(config) {
1265
+
1266
+ config._a = [];
1267
+ config._pf.empty = true;
1268
+
1269
+ // This array is used to make a Date, either with `new Date` or `Date.UTC`
1270
+ var lang = getLangDefinition(config._l),
1271
+ string = '' + config._i,
1272
+ i, parsedInput, tokens, token, skipped,
1273
+ stringLength = string.length,
1274
+ totalParsedInputLength = 0;
1275
+
1276
+ tokens = expandFormat(config._f, lang).match(formattingTokens) || [];
1277
+
1278
+ for (i = 0; i < tokens.length; i++) {
1279
+ token = tokens[i];
1280
+ parsedInput = (string.match(getParseRegexForToken(token, config)) || [])[0];
1281
+ if (parsedInput) {
1282
+ skipped = string.substr(0, string.indexOf(parsedInput));
1283
+ if (skipped.length > 0) {
1284
+ config._pf.unusedInput.push(skipped);
1285
+ }
1286
+ string = string.slice(string.indexOf(parsedInput) + parsedInput.length);
1287
+ totalParsedInputLength += parsedInput.length;
1288
+ }
1289
+ // don't parse if it's not a known token
1290
+ if (formatTokenFunctions[token]) {
1291
+ if (parsedInput) {
1292
+ config._pf.empty = false;
1293
+ }
1294
+ else {
1295
+ config._pf.unusedTokens.push(token);
1296
+ }
1297
+ addTimeToArrayFromToken(token, parsedInput, config);
1298
+ }
1299
+ else if (config._strict && !parsedInput) {
1300
+ config._pf.unusedTokens.push(token);
1301
+ }
1302
+ }
1303
+
1304
+ // add remaining unparsed input length to the string
1305
+ config._pf.charsLeftOver = stringLength - totalParsedInputLength;
1306
+ if (string.length > 0) {
1307
+ config._pf.unusedInput.push(string);
1308
+ }
1309
+
1310
+ // handle am pm
1311
+ if (config._isPm && config._a[HOUR] < 12) {
1312
+ config._a[HOUR] += 12;
1313
+ }
1314
+ // if is 12 am, change hours to 0
1315
+ if (config._isPm === false && config._a[HOUR] === 12) {
1316
+ config._a[HOUR] = 0;
1317
+ }
1318
+
1319
+ dateFromConfig(config);
1320
+ checkOverflow(config);
1321
+ }
1322
+
1323
+ function unescapeFormat(s) {
1324
+ return s.replace(/\\(\[)|\\(\])|\[([^\]\[]*)\]|\\(.)/g, function (matched, p1, p2, p3, p4) {
1325
+ return p1 || p2 || p3 || p4;
1326
+ });
1327
+ }
1328
+
1329
+ // Code from http://stackoverflow.com/questions/3561493/is-there-a-regexp-escape-function-in-javascript
1330
+ function regexpEscape(s) {
1331
+ return s.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&');
1332
+ }
1333
+
1334
+ // date from string and array of format strings
1335
+ function makeDateFromStringAndArray(config) {
1336
+ var tempConfig,
1337
+ bestMoment,
1338
+
1339
+ scoreToBeat,
1340
+ i,
1341
+ currentScore;
1342
+
1343
+ if (config._f.length === 0) {
1344
+ config._pf.invalidFormat = true;
1345
+ config._d = new Date(NaN);
1346
+ return;
1347
+ }
1348
+
1349
+ for (i = 0; i < config._f.length; i++) {
1350
+ currentScore = 0;
1351
+ tempConfig = extend({}, config);
1352
+ tempConfig._pf = defaultParsingFlags();
1353
+ tempConfig._f = config._f[i];
1354
+ makeDateFromStringAndFormat(tempConfig);
1355
+
1356
+ if (!isValid(tempConfig)) {
1357
+ continue;
1358
+ }
1359
+
1360
+ // if there is any input that was not parsed add a penalty for that format
1361
+ currentScore += tempConfig._pf.charsLeftOver;
1362
+
1363
+ //or tokens
1364
+ currentScore += tempConfig._pf.unusedTokens.length * 10;
1365
+
1366
+ tempConfig._pf.score = currentScore;
1367
+
1368
+ if (scoreToBeat == null || currentScore < scoreToBeat) {
1369
+ scoreToBeat = currentScore;
1370
+ bestMoment = tempConfig;
1371
+ }
1372
+ }
1373
+
1374
+ extend(config, bestMoment || tempConfig);
1375
+ }
1376
+
1377
+ // date from iso format
1378
+ function makeDateFromString(config) {
1379
+ var i, l,
1380
+ string = config._i,
1381
+ match = isoRegex.exec(string);
1382
+
1383
+ if (match) {
1384
+ config._pf.iso = true;
1385
+ for (i = 0, l = isoDates.length; i < l; i++) {
1386
+ if (isoDates[i][1].exec(string)) {
1387
+ // match[5] should be "T" or undefined
1388
+ config._f = isoDates[i][0] + (match[6] || " ");
1389
+ break;
1390
+ }
1391
+ }
1392
+ for (i = 0, l = isoTimes.length; i < l; i++) {
1393
+ if (isoTimes[i][1].exec(string)) {
1394
+ config._f += isoTimes[i][0];
1395
+ break;
1396
+ }
1397
+ }
1398
+ if (string.match(parseTokenTimezone)) {
1399
+ config._f += "Z";
1400
+ }
1401
+ makeDateFromStringAndFormat(config);
1402
+ }
1403
+ else {
1404
+ config._d = new Date(string);
1405
+ }
1406
+ }
1407
+
1408
+ function makeDateFromInput(config) {
1409
+ var input = config._i,
1410
+ matched = aspNetJsonRegex.exec(input);
1411
+
1412
+ if (input === undefined) {
1413
+ config._d = new Date();
1414
+ } else if (matched) {
1415
+ config._d = new Date(+matched[1]);
1416
+ } else if (typeof input === 'string') {
1417
+ makeDateFromString(config);
1418
+ } else if (isArray(input)) {
1419
+ config._a = input.slice(0);
1420
+ dateFromConfig(config);
1421
+ } else if (isDate(input)) {
1422
+ config._d = new Date(+input);
1423
+ } else if (typeof(input) === 'object') {
1424
+ dateFromObject(config);
1425
+ } else {
1426
+ config._d = new Date(input);
1427
+ }
1428
+ }
1429
+
1430
+ function makeDate(y, m, d, h, M, s, ms) {
1431
+ //can't just apply() to create a date:
1432
+ //http://stackoverflow.com/questions/181348/instantiating-a-javascript-object-by-calling-prototype-constructor-apply
1433
+ var date = new Date(y, m, d, h, M, s, ms);
1434
+
1435
+ //the date constructor doesn't accept years < 1970
1436
+ if (y < 1970) {
1437
+ date.setFullYear(y);
1438
+ }
1439
+ return date;
1440
+ }
1441
+
1442
+ function makeUTCDate(y) {
1443
+ var date = new Date(Date.UTC.apply(null, arguments));
1444
+ if (y < 1970) {
1445
+ date.setUTCFullYear(y);
1446
+ }
1447
+ return date;
1448
+ }
1449
+
1450
+ function parseWeekday(input, language) {
1451
+ if (typeof input === 'string') {
1452
+ if (!isNaN(input)) {
1453
+ input = parseInt(input, 10);
1454
+ }
1455
+ else {
1456
+ input = language.weekdaysParse(input);
1457
+ if (typeof input !== 'number') {
1458
+ return null;
1459
+ }
1460
+ }
1461
+ }
1462
+ return input;
1463
+ }
1464
+
1465
+ /************************************
1466
+ Relative Time
1467
+ ************************************/
1468
+
1469
+
1470
+ // helper function for moment.fn.from, moment.fn.fromNow, and moment.duration.fn.humanize
1471
+ function substituteTimeAgo(string, number, withoutSuffix, isFuture, lang) {
1472
+ return lang.relativeTime(number || 1, !!withoutSuffix, string, isFuture);
1473
+ }
1474
+
1475
+ function relativeTime(milliseconds, withoutSuffix, lang) {
1476
+ var seconds = round(Math.abs(milliseconds) / 1000),
1477
+ minutes = round(seconds / 60),
1478
+ hours = round(minutes / 60),
1479
+ days = round(hours / 24),
1480
+ years = round(days / 365),
1481
+ args = seconds < 45 && ['s', seconds] ||
1482
+ minutes === 1 && ['m'] ||
1483
+ minutes < 45 && ['mm', minutes] ||
1484
+ hours === 1 && ['h'] ||
1485
+ hours < 22 && ['hh', hours] ||
1486
+ days === 1 && ['d'] ||
1487
+ days <= 25 && ['dd', days] ||
1488
+ days <= 45 && ['M'] ||
1489
+ days < 345 && ['MM', round(days / 30)] ||
1490
+ years === 1 && ['y'] || ['yy', years];
1491
+ args[2] = withoutSuffix;
1492
+ args[3] = milliseconds > 0;
1493
+ args[4] = lang;
1494
+ return substituteTimeAgo.apply({}, args);
1495
+ }
1496
+
1497
+
1498
+ /************************************
1499
+ Week of Year
1500
+ ************************************/
1501
+
1502
+
1503
+ // firstDayOfWeek 0 = sun, 6 = sat
1504
+ // the day of the week that starts the week
1505
+ // (usually sunday or monday)
1506
+ // firstDayOfWeekOfYear 0 = sun, 6 = sat
1507
+ // the first week is the week that contains the first
1508
+ // of this day of the week
1509
+ // (eg. ISO weeks use thursday (4))
1510
+ function weekOfYear(mom, firstDayOfWeek, firstDayOfWeekOfYear) {
1511
+ var end = firstDayOfWeekOfYear - firstDayOfWeek,
1512
+ daysToDayOfWeek = firstDayOfWeekOfYear - mom.day(),
1513
+ adjustedMoment;
1514
+
1515
+
1516
+ if (daysToDayOfWeek > end) {
1517
+ daysToDayOfWeek -= 7;
1518
+ }
1519
+
1520
+ if (daysToDayOfWeek < end - 7) {
1521
+ daysToDayOfWeek += 7;
1522
+ }
1523
+
1524
+ adjustedMoment = moment(mom).add('d', daysToDayOfWeek);
1525
+ return {
1526
+ week: Math.ceil(adjustedMoment.dayOfYear() / 7),
1527
+ year: adjustedMoment.year()
1528
+ };
1529
+ }
1530
+
1531
+ //http://en.wikipedia.org/wiki/ISO_week_date#Calculating_a_date_given_the_year.2C_week_number_and_weekday
1532
+ function dayOfYearFromWeeks(year, week, weekday, firstDayOfWeekOfYear, firstDayOfWeek) {
1533
+ var d = makeUTCDate(year, 0, 1).getUTCDay(), daysToAdd, dayOfYear;
1534
+
1535
+ weekday = weekday != null ? weekday : firstDayOfWeek;
1536
+ daysToAdd = firstDayOfWeek - d + (d > firstDayOfWeekOfYear ? 7 : 0) - (d < firstDayOfWeek ? 7 : 0);
1537
+ dayOfYear = 7 * (week - 1) + (weekday - firstDayOfWeek) + daysToAdd + 1;
1538
+
1539
+ return {
1540
+ year: dayOfYear > 0 ? year : year - 1,
1541
+ dayOfYear: dayOfYear > 0 ? dayOfYear : daysInYear(year - 1) + dayOfYear
1542
+ };
1543
+ }
1544
+
1545
+ /************************************
1546
+ Top Level Functions
1547
+ ************************************/
1548
+
1549
+ function makeMoment(config) {
1550
+ var input = config._i,
1551
+ format = config._f;
1552
+
1553
+ if (input === null) {
1554
+ return moment.invalid({nullInput: true});
1555
+ }
1556
+
1557
+ if (typeof input === 'string') {
1558
+ config._i = input = getLangDefinition().preparse(input);
1559
+ }
1560
+
1561
+ if (moment.isMoment(input)) {
1562
+ config = cloneMoment(input);
1563
+
1564
+ config._d = new Date(+input._d);
1565
+ } else if (format) {
1566
+ if (isArray(format)) {
1567
+ makeDateFromStringAndArray(config);
1568
+ } else {
1569
+ makeDateFromStringAndFormat(config);
1570
+ }
1571
+ } else {
1572
+ makeDateFromInput(config);
1573
+ }
1574
+
1575
+ return new Moment(config);
1576
+ }
1577
+
1578
+ moment = function (input, format, lang, strict) {
1579
+ var c;
1580
+
1581
+ if (typeof(lang) === "boolean") {
1582
+ strict = lang;
1583
+ lang = undefined;
1584
+ }
1585
+ // object construction must be done this way.
1586
+ // https://github.com/moment/moment/issues/1423
1587
+ c = {};
1588
+ c._isAMomentObject = true;
1589
+ c._i = input;
1590
+ c._f = format;
1591
+ c._l = lang;
1592
+ c._strict = strict;
1593
+ c._isUTC = false;
1594
+ c._pf = defaultParsingFlags();
1595
+
1596
+ return makeMoment(c);
1597
+ };
1598
+
1599
+ // creating with utc
1600
+ moment.utc = function (input, format, lang, strict) {
1601
+ var c;
1602
+
1603
+ if (typeof(lang) === "boolean") {
1604
+ strict = lang;
1605
+ lang = undefined;
1606
+ }
1607
+ // object construction must be done this way.
1608
+ // https://github.com/moment/moment/issues/1423
1609
+ c = {};
1610
+ c._isAMomentObject = true;
1611
+ c._useUTC = true;
1612
+ c._isUTC = true;
1613
+ c._l = lang;
1614
+ c._i = input;
1615
+ c._f = format;
1616
+ c._strict = strict;
1617
+ c._pf = defaultParsingFlags();
1618
+
1619
+ return makeMoment(c).utc();
1620
+ };
1621
+
1622
+ // creating with unix timestamp (in seconds)
1623
+ moment.unix = function (input) {
1624
+ return moment(input * 1000);
1625
+ };
1626
+
1627
+ // duration
1628
+ moment.duration = function (input, key) {
1629
+ var duration = input,
1630
+ // matching against regexp is expensive, do it on demand
1631
+ match = null,
1632
+ sign,
1633
+ ret,
1634
+ parseIso;
1635
+
1636
+ if (moment.isDuration(input)) {
1637
+ duration = {
1638
+ ms: input._milliseconds,
1639
+ d: input._days,
1640
+ M: input._months
1641
+ };
1642
+ } else if (typeof input === 'number') {
1643
+ duration = {};
1644
+ if (key) {
1645
+ duration[key] = input;
1646
+ } else {
1647
+ duration.milliseconds = input;
1648
+ }
1649
+ } else if (!!(match = aspNetTimeSpanJsonRegex.exec(input))) {
1650
+ sign = (match[1] === "-") ? -1 : 1;
1651
+ duration = {
1652
+ y: 0,
1653
+ d: toInt(match[DATE]) * sign,
1654
+ h: toInt(match[HOUR]) * sign,
1655
+ m: toInt(match[MINUTE]) * sign,
1656
+ s: toInt(match[SECOND]) * sign,
1657
+ ms: toInt(match[MILLISECOND]) * sign
1658
+ };
1659
+ } else if (!!(match = isoDurationRegex.exec(input))) {
1660
+ sign = (match[1] === "-") ? -1 : 1;
1661
+ parseIso = function (inp) {
1662
+ // We'd normally use ~~inp for this, but unfortunately it also
1663
+ // converts floats to ints.
1664
+ // inp may be undefined, so careful calling replace on it.
1665
+ var res = inp && parseFloat(inp.replace(',', '.'));
1666
+ // apply sign while we're at it
1667
+ return (isNaN(res) ? 0 : res) * sign;
1668
+ };
1669
+ duration = {
1670
+ y: parseIso(match[2]),
1671
+ M: parseIso(match[3]),
1672
+ d: parseIso(match[4]),
1673
+ h: parseIso(match[5]),
1674
+ m: parseIso(match[6]),
1675
+ s: parseIso(match[7]),
1676
+ w: parseIso(match[8])
1677
+ };
1678
+ }
1679
+
1680
+ ret = new Duration(duration);
1681
+
1682
+ if (moment.isDuration(input) && input.hasOwnProperty('_lang')) {
1683
+ ret._lang = input._lang;
1684
+ }
1685
+
1686
+ return ret;
1687
+ };
1688
+
1689
+ // version number
1690
+ moment.version = VERSION;
1691
+
1692
+ // default format
1693
+ moment.defaultFormat = isoFormat;
1694
+
1695
+ // This function will be called whenever a moment is mutated.
1696
+ // It is intended to keep the offset in sync with the timezone.
1697
+ moment.updateOffset = function () {};
1698
+
1699
+ // This function will load languages and then set the global language. If
1700
+ // no arguments are passed in, it will simply return the current global
1701
+ // language key.
1702
+ moment.lang = function (key, values) {
1703
+ var r;
1704
+ if (!key) {
1705
+ return moment.fn._lang._abbr;
1706
+ }
1707
+ if (values) {
1708
+ loadLang(normalizeLanguage(key), values);
1709
+ } else if (values === null) {
1710
+ unloadLang(key);
1711
+ key = 'en';
1712
+ } else if (!languages[key]) {
1713
+ getLangDefinition(key);
1714
+ }
1715
+ r = moment.duration.fn._lang = moment.fn._lang = getLangDefinition(key);
1716
+ return r._abbr;
1717
+ };
1718
+
1719
+ // returns language data
1720
+ moment.langData = function (key) {
1721
+ if (key && key._lang && key._lang._abbr) {
1722
+ key = key._lang._abbr;
1723
+ }
1724
+ return getLangDefinition(key);
1725
+ };
1726
+
1727
+ // compare moment object
1728
+ moment.isMoment = function (obj) {
1729
+ return obj instanceof Moment ||
1730
+ (obj != null && obj.hasOwnProperty('_isAMomentObject'));
1731
+ };
1732
+
1733
+ // for typechecking Duration objects
1734
+ moment.isDuration = function (obj) {
1735
+ return obj instanceof Duration;
1736
+ };
1737
+
1738
+ for (i = lists.length - 1; i >= 0; --i) {
1739
+ makeList(lists[i]);
1740
+ }
1741
+
1742
+ moment.normalizeUnits = function (units) {
1743
+ return normalizeUnits(units);
1744
+ };
1745
+
1746
+ moment.invalid = function (flags) {
1747
+ var m = moment.utc(NaN);
1748
+ if (flags != null) {
1749
+ extend(m._pf, flags);
1750
+ }
1751
+ else {
1752
+ m._pf.userInvalidated = true;
1753
+ }
1754
+
1755
+ return m;
1756
+ };
1757
+
1758
+ moment.parseZone = function (input) {
1759
+ return moment(input).parseZone();
1760
+ };
1761
+
1762
+ /************************************
1763
+ Moment Prototype
1764
+ ************************************/
1765
+
1766
+
1767
+ extend(moment.fn = Moment.prototype, {
1768
+
1769
+ clone : function () {
1770
+ return moment(this);
1771
+ },
1772
+
1773
+ valueOf : function () {
1774
+ return +this._d + ((this._offset || 0) * 60000);
1775
+ },
1776
+
1777
+ unix : function () {
1778
+ return Math.floor(+this / 1000);
1779
+ },
1780
+
1781
+ toString : function () {
1782
+ return this.clone().lang('en').format("ddd MMM DD YYYY HH:mm:ss [GMT]ZZ");
1783
+ },
1784
+
1785
+ toDate : function () {
1786
+ return this._offset ? new Date(+this) : this._d;
1787
+ },
1788
+
1789
+ toISOString : function () {
1790
+ var m = moment(this).utc();
1791
+ if (0 < m.year() && m.year() <= 9999) {
1792
+ return formatMoment(m, 'YYYY-MM-DD[T]HH:mm:ss.SSS[Z]');
1793
+ } else {
1794
+ return formatMoment(m, 'YYYYYY-MM-DD[T]HH:mm:ss.SSS[Z]');
1795
+ }
1796
+ },
1797
+
1798
+ toArray : function () {
1799
+ var m = this;
1800
+ return [
1801
+ m.year(),
1802
+ m.month(),
1803
+ m.date(),
1804
+ m.hours(),
1805
+ m.minutes(),
1806
+ m.seconds(),
1807
+ m.milliseconds()
1808
+ ];
1809
+ },
1810
+
1811
+ isValid : function () {
1812
+ return isValid(this);
1813
+ },
1814
+
1815
+ isDSTShifted : function () {
1816
+
1817
+ if (this._a) {
1818
+ return this.isValid() && compareArrays(this._a, (this._isUTC ? moment.utc(this._a) : moment(this._a)).toArray()) > 0;
1819
+ }
1820
+
1821
+ return false;
1822
+ },
1823
+
1824
+ parsingFlags : function () {
1825
+ return extend({}, this._pf);
1826
+ },
1827
+
1828
+ invalidAt: function () {
1829
+ return this._pf.overflow;
1830
+ },
1831
+
1832
+ utc : function () {
1833
+ return this.zone(0);
1834
+ },
1835
+
1836
+ local : function () {
1837
+ this.zone(0);
1838
+ this._isUTC = false;
1839
+ return this;
1840
+ },
1841
+
1842
+ format : function (inputString) {
1843
+ var output = formatMoment(this, inputString || moment.defaultFormat);
1844
+ return this.lang().postformat(output);
1845
+ },
1846
+
1847
+ add : function (input, val) {
1848
+ var dur;
1849
+ // switch args to support add('s', 1) and add(1, 's')
1850
+ if (typeof input === 'string') {
1851
+ dur = moment.duration(+val, input);
1852
+ } else {
1853
+ dur = moment.duration(input, val);
1854
+ }
1855
+ addOrSubtractDurationFromMoment(this, dur, 1);
1856
+ return this;
1857
+ },
1858
+
1859
+ subtract : function (input, val) {
1860
+ var dur;
1861
+ // switch args to support subtract('s', 1) and subtract(1, 's')
1862
+ if (typeof input === 'string') {
1863
+ dur = moment.duration(+val, input);
1864
+ } else {
1865
+ dur = moment.duration(input, val);
1866
+ }
1867
+ addOrSubtractDurationFromMoment(this, dur, -1);
1868
+ return this;
1869
+ },
1870
+
1871
+ diff : function (input, units, asFloat) {
1872
+ var that = makeAs(input, this),
1873
+ zoneDiff = (this.zone() - that.zone()) * 6e4,
1874
+ diff, output;
1875
+
1876
+ units = normalizeUnits(units);
1877
+
1878
+ if (units === 'year' || units === 'month') {
1879
+ // average number of days in the months in the given dates
1880
+ diff = (this.daysInMonth() + that.daysInMonth()) * 432e5; // 24 * 60 * 60 * 1000 / 2
1881
+ // difference in months
1882
+ output = ((this.year() - that.year()) * 12) + (this.month() - that.month());
1883
+ // adjust by taking difference in days, average number of days
1884
+ // and dst in the given months.
1885
+ output += ((this - moment(this).startOf('month')) -
1886
+ (that - moment(that).startOf('month'))) / diff;
1887
+ // same as above but with zones, to negate all dst
1888
+ output -= ((this.zone() - moment(this).startOf('month').zone()) -
1889
+ (that.zone() - moment(that).startOf('month').zone())) * 6e4 / diff;
1890
+ if (units === 'year') {
1891
+ output = output / 12;
1892
+ }
1893
+ } else {
1894
+ diff = (this - that);
1895
+ output = units === 'second' ? diff / 1e3 : // 1000
1896
+ units === 'minute' ? diff / 6e4 : // 1000 * 60
1897
+ units === 'hour' ? diff / 36e5 : // 1000 * 60 * 60
1898
+ units === 'day' ? (diff - zoneDiff) / 864e5 : // 1000 * 60 * 60 * 24, negate dst
1899
+ units === 'week' ? (diff - zoneDiff) / 6048e5 : // 1000 * 60 * 60 * 24 * 7, negate dst
1900
+ diff;
1901
+ }
1902
+ return asFloat ? output : absRound(output);
1903
+ },
1904
+
1905
+ from : function (time, withoutSuffix) {
1906
+ return moment.duration(this.diff(time)).lang(this.lang()._abbr).humanize(!withoutSuffix);
1907
+ },
1908
+
1909
+ fromNow : function (withoutSuffix) {
1910
+ return this.from(moment(), withoutSuffix);
1911
+ },
1912
+
1913
+ calendar : function () {
1914
+ // We want to compare the start of today, vs this.
1915
+ // Getting start-of-today depends on whether we're zone'd or not.
1916
+ var sod = makeAs(moment(), this).startOf('day'),
1917
+ diff = this.diff(sod, 'days', true),
1918
+ format = diff < -6 ? 'sameElse' :
1919
+ diff < -1 ? 'lastWeek' :
1920
+ diff < 0 ? 'lastDay' :
1921
+ diff < 1 ? 'sameDay' :
1922
+ diff < 2 ? 'nextDay' :
1923
+ diff < 7 ? 'nextWeek' : 'sameElse';
1924
+ return this.format(this.lang().calendar(format, this));
1925
+ },
1926
+
1927
+ isLeapYear : function () {
1928
+ return isLeapYear(this.year());
1929
+ },
1930
+
1931
+ isDST : function () {
1932
+ return (this.zone() < this.clone().month(0).zone() ||
1933
+ this.zone() < this.clone().month(5).zone());
1934
+ },
1935
+
1936
+ day : function (input) {
1937
+ var day = this._isUTC ? this._d.getUTCDay() : this._d.getDay();
1938
+ if (input != null) {
1939
+ input = parseWeekday(input, this.lang());
1940
+ return this.add({ d : input - day });
1941
+ } else {
1942
+ return day;
1943
+ }
1944
+ },
1945
+
1946
+ month : function (input) {
1947
+ var utc = this._isUTC ? 'UTC' : '',
1948
+ dayOfMonth;
1949
+
1950
+ if (input != null) {
1951
+ if (typeof input === 'string') {
1952
+ input = this.lang().monthsParse(input);
1953
+ if (typeof input !== 'number') {
1954
+ return this;
1955
+ }
1956
+ }
1957
+
1958
+ dayOfMonth = this.date();
1959
+ this.date(1);
1960
+ this._d['set' + utc + 'Month'](input);
1961
+ this.date(Math.min(dayOfMonth, this.daysInMonth()));
1962
+
1963
+ moment.updateOffset(this);
1964
+ return this;
1965
+ } else {
1966
+ return this._d['get' + utc + 'Month']();
1967
+ }
1968
+ },
1969
+
1970
+ startOf: function (units) {
1971
+ units = normalizeUnits(units);
1972
+ // the following switch intentionally omits break keywords
1973
+ // to utilize falling through the cases.
1974
+ switch (units) {
1975
+ case 'year':
1976
+ this.month(0);
1977
+ /* falls through */
1978
+ case 'month':
1979
+ this.date(1);
1980
+ /* falls through */
1981
+ case 'week':
1982
+ case 'isoWeek':
1983
+ case 'day':
1984
+ this.hours(0);
1985
+ /* falls through */
1986
+ case 'hour':
1987
+ this.minutes(0);
1988
+ /* falls through */
1989
+ case 'minute':
1990
+ this.seconds(0);
1991
+ /* falls through */
1992
+ case 'second':
1993
+ this.milliseconds(0);
1994
+ /* falls through */
1995
+ }
1996
+
1997
+ // weeks are a special case
1998
+ if (units === 'week') {
1999
+ this.weekday(0);
2000
+ } else if (units === 'isoWeek') {
2001
+ this.isoWeekday(1);
2002
+ }
2003
+
2004
+ return this;
2005
+ },
2006
+
2007
+ endOf: function (units) {
2008
+ units = normalizeUnits(units);
2009
+ return this.startOf(units).add((units === 'isoWeek' ? 'week' : units), 1).subtract('ms', 1);
2010
+ },
2011
+
2012
+ isAfter: function (input, units) {
2013
+ units = typeof units !== 'undefined' ? units : 'millisecond';
2014
+ return +this.clone().startOf(units) > +moment(input).startOf(units);
2015
+ },
2016
+
2017
+ isBefore: function (input, units) {
2018
+ units = typeof units !== 'undefined' ? units : 'millisecond';
2019
+ return +this.clone().startOf(units) < +moment(input).startOf(units);
2020
+ },
2021
+
2022
+ isSame: function (input, units) {
2023
+ units = units || 'ms';
2024
+ return +this.clone().startOf(units) === +makeAs(input, this).startOf(units);
2025
+ },
2026
+
2027
+ min: function (other) {
2028
+ other = moment.apply(null, arguments);
2029
+ return other < this ? this : other;
2030
+ },
2031
+
2032
+ max: function (other) {
2033
+ other = moment.apply(null, arguments);
2034
+ return other > this ? this : other;
2035
+ },
2036
+
2037
+ zone : function (input) {
2038
+ var offset = this._offset || 0;
2039
+ if (input != null) {
2040
+ if (typeof input === "string") {
2041
+ input = timezoneMinutesFromString(input);
2042
+ }
2043
+ if (Math.abs(input) < 16) {
2044
+ input = input * 60;
2045
+ }
2046
+ this._offset = input;
2047
+ this._isUTC = true;
2048
+ if (offset !== input) {
2049
+ addOrSubtractDurationFromMoment(this, moment.duration(offset - input, 'm'), 1, true);
2050
+ }
2051
+ } else {
2052
+ return this._isUTC ? offset : this._d.getTimezoneOffset();
2053
+ }
2054
+ return this;
2055
+ },
2056
+
2057
+ zoneAbbr : function () {
2058
+ return this._isUTC ? "UTC" : "";
2059
+ },
2060
+
2061
+ zoneName : function () {
2062
+ return this._isUTC ? "Coordinated Universal Time" : "";
2063
+ },
2064
+
2065
+ parseZone : function () {
2066
+ if (this._tzm) {
2067
+ this.zone(this._tzm);
2068
+ } else if (typeof this._i === 'string') {
2069
+ this.zone(this._i);
2070
+ }
2071
+ return this;
2072
+ },
2073
+
2074
+ hasAlignedHourOffset : function (input) {
2075
+ if (!input) {
2076
+ input = 0;
2077
+ }
2078
+ else {
2079
+ input = moment(input).zone();
2080
+ }
2081
+
2082
+ return (this.zone() - input) % 60 === 0;
2083
+ },
2084
+
2085
+ daysInMonth : function () {
2086
+ return daysInMonth(this.year(), this.month());
2087
+ },
2088
+
2089
+ dayOfYear : function (input) {
2090
+ var dayOfYear = round((moment(this).startOf('day') - moment(this).startOf('year')) / 864e5) + 1;
2091
+ return input == null ? dayOfYear : this.add("d", (input - dayOfYear));
2092
+ },
2093
+
2094
+ quarter : function () {
2095
+ return Math.ceil((this.month() + 1.0) / 3.0);
2096
+ },
2097
+
2098
+ weekYear : function (input) {
2099
+ var year = weekOfYear(this, this.lang()._week.dow, this.lang()._week.doy).year;
2100
+ return input == null ? year : this.add("y", (input - year));
2101
+ },
2102
+
2103
+ isoWeekYear : function (input) {
2104
+ var year = weekOfYear(this, 1, 4).year;
2105
+ return input == null ? year : this.add("y", (input - year));
2106
+ },
2107
+
2108
+ week : function (input) {
2109
+ var week = this.lang().week(this);
2110
+ return input == null ? week : this.add("d", (input - week) * 7);
2111
+ },
2112
+
2113
+ isoWeek : function (input) {
2114
+ var week = weekOfYear(this, 1, 4).week;
2115
+ return input == null ? week : this.add("d", (input - week) * 7);
2116
+ },
2117
+
2118
+ weekday : function (input) {
2119
+ var weekday = (this.day() + 7 - this.lang()._week.dow) % 7;
2120
+ return input == null ? weekday : this.add("d", input - weekday);
2121
+ },
2122
+
2123
+ isoWeekday : function (input) {
2124
+ // behaves the same as moment#day except
2125
+ // as a getter, returns 7 instead of 0 (1-7 range instead of 0-6)
2126
+ // as a setter, sunday should belong to the previous week.
2127
+ return input == null ? this.day() || 7 : this.day(this.day() % 7 ? input : input - 7);
2128
+ },
2129
+
2130
+ get : function (units) {
2131
+ units = normalizeUnits(units);
2132
+ return this[units]();
2133
+ },
2134
+
2135
+ set : function (units, value) {
2136
+ units = normalizeUnits(units);
2137
+ if (typeof this[units] === 'function') {
2138
+ this[units](value);
2139
+ }
2140
+ return this;
2141
+ },
2142
+
2143
+ // If passed a language key, it will set the language for this
2144
+ // instance. Otherwise, it will return the language configuration
2145
+ // variables for this instance.
2146
+ lang : function (key) {
2147
+ if (key === undefined) {
2148
+ return this._lang;
2149
+ } else {
2150
+ this._lang = getLangDefinition(key);
2151
+ return this;
2152
+ }
2153
+ }
2154
+ });
2155
+
2156
+ // helper for adding shortcuts
2157
+ function makeGetterAndSetter(name, key) {
2158
+ moment.fn[name] = moment.fn[name + 's'] = function (input) {
2159
+ var utc = this._isUTC ? 'UTC' : '';
2160
+ if (input != null) {
2161
+ this._d['set' + utc + key](input);
2162
+ moment.updateOffset(this);
2163
+ return this;
2164
+ } else {
2165
+ return this._d['get' + utc + key]();
2166
+ }
2167
+ };
2168
+ }
2169
+
2170
+ // loop through and add shortcuts (Month, Date, Hours, Minutes, Seconds, Milliseconds)
2171
+ for (i = 0; i < proxyGettersAndSetters.length; i ++) {
2172
+ makeGetterAndSetter(proxyGettersAndSetters[i].toLowerCase().replace(/s$/, ''), proxyGettersAndSetters[i]);
2173
+ }
2174
+
2175
+ // add shortcut for year (uses different syntax than the getter/setter 'year' == 'FullYear')
2176
+ makeGetterAndSetter('year', 'FullYear');
2177
+
2178
+ // add plural methods
2179
+ moment.fn.days = moment.fn.day;
2180
+ moment.fn.months = moment.fn.month;
2181
+ moment.fn.weeks = moment.fn.week;
2182
+ moment.fn.isoWeeks = moment.fn.isoWeek;
2183
+
2184
+ // add aliased format methods
2185
+ moment.fn.toJSON = moment.fn.toISOString;
2186
+
2187
+ /************************************
2188
+ Duration Prototype
2189
+ ************************************/
2190
+
2191
+
2192
+ extend(moment.duration.fn = Duration.prototype, {
2193
+
2194
+ _bubble : function () {
2195
+ var milliseconds = this._milliseconds,
2196
+ days = this._days,
2197
+ months = this._months,
2198
+ data = this._data,
2199
+ seconds, minutes, hours, years;
2200
+
2201
+ // The following code bubbles up values, see the tests for
2202
+ // examples of what that means.
2203
+ data.milliseconds = milliseconds % 1000;
2204
+
2205
+ seconds = absRound(milliseconds / 1000);
2206
+ data.seconds = seconds % 60;
2207
+
2208
+ minutes = absRound(seconds / 60);
2209
+ data.minutes = minutes % 60;
2210
+
2211
+ hours = absRound(minutes / 60);
2212
+ data.hours = hours % 24;
2213
+
2214
+ days += absRound(hours / 24);
2215
+ data.days = days % 30;
2216
+
2217
+ months += absRound(days / 30);
2218
+ data.months = months % 12;
2219
+
2220
+ years = absRound(months / 12);
2221
+ data.years = years;
2222
+ },
2223
+
2224
+ weeks : function () {
2225
+ return absRound(this.days() / 7);
2226
+ },
2227
+
2228
+ valueOf : function () {
2229
+ return this._milliseconds +
2230
+ this._days * 864e5 +
2231
+ (this._months % 12) * 2592e6 +
2232
+ toInt(this._months / 12) * 31536e6;
2233
+ },
2234
+
2235
+ humanize : function (withSuffix) {
2236
+ var difference = +this,
2237
+ output = relativeTime(difference, !withSuffix, this.lang());
2238
+
2239
+ if (withSuffix) {
2240
+ output = this.lang().pastFuture(difference, output);
2241
+ }
2242
+
2243
+ return this.lang().postformat(output);
2244
+ },
2245
+
2246
+ add : function (input, val) {
2247
+ // supports only 2.0-style add(1, 's') or add(moment)
2248
+ var dur = moment.duration(input, val);
2249
+
2250
+ this._milliseconds += dur._milliseconds;
2251
+ this._days += dur._days;
2252
+ this._months += dur._months;
2253
+
2254
+ this._bubble();
2255
+
2256
+ return this;
2257
+ },
2258
+
2259
+ subtract : function (input, val) {
2260
+ var dur = moment.duration(input, val);
2261
+
2262
+ this._milliseconds -= dur._milliseconds;
2263
+ this._days -= dur._days;
2264
+ this._months -= dur._months;
2265
+
2266
+ this._bubble();
2267
+
2268
+ return this;
2269
+ },
2270
+
2271
+ get : function (units) {
2272
+ units = normalizeUnits(units);
2273
+ return this[units.toLowerCase() + 's']();
2274
+ },
2275
+
2276
+ as : function (units) {
2277
+ units = normalizeUnits(units);
2278
+ return this['as' + units.charAt(0).toUpperCase() + units.slice(1) + 's']();
2279
+ },
2280
+
2281
+ lang : moment.fn.lang,
2282
+
2283
+ toIsoString : function () {
2284
+ // inspired by https://github.com/dordille/moment-isoduration/blob/master/moment.isoduration.js
2285
+ var years = Math.abs(this.years()),
2286
+ months = Math.abs(this.months()),
2287
+ days = Math.abs(this.days()),
2288
+ hours = Math.abs(this.hours()),
2289
+ minutes = Math.abs(this.minutes()),
2290
+ seconds = Math.abs(this.seconds() + this.milliseconds() / 1000);
2291
+
2292
+ if (!this.asSeconds()) {
2293
+ // this is the same as C#'s (Noda) and python (isodate)...
2294
+ // but not other JS (goog.date)
2295
+ return 'P0D';
2296
+ }
2297
+
2298
+ return (this.asSeconds() < 0 ? '-' : '') +
2299
+ 'P' +
2300
+ (years ? years + 'Y' : '') +
2301
+ (months ? months + 'M' : '') +
2302
+ (days ? days + 'D' : '') +
2303
+ ((hours || minutes || seconds) ? 'T' : '') +
2304
+ (hours ? hours + 'H' : '') +
2305
+ (minutes ? minutes + 'M' : '') +
2306
+ (seconds ? seconds + 'S' : '');
2307
+ }
2308
+ });
2309
+
2310
+ function makeDurationGetter(name) {
2311
+ moment.duration.fn[name] = function () {
2312
+ return this._data[name];
2313
+ };
2314
+ }
2315
+
2316
+ function makeDurationAsGetter(name, factor) {
2317
+ moment.duration.fn['as' + name] = function () {
2318
+ return +this / factor;
2319
+ };
2320
+ }
2321
+
2322
+ for (i in unitMillisecondFactors) {
2323
+ if (unitMillisecondFactors.hasOwnProperty(i)) {
2324
+ makeDurationAsGetter(i, unitMillisecondFactors[i]);
2325
+ makeDurationGetter(i.toLowerCase());
2326
+ }
2327
+ }
2328
+
2329
+ makeDurationAsGetter('Weeks', 6048e5);
2330
+ moment.duration.fn.asMonths = function () {
2331
+ return (+this - this.years() * 31536e6) / 2592e6 + this.years() * 12;
2332
+ };
2333
+
2334
+
2335
+ /************************************
2336
+ Default Lang
2337
+ ************************************/
2338
+
2339
+
2340
+ // Set default language, other languages will inherit from English.
2341
+ moment.lang('en', {
2342
+ ordinal : function (number) {
2343
+ var b = number % 10,
2344
+ output = (toInt(number % 100 / 10) === 1) ? 'th' :
2345
+ (b === 1) ? 'st' :
2346
+ (b === 2) ? 'nd' :
2347
+ (b === 3) ? 'rd' : 'th';
2348
+ return number + output;
2349
+ }
2350
+ });
2351
+
2352
+ /* EMBED_LANGUAGES */
2353
+
2354
+ /************************************
2355
+ Exposing Moment
2356
+ ************************************/
2357
+
2358
+ function makeGlobal(deprecate) {
2359
+ var warned = false, local_moment = moment;
2360
+ /*global ender:false */
2361
+ if (typeof ender !== 'undefined') {
2362
+ return;
2363
+ }
2364
+ // here, `this` means `window` in the browser, or `global` on the server
2365
+ // add `moment` as a global object via a string identifier,
2366
+ // for Closure Compiler "advanced" mode
2367
+ if (deprecate) {
2368
+ global.moment = function () {
2369
+ if (!warned && console && console.warn) {
2370
+ warned = true;
2371
+ console.warn(
2372
+ "Accessing Moment through the global scope is " +
2373
+ "deprecated, and will be removed in an upcoming " +
2374
+ "release.");
2375
+ }
2376
+ return local_moment.apply(null, arguments);
2377
+ };
2378
+ extend(global.moment, local_moment);
2379
+ } else {
2380
+ global['moment'] = moment;
2381
+ }
2382
+ }
2383
+
2384
+ // CommonJS module is defined
2385
+ if (hasModule) {
2386
+ module.exports = moment;
2387
+ makeGlobal(true);
2388
+ } else if (typeof define === "function" && define.amd) {
2389
+ define("moment", function (require, exports, module) {
2390
+ if (module.config && module.config() && module.config().noGlobal !== true) {
2391
+ // If user provided noGlobal, he is aware of global
2392
+ makeGlobal(module.config().noGlobal === undefined);
2393
+ }
2394
+
2395
+ return moment;
2396
+ });
2397
+ } else {
2398
+ makeGlobal();
2399
+ }
2400
+ }).call(this);
2401
+
2402
+ /**
2403
+ * @version: 1.3.4
2404
+ * @author: Dan Grossman http://www.dangrossman.info/
2405
+ * @date: 2014-03-19
2406
+ * @copyright: Copyright (c) 2012-2014 Dan Grossman. All rights reserved.
2407
+ * @license: Licensed under Apache License v2.0. See http://www.apache.org/licenses/LICENSE-2.0
2408
+ * @website: http://www.improvely.com/
2409
+ */
2410
+ !function ($, moment) {
2411
+
2412
+ var DateRangePicker = function (element, options, cb) {
2413
+
2414
+ // by default, the daterangepicker element is placed at the bottom of HTML body
2415
+ this.parentEl = 'body';
2416
+
2417
+ //element that triggered the date range picker
2418
+ this.element = $(element);
2419
+
2420
+ //create the picker HTML object
2421
+ var DRPTemplate = '<div class="daterangepicker dropdown-menu">' +
2422
+ '<div class="calendar left"></div>' +
2423
+ '<div class="calendar right"></div>' +
2424
+ '<div class="ranges">' +
2425
+ '<div class="range_inputs">' +
2426
+ '<div class="daterangepicker_start_input">' +
2427
+ '<label for="daterangepicker_start"></label>' +
2428
+ '<input class="input-mini" type="text" name="daterangepicker_start" value="" disabled="disabled" />' +
2429
+ '</div>' +
2430
+ '<div class="daterangepicker_end_input">' +
2431
+ '<label for="daterangepicker_end"></label>' +
2432
+ '<input class="input-mini" type="text" name="daterangepicker_end" value="" disabled="disabled" />' +
2433
+ '</div>' +
2434
+ '<button class="applyBtn" disabled="disabled"></button>&nbsp;' +
2435
+ '<button class="cancelBtn"></button>' +
2436
+ '</div>' +
2437
+ '</div>' +
2438
+ '</div>';
2439
+
2440
+ //custom options
2441
+ if (typeof options !== 'object' || options === null)
2442
+ options = {};
2443
+
2444
+ this.parentEl = (typeof options === 'object' && options.parentEl && $(options.parentEl)) || $(this.parentEl);
2445
+ this.container = $(DRPTemplate).appendTo(this.parentEl);
2446
+
2447
+ this.setOptions(options, cb);
2448
+
2449
+ //apply CSS classes and labels to buttons
2450
+ var c = this.container;
2451
+ $.each(this.buttonClasses, function (idx, val) {
2452
+ c.find('button').addClass(val);
2453
+ });
2454
+ this.container.find('.daterangepicker_start_input label').html(this.locale.fromLabel);
2455
+ this.container.find('.daterangepicker_end_input label').html(this.locale.toLabel);
2456
+ if (this.applyClass.length)
2457
+ this.container.find('.applyBtn').addClass(this.applyClass);
2458
+ if (this.cancelClass.length)
2459
+ this.container.find('.cancelBtn').addClass(this.cancelClass);
2460
+ this.container.find('.applyBtn').html(this.locale.applyLabel);
2461
+ this.container.find('.cancelBtn').html(this.locale.cancelLabel);
2462
+
2463
+ //event listeners
2464
+
2465
+ this.container.find('.calendar')
2466
+ .on('click.daterangepicker', '.prev', $.proxy(this.clickPrev, this))
2467
+ .on('click.daterangepicker', '.next', $.proxy(this.clickNext, this))
2468
+ .on('click.daterangepicker', 'td.available', $.proxy(this.clickDate, this))
2469
+ .on('mouseenter.daterangepicker', 'td.available', $.proxy(this.enterDate, this))
2470
+ .on('mouseleave.daterangepicker', 'td.available', $.proxy(this.updateFormInputs, this))
2471
+ .on('change.daterangepicker', 'select.yearselect', $.proxy(this.updateMonthYear, this))
2472
+ .on('change.daterangepicker', 'select.monthselect', $.proxy(this.updateMonthYear, this))
2473
+ .on('change.daterangepicker', 'select.hourselect,select.minuteselect,select.ampmselect', $.proxy(this.updateTime, this));
2474
+
2475
+ this.container.find('.ranges')
2476
+ .on('click.daterangepicker', 'button.applyBtn', $.proxy(this.clickApply, this))
2477
+ .on('click.daterangepicker', 'button.cancelBtn', $.proxy(this.clickCancel, this))
2478
+ .on('click.daterangepicker', '.daterangepicker_start_input,.daterangepicker_end_input', $.proxy(this.showCalendars, this))
2479
+ .on('click.daterangepicker', 'li', $.proxy(this.clickRange, this))
2480
+ .on('mouseenter.daterangepicker', 'li', $.proxy(this.enterRange, this))
2481
+ .on('mouseleave.daterangepicker', 'li', $.proxy(this.updateFormInputs, this));
2482
+
2483
+ if (this.element.is('input')) {
2484
+ this.element.on({
2485
+ 'click.daterangepicker': $.proxy(this.show, this),
2486
+ 'focus.daterangepicker': $.proxy(this.show, this),
2487
+ 'keyup.daterangepicker': $.proxy(this.updateFromControl, this)
2488
+ });
2489
+ } else {
2490
+ this.element.on('click.daterangepicker', $.proxy(this.toggle, this));
2491
+ }
2492
+
2493
+ };
2494
+
2495
+ DateRangePicker.prototype = {
2496
+
2497
+ constructor: DateRangePicker,
2498
+
2499
+ setOptions: function(options, callback) {
2500
+
2501
+ this.startDate = moment().startOf('day');
2502
+ this.endDate = moment().endOf('day');
2503
+ this.minDate = false;
2504
+ this.maxDate = false;
2505
+ this.dateLimit = false;
2506
+
2507
+ this.showDropdowns = false;
2508
+ this.showWeekNumbers = false;
2509
+ this.timePicker = false;
2510
+ this.timePickerIncrement = 30;
2511
+ this.timePicker12Hour = true;
2512
+ this.singleDatePicker = false;
2513
+ this.ranges = {};
2514
+
2515
+ this.opens = 'right';
2516
+ if (this.element.hasClass('pull-right'))
2517
+ this.opens = 'left';
2518
+
2519
+ this.buttonClasses = ['btn', 'btn-small'];
2520
+ this.applyClass = 'btn-success';
2521
+ this.cancelClass = 'btn-default';
2522
+
2523
+ this.format = 'MM/DD/YYYY';
2524
+ this.separator = ' - ';
2525
+
2526
+ this.locale = {
2527
+ applyLabel: 'Apply',
2528
+ cancelLabel: 'Cancel',
2529
+ fromLabel: 'From',
2530
+ toLabel: 'To',
2531
+ weekLabel: 'W',
2532
+ customRangeLabel: 'Custom Range',
2533
+ daysOfWeek: moment()._lang._weekdaysMin.slice(),
2534
+ monthNames: moment()._lang._monthsShort.slice(),
2535
+ firstDay: 0
2536
+ };
2537
+
2538
+ this.cb = function () { };
2539
+
2540
+ if (typeof options.format === 'string')
2541
+ this.format = options.format;
2542
+
2543
+ if (typeof options.separator === 'string')
2544
+ this.separator = options.separator;
2545
+
2546
+ if (typeof options.startDate === 'string')
2547
+ this.startDate = moment(options.startDate, this.format);
2548
+
2549
+ if (typeof options.endDate === 'string')
2550
+ this.endDate = moment(options.endDate, this.format);
2551
+
2552
+ if (typeof options.minDate === 'string')
2553
+ this.minDate = moment(options.minDate, this.format);
2554
+
2555
+ if (typeof options.maxDate === 'string')
2556
+ this.maxDate = moment(options.maxDate, this.format);
2557
+
2558
+ if (typeof options.startDate === 'object')
2559
+ this.startDate = moment(options.startDate);
2560
+
2561
+ if (typeof options.endDate === 'object')
2562
+ this.endDate = moment(options.endDate);
2563
+
2564
+ if (typeof options.minDate === 'object')
2565
+ this.minDate = moment(options.minDate);
2566
+
2567
+ if (typeof options.maxDate === 'object')
2568
+ this.maxDate = moment(options.maxDate);
2569
+
2570
+ if (typeof options.applyClass === 'string')
2571
+ this.applyClass = options.applyClass;
2572
+
2573
+ if (typeof options.cancelClass === 'string')
2574
+ this.cancelClass = options.cancelClass;
2575
+
2576
+ if (typeof options.dateLimit === 'object')
2577
+ this.dateLimit = options.dateLimit;
2578
+
2579
+ // update day names order to firstDay
2580
+ if (typeof options.locale === 'object') {
2581
+
2582
+ if (typeof options.locale.daysOfWeek === 'object') {
2583
+ // Create a copy of daysOfWeek to avoid modification of original
2584
+ // options object for reusability in multiple daterangepicker instances
2585
+ this.locale.daysOfWeek = options.locale.daysOfWeek.slice();
2586
+ }
2587
+
2588
+ if (typeof options.locale.monthNames === 'object') {
2589
+ this.locale.monthNames = options.locale.monthNames.slice();
2590
+ }
2591
+
2592
+ if (typeof options.locale.firstDay === 'number') {
2593
+ this.locale.firstDay = options.locale.firstDay;
2594
+ var iterator = options.locale.firstDay;
2595
+ while (iterator > 0) {
2596
+ this.locale.daysOfWeek.push(this.locale.daysOfWeek.shift());
2597
+ iterator--;
2598
+ }
2599
+ }
2600
+
2601
+ if (typeof options.locale.applyLabel === 'string') {
2602
+ this.locale.applyLabel = options.locale.applyLabel;
2603
+ }
2604
+
2605
+ if (typeof options.locale.cancelLabel === 'string') {
2606
+ this.locale.cancelLabel = options.locale.cancelLabel;
2607
+ }
2608
+
2609
+ if (typeof options.locale.fromLabel === 'string') {
2610
+ this.locale.fromLabel = options.locale.fromLabel;
2611
+ }
2612
+
2613
+ if (typeof options.locale.toLabel === 'string') {
2614
+ this.locale.toLabel = options.locale.toLabel;
2615
+ }
2616
+
2617
+ if (typeof options.locale.weekLabel === 'string') {
2618
+ this.locale.weekLabel = options.locale.weekLabel;
2619
+ }
2620
+
2621
+ if (typeof options.locale.customRangeLabel === 'string') {
2622
+ this.locale.customRangeLabel = options.locale.customRangeLabel;
2623
+ }
2624
+ }
2625
+
2626
+ if (typeof options.opens === 'string')
2627
+ this.opens = options.opens;
2628
+
2629
+ if (typeof options.showWeekNumbers === 'boolean') {
2630
+ this.showWeekNumbers = options.showWeekNumbers;
2631
+ }
2632
+
2633
+ if (typeof options.buttonClasses === 'string') {
2634
+ this.buttonClasses = [options.buttonClasses];
2635
+ }
2636
+
2637
+ if (typeof options.buttonClasses === 'object') {
2638
+ this.buttonClasses = options.buttonClasses;
2639
+ }
2640
+
2641
+ if (typeof options.showDropdowns === 'boolean') {
2642
+ this.showDropdowns = options.showDropdowns;
2643
+ }
2644
+
2645
+ if (typeof options.singleDatePicker === 'boolean') {
2646
+ this.singleDatePicker = options.singleDatePicker;
2647
+ }
2648
+
2649
+ if (typeof options.timePicker === 'boolean') {
2650
+ this.timePicker = options.timePicker;
2651
+ }
2652
+
2653
+ if (typeof options.timePickerIncrement === 'number') {
2654
+ this.timePickerIncrement = options.timePickerIncrement;
2655
+ }
2656
+
2657
+ if (typeof options.timePicker12Hour === 'boolean') {
2658
+ this.timePicker12Hour = options.timePicker12Hour;
2659
+ }
2660
+
2661
+ var start, end, range;
2662
+
2663
+ //if no start/end dates set, check if an input element contains initial values
2664
+ if (typeof options.startDate === 'undefined' && typeof options.endDate === 'undefined') {
2665
+ if ($(this.element).is('input[type=text]')) {
2666
+ var val = $(this.element).val();
2667
+ var split = val.split(this.separator);
2668
+ start = end = null;
2669
+ if (split.length == 2) {
2670
+ start = moment(split[0], this.format);
2671
+ end = moment(split[1], this.format);
2672
+ } else if (this.singleDatePicker) {
2673
+ start = moment(val, this.format);
2674
+ end = moment(val, this.format);
2675
+ }
2676
+ if (start !== null && end !== null) {
2677
+ this.startDate = start;
2678
+ this.endDate = end;
2679
+ }
2680
+ }
2681
+ }
2682
+
2683
+ if (typeof options.ranges === 'object') {
2684
+ for (range in options.ranges) {
2685
+
2686
+ start = moment(options.ranges[range][0]);
2687
+ end = moment(options.ranges[range][1]);
2688
+
2689
+ // If we have a min/max date set, bound this range
2690
+ // to it, but only if it would otherwise fall
2691
+ // outside of the min/max.
2692
+ if (this.minDate && start.isBefore(this.minDate))
2693
+ start = moment(this.minDate);
2694
+
2695
+ if (this.maxDate && end.isAfter(this.maxDate))
2696
+ end = moment(this.maxDate);
2697
+
2698
+ // If the end of the range is before the minimum (if min is set) OR
2699
+ // the start of the range is after the max (also if set) don't display this
2700
+ // range option.
2701
+ if ((this.minDate && end.isBefore(this.minDate)) || (this.maxDate && start.isAfter(this.maxDate))) {
2702
+ continue;
2703
+ }
2704
+
2705
+ this.ranges[range] = [start, end];
2706
+ }
2707
+
2708
+ var list = '<ul>';
2709
+ for (range in this.ranges) {
2710
+ list += '<li>' + range + '</li>';
2711
+ }
2712
+ list += '<li>' + this.locale.customRangeLabel + '</li>';
2713
+ list += '</ul>';
2714
+ this.container.find('.ranges ul').remove();
2715
+ this.container.find('.ranges').prepend(list);
2716
+ }
2717
+
2718
+ if (typeof callback === 'function') {
2719
+ this.cb = callback;
2720
+ }
2721
+
2722
+ if (!this.timePicker) {
2723
+ this.startDate = this.startDate.startOf('day');
2724
+ this.endDate = this.endDate.endOf('day');
2725
+ }
2726
+
2727
+ if (this.singleDatePicker) {
2728
+ this.opens = 'right';
2729
+ this.container.find('.calendar.right').show();
2730
+ this.container.find('.calendar.left').hide();
2731
+ this.container.find('.ranges').hide();
2732
+ if (!this.container.find('.calendar.right').hasClass('single'))
2733
+ this.container.find('.calendar.right').addClass('single');
2734
+ } else {
2735
+ this.container.find('.calendar.right').removeClass('single');
2736
+ this.container.find('.ranges').show();
2737
+ }
2738
+
2739
+ this.oldStartDate = this.startDate.clone();
2740
+ this.oldEndDate = this.endDate.clone();
2741
+ this.oldChosenLabel = this.chosenLabel;
2742
+
2743
+ this.leftCalendar = {
2744
+ month: moment([this.startDate.year(), this.startDate.month(), 1, this.startDate.hour(), this.startDate.minute()]),
2745
+ calendar: []
2746
+ };
2747
+
2748
+ this.rightCalendar = {
2749
+ month: moment([this.endDate.year(), this.endDate.month(), 1, this.endDate.hour(), this.endDate.minute()]),
2750
+ calendar: []
2751
+ };
2752
+
2753
+ if (this.opens == 'right') {
2754
+ //swap calendar positions
2755
+ var left = this.container.find('.calendar.left');
2756
+ var right = this.container.find('.calendar.right');
2757
+ left.removeClass('left').addClass('right');
2758
+ right.removeClass('right').addClass('left');
2759
+ }
2760
+
2761
+ if (typeof options.ranges === 'undefined' && !this.singleDatePicker) {
2762
+ this.container.addClass('show-calendar');
2763
+ }
2764
+
2765
+ this.container.addClass('opens' + this.opens);
2766
+
2767
+ this.updateView();
2768
+ this.updateCalendars();
2769
+
2770
+ },
2771
+
2772
+ setStartDate: function(startDate) {
2773
+ if (typeof startDate === 'string')
2774
+ this.startDate = moment(startDate, this.format);
2775
+
2776
+ if (typeof startDate === 'object')
2777
+ this.startDate = moment(startDate);
2778
+
2779
+ if (!this.timePicker)
2780
+ this.startDate = this.startDate.startOf('day');
2781
+
2782
+ this.oldStartDate = this.startDate.clone();
2783
+
2784
+ this.updateView();
2785
+ this.updateCalendars();
2786
+ },
2787
+
2788
+ setEndDate: function(endDate) {
2789
+ if (typeof endDate === 'string')
2790
+ this.endDate = moment(endDate, this.format);
2791
+
2792
+ if (typeof endDate === 'object')
2793
+ this.endDate = moment(endDate);
2794
+
2795
+ if (!this.timePicker)
2796
+ this.endDate = this.endDate.endOf('day');
2797
+
2798
+ this.oldEndDate = this.endDate.clone();
2799
+
2800
+ this.updateView();
2801
+ this.updateCalendars();
2802
+ },
2803
+
2804
+ updateView: function () {
2805
+ this.leftCalendar.month.month(this.startDate.month()).year(this.startDate.year());
2806
+ this.rightCalendar.month.month(this.endDate.month()).year(this.endDate.year());
2807
+ this.updateFormInputs();
2808
+ },
2809
+
2810
+ updateFormInputs: function () {
2811
+ this.container.find('input[name=daterangepicker_start]').val(this.startDate.format(this.format));
2812
+ this.container.find('input[name=daterangepicker_end]').val(this.endDate.format(this.format));
2813
+
2814
+ if (this.startDate.isSame(this.endDate) || this.startDate.isBefore(this.endDate)) {
2815
+ this.container.find('button.applyBtn').removeAttr('disabled');
2816
+ } else {
2817
+ this.container.find('button.applyBtn').attr('disabled', 'disabled');
2818
+ }
2819
+ },
2820
+
2821
+ updateFromControl: function () {
2822
+ if (!this.element.is('input')) return;
2823
+ if (!this.element.val().length) return;
2824
+
2825
+ var dateString = this.element.val().split(this.separator);
2826
+ var start = moment(dateString[0], this.format);
2827
+ var end = moment(dateString[1], this.format);
2828
+
2829
+ if (this.singleDatePicker) {
2830
+ start = moment(this.element.val(), this.format);
2831
+ end = start;
2832
+ }
2833
+
2834
+ if (end.isBefore(start)) return;
2835
+
2836
+ this.oldStartDate = this.startDate.clone();
2837
+ this.oldEndDate = this.endDate.clone();
2838
+
2839
+ this.startDate = start;
2840
+ this.endDate = end;
2841
+
2842
+ if (!this.startDate.isSame(this.oldStartDate) || !this.endDate.isSame(this.oldEndDate))
2843
+ this.notify();
2844
+
2845
+ this.updateCalendars();
2846
+ },
2847
+
2848
+ notify: function () {
2849
+ this.updateView();
2850
+ this.cb(this.startDate, this.endDate, this.chosenLabel);
2851
+ },
2852
+
2853
+ move: function () {
2854
+ var parentOffset = { top: 0, left: 0 };
2855
+ if (!this.parentEl.is('body')) {
2856
+ parentOffset = {
2857
+ top: this.parentEl.offset().top - this.parentEl.scrollTop(),
2858
+ left: this.parentEl.offset().left - this.parentEl.scrollLeft()
2859
+ };
2860
+ }
2861
+
2862
+ if (this.opens == 'left') {
2863
+ this.container.css({
2864
+ top: this.element.offset().top + this.element.outerHeight() - parentOffset.top,
2865
+ right: $(window).width() - this.element.offset().left - this.element.outerWidth() - parentOffset.left,
2866
+ left: 'auto'
2867
+ });
2868
+ if (this.container.offset().left < 0) {
2869
+ this.container.css({
2870
+ right: 'auto',
2871
+ left: 9
2872
+ });
2873
+ }
2874
+ } else {
2875
+ this.container.css({
2876
+ top: this.element.offset().top + this.element.outerHeight() - parentOffset.top,
2877
+ left: this.element.offset().left - parentOffset.left,
2878
+ right: 'auto'
2879
+ });
2880
+ if (this.container.offset().left + this.container.outerWidth() > $(window).width()) {
2881
+ this.container.css({
2882
+ left: 'auto',
2883
+ right: 0
2884
+ });
2885
+ }
2886
+ }
2887
+ },
2888
+
2889
+ toggle: function (e) {
2890
+ if (this.element.hasClass('active')) {
2891
+ this.hide();
2892
+ } else {
2893
+ this.show();
2894
+ }
2895
+ },
2896
+
2897
+ show: function (e) {
2898
+ this.element.addClass('active');
2899
+ this.container.show();
2900
+ this.move();
2901
+
2902
+ $(document).on('click.daterangepicker', $.proxy(this.outsideClick, this));
2903
+ // also explicitly play nice with Bootstrap dropdowns, which stopPropagation when clicking them
2904
+ $(document).on('click.daterangepicker', '[data-toggle=dropdown]', $.proxy(this.outsideClick, this));
2905
+
2906
+ this.element.trigger('show.daterangepicker', this);
2907
+ },
2908
+
2909
+ outsideClick: function (e) {
2910
+ var target = $(e.target);
2911
+ // if the page is clicked anywhere except within the daterangerpicker/button
2912
+ // itself then call this.hide()
2913
+ if (
2914
+ target.closest(this.element).length ||
2915
+ target.closest(this.container).length ||
2916
+ target.closest('.calendar-date').length
2917
+ ) return;
2918
+ this.hide();
2919
+ },
2920
+
2921
+ hide: function (e) {
2922
+ this.element.removeClass('active');
2923
+ this.container.hide();
2924
+
2925
+ if (!this.startDate.isSame(this.oldStartDate) || !this.endDate.isSame(this.oldEndDate))
2926
+ this.notify();
2927
+
2928
+ this.oldStartDate = this.startDate.clone();
2929
+ this.oldEndDate = this.endDate.clone();
2930
+
2931
+ $(document).off('click.daterangepicker', this.outsideClick);
2932
+ this.element.trigger('hide.daterangepicker', this);
2933
+ },
2934
+
2935
+ enterRange: function (e) {
2936
+ // mouse pointer has entered a range label
2937
+ var label = e.target.innerHTML;
2938
+ if (label == this.locale.customRangeLabel) {
2939
+ this.updateView();
2940
+ } else {
2941
+ var dates = this.ranges[label];
2942
+ this.container.find('input[name=daterangepicker_start]').val(dates[0].format(this.format));
2943
+ this.container.find('input[name=daterangepicker_end]').val(dates[1].format(this.format));
2944
+ }
2945
+ },
2946
+
2947
+ showCalendars: function() {
2948
+ this.container.addClass('show-calendar');
2949
+ this.move();
2950
+ },
2951
+
2952
+ hideCalendars: function() {
2953
+ this.container.removeClass('show-calendar');
2954
+ },
2955
+
2956
+ updateInputText: function() {
2957
+ if (this.element.is('input') && !this.singleDatePicker) {
2958
+ this.element.val(this.startDate.format(this.format) + this.separator + this.endDate.format(this.format));
2959
+ } else if (this.element.is('input')) {
2960
+ this.element.val(this.startDate.format(this.format));
2961
+ }
2962
+ },
2963
+
2964
+ clickRange: function (e) {
2965
+ var label = e.target.innerHTML;
2966
+ this.chosenLabel = label;
2967
+ if (label == this.locale.customRangeLabel) {
2968
+ this.showCalendars();
2969
+ } else {
2970
+ var dates = this.ranges[label];
2971
+
2972
+ this.startDate = dates[0];
2973
+ this.endDate = dates[1];
2974
+
2975
+ if (!this.timePicker) {
2976
+ this.startDate.startOf('day');
2977
+ this.endDate.endOf('day');
2978
+ }
2979
+
2980
+ this.leftCalendar.month.month(this.startDate.month()).year(this.startDate.year()).hour(this.startDate.hour()).minute(this.startDate.minute());
2981
+ this.rightCalendar.month.month(this.endDate.month()).year(this.endDate.year()).hour(this.endDate.hour()).minute(this.endDate.minute());
2982
+ this.updateCalendars();
2983
+
2984
+ this.updateInputText();
2985
+
2986
+ this.hideCalendars();
2987
+ this.hide();
2988
+ this.element.trigger('apply.daterangepicker', this);
2989
+ }
2990
+ },
2991
+
2992
+ clickPrev: function (e) {
2993
+ var cal = $(e.target).parents('.calendar');
2994
+ if (cal.hasClass('left')) {
2995
+ this.leftCalendar.month.subtract('month', 1);
2996
+ } else {
2997
+ this.rightCalendar.month.subtract('month', 1);
2998
+ }
2999
+ this.updateCalendars();
3000
+ },
3001
+
3002
+ clickNext: function (e) {
3003
+ var cal = $(e.target).parents('.calendar');
3004
+ if (cal.hasClass('left')) {
3005
+ this.leftCalendar.month.add('month', 1);
3006
+ } else {
3007
+ this.rightCalendar.month.add('month', 1);
3008
+ }
3009
+ this.updateCalendars();
3010
+ },
3011
+
3012
+ enterDate: function (e) {
3013
+
3014
+ var title = $(e.target).attr('data-title');
3015
+ var row = title.substr(1, 1);
3016
+ var col = title.substr(3, 1);
3017
+ var cal = $(e.target).parents('.calendar');
3018
+
3019
+ if (cal.hasClass('left')) {
3020
+ this.container.find('input[name=daterangepicker_start]').val(this.leftCalendar.calendar[row][col].format(this.format));
3021
+ } else {
3022
+ this.container.find('input[name=daterangepicker_end]').val(this.rightCalendar.calendar[row][col].format(this.format));
3023
+ }
3024
+
3025
+ },
3026
+
3027
+ clickDate: function (e) {
3028
+ var title = $(e.target).attr('data-title');
3029
+ var row = title.substr(1, 1);
3030
+ var col = title.substr(3, 1);
3031
+ var cal = $(e.target).parents('.calendar');
3032
+
3033
+ var startDate, endDate;
3034
+ if (cal.hasClass('left')) {
3035
+ startDate = this.leftCalendar.calendar[row][col];
3036
+ endDate = this.endDate;
3037
+ if (typeof this.dateLimit === 'object') {
3038
+ var maxDate = moment(startDate).add(this.dateLimit).startOf('day');
3039
+ if (endDate.isAfter(maxDate)) {
3040
+ endDate = maxDate;
3041
+ }
3042
+ }
3043
+ } else {
3044
+ startDate = this.startDate;
3045
+ endDate = this.rightCalendar.calendar[row][col];
3046
+ if (typeof this.dateLimit === 'object') {
3047
+ var minDate = moment(endDate).subtract(this.dateLimit).startOf('day');
3048
+ if (startDate.isBefore(minDate)) {
3049
+ startDate = minDate;
3050
+ }
3051
+ }
3052
+ }
3053
+
3054
+ if (this.singleDatePicker && cal.hasClass('left')) {
3055
+ endDate = startDate.clone();
3056
+ } else if (this.singleDatePicker && cal.hasClass('right')) {
3057
+ startDate = endDate.clone();
3058
+ }
3059
+
3060
+ cal.find('td').removeClass('active');
3061
+
3062
+ if (startDate.isSame(endDate) || startDate.isBefore(endDate)) {
3063
+ $(e.target).addClass('active');
3064
+ this.startDate = startDate;
3065
+ this.endDate = endDate;
3066
+ this.chosenLabel = this.locale.customRangeLabel;
3067
+ } else if (startDate.isAfter(endDate)) {
3068
+ $(e.target).addClass('active');
3069
+ var difference = this.endDate.diff(this.startDate);
3070
+ this.startDate = startDate;
3071
+ this.endDate = moment(startDate).add('ms', difference);
3072
+ this.chosenLabel = this.locale.customRangeLabel;
3073
+ }
3074
+
3075
+ this.leftCalendar.month.month(this.startDate.month()).year(this.startDate.year());
3076
+ this.rightCalendar.month.month(this.endDate.month()).year(this.endDate.year());
3077
+ this.updateCalendars();
3078
+
3079
+ endDate.endOf('day');
3080
+
3081
+ if (this.singleDatePicker)
3082
+ this.clickApply();
3083
+ },
3084
+
3085
+ clickApply: function (e) {
3086
+ this.updateInputText();
3087
+ this.hide();
3088
+ this.element.trigger('apply.daterangepicker', this);
3089
+ },
3090
+
3091
+ clickCancel: function (e) {
3092
+ this.startDate = this.oldStartDate;
3093
+ this.endDate = this.oldEndDate;
3094
+ this.chosenLabel = this.oldChosenLabel;
3095
+ this.updateView();
3096
+ this.updateCalendars();
3097
+ this.hide();
3098
+ this.element.trigger('cancel.daterangepicker', this);
3099
+ },
3100
+
3101
+ updateMonthYear: function (e) {
3102
+ var isLeft = $(e.target).closest('.calendar').hasClass('left'),
3103
+ leftOrRight = isLeft ? 'left' : 'right',
3104
+ cal = this.container.find('.calendar.'+leftOrRight);
3105
+
3106
+ // Month must be Number for new moment versions
3107
+ var month = parseInt(cal.find('.monthselect').val(), 10);
3108
+ var year = cal.find('.yearselect').val();
3109
+
3110
+ this[leftOrRight+'Calendar'].month.month(month).year(year);
3111
+ this.updateCalendars();
3112
+ },
3113
+
3114
+ updateTime: function(e) {
3115
+ var isLeft = $(e.target).closest('.calendar').hasClass('left'),
3116
+ leftOrRight = isLeft ? 'left' : 'right',
3117
+ cal = this.container.find('.calendar.'+leftOrRight);
3118
+
3119
+ var hour = parseInt(cal.find('.hourselect').val(), 10);
3120
+ var minute = parseInt(cal.find('.minuteselect').val(), 10);
3121
+
3122
+ if (this.timePicker12Hour) {
3123
+ var ampm = cal.find('.ampmselect').val();
3124
+ if (ampm === 'PM' && hour < 12)
3125
+ hour += 12;
3126
+ if (ampm === 'AM' && hour === 12)
3127
+ hour = 0;
3128
+ }
3129
+
3130
+ if (isLeft) {
3131
+ var start = this.startDate.clone();
3132
+ start.hour(hour);
3133
+ start.minute(minute);
3134
+ this.startDate = start;
3135
+ this.leftCalendar.month.hour(hour).minute(minute);
3136
+ } else {
3137
+ var end = this.endDate.clone();
3138
+ end.hour(hour);
3139
+ end.minute(minute);
3140
+ this.endDate = end;
3141
+ this.rightCalendar.month.hour(hour).minute(minute);
3142
+ }
3143
+
3144
+ this.updateCalendars();
3145
+ },
3146
+
3147
+ updateCalendars: function () {
3148
+ this.leftCalendar.calendar = this.buildCalendar(this.leftCalendar.month.month(), this.leftCalendar.month.year(), this.leftCalendar.month.hour(), this.leftCalendar.month.minute(), 'left');
3149
+ this.rightCalendar.calendar = this.buildCalendar(this.rightCalendar.month.month(), this.rightCalendar.month.year(), this.rightCalendar.month.hour(), this.rightCalendar.month.minute(), 'right');
3150
+ this.container.find('.calendar.left').html(this.renderCalendar(this.leftCalendar.calendar, this.startDate, this.minDate, this.maxDate));
3151
+ this.container.find('.calendar.right').html(this.renderCalendar(this.rightCalendar.calendar, this.endDate, this.startDate, this.maxDate));
3152
+
3153
+ this.container.find('.ranges li').removeClass('active');
3154
+ var customRange = true;
3155
+ var i = 0;
3156
+ for (var range in this.ranges) {
3157
+ if (this.timePicker) {
3158
+ if (this.startDate.isSame(this.ranges[range][0]) && this.endDate.isSame(this.ranges[range][1])) {
3159
+ customRange = false;
3160
+ this.container.find('.ranges li:eq(' + i + ')').addClass('active');
3161
+ }
3162
+ } else {
3163
+ //ignore times when comparing dates if time picker is not enabled
3164
+ if (this.startDate.format('YYYY-MM-DD') == this.ranges[range][0].format('YYYY-MM-DD') && this.endDate.format('YYYY-MM-DD') == this.ranges[range][1].format('YYYY-MM-DD')) {
3165
+ customRange = false;
3166
+ this.container.find('.ranges li:eq(' + i + ')').addClass('active');
3167
+ }
3168
+ }
3169
+ i++;
3170
+ }
3171
+ if (customRange)
3172
+ this.container.find('.ranges li:last').addClass('active');
3173
+ },
3174
+
3175
+ buildCalendar: function (month, year, hour, minute, side) {
3176
+ var firstDay = moment([year, month, 1]);
3177
+ var lastMonth = moment(firstDay).subtract('month', 1).month();
3178
+ var lastYear = moment(firstDay).subtract('month', 1).year();
3179
+
3180
+ var daysInLastMonth = moment([lastYear, lastMonth]).daysInMonth();
3181
+
3182
+ var dayOfWeek = firstDay.day();
3183
+
3184
+ var i;
3185
+
3186
+ //initialize a 6 rows x 7 columns array for the calendar
3187
+ var calendar = [];
3188
+ for (i = 0; i < 6; i++) {
3189
+ calendar[i] = [];
3190
+ }
3191
+
3192
+ //populate the calendar with date objects
3193
+ var startDay = daysInLastMonth - dayOfWeek + this.locale.firstDay + 1;
3194
+ if (startDay > daysInLastMonth)
3195
+ startDay -= 7;
3196
+
3197
+ if (dayOfWeek == this.locale.firstDay)
3198
+ startDay = daysInLastMonth - 6;
3199
+
3200
+ var curDate = moment([lastYear, lastMonth, startDay, 12, minute]);
3201
+ var col, row;
3202
+ for (i = 0, col = 0, row = 0; i < 42; i++, col++, curDate = moment(curDate).add('hour', 24)) {
3203
+ if (i > 0 && col % 7 === 0) {
3204
+ col = 0;
3205
+ row++;
3206
+ }
3207
+ calendar[row][col] = curDate.clone().hour(hour);
3208
+ curDate.hour(12);
3209
+ }
3210
+
3211
+ return calendar;
3212
+ },
3213
+
3214
+ renderDropdowns: function (selected, minDate, maxDate) {
3215
+ var currentMonth = selected.month();
3216
+ var monthHtml = '<select class="monthselect">';
3217
+ var inMinYear = false;
3218
+ var inMaxYear = false;
3219
+
3220
+ for (var m = 0; m < 12; m++) {
3221
+ if ((!inMinYear || m >= minDate.month()) && (!inMaxYear || m <= maxDate.month())) {
3222
+ monthHtml += "<option value='" + m + "'" +
3223
+ (m === currentMonth ? " selected='selected'" : "") +
3224
+ ">" + this.locale.monthNames[m] + "</option>";
3225
+ }
3226
+ }
3227
+ monthHtml += "</select>";
3228
+
3229
+ var currentYear = selected.year();
3230
+ var maxYear = (maxDate && maxDate.year()) || (currentYear + 5);
3231
+ var minYear = (minDate && minDate.year()) || (currentYear - 50);
3232
+ var yearHtml = '<select class="yearselect">';
3233
+
3234
+ for (var y = minYear; y <= maxYear; y++) {
3235
+ yearHtml += '<option value="' + y + '"' +
3236
+ (y === currentYear ? ' selected="selected"' : '') +
3237
+ '>' + y + '</option>';
3238
+ }
3239
+
3240
+ yearHtml += '</select>';
3241
+
3242
+ return monthHtml + yearHtml;
3243
+ },
3244
+
3245
+ renderCalendar: function (calendar, selected, minDate, maxDate) {
3246
+
3247
+ var html = '<div class="calendar-date">';
3248
+ html += '<table class="table-condensed">';
3249
+ html += '<thead>';
3250
+ html += '<tr>';
3251
+
3252
+ // add empty cell for week number
3253
+ if (this.showWeekNumbers)
3254
+ html += '<th></th>';
3255
+
3256
+ if (!minDate || minDate.isBefore(calendar[1][1])) {
3257
+ html += '<th class="prev available"><i class="fa fa-arrow-left icon-arrow-left glyphicon glyphicon-arrow-left"></i></th>';
3258
+ } else {
3259
+ html += '<th></th>';
3260
+ }
3261
+
3262
+ var dateHtml = this.locale.monthNames[calendar[1][1].month()] + calendar[1][1].format(" YYYY");
3263
+
3264
+ if (this.showDropdowns) {
3265
+ dateHtml = this.renderDropdowns(calendar[1][1], minDate, maxDate);
3266
+ }
3267
+
3268
+ html += '<th colspan="5" class="month">' + dateHtml + '</th>';
3269
+ if (!maxDate || maxDate.isAfter(calendar[1][1])) {
3270
+ html += '<th class="next available"><i class="fa fa-arrow-right icon-arrow-right glyphicon glyphicon-arrow-right"></i></th>';
3271
+ } else {
3272
+ html += '<th></th>';
3273
+ }
3274
+
3275
+ html += '</tr>';
3276
+ html += '<tr>';
3277
+
3278
+ // add week number label
3279
+ if (this.showWeekNumbers)
3280
+ html += '<th class="week">' + this.locale.weekLabel + '</th>';
3281
+
3282
+ $.each(this.locale.daysOfWeek, function (index, dayOfWeek) {
3283
+ html += '<th>' + dayOfWeek + '</th>';
3284
+ });
3285
+
3286
+ html += '</tr>';
3287
+ html += '</thead>';
3288
+ html += '<tbody>';
3289
+
3290
+ for (var row = 0; row < 6; row++) {
3291
+ html += '<tr>';
3292
+
3293
+ // add week number
3294
+ if (this.showWeekNumbers)
3295
+ html += '<td class="week">' + calendar[row][0].week() + '</td>';
3296
+
3297
+ for (var col = 0; col < 7; col++) {
3298
+ var cname = 'available ';
3299
+ cname += (calendar[row][col].month() == calendar[1][1].month()) ? '' : 'off';
3300
+
3301
+ if ((minDate && calendar[row][col].isBefore(minDate)) || (maxDate && calendar[row][col].isAfter(maxDate))) {
3302
+ cname = ' off disabled ';
3303
+ } else if (calendar[row][col].format('YYYY-MM-DD') == selected.format('YYYY-MM-DD')) {
3304
+ cname += ' active ';
3305
+ if (calendar[row][col].format('YYYY-MM-DD') == this.startDate.format('YYYY-MM-DD')) {
3306
+ cname += ' start-date ';
3307
+ }
3308
+ if (calendar[row][col].format('YYYY-MM-DD') == this.endDate.format('YYYY-MM-DD')) {
3309
+ cname += ' end-date ';
3310
+ }
3311
+ } else if (calendar[row][col] >= this.startDate && calendar[row][col] <= this.endDate) {
3312
+ cname += ' in-range ';
3313
+ if (calendar[row][col].isSame(this.startDate)) { cname += ' start-date '; }
3314
+ if (calendar[row][col].isSame(this.endDate)) { cname += ' end-date '; }
3315
+ }
3316
+
3317
+ var title = 'r' + row + 'c' + col;
3318
+ html += '<td class="' + cname.replace(/\s+/g, ' ').replace(/^\s?(.*?)\s?$/, '$1') + '" data-title="' + title + '">' + calendar[row][col].date() + '</td>';
3319
+ }
3320
+ html += '</tr>';
3321
+ }
3322
+
3323
+ html += '</tbody>';
3324
+ html += '</table>';
3325
+ html += '</div>';
3326
+
3327
+ var i;
3328
+ if (this.timePicker) {
3329
+
3330
+ html += '<div class="calendar-time">';
3331
+ html += '<select class="hourselect">';
3332
+ var start = 0;
3333
+ var end = 23;
3334
+ var selected_hour = selected.hour();
3335
+ if (this.timePicker12Hour) {
3336
+ start = 1;
3337
+ end = 12;
3338
+ if (selected_hour >= 12)
3339
+ selected_hour -= 12;
3340
+ if (selected_hour === 0)
3341
+ selected_hour = 12;
3342
+ }
3343
+
3344
+ for (i = start; i <= end; i++) {
3345
+ if (i == selected_hour) {
3346
+ html += '<option value="' + i + '" selected="selected">' + i + '</option>';
3347
+ } else {
3348
+ html += '<option value="' + i + '">' + i + '</option>';
3349
+ }
3350
+ }
3351
+
3352
+ html += '</select> : ';
3353
+
3354
+ html += '<select class="minuteselect">';
3355
+
3356
+ for (i = 0; i < 60; i += this.timePickerIncrement) {
3357
+ var num = i;
3358
+ if (num < 10)
3359
+ num = '0' + num;
3360
+ if (i == selected.minute()) {
3361
+ html += '<option value="' + i + '" selected="selected">' + num + '</option>';
3362
+ } else {
3363
+ html += '<option value="' + i + '">' + num + '</option>';
3364
+ }
3365
+ }
3366
+
3367
+ html += '</select> ';
3368
+
3369
+ if (this.timePicker12Hour) {
3370
+ html += '<select class="ampmselect">';
3371
+ if (selected.hour() >= 12) {
3372
+ html += '<option value="AM">AM</option><option value="PM" selected="selected">PM</option>';
3373
+ } else {
3374
+ html += '<option value="AM" selected="selected">AM</option><option value="PM">PM</option>';
3375
+ }
3376
+ html += '</select>';
3377
+ }
3378
+
3379
+ html += '</div>';
3380
+
3381
+ }
3382
+
3383
+ return html;
3384
+
3385
+ },
3386
+
3387
+ remove: function() {
3388
+
3389
+ this.container.remove();
3390
+ this.element.off('.daterangepicker');
3391
+ this.element.removeData('daterangepicker');
3392
+
3393
+ }
3394
+
3395
+ };
3396
+
3397
+ $.fn.daterangepicker = function (options, cb) {
3398
+ this.each(function () {
3399
+ var el = $(this);
3400
+ if (el.data('daterangepicker'))
3401
+ el.data('daterangepicker').remove();
3402
+ el.data('daterangepicker', new DateRangePicker(el, options, cb));
3403
+ });
3404
+ return this;
3405
+ };
3406
+
3407
+ }(window.jQuery, window.moment);