History

ModbusAdapters: Fixed security issues in Modbus configuration screen GSF.Web: Cleaned up new embedded resources

J. Ritchie Carroll committed 9 years ago

Commit 970956d1 parent 230686d36 files · +72369 −1648Browse files

Showing the changes to Source/Libraries/GSF.Web/Model/Scripts (3 of 36 files). Show all

Unified · Split

3 files
  1. Source/Libraries/GSF.Web/Model/Scripts/ObsoleteFiles.txt +10 −0
  2. Source/Libraries/GSF.Web/Model/Scripts/bootstrap-datepicker.js +1918 −0
  3. Source/Libraries/GSF.Web/Model/Scripts/bootstrap-toolkit.js +234 −0
Source/Libraries/GSF.Web/Model/Scripts/ObsoleteFiles.txt+10−0
@@ -0,0 +1,10 @@
1!WARNING: The location for the following resources have been moved!
2 New resource path is "/@GSF/Web/Shared/Scripts/", please update scripts to use these new locations:
3
4 /@GSF/Web/Model/Scripts/angular1.5.8.js => /@GSF/Web/Shared/Scripts/angular.js
5 /@GSF/Web/Model/Scripts/gsf.web.client.js => /@GSF/Web/Shared/Scripts/gsf.web.client.js
6 /@GSF/Web/Model/Scripts/gsf.web.knockout.js => /@GSF/Web/Shared/Scripts/gsf.web.knockout.js
7 /@GSF/Web/Model/Scripts/gsf.web.primeui.js => /@GSF/Web/Shared/Scripts/gsf.web.primeui.js
8 /@GSF/Web/Model/Scripts/js.cookie.js => /@GSF/Web/Shared/Scripts/js.cookie.js
9 /@GSF/Web/Model/Scripts/ko.reactor.js => /@GSF/Web/Shared/Scripts/knockout.reactor.js
10/@GSF/Web/Model/Scripts/ko.observableDictionary.js => /@GSF/Web/Shared/Scripts/knockout.obeservableDictionary.js
Source/Libraries/GSF.Web/Model/Scripts/bootstrap-datepicker.js+1918−0
@@ -0,0 +1,1918 @@
1/*!
2 * Datepicker for Bootstrap v1.5.1 (https://github.com/eternicode/bootstrap-datepicker)
3 *
4 * Copyright 2012 Stefan Petre
5 * Improvements by Andrew Rowls
6 * Licensed under the Apache License v2.0 (http://www.apache.org/licenses/LICENSE-2.0)
7 */(function(factory){
8 if (typeof define === "function" && define.amd) {
9 define(["jquery"], factory);
10 } else if (typeof exports === 'object') {
11 factory(require('jquery'));
12 } else {
13 factory(jQuery);
14 }
15}(function($, undefined){
16
17 function UTCDate(){
18 return new Date(Date.UTC.apply(Date, arguments));
19 }
20 function UTCToday(){
21 var today = new Date();
22 return UTCDate(today.getFullYear(), today.getMonth(), today.getDate());
23 }
24 function isUTCEquals(date1, date2) {
25 return (
26 date1.getUTCFullYear() === date2.getUTCFullYear() &&
27 date1.getUTCMonth() === date2.getUTCMonth() &&
28 date1.getUTCDate() === date2.getUTCDate()
29 );
30 }
31 function alias(method){
32 return function(){
33 return this[method].apply(this, arguments);
34 };
35 }
36 function isValidDate(d) {
37 return d && !isNaN(d.getTime());
38 }
39
40 var DateArray = (function(){
41 var extras = {
42 get: function(i){
43 return this.slice(i)[0];
44 },
45 contains: function(d){
46 // Array.indexOf is not cross-browser;
47 // $.inArray doesn't work with Dates
48 var val = d && d.valueOf();
49 for (var i=0, l=this.length; i < l; i++)
50 if (this[i].valueOf() === val)
51 return i;
52 return -1;
53 },
54 remove: function(i){
55 this.splice(i,1);
56 },
57 replace: function(new_array){
58 if (!new_array)
59 return;
60 if (!$.isArray(new_array))
61 new_array = [new_array];
62 this.clear();
63 this.push.apply(this, new_array);
64 },
65 clear: function(){
66 this.length = 0;
67 },
68 copy: function(){
69 var a = new DateArray();
70 a.replace(this);
71 return a;
72 }
73 };
74
75 return function(){
76 var a = [];
77 a.push.apply(a, arguments);
78 $.extend(a, extras);
79 return a;
80 };
81 })();
82
83
84 // Picker object
85
86 var Datepicker = function(element, options){
87 $(element).data('datepicker', this);
88 this._process_options(options);
89
90 this.dates = new DateArray();
91 this.viewDate = this.o.defaultViewDate;
92 this.focusDate = null;
93
94 this.element = $(element);
95 this.isInline = false;
96 this.isInput = this.element.is('input');
97 this.component = this.element.hasClass('date') ? this.element.find('.add-on, .input-group-addon, .btn') : false;
98 this.hasInput = this.component && this.element.find('input').length;
99 if (this.component && this.component.length === 0)
100 this.component = false;
101
102 this.picker = $(DPGlobal.template);
103 this._buildEvents();
104 this._attachEvents();
105
106 if (this.isInline){
107 this.picker.addClass('datepicker-inline').appendTo(this.element);
108 }
109 else {
110 this.picker.addClass('datepicker-dropdown dropdown-menu');
111 }
112
113 if (this.o.rtl){
114 this.picker.addClass('datepicker-rtl');
115 }
116
117 this.viewMode = this.o.startView;
118
119 if (this.o.calendarWeeks)
120 this.picker.find('thead .datepicker-title, tfoot .today, tfoot .clear')
121 .attr('colspan', function(i, val){
122 return parseInt(val) + 1;
123 });
124
125 this._allow_update = false;
126
127 this.setStartDate(this._o.startDate);
128 this.setEndDate(this._o.endDate);
129 this.setDaysOfWeekDisabled(this.o.daysOfWeekDisabled);
130 this.setDaysOfWeekHighlighted(this.o.daysOfWeekHighlighted);
131 this.setDatesDisabled(this.o.datesDisabled);
132
133 this.fillDow();
134 this.fillMonths();
135
136 this._allow_update = true;
137
138 this.update();
139 this.showMode();
140
141 if (this.isInline){
142 this.show();
143 }
144 };
145
146 Datepicker.prototype = {
147 constructor: Datepicker,
148
149 _process_options: function(opts){
150 // Store raw options for reference
151 this._o = $.extend({}, this._o, opts);
152 // Processed options
153 var o = this.o = $.extend({}, this._o);
154
155 // Check if "de-DE" style date is available, if not language should
156 // fallback to 2 letter code eg "de"
157 var lang = o.language;
158 if (!dates[lang]){
159 lang = lang.split('-')[0];
160 if (!dates[lang])
161 lang = defaults.language;
162 }
163 o.language = lang;
164
165 switch (o.startView){
166 case 2:
167 case 'decade':
168 o.startView = 2;
169 break;
170 case 1:
171 case 'year':
172 o.startView = 1;
173 break;
174 default:
175 o.startView = 0;
176 }
177
178 switch (o.minViewMode){
179 case 1:
180 case 'months':
181 o.minViewMode = 1;
182 break;
183 case 2:
184 case 'years':
185 o.minViewMode = 2;
186 break;
187 default:
188 o.minViewMode = 0;
189 }
190
191 switch (o.maxViewMode) {
192 case 0:
193 case 'days':
194 o.maxViewMode = 0;
195 break;
196 case 1:
197 case 'months':
198 o.maxViewMode = 1;
199 break;
200 default:
201 o.maxViewMode = 2;
202 }
203
204 o.startView = Math.min(o.startView, o.maxViewMode);
205 o.startView = Math.max(o.startView, o.minViewMode);
206
207 // true, false, or Number > 0
208 if (o.multidate !== true){
209 o.multidate = Number(o.multidate) || false;
210 if (o.multidate !== false)
211 o.multidate = Math.max(0, o.multidate);
212 }
213 o.multidateSeparator = String(o.multidateSeparator);
214
215 o.weekStart %= 7;
216 o.weekEnd = (o.weekStart + 6) % 7;
217
218 var format = DPGlobal.parseFormat(o.format);
219 if (o.startDate !== -Infinity){
220 if (!!o.startDate){
221 if (o.startDate instanceof Date)
222 o.startDate = this._local_to_utc(this._zero_time(o.startDate));
223 else
224 o.startDate = DPGlobal.parseDate(o.startDate, format, o.language);
225 }
226 else {
227 o.startDate = -Infinity;
228 }
229 }
230 if (o.endDate !== Infinity){
231 if (!!o.endDate){
232 if (o.endDate instanceof Date)
233 o.endDate = this._local_to_utc(this._zero_time(o.endDate));
234 else
235 o.endDate = DPGlobal.parseDate(o.endDate, format, o.language);
236 }
237 else {
238 o.endDate = Infinity;
239 }
240 }
241
242 o.daysOfWeekDisabled = o.daysOfWeekDisabled||[];
243 if (!$.isArray(o.daysOfWeekDisabled))
244 o.daysOfWeekDisabled = o.daysOfWeekDisabled.split(/[,\s]*/);
245 o.daysOfWeekDisabled = $.map(o.daysOfWeekDisabled, function(d){
246 return parseInt(d, 10);
247 });
248
249 o.daysOfWeekHighlighted = o.daysOfWeekHighlighted||[];
250 if (!$.isArray(o.daysOfWeekHighlighted))
251 o.daysOfWeekHighlighted = o.daysOfWeekHighlighted.split(/[,\s]*/);
252 o.daysOfWeekHighlighted = $.map(o.daysOfWeekHighlighted, function(d){
253 return parseInt(d, 10);
254 });
255
256 o.datesDisabled = o.datesDisabled||[];
257 if (!$.isArray(o.datesDisabled)) {
258 var datesDisabled = [];
259 datesDisabled.push(DPGlobal.parseDate(o.datesDisabled, format, o.language));
260 o.datesDisabled = datesDisabled;
261 }
262 o.datesDisabled = $.map(o.datesDisabled,function(d){
263 return DPGlobal.parseDate(d, format, o.language);
264 });
265
266 var plc = String(o.orientation).toLowerCase().split(/\s+/g),
267 _plc = o.orientation.toLowerCase();
268 plc = $.grep(plc, function(word){
269 return /^auto|left|right|top|bottom$/.test(word);
270 });
271 o.orientation = {x: 'auto', y: 'auto'};
272 if (!_plc || _plc === 'auto')
273 ; // no action
274 else if (plc.length === 1){
275 switch (plc[0]){
276 case 'top':
277 case 'bottom':
278 o.orientation.y = plc[0];
279 break;
280 case 'left':
281 case 'right':
282 o.orientation.x = plc[0];
283 break;
284 }
285 }
286 else {
287 _plc = $.grep(plc, function(word){
288 return /^left|right$/.test(word);
289 });
290 o.orientation.x = _plc[0] || 'auto';
291
292 _plc = $.grep(plc, function(word){
293 return /^top|bottom$/.test(word);
294 });
295 o.orientation.y = _plc[0] || 'auto';
296 }
297 if (o.defaultViewDate) {
298 var year = o.defaultViewDate.year || new Date().getFullYear();
299 var month = o.defaultViewDate.month || 0;
300 var day = o.defaultViewDate.day || 1;
301 o.defaultViewDate = UTCDate(year, month, day);
302 } else {
303 o.defaultViewDate = UTCToday();
304 }
305 },
306 _events: [],
307 _secondaryEvents: [],
308 _applyEvents: function(evs){
309 for (var i=0, el, ch, ev; i < evs.length; i++){
310 el = evs[i][0];
311 if (evs[i].length === 2){
312 ch = undefined;
313 ev = evs[i][1];
314 }
315 else if (evs[i].length === 3){
316 ch = evs[i][1];
317 ev = evs[i][2];
318 }
319 el.on(ev, ch);
320 }
321 },
322 _unapplyEvents: function(evs){
323 for (var i=0, el, ev, ch; i < evs.length; i++){
324 el = evs[i][0];
325 if (evs[i].length === 2){
326 ch = undefined;
327 ev = evs[i][1];
328 }
329 else if (evs[i].length === 3){
330 ch = evs[i][1];
331 ev = evs[i][2];
332 }
333 el.off(ev, ch);
334 }
335 },
336 _buildEvents: function(){
337 var events = {
338 keyup: $.proxy(function(e){
339 if ($.inArray(e.keyCode, [27, 37, 39, 38, 40, 32, 13, 9]) === -1)
340 this.update();
341 }, this),
342 keydown: $.proxy(this.keydown, this),
343 paste: $.proxy(this.paste, this)
344 };
345
346 if (this.o.showOnFocus === true) {
347 events.focus = $.proxy(this.show, this);
348 }
349
350 if (this.isInput) { // single input
351 this._events = [
352 [this.element, events]
353 ];
354 }
355 else if (this.component && this.hasInput) { // component: input + button
356 this._events = [
357 // For components that are not readonly, allow keyboard nav
358 [this.element.find('input'), events],
359 [this.component, {
360 click: $.proxy(this.show, this)
361 }]
362 ];
363 }
364 else if (this.element.is('div')){ // inline datepicker
365 this.isInline = true;
366 }
367 else {
368 this._events = [
369 [this.element, {
370 click: $.proxy(this.show, this)
371 }]
372 ];
373 }
374 this._events.push(
375 // Component: listen for blur on element descendants
376 [this.element, '*', {
377 blur: $.proxy(function(e){
378 this._focused_from = e.target;
379 }, this)
380 }],
381 // Input: listen for blur on element
382 [this.element, {
383 blur: $.proxy(function(e){
384 this._focused_from = e.target;
385 }, this)
386 }]
387 );
388
389 if (this.o.immediateUpdates) {
390 // Trigger input updates immediately on changed year/month
391 this._events.push([this.element, {
392 'changeYear changeMonth': $.proxy(function(e){
393 this.update(e.date);
394 }, this)
395 }]);
396 }
397
398 this._secondaryEvents = [
399 [this.picker, {
400 click: $.proxy(this.click, this)
401 }],
402 [$(window), {
403 resize: $.proxy(this.place, this)
404 }],
405 [$(document), {
406 mousedown: $.proxy(function(e){
407 // Clicked outside the datepicker, hide it
408 if (!(
409 this.element.is(e.target) ||
410 this.element.find(e.target).length ||
411 this.picker.is(e.target) ||
412 this.picker.find(e.target).length ||
413 this.picker.hasClass('datepicker-inline')
414 )){
415 this.hide();
416 }
417 }, this)
418 }]
419 ];
420 },
421 _attachEvents: function(){
422 this._detachEvents();
423 this._applyEvents(this._events);
424 },
425 _detachEvents: function(){
426 this._unapplyEvents(this._events);
427 },
428 _attachSecondaryEvents: function(){
429 this._detachSecondaryEvents();
430 this._applyEvents(this._secondaryEvents);
431 },
432 _detachSecondaryEvents: function(){
433 this._unapplyEvents(this._secondaryEvents);
434 },
435 _trigger: function(event, altdate){
436 var date = altdate || this.dates.get(-1),
437 local_date = this._utc_to_local(date);
438
439 this.element.trigger({
440 type: event,
441 date: local_date,
442 dates: $.map(this.dates, this._utc_to_local),
443 format: $.proxy(function(ix, format){
444 if (arguments.length === 0){
445 ix = this.dates.length - 1;
446 format = this.o.format;
447 }
448 else if (typeof ix === 'string'){
449 format = ix;
450 ix = this.dates.length - 1;
451 }
452 format = format || this.o.format;
453 var date = this.dates.get(ix);
454 return DPGlobal.formatDate(date, format, this.o.language);
455 }, this)
456 });
457 },
458
459 show: function(){
460 var element = this.component ? this.element.find('input') : this.element;
461 if (element.attr('readonly') && this.o.enableOnReadonly === false)
462 return;
463 if (!this.isInline)
464 this.picker.appendTo(this.o.container);
465 this.place();
466 this.picker.show();
467 this._attachSecondaryEvents();
468 this._trigger('show');
469 if ((window.navigator.msMaxTouchPoints || 'ontouchstart' in document) && this.o.disableTouchKeyboard) {
470 $(this.element).blur();
471 }
472 return this;
473 },
474
475 hide: function(){
476 if (this.isInline)
477 return this;
478 if (!this.picker.is(':visible'))
479 return this;
480 this.focusDate = null;
481 this.picker.hide().detach();
482 this._detachSecondaryEvents();
483 this.viewMode = this.o.startView;
484 this.showMode();
485
486 if (
487 this.o.forceParse &&
488 (
489 this.isInput && this.element.val() ||
490 this.hasInput && this.element.find('input').val()
491 )
492 )
493 this.setValue();
494 this._trigger('hide');
495 return this;
496 },
497
498 remove: function(){
499 this.hide();
500 this._detachEvents();
501 this._detachSecondaryEvents();
502 this.picker.remove();
503 delete this.element.data().datepicker;
504 if (!this.isInput){
505 delete this.element.data().date;
506 }
507 return this;
508 },
509
510 paste: function(evt){
511 var dateString;
512 if (evt.originalEvent.clipboardData && evt.originalEvent.clipboardData.types
513 && $.inArray('text/plain', evt.originalEvent.clipboardData.types) !== -1) {
514 dateString = evt.originalEvent.clipboardData.getData('text/plain');
515 }
516 else if (window.clipboardData) {
517 dateString = window.clipboardData.getData('Text');
518 }
519 else {
520 return;
521 }
522 this.setDate(dateString);
523 this.update();
524 evt.preventDefault();
525 },
526
527 _utc_to_local: function(utc){
528 return utc && new Date(utc.getTime() + (utc.getTimezoneOffset()*60000));
529 },
530 _local_to_utc: function(local){
531 return local && new Date(local.getTime() - (local.getTimezoneOffset()*60000));
532 },
533 _zero_time: function(local){
534 return local && new Date(local.getFullYear(), local.getMonth(), local.getDate());
535 },
536 _zero_utc_time: function(utc){
537 return utc && new Date(Date.UTC(utc.getUTCFullYear(), utc.getUTCMonth(), utc.getUTCDate()));
538 },
539
540 getDates: function(){
541 return $.map(this.dates, this._utc_to_local);
542 },
543
544 getUTCDates: function(){
545 return $.map(this.dates, function(d){
546 return new Date(d);
547 });
548 },
549
550 getDate: function(){
551 return this._utc_to_local(this.getUTCDate());
552 },
553
554 getUTCDate: function(){
555 var selected_date = this.dates.get(-1);
556 if (typeof selected_date !== 'undefined') {
557 return new Date(selected_date);
558 } else {
559 return null;
560 }
561 },
562
563 clearDates: function(){
564 var element;
565 if (this.isInput) {
566 element = this.element;
567 } else if (this.component) {
568 element = this.element.find('input');
569 }
570
571 if (element) {
572 element.val('');
573 }
574
575 this.update();
576 this._trigger('changeDate');
577
578 if (this.o.autoclose) {
579 this.hide();
580 }
581 },
582 setDates: function(){
583 var args = $.isArray(arguments[0]) ? arguments[0] : arguments;
584 this.update.apply(this, args);
585 this._trigger('changeDate');
586 this.setValue();
587 return this;
588 },
589
590 setUTCDates: function(){
591 var args = $.isArray(arguments[0]) ? arguments[0] : arguments;
592 this.update.apply(this, $.map(args, this._utc_to_local));
593 this._trigger('changeDate');
594 this.setValue();
595 return this;
596 },
597
598 setDate: alias('setDates'),
599 setUTCDate: alias('setUTCDates'),
600
601 setValue: function(){
602 var formatted = this.getFormattedDate();
603 if (!this.isInput){
604 if (this.component){
605 this.element.find('input').val(formatted);
606 }
607 }
608 else {
609 this.element.val(formatted);
610 }
611 return this;
612 },
613
614 getFormattedDate: function(format){
615 if (format === undefined)
616 format = this.o.format;
617
618 var lang = this.o.language;
619 return $.map(this.dates, function(d){
620 return DPGlobal.formatDate(d, format, lang);
621 }).join(this.o.multidateSeparator);
622 },
623
624 setStartDate: function(startDate){
625 this._process_options({startDate: startDate});
626 this.update();
627 this.updateNavArrows();
628 return this;
629 },
630
631 setEndDate: function(endDate){
632 this._process_options({endDate: endDate});
633 this.update();
634 this.updateNavArrows();
635 return this;
636 },
637
638 setDaysOfWeekDisabled: function(daysOfWeekDisabled){
639 this._process_options({daysOfWeekDisabled: daysOfWeekDisabled});
640 this.update();
641 this.updateNavArrows();
642 return this;
643 },
644
645 setDaysOfWeekHighlighted: function(daysOfWeekHighlighted){
646 this._process_options({daysOfWeekHighlighted: daysOfWeekHighlighted});
647 this.update();
648 return this;
649 },
650
651 setDatesDisabled: function(datesDisabled){
652 this._process_options({datesDisabled: datesDisabled});
653 this.update();
654 this.updateNavArrows();
655 },
656
657 place: function(){
658 if (this.isInline)
659 return this;
660 var calendarWidth = this.picker.outerWidth(),
661 calendarHeight = this.picker.outerHeight(),
662 visualPadding = 10,
663 container = $(this.o.container),
664 windowWidth = container.width(),
665 scrollTop = this.o.container === 'body' ? $(document).scrollTop() : container.scrollTop(),
666 appendOffset = container.offset();
667
668 var parentsZindex = [];
669 this.element.parents().each(function(){
670 var itemZIndex = $(this).css('z-index');
671 if (itemZIndex !== 'auto' && itemZIndex !== 0) parentsZindex.push(parseInt(itemZIndex));
672 });
673 var zIndex = Math.max.apply(Math, parentsZindex) + this.o.zIndexOffset;
674 var offset = this.component ? this.component.parent().offset() : this.element.offset();
675 var height = this.component ? this.component.outerHeight(true) : this.element.outerHeight(false);
676 var width = this.component ? this.component.outerWidth(true) : this.element.outerWidth(false);
677 var left = offset.left - appendOffset.left,
678 top = offset.top - appendOffset.top;
679
680 if (this.o.container !== 'body') {
681 top += scrollTop;
682 }
683
684 this.picker.removeClass(
685 'datepicker-orient-top datepicker-orient-bottom '+
686 'datepicker-orient-right datepicker-orient-left'
687 );
688
689 if (this.o.orientation.x !== 'auto'){
690 this.picker.addClass('datepicker-orient-' + this.o.orientation.x);
691 if (this.o.orientation.x === 'right')
692 left -= calendarWidth - width;
693 }
694 // auto x orientation is best-placement: if it crosses a window
695 // edge, fudge it sideways
696 else {
697 if (offset.left < 0) {
698 // component is outside the window on the left side. Move it into visible range
699 this.picker.addClass('datepicker-orient-left');
700 left -= offset.left - visualPadding;
701 } else if (left + calendarWidth > windowWidth) {
702 // the calendar passes the widow right edge. Align it to component right side
703 this.picker.addClass('datepicker-orient-right');
704 left += width - calendarWidth;
705 } else {
706 // Default to left
707 this.picker.addClass('datepicker-orient-left');
708 }
709 }
710
711 // auto y orientation is best-situation: top or bottom, no fudging,
712 // decision based on which shows more of the calendar
713 var yorient = this.o.orientation.y,
714 top_overflow;
715 if (yorient === 'auto'){
716 top_overflow = -scrollTop + top - calendarHeight;
717 yorient = top_overflow < 0 ? 'bottom' : 'top';
718 }
719
720 this.picker.addClass('datepicker-orient-' + yorient);
721 if (yorient === 'top')
722 top -= calendarHeight + parseInt(this.picker.css('padding-top'));
723 else
724 top += height;
725
726 if (this.o.rtl) {
727 var right = windowWidth - (left + width);
728 this.picker.css({
729 top: top,
730 right: right,
731 zIndex: zIndex
732 });
733 } else {
734 this.picker.css({
735 top: top,
736 left: left,
737 zIndex: zIndex
738 });
739 }
740 return this;
741 },
742
743 _allow_update: true,
744 update: function(){
745 if (!this._allow_update)
746 return this;
747
748 var oldDates = this.dates.copy(),
749 dates = [],
750 fromArgs = false;
751 if (arguments.length){
752 $.each(arguments, $.proxy(function(i, date){
753 if (date instanceof Date)
754 date = this._local_to_utc(date);
755 dates.push(date);
756 }, this));
757 fromArgs = true;
758 }
759 else {
760 dates = this.isInput
761 ? this.element.val()
762 : this.element.data('date') || this.element.find('input').val();
763 if (dates && this.o.multidate)
764 dates = dates.split(this.o.multidateSeparator);
765 else
766 dates = [dates];
767 delete this.element.data().date;
768 }
769
770 dates = $.map(dates, $.proxy(function(date){
771 return DPGlobal.parseDate(date, this.o.format, this.o.language);
772 }, this));
773 dates = $.grep(dates, $.proxy(function(date){
774 return (
775 !this.dateWithinRange(date) ||
776 !date
777 );
778 }, this), true);
779 this.dates.replace(dates);
780
781 if (this.dates.length)
782 this.viewDate = new Date(this.dates.get(-1));
783 else if (this.viewDate < this.o.startDate)
784 this.viewDate = new Date(this.o.startDate);
785 else if (this.viewDate > this.o.endDate)
786 this.viewDate = new Date(this.o.endDate);
787 else
788 this.viewDate = this.o.defaultViewDate;
789
790 if (fromArgs){
791 // setting date by clicking
792 this.setValue();
793 }
794 else if (dates.length){
795 // setting date by typing
796 if (String(oldDates) !== String(this.dates))
797 this._trigger('changeDate');
798 }
799 if (!this.dates.length && oldDates.length)
800 this._trigger('clearDate');
801
802 this.fill();
803 this.element.change();
804 return this;
805 },
806
807 fillDow: function(){
808 var dowCnt = this.o.weekStart,
809 html = '<tr>';
810 if (this.o.calendarWeeks){
811 this.picker.find('.datepicker-days .datepicker-switch')
812 .attr('colspan', function(i, val){
813 return parseInt(val) + 1;
814 });
815 html += '<th class="cw">&#160;</th>';
816 }
817 while (dowCnt < this.o.weekStart + 7){
818 html += '<th class="dow">'+dates[this.o.language].daysMin[(dowCnt++)%7]+'</th>';
819 }
820 html += '</tr>';
821 this.picker.find('.datepicker-days thead').append(html);
822 },
823
824 fillMonths: function(){
825 var html = '',
826 i = 0;
827 while (i < 12){
828 html += '<span class="month">'+dates[this.o.language].monthsShort[i++]+'</span>';
829 }
830 this.picker.find('.datepicker-months td').html(html);
831 },
832
833 setRange: function(range){
834 if (!range || !range.length)
835 delete this.range;
836 else
837 this.range = $.map(range, function(d){
838 return d.valueOf();
839 });
840 this.fill();
841 },
842
843 getClassNames: function(date){
844 var cls = [],
845 year = this.viewDate.getUTCFullYear(),
846 month = this.viewDate.getUTCMonth(),
847 today = new Date();
848 if (date.getUTCFullYear() < year || (date.getUTCFullYear() === year && date.getUTCMonth() < month)){
849 cls.push('old');
850 }
851 else if (date.getUTCFullYear() > year || (date.getUTCFullYear() === year && date.getUTCMonth() > month)){
852 cls.push('new');
853 }
854 if (this.focusDate && date.valueOf() === this.focusDate.valueOf())
855 cls.push('focused');
856 // Compare internal UTC date with local today, not UTC today
857 if (this.o.todayHighlight &&
858 date.getUTCFullYear() === today.getFullYear() &&
859 date.getUTCMonth() === today.getMonth() &&
860 date.getUTCDate() === today.getDate()){
861 cls.push('today');
862 }
863 if (this.dates.contains(date) !== -1)
864 cls.push('active');
865 if (!this.dateWithinRange(date) || this.dateIsDisabled(date)){
866 cls.push('disabled');
867 }
868 if ($.inArray(date.getUTCDay(), this.o.daysOfWeekHighlighted) !== -1){
869 cls.push('highlighted');
870 }
871
872 if (this.range){
873 if (date > this.range[0] && date < this.range[this.range.length-1]){
874 cls.push('range');
875 }
876 if ($.inArray(date.valueOf(), this.range) !== -1){
877 cls.push('selected');
878 }
879 if (date.valueOf() === this.range[0]){
880 cls.push('range-start');
881 }
882 if (date.valueOf() === this.range[this.range.length-1]){
883 cls.push('range-end');
884 }
885 }
886 return cls;
887 },
888
889 fill: function(){
890 var d = new Date(this.viewDate),
891 year = d.getUTCFullYear(),
892 month = d.getUTCMonth(),
893 startYear = this.o.startDate !== -Infinity ? this.o.startDate.getUTCFullYear() : -Infinity,
894 startMonth = this.o.startDate !== -Infinity ? this.o.startDate.getUTCMonth() : -Infinity,
895 endYear = this.o.endDate !== Infinity ? this.o.endDate.getUTCFullYear() : Infinity,
896 endMonth = this.o.endDate !== Infinity ? this.o.endDate.getUTCMonth() : Infinity,
897 todaytxt = dates[this.o.language].today || dates['en'].today || '',
898 cleartxt = dates[this.o.language].clear || dates['en'].clear || '',
899 titleFormat = dates[this.o.language].titleFormat || dates['en'].titleFormat,
900 tooltip;
901 if (isNaN(year) || isNaN(month))
902 return;
903 this.picker.find('.datepicker-days thead .datepicker-switch')
904 .text(DPGlobal.formatDate(new UTCDate(year, month), titleFormat, this.o.language));
905 this.picker.find('tfoot .today')
906 .text(todaytxt)
907 .toggle(this.o.todayBtn !== false);
908 this.picker.find('tfoot .clear')
909 .text(cleartxt)
910 .toggle(this.o.clearBtn !== false);
911 this.picker.find('thead .datepicker-title')
912 .text(this.o.title)
913 .toggle(this.o.title !== '');
914 this.updateNavArrows();
915 this.fillMonths();
916 var prevMonth = UTCDate(year, month-1, 28),
917 day = DPGlobal.getDaysInMonth(prevMonth.getUTCFullYear(), prevMonth.getUTCMonth());
918 prevMonth.setUTCDate(day);
919 prevMonth.setUTCDate(day - (prevMonth.getUTCDay() - this.o.weekStart + 7)%7);
920 var nextMonth = new Date(prevMonth);
921 if (prevMonth.getUTCFullYear() < 100){
922 nextMonth.setUTCFullYear(prevMonth.getUTCFullYear());
923 }
924 nextMonth.setUTCDate(nextMonth.getUTCDate() + 42);
925 nextMonth = nextMonth.valueOf();
926 var html = [];
927 var clsName;
928 while (prevMonth.valueOf() < nextMonth){
929 if (prevMonth.getUTCDay() === this.o.weekStart){
930 html.push('<tr>');
931 if (this.o.calendarWeeks){
932 // ISO 8601: First week contains first thursday.
933 // ISO also states week starts on Monday, but we can be more abstract here.
934 var
935 // Start of current week: based on weekstart/current date
936 ws = new Date(+prevMonth + (this.o.weekStart - prevMonth.getUTCDay() - 7) % 7 * 864e5),
937 // Thursday of this week
938 th = new Date(Number(ws) + (7 + 4 - ws.getUTCDay()) % 7 * 864e5),
939 // First Thursday of year, year from thursday
940 yth = new Date(Number(yth = UTCDate(th.getUTCFullYear(), 0, 1)) + (7 + 4 - yth.getUTCDay())%7*864e5),
941 // Calendar week: ms between thursdays, div ms per day, div 7 days
942 calWeek = (th - yth) / 864e5 / 7 + 1;
943 html.push('<td class="cw">'+ calWeek +'</td>');
944
945 }
946 }
947 clsName = this.getClassNames(prevMonth);
948 clsName.push('day');
949
950 if (this.o.beforeShowDay !== $.noop){
951 var before = this.o.beforeShowDay(this._utc_to_local(prevMonth));
952 if (before === undefined)
953 before = {};
954 else if (typeof(before) === 'boolean')
955 before = {enabled: before};
956 else if (typeof(before) === 'string')
957 before = {classes: before};
958 if (before.enabled === false)
959 clsName.push('disabled');
960 if (before.classes)
961 clsName = clsName.concat(before.classes.split(/\s+/));
962 if (before.tooltip)
963 tooltip = before.tooltip;
964 }
965
966 clsName = $.unique(clsName);
967 html.push('<td class="'+clsName.join(' ')+'"' + (tooltip ? ' title="'+tooltip+'"' : '') + '>'+prevMonth.getUTCDate() + '</td>');
968 tooltip = null;
969 if (prevMonth.getUTCDay() === this.o.weekEnd){
970 html.push('</tr>');
971 }
972 prevMonth.setUTCDate(prevMonth.getUTCDate()+1);
973 }
974 this.picker.find('.datepicker-days tbody').empty().append(html.join(''));
975
976 var monthsTitle = dates[this.o.language].monthsTitle || dates['en'].monthsTitle || 'Months';
977 var months = this.picker.find('.datepicker-months')
978 .find('.datepicker-switch')
979 .text(this.o.maxViewMode < 2 ? monthsTitle : year)
980 .end()
981 .find('span').removeClass('active');
982
983 $.each(this.dates, function(i, d){
984 if (d.getUTCFullYear() === year)
985 months.eq(d.getUTCMonth()).addClass('active');
986 });
987
988 if (year < startYear || year > endYear){
989 months.addClass('disabled');
990 }
991 if (year === startYear){
992 months.slice(0, startMonth).addClass('disabled');
993 }
994 if (year === endYear){
995 months.slice(endMonth+1).addClass('disabled');
996 }
997
998 if (this.o.beforeShowMonth !== $.noop){
999 var that = this;
1000 $.each(months, function(i, month){
1001 if (!$(month).hasClass('disabled')) {
1002 var moDate = new Date(year, i, 1);
1003 var before = that.o.beforeShowMonth(moDate);
1004 if (before === false)
1005 $(month).addClass('disabled');
1006 }
1007 });
1008 }
1009
1010 html = '';
1011 year = parseInt(year/10, 10) * 10;
1012 var yearCont = this.picker.find('.datepicker-years')
1013 .find('.datepicker-switch')
1014 .text(year + '-' + (year + 9))
1015 .end()
1016 .find('td');
1017 year -= 1;
1018 var years = $.map(this.dates, function(d){
1019 return d.getUTCFullYear();
1020 }),
1021 classes;
1022 for (var i = -1; i < 11; i++){
1023 classes = ['year'];
1024 tooltip = null;
1025
1026 if (i === -1)
1027 classes.push('old');
1028 else if (i === 10)
1029 classes.push('new');
1030 if ($.inArray(year, years) !== -1)
1031 classes.push('active');
1032 if (year < startYear || year > endYear)
1033 classes.push('disabled');
1034
1035 if (this.o.beforeShowYear !== $.noop) {
1036 var yrBefore = this.o.beforeShowYear(new Date(year, 0, 1));
1037 if (yrBefore === undefined)
1038 yrBefore = {};
1039 else if (typeof(yrBefore) === 'boolean')
1040 yrBefore = {enabled: yrBefore};
1041 else if (typeof(yrBefore) === 'string')
1042 yrBefore = {classes: yrBefore};
1043 if (yrBefore.enabled === false)
1044 classes.push('disabled');
1045 if (yrBefore.classes)
1046 classes = classes.concat(yrBefore.classes.split(/\s+/));
1047 if (yrBefore.tooltip)
1048 tooltip = yrBefore.tooltip;
1049 }
1050
1051 html += '<span class="' + classes.join(' ') + '"' + (tooltip ? ' title="'+tooltip+'"' : '') + '>' + year + '</span>';
1052 year += 1;
1053 }
1054 yearCont.html(html);
1055 },
1056
1057 updateNavArrows: function(){
1058 if (!this._allow_update)
1059 return;
1060
1061 var d = new Date(this.viewDate),
1062 year = d.getUTCFullYear(),
1063 month = d.getUTCMonth();
1064 switch (this.viewMode){
1065 case 0:
1066 if (this.o.startDate !== -Infinity && year <= this.o.startDate.getUTCFullYear() && month <= this.o.startDate.getUTCMonth()){
1067 this.picker.find('.prev').css({visibility: 'hidden'});
1068 }
1069 else {
1070 this.picker.find('.prev').css({visibility: 'visible'});
1071 }
1072 if (this.o.endDate !== Infinity && year >= this.o.endDate.getUTCFullYear() && month >= this.o.endDate.getUTCMonth()){
1073 this.picker.find('.next').css({visibility: 'hidden'});
1074 }
1075 else {
1076 this.picker.find('.next').css({visibility: 'visible'});
1077 }
1078 break;
1079 case 1:
1080 case 2:
1081 if (this.o.startDate !== -Infinity && year <= this.o.startDate.getUTCFullYear() || this.o.maxViewMode < 2){
1082 this.picker.find('.prev').css({visibility: 'hidden'});
1083 }
1084 else {
1085 this.picker.find('.prev').css({visibility: 'visible'});
1086 }
1087 if (this.o.endDate !== Infinity && year >= this.o.endDate.getUTCFullYear() || this.o.maxViewMode < 2){
1088 this.picker.find('.next').css({visibility: 'hidden'});
1089 }
1090 else {
1091 this.picker.find('.next').css({visibility: 'visible'});
1092 }
1093 break;
1094 }
1095 },
1096
1097 click: function(e){
1098 e.preventDefault();
1099 e.stopPropagation();
1100 var target = $(e.target).closest('span, td, th'),
1101 year, month, day;
1102 if (target.length === 1){
1103 switch (target[0].nodeName.toLowerCase()){
1104 case 'th':
1105 switch (target[0].className){
1106 case 'datepicker-switch':
1107 this.showMode(1);
1108 break;
1109 case 'prev':
1110 case 'next':
1111 var dir = DPGlobal.modes[this.viewMode].navStep * (target[0].className === 'prev' ? -1 : 1);
1112 switch (this.viewMode){
1113 case 0:
1114 this.viewDate = this.moveMonth(this.viewDate, dir);
1115 this._trigger('changeMonth', this.viewDate);
1116 break;
1117 case 1:
1118 case 2:
1119 this.viewDate = this.moveYear(this.viewDate, dir);
1120 if (this.viewMode === 1)
1121 this._trigger('changeYear', this.viewDate);
1122 break;
1123 }
1124 this.fill();
1125 break;
1126 case 'today':
1127 this.showMode(-2);
1128 var which = this.o.todayBtn === 'linked' ? null : 'view';
1129 this._setDate(UTCToday(), which);
1130 break;
1131 case 'clear':
1132 this.clearDates();
1133 break;
1134 }
1135 break;
1136 case 'span':
1137 if (!target.hasClass('disabled')){
1138 this.viewDate.setUTCDate(1);
1139 if (target.hasClass('month')){
1140 day = 1;
1141 month = target.parent().find('span').index(target);
1142 year = this.viewDate.getUTCFullYear();
1143 this.viewDate.setUTCMonth(month);
1144 this._trigger('changeMonth', this.viewDate);
1145 if (this.o.minViewMode === 1){
1146 this._setDate(UTCDate(year, month, day));
1147 this.showMode();
1148 } else {
1149 this.showMode(-1);
1150 }
1151 }
1152 else {
1153 day = 1;
1154 month = 0;
1155 year = parseInt(target.text(), 10)||0;
1156 this.viewDate.setUTCFullYear(year);
1157 this._trigger('changeYear', this.viewDate);
1158 if (this.o.minViewMode === 2){
1159 this._setDate(UTCDate(year, month, day));
1160 }
1161 this.showMode(-1);
1162 }
1163 this.fill();
1164 }
1165 break;
1166 case 'td':
1167 if (target.hasClass('day') && !target.hasClass('disabled')){
1168 day = parseInt(target.text(), 10)||1;
1169 year = this.viewDate.getUTCFullYear();
1170 month = this.viewDate.getUTCMonth();
1171 if (target.hasClass('old')){
1172 if (month === 0){
1173 month = 11;
1174 year -= 1;
1175 }
1176 else {
1177 month -= 1;
1178 }
1179 }
1180 else if (target.hasClass('new')){
1181 if (month === 11){
1182 month = 0;
1183 year += 1;
1184 }
1185 else {
1186 month += 1;
1187 }
1188 }
1189 this._setDate(UTCDate(year, month, day));
1190 }
1191 break;
1192 }
1193 }
1194 if (this.picker.is(':visible') && this._focused_from){
1195 $(this._focused_from).focus();
1196 }
1197 delete this._focused_from;
1198 },
1199
1200 _toggle_multidate: function(date){
1201 var ix = this.dates.contains(date);
1202 if (!date){
1203 this.dates.clear();
1204 }
1205
1206 if (ix !== -1){
1207 if (this.o.multidate === true || this.o.multidate > 1 || this.o.toggleActive){
1208 this.dates.remove(ix);
1209 }
1210 } else if (this.o.multidate === false) {
1211 this.dates.clear();
1212 this.dates.push(date);
1213 }
1214 else {
1215 this.dates.push(date);
1216 }
1217
1218 if (typeof this.o.multidate === 'number')
1219 while (this.dates.length > this.o.multidate)
1220 this.dates.remove(0);
1221 },
1222
1223 _setDate: function(date, which){
1224 if (!which || which === 'date')
1225 this._toggle_multidate(date && new Date(date));
1226 if (!which || which === 'view')
1227 this.viewDate = date && new Date(date);
1228
1229 this.fill();
1230 this.setValue();
1231 if (!which || which !== 'view') {
1232 this._trigger('changeDate');
1233 }
1234 var element;
1235 if (this.isInput){
1236 element = this.element;
1237 }
1238 else if (this.component){
1239 element = this.element.find('input');
1240 }
1241 if (element){
1242 element.change();
1243 }
1244 if (this.o.autoclose && (!which || which === 'date')){
1245 this.hide();
1246 }
1247 },
1248
1249 moveDay: function(date, dir){
1250 var newDate = new Date(date);
1251 newDate.setUTCDate(date.getUTCDate() + dir);
1252
1253 return newDate;
1254 },
1255
1256 moveWeek: function(date, dir){
1257 return this.moveDay(date, dir * 7);
1258 },
1259
1260 moveMonth: function(date, dir){
1261 if (!isValidDate(date))
1262 return this.o.defaultViewDate;
1263 if (!dir)
1264 return date;
1265 var new_date = new Date(date.valueOf()),
1266 day = new_date.getUTCDate(),
1267 month = new_date.getUTCMonth(),
1268 mag = Math.abs(dir),
1269 new_month, test;
1270 dir = dir > 0 ? 1 : -1;
1271 if (mag === 1){
1272 test = dir === -1
1273 // If going back one month, make sure month is not current month
1274 // (eg, Mar 31 -> Feb 31 == Feb 28, not Mar 02)
1275 ? function(){
1276 return new_date.getUTCMonth() === month;
1277 }
1278 // If going forward one month, make sure month is as expected
1279 // (eg, Jan 31 -> Feb 31 == Feb 28, not Mar 02)
1280 : function(){
1281 return new_date.getUTCMonth() !== new_month;
1282 };
1283 new_month = month + dir;
1284 new_date.setUTCMonth(new_month);
1285 // Dec -> Jan (12) or Jan -> Dec (-1) -- limit expected date to 0-11
1286 if (new_month < 0 || new_month > 11)
1287 new_month = (new_month + 12) % 12;
1288 }
1289 else {
1290 // For magnitudes >1, move one month at a time...
1291 for (var i=0; i < mag; i++)
1292 // ...which might decrease the day (eg, Jan 31 to Feb 28, etc)...
1293 new_date = this.moveMonth(new_date, dir);
1294 // ...then reset the day, keeping it in the new month
1295 new_month = new_date.getUTCMonth();
1296 new_date.setUTCDate(day);
1297 test = function(){
1298 return new_month !== new_date.getUTCMonth();
1299 };
1300 }
1301 // Common date-resetting loop -- if date is beyond end of month, make it
1302 // end of month
1303 while (test()){
1304 new_date.setUTCDate(--day);
1305 new_date.setUTCMonth(new_month);
1306 }
1307 return new_date;
1308 },
1309
1310 moveYear: function(date, dir){
1311 return this.moveMonth(date, dir*12);
1312 },
1313
1314 moveAvailableDate: function(date, dir, fn){
1315 do {
1316 date = this[fn](date, dir);
1317
1318 if (!this.dateWithinRange(date))
1319 return false;
1320
1321 fn = 'moveDay';
1322 }
1323 while (this.dateIsDisabled(date));
1324
1325 return date;
1326 },
1327
1328 weekOfDateIsDisabled: function(date){
1329 return $.inArray(date.getUTCDay(), this.o.daysOfWeekDisabled) !== -1;
1330 },
1331
1332 dateIsDisabled: function(date){
1333 return (
1334 this.weekOfDateIsDisabled(date) ||
1335 $.grep(this.o.datesDisabled, function(d){
1336 return isUTCEquals(date, d);
1337 }).length > 0
1338 );
1339 },
1340
1341 dateWithinRange: function(date){
1342 return date >= this.o.startDate && date <= this.o.endDate;
1343 },
1344
1345 keydown: function(e){
1346 if (!this.picker.is(':visible')){
1347 if (e.keyCode === 40 || e.keyCode === 27) { // allow down to re-show picker
1348 this.show();
1349 e.stopPropagation();
1350 }
1351 return;
1352 }
1353 var dateChanged = false,
1354 dir, newViewDate,
1355 focusDate = this.focusDate || this.viewDate;
1356 switch (e.keyCode){
1357 case 27: // escape
1358 if (this.focusDate){
1359 this.focusDate = null;
1360 this.viewDate = this.dates.get(-1) || this.viewDate;
1361 this.fill();
1362 }
1363 else
1364 this.hide();
1365 e.preventDefault();
1366 e.stopPropagation();
1367 break;
1368 case 37: // left
1369 case 38: // up
1370 case 39: // right
1371 case 40: // down
1372 if (!this.o.keyboardNavigation || this.o.daysOfWeekDisabled.length === 7)
1373 break;
1374 dir = e.keyCode === 37 || e.keyCode === 38 ? -1 : 1;
1375 if (e.ctrlKey){
1376 newViewDate = this.moveAvailableDate(focusDate, dir, 'moveYear');
1377
1378 if (newViewDate)
1379 this._trigger('changeYear', this.viewDate);
1380 }
1381 else if (e.shiftKey){
1382 newViewDate = this.moveAvailableDate(focusDate, dir, 'moveMonth');
1383
1384 if (newViewDate)
1385 this._trigger('changeMonth', this.viewDate);
1386 }
1387 else if (e.keyCode === 37 || e.keyCode === 39){
1388 newViewDate = this.moveAvailableDate(focusDate, dir, 'moveDay');
1389 }
1390 else if (!this.weekOfDateIsDisabled(focusDate)){
1391 newViewDate = this.moveAvailableDate(focusDate, dir, 'moveWeek');
1392 }
1393 if (newViewDate){
1394 this.focusDate = this.viewDate = newViewDate;
1395 this.setValue();
1396 this.fill();
1397 e.preventDefault();
1398 }
1399 break;
1400 case 13: // enter
1401 if (!this.o.forceParse)
1402 break;
1403 focusDate = this.focusDate || this.dates.get(-1) || this.viewDate;
1404 if (this.o.keyboardNavigation) {
1405 this._toggle_multidate(focusDate);
1406 dateChanged = true;
1407 }
1408 this.focusDate = null;
1409 this.viewDate = this.dates.get(-1) || this.viewDate;
1410 this.setValue();
1411 this.fill();
1412 if (this.picker.is(':visible')){
1413 e.preventDefault();
1414 e.stopPropagation();
1415 if (this.o.autoclose)
1416 this.hide();
1417 }
1418 break;
1419 case 9: // tab
1420 this.focusDate = null;
1421 this.viewDate = this.dates.get(-1) || this.viewDate;
1422 this.fill();
1423 this.hide();
1424 break;
1425 }
1426 if (dateChanged){
1427 if (this.dates.length)
1428 this._trigger('changeDate');
1429 else
1430 this._trigger('clearDate');
1431 var element;
1432 if (this.isInput){
1433 element = this.element;
1434 }
1435 else if (this.component){
1436 element = this.element.find('input');
1437 }
1438 if (element){
1439 element.change();
1440 }
1441 }
1442 },
1443
1444 showMode: function(dir){
1445 if (dir){
1446 this.viewMode = Math.max(this.o.minViewMode, Math.min(this.o.maxViewMode, this.viewMode + dir));
1447 }
1448 this.picker
1449 .children('div')
1450 .hide()
1451 .filter('.datepicker-' + DPGlobal.modes[this.viewMode].clsName)
1452 .show();
1453 this.updateNavArrows();
1454 }
1455 };
1456
1457 var DateRangePicker = function(element, options){
1458 $(element).data('datepicker', this);
1459 this.element = $(element);
1460 this.inputs = $.map(options.inputs, function(i){
1461 return i.jquery ? i[0] : i;
1462 });
1463 delete options.inputs;
1464
1465 datepickerPlugin.call($(this.inputs), options)
1466 .on('changeDate', $.proxy(this.dateUpdated, this));
1467
1468 this.pickers = $.map(this.inputs, function(i){
1469 return $(i).data('datepicker');
1470 });
1471 this.updateDates();
1472 };
1473 DateRangePicker.prototype = {
1474 updateDates: function(){
1475 this.dates = $.map(this.pickers, function(i){
1476 return i.getUTCDate();
1477 });
1478 this.updateRanges();
1479 },
1480 updateRanges: function(){
1481 var range = $.map(this.dates, function(d){
1482 return d.valueOf();
1483 });
1484 $.each(this.pickers, function(i, p){
1485 p.setRange(range);
1486 });
1487 },
1488 dateUpdated: function(e){
1489 // `this.updating` is a workaround for preventing infinite recursion
1490 // between `changeDate` triggering and `setUTCDate` calling. Until
1491 // there is a better mechanism.
1492 if (this.updating)
1493 return;
1494 this.updating = true;
1495
1496 var dp = $(e.target).data('datepicker');
1497
1498 if (typeof(dp) === "undefined") {
1499 return;
1500 }
1501
1502 var new_date = dp.getUTCDate(),
1503 i = $.inArray(e.target, this.inputs),
1504 j = i - 1,
1505 k = i + 1,
1506 l = this.inputs.length;
1507 if (i === -1)
1508 return;
1509
1510 $.each(this.pickers, function(i, p){
1511 if (!p.getUTCDate())
1512 p.setUTCDate(new_date);
1513 });
1514
1515 if (new_date < this.dates[j]){
1516 // Date being moved earlier/left
1517 while (j >= 0 && new_date < this.dates[j]){
1518 this.pickers[j--].setUTCDate(new_date);
1519 }
1520 }
1521 else if (new_date > this.dates[k]){
1522 // Date being moved later/right
1523 while (k < l && new_date > this.dates[k]){
1524 this.pickers[k++].setUTCDate(new_date);
1525 }
1526 }
1527 this.updateDates();
1528
1529 delete this.updating;
1530 },
1531 remove: function(){
1532 $.map(this.pickers, function(p){ p.remove(); });
1533 delete this.element.data().datepicker;
1534 }
1535 };
1536
1537 function opts_from_el(el, prefix){
1538 // Derive options from element data-attrs
1539 var data = $(el).data(),
1540 out = {}, inkey,
1541 replace = new RegExp('^' + prefix.toLowerCase() + '([A-Z])');
1542 prefix = new RegExp('^' + prefix.toLowerCase());
1543 function re_lower(_,a){
1544 return a.toLowerCase();
1545 }
1546 for (var key in data)
1547 if (prefix.test(key)){
1548 inkey = key.replace(replace, re_lower);
1549 out[inkey] = data[key];
1550 }
1551 return out;
1552 }
1553
1554 function opts_from_locale(lang){
1555 // Derive options from locale plugins
1556 var out = {};
1557 // Check if "de-DE" style date is available, if not language should
1558 // fallback to 2 letter code eg "de"
1559 if (!dates[lang]){
1560 lang = lang.split('-')[0];
1561 if (!dates[lang])
1562 return;
1563 }
1564 var d = dates[lang];
1565 $.each(locale_opts, function(i,k){
1566 if (k in d)
1567 out[k] = d[k];
1568 });
1569 return out;
1570 }
1571
1572 var old = $.fn.datepicker;
1573 var datepickerPlugin = function(option){
1574 var args = Array.apply(null, arguments);
1575 args.shift();
1576 var internal_return;
1577 this.each(function(){
1578 var $this = $(this),
1579 data = $this.data('datepicker'),
1580 options = typeof option === 'object' && option;
1581 if (!data){
1582 var elopts = opts_from_el(this, 'date'),
1583 // Preliminary otions
1584 xopts = $.extend({}, defaults, elopts, options),
1585 locopts = opts_from_locale(xopts.language),
1586 // Options priority: js args, data-attrs, locales, defaults
1587 opts = $.extend({}, defaults, locopts, elopts, options);
1588 if ($this.hasClass('input-daterange') || opts.inputs){
1589 $.extend(opts, {
1590 inputs: opts.inputs || $this.find('input').toArray()
1591 });
1592 data = new DateRangePicker(this, opts);
1593 }
1594 else {
1595 data = new Datepicker(this, opts);
1596 }
1597 $this.data('datepicker', data);
1598 }
1599 if (typeof option === 'string' && typeof data[option] === 'function'){
1600 internal_return = data[option].apply(data, args);
1601 }
1602 });
1603
1604 if (
1605 internal_return === undefined ||
1606 internal_return instanceof Datepicker ||
1607 internal_return instanceof DateRangePicker
1608 )
1609 return this;
1610
1611 if (this.length > 1)
1612 throw new Error('Using only allowed for the collection of a single element (' + option + ' function)');
1613 else
1614 return internal_return;
1615 };
1616 $.fn.datepicker = datepickerPlugin;
1617
1618 var defaults = $.fn.datepicker.defaults = {
1619 autoclose: false,
1620 beforeShowDay: $.noop,
1621 beforeShowMonth: $.noop,
1622 beforeShowYear: $.noop,
1623 calendarWeeks: false,
1624 clearBtn: false,
1625 toggleActive: false,
1626 daysOfWeekDisabled: [],
1627 daysOfWeekHighlighted: [],
1628 datesDisabled: [],
1629 endDate: Infinity,
1630 forceParse: true,
1631 format: 'mm/dd/yyyy',
1632 keyboardNavigation: true,
1633 language: 'en',
1634 minViewMode: 0,
1635 maxViewMode: 2,
1636 multidate: false,
1637 multidateSeparator: ',',
1638 orientation: "auto",
1639 rtl: false,
1640 startDate: -Infinity,
1641 startView: 0,
1642 todayBtn: false,
1643 todayHighlight: false,
1644 weekStart: 0,
1645 disableTouchKeyboard: false,
1646 enableOnReadonly: true,
1647 showOnFocus: true,
1648 zIndexOffset: 10,
1649 container: 'body',
1650 immediateUpdates: false,
1651 title: ''
1652 };
1653 var locale_opts = $.fn.datepicker.locale_opts = [
1654 'format',
1655 'rtl',
1656 'weekStart'
1657 ];
1658 $.fn.datepicker.Constructor = Datepicker;
1659 var dates = $.fn.datepicker.dates = {
1660 en: {
1661 days: ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"],
1662 daysShort: ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"],
1663 daysMin: ["Su", "Mo", "Tu", "We", "Th", "Fr", "Sa"],
1664 months: ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"],
1665 monthsShort: ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"],
1666 today: "Today",
1667 clear: "Clear",
1668 titleFormat: "MM yyyy"
1669 }
1670 };
1671
1672 var DPGlobal = {
1673 modes: [
1674 {
1675 clsName: 'days',
1676 navFnc: 'Month',
1677 navStep: 1
1678 },
1679 {
1680 clsName: 'months',
1681 navFnc: 'FullYear',
1682 navStep: 1
1683 },
1684 {
1685 clsName: 'years',
1686 navFnc: 'FullYear',
1687 navStep: 10
1688 }],
1689 isLeapYear: function(year){
1690 return (((year % 4 === 0) && (year % 100 !== 0)) || (year % 400 === 0));
1691 },
1692 getDaysInMonth: function(year, month){
1693 return [31, (DPGlobal.isLeapYear(year) ? 29 : 28), 31, 30, 31, 30, 31, 31, 30, 31, 30, 31][month];
1694 },
1695 validParts: /dd?|DD?|mm?|MM?|yy(?:yy)?/g,
1696 nonpunctuation: /[^ -\/:-@\[\u3400-\u9fff-`{-~\t\n\r]+/g,
1697 parseFormat: function(format){
1698 if (typeof format.toValue === 'function' && typeof format.toDisplay === 'function')
1699 return format;
1700 // IE treats \0 as a string end in inputs (truncating the value),
1701 // so it's a bad format delimiter, anyway
1702 var separators = format.replace(this.validParts, '\0').split('\0'),
1703 parts = format.match(this.validParts);
1704 if (!separators || !separators.length || !parts || parts.length === 0){
1705 throw new Error("Invalid date format.");
1706 }
1707 return {separators: separators, parts: parts};
1708 },
1709 parseDate: function(date, format, language){
1710 if (!date)
1711 return undefined;
1712 if (date instanceof Date)
1713 return date;
1714 if (typeof format === 'string')
1715 format = DPGlobal.parseFormat(format);
1716 if (format.toValue)
1717 return format.toValue(date, format, language);
1718 var part_re = /([\-+]\d+)([dmwy])/,
1719 parts = date.match(/([\-+]\d+)([dmwy])/g),
1720 fn_map = {
1721 d: 'moveDay',
1722 m: 'moveMonth',
1723 w: 'moveWeek',
1724 y: 'moveYear'
1725 },
1726 part, dir, i, fn;
1727 if (/^[\-+]\d+[dmwy]([\s,]+[\-+]\d+[dmwy])*$/.test(date)){
1728 date = new Date();
1729 for (i=0; i < parts.length; i++){
1730 part = part_re.exec(parts[i]);
1731 dir = parseInt(part[1]);
1732 fn = fn_map[part[2]];
1733 date = Datepicker.prototype[fn](date, dir);
1734 }
1735 return UTCDate(date.getUTCFullYear(), date.getUTCMonth(), date.getUTCDate());
1736 }
1737 parts = date && date.match(this.nonpunctuation) || [];
1738 date = new Date();
1739 var parsed = {},
1740 setters_order = ['yyyy', 'yy', 'M', 'MM', 'm', 'mm', 'd', 'dd'],
1741 setters_map = {
1742 yyyy: function(d,v){
1743 return d.setUTCFullYear(v);
1744 },
1745 yy: function(d,v){
1746 return d.setUTCFullYear(2000+v);
1747 },
1748 m: function(d,v){
1749 if (isNaN(d))
1750 return d;
1751 v -= 1;
1752 while (v < 0) v += 12;
1753 v %= 12;
1754 d.setUTCMonth(v);
1755 while (d.getUTCMonth() !== v)
1756 d.setUTCDate(d.getUTCDate()-1);
1757 return d;
1758 },
1759 d: function(d,v){
1760 return d.setUTCDate(v);
1761 }
1762 },
1763 val, filtered;
1764 setters_map['M'] = setters_map['MM'] = setters_map['mm'] = setters_map['m'];
1765 setters_map['dd'] = setters_map['d'];
1766 date = UTCToday();
1767 var fparts = format.parts.slice();
1768 // Remove noop parts
1769 if (parts.length !== fparts.length){
1770 fparts = $(fparts).filter(function(i,p){
1771 return $.inArray(p, setters_order) !== -1;
1772 }).toArray();
1773 }
1774 // Process remainder
1775 function match_part(){
1776 var m = this.slice(0, parts[i].length),
1777 p = parts[i].slice(0, m.length);
1778 return m.toLowerCase() === p.toLowerCase();
1779 }
1780 if (parts.length === fparts.length){
1781 var cnt;
1782 for (i=0, cnt = fparts.length; i < cnt; i++){
1783 val = parseInt(parts[i], 10);
1784 part = fparts[i];
1785 if (isNaN(val)){
1786 switch (part){
1787 case 'MM':
1788 filtered = $(dates[language].months).filter(match_part);
1789 val = $.inArray(filtered[0], dates[language].months) + 1;
1790 break;
1791 case 'M':
1792 filtered = $(dates[language].monthsShort).filter(match_part);
1793 val = $.inArray(filtered[0], dates[language].monthsShort) + 1;
1794 break;
1795 }
1796 }
1797 parsed[part] = val;
1798 }
1799 var _date, s;
1800 for (i=0; i < setters_order.length; i++){
1801 s = setters_order[i];
1802 if (s in parsed && !isNaN(parsed[s])){
1803 _date = new Date(date);
1804 setters_map[s](_date, parsed[s]);
1805 if (!isNaN(_date))
1806 date = _date;
1807 }
1808 }
1809 }
1810 return date;
1811 },
1812 formatDate: function(date, format, language){
1813 if (!date)
1814 return '';
1815 if (typeof format === 'string')
1816 format = DPGlobal.parseFormat(format);
1817 if (format.toDisplay)
1818 return format.toDisplay(date, format, language);
1819 var val = {
1820 d: date.getUTCDate(),
1821 D: dates[language].daysShort[date.getUTCDay()],
1822 DD: dates[language].days[date.getUTCDay()],
1823 m: date.getUTCMonth() + 1,
1824 M: dates[language].monthsShort[date.getUTCMonth()],
1825 MM: dates[language].months[date.getUTCMonth()],
1826 yy: date.getUTCFullYear().toString().substring(2),
1827 yyyy: date.getUTCFullYear()
1828 };
1829 val.dd = (val.d < 10 ? '0' : '') + val.d;
1830 val.mm = (val.m < 10 ? '0' : '') + val.m;
1831 date = [];
1832 var seps = $.extend([], format.separators);
1833 for (var i=0, cnt = format.parts.length; i <= cnt; i++){
1834 if (seps.length)
1835 date.push(seps.shift());
1836 date.push(val[format.parts[i]]);
1837 }
1838 return date.join('');
1839 },
1840 headTemplate: '<thead>'+
1841 '<tr>'+
1842 '<th colspan="7" class="datepicker-title"></th>'+
1843 '</tr>'+
1844 '<tr>'+
1845 '<th class="prev">&#171;</th>'+
1846 '<th colspan="5" class="datepicker-switch"></th>'+
1847 '<th class="next">&#187;</th>'+
1848 '</tr>'+
1849 '</thead>',
1850 contTemplate: '<tbody><tr><td colspan="7"></td></tr></tbody>',
1851 footTemplate: '<tfoot>'+
1852 '<tr>'+
1853 '<th colspan="7" class="today"></th>'+
1854 '</tr>'+
1855 '<tr>'+
1856 '<th colspan="7" class="clear"></th>'+
1857 '</tr>'+
1858 '</tfoot>'
1859 };
1860 DPGlobal.template = '<div class="datepicker">'+
1861 '<div class="datepicker-days">'+
1862 '<table class=" table-condensed">'+
1863 DPGlobal.headTemplate+
1864 '<tbody></tbody>'+
1865 DPGlobal.footTemplate+
1866 '</table>'+
1867 '</div>'+
1868 '<div class="datepicker-months">'+
1869 '<table class="table-condensed">'+
1870 DPGlobal.headTemplate+
1871 DPGlobal.contTemplate+
1872 DPGlobal.footTemplate+
1873 '</table>'+
1874 '</div>'+
1875 '<div class="datepicker-years">'+
1876 '<table class="table-condensed">'+
1877 DPGlobal.headTemplate+
1878 DPGlobal.contTemplate+
1879 DPGlobal.footTemplate+
1880 '</table>'+
1881 '</div>'+
1882 '</div>';
1883
1884 $.fn.datepicker.DPGlobal = DPGlobal;
1885
1886
1887 /* DATEPICKER NO CONFLICT
1888 * =================== */
1889
1890 $.fn.datepicker.noConflict = function(){
1891 $.fn.datepicker = old;
1892 return this;
1893 };
1894
1895 /* DATEPICKER VERSION
1896 * =================== */
1897 $.fn.datepicker.version = '1.5.1';
1898
1899 /* DATEPICKER DATA-API
1900 * ================== */
1901
1902 $(document).on(
1903 'focus.datepicker.data-api click.datepicker.data-api',
1904 '[data-provide="datepicker"]',
1905 function(e){
1906 var $this = $(this);
1907 if ($this.data('datepicker'))
1908 return;
1909 e.preventDefault();
1910 // component click requires us to explicitly show it
1911 datepickerPlugin.call($this, 'show');
1912 }
1913 );
1914 $(function(){
1915 datepickerPlugin.call($('[data-provide="datepicker-inline"]'));
1916 });
1917
1918}));
Source/Libraries/GSF.Web/Model/Scripts/bootstrap-toolkit.js+234−0
@@ -0,0 +1,234 @@
1/*!
2 * Responsive Bootstrap Toolkit
3 * Author: Maciej Gurban
4 * License: MIT
5 * Version: 2.5.1 (2015-11-02)
6 * Origin: https://github.com/maciej-gurban/responsive-bootstrap-toolkit
7 */
8;var ResponsiveBootstrapToolkit = (function($){
9
10 // Internal methods
11 var internal = {
12
13 /**
14 * Breakpoint detection divs for each framework version
15 */
16 detectionDivs: {
17 // Bootstrap 3
18 bootstrap: {
19 'xs': $('<div class="device-xs visible-xs visible-xs-block"></div>'),
20 'sm': $('<div class="device-sm visible-sm visible-sm-block"></div>'),
21 'md': $('<div class="device-md visible-md visible-md-block"></div>'),
22 'lg': $('<div class="device-lg visible-lg visible-lg-block"></div>')
23 },
24 // Foundation 5
25 foundation: {
26 'small': $('<div class="device-xs show-for-small-only"></div>'),
27 'medium': $('<div class="device-sm show-for-medium-only"></div>'),
28 'large': $('<div class="device-md show-for-large-only"></div>'),
29 'xlarge': $('<div class="device-lg show-for-xlarge-only"></div>')
30 }
31 },
32
33 /**
34 * Append visibility divs after DOM laoded
35 */
36 applyDetectionDivs: function() {
37 $(document).ready(function(){
38 $.each(self.breakpoints, function(alias){
39 self.breakpoints[alias].appendTo('.responsive-bootstrap-toolkit');
40 });
41 });
42 },
43
44 /**
45 * Determines whether passed string is a parsable expression
46 */
47 isAnExpression: function( str ) {
48 return (str.charAt(0) == '<' || str.charAt(0) == '>');
49 },
50
51 /**
52 * Splits the expression in into <|> [=] alias
53 */
54 splitExpression: function( str ) {
55
56 // Used operator
57 var operator = str.charAt(0);
58 // Include breakpoint equal to alias?
59 var orEqual = (str.charAt(1) == '=') ? true : false;
60
61 /**
62 * Index at which breakpoint name starts.
63 *
64 * For: >sm, index = 1
65 * For: >=sm, index = 2
66 */
67 var index = 1 + (orEqual ? 1 : 0);
68
69 /**
70 * The remaining part of the expression, after the operator, will be treated as the
71 * breakpoint name to compare with
72 */
73 var breakpointName = str.slice(index);
74
75 return {
76 operator: operator,
77 orEqual: orEqual,
78 breakpointName: breakpointName
79 };
80 },
81
82 /**
83 * Returns true if currently active breakpoint matches the expression
84 */
85 isAnyActive: function( breakpoints ) {
86 var found = false;
87 $.each(breakpoints, function( index, alias ) {
88 // Once first breakpoint matches, return true and break out of the loop
89 if( self.breakpoints[ alias ].is(':visible') ) {
90 found = true;
91 return false;
92 }
93 });
94 return found;
95 },
96
97 /**
98 * Determines whether current breakpoint matches the expression given
99 */
100 isMatchingExpression: function( str ) {
101
102 var expression = internal.splitExpression( str );
103
104 // Get names of all breakpoints
105 var breakpointList = Object.keys(self.breakpoints);
106
107 // Get index of sought breakpoint in the list
108 var pos = breakpointList.indexOf( expression.breakpointName );
109
110 // Breakpoint found
111 if( pos !== -1 ) {
112
113 var start = 0;
114 var end = 0;
115
116 /**
117 * Parsing viewport.is('<=md') we interate from smallest breakpoint ('xs') and end
118 * at 'md' breakpoint, indicated in the expression,
119 * That makes: start = 0, end = 2 (index of 'md' breakpoint)
120 *
121 * Parsing viewport.is('<md') we start at index 'xs' breakpoint, and end at
122 * 'sm' breakpoint, one before 'md'.
123 * Which makes: start = 0, end = 1
124 */
125 if( expression.operator == '<' ) {
126 start = 0;
127 end = expression.orEqual ? ++pos : pos;
128 }
129 /**
130 * Parsing viewport.is('>=sm') we interate from breakpoint 'sm' and end at the end
131 * of breakpoint list.
132 * That makes: start = 1, end = undefined
133 *
134 * Parsing viewport.is('>sm') we start at breakpoint 'md' and end at the end of
135 * breakpoint list.
136 * Which makes: start = 2, end = undefined
137 */
138 if( expression.operator == '>' ) {
139 start = expression.orEqual ? pos : ++pos;
140 end = undefined;
141 }
142
143 var acceptedBreakpoints = breakpointList.slice(start, end);
144
145 return internal.isAnyActive( acceptedBreakpoints );
146
147 }
148 }
149
150 };
151
152 // Public methods and properties
153 var self = {
154
155 /**
156 * Determines default debouncing interval of 'changed' method
157 */
158 interval: 300,
159
160 /**
161 *
162 */
163 framework: null,
164
165 /**
166 * Breakpoint aliases, listed from smallest to biggest
167 */
168 breakpoints: null,
169
170 /**
171 * Returns true if current breakpoint matches passed alias
172 */
173 is: function( str ) {
174 if( internal.isAnExpression( str ) ) {
175 return internal.isMatchingExpression( str );
176 }
177 return self.breakpoints[ str ] && self.breakpoints[ str ].is(':visible');
178 },
179
180 /**
181 * Determines which framework-specific breakpoint detection divs to use
182 */
183 use: function( frameworkName, breakpoints ) {
184 self.framework = frameworkName.toLowerCase();
185
186 if( self.framework === 'bootstrap' || self.framework === 'foundation') {
187 self.breakpoints = internal.detectionDivs[ self.framework ];
188 } else {
189 self.breakpoints = breakpoints;
190 }
191
192 internal.applyDetectionDivs();
193 },
194
195 /**
196 * Returns current breakpoint alias
197 */
198 current: function(){
199 var name = 'unrecognized';
200 $.each(self.breakpoints, function(alias){
201 if (self.is(alias)) {
202 name = alias;
203 }
204 });
205 return name;
206 },
207
208 /*
209 * Waits specified number of miliseconds before executing a callback
210 */
211 changed: function(fn, ms) {
212 var timer;
213 return function(){
214 clearTimeout(timer);
215 timer = setTimeout(function(){
216 fn();
217 }, ms || self.interval);
218 };
219 }
220
221 };
222
223 // Create a placeholder
224 $(document).ready(function(){
225 $('<div class="responsive-bootstrap-toolkit"></div>').appendTo('body');
226 });
227
228 if( self.framework === null ) {
229 self.use('bootstrap');
230 }
231
232 return self;
233
234})(jQuery);

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t