tsichart-core 2.0.0-beta.7 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs CHANGED
@@ -552,50 +552,89 @@ class Utils {
552
552
  }
553
553
  return hclColor.toString();
554
554
  }
555
+ /**
556
+ * Creates an array of colors for split-by series
557
+ * @param displayState - The current display state
558
+ * @param aggKey - The aggregate key
559
+ * @param ignoreIsOnlyAgg - Whether to ignore the "only aggregate" optimization
560
+ * @returns Array of color strings for each split-by
561
+ */
555
562
  static createSplitByColors(displayState, aggKey, ignoreIsOnlyAgg = false) {
556
- if (Object.keys(displayState[aggKey]["splitBys"]).length == 1)
563
+ const splitBys = displayState[aggKey]?.splitBys;
564
+ if (!splitBys) {
565
+ return [];
566
+ }
567
+ const splitByCount = Object.keys(splitBys).length;
568
+ // Early return for single split-by
569
+ if (splitByCount === 1) {
557
570
  return [displayState[aggKey].color];
558
- var isOnlyAgg = Object.keys(displayState).reduce((accum, currAgg) => {
559
- if (currAgg == aggKey)
560
- return accum;
561
- if (displayState[currAgg]["visible"] == false)
562
- return accum && true;
563
- return false;
564
- }, true);
565
- if (isOnlyAgg && !ignoreIsOnlyAgg) {
566
- return this.generateColors(Object.keys(displayState[aggKey]["splitBys"]).length);
567
571
  }
568
- var aggColor = displayState[aggKey].color;
569
- var interpolateColor = d3.scaleLinear().domain([0, Object.keys(displayState[aggKey]["splitBys"]).length])
570
- .range([d3.hcl(aggColor).darker().l, d3.hcl(aggColor).brighter().l]);
571
- var colors = [];
572
- for (var i = 0; i < Object.keys(displayState[aggKey]["splitBys"]).length; i++) {
573
- const newColor = d3.hcl(aggColor);
572
+ // Create cache key for memoization
573
+ const cacheKey = `${aggKey}_${splitByCount}_${displayState[aggKey].color}_${ignoreIsOnlyAgg}`;
574
+ if (this.splitByColorCache.has(cacheKey)) {
575
+ return this.splitByColorCache.get(cacheKey);
576
+ }
577
+ const isOnlyVisibleAgg = !ignoreIsOnlyAgg && this.isOnlyVisibleAggregate(displayState, aggKey);
578
+ let colors;
579
+ if (isOnlyVisibleAgg) {
580
+ // Generate distinct colors when this is the only visible aggregate
581
+ colors = this.generateColors(splitByCount);
582
+ }
583
+ else {
584
+ // Generate color variations based on aggregate color
585
+ colors = this.generateSplitByColorVariations(displayState[aggKey].color, splitByCount);
586
+ }
587
+ // Cache the result
588
+ this.splitByColorCache.set(cacheKey, colors);
589
+ // Limit cache size to prevent memory leaks
590
+ if (this.splitByColorCache.size > 100) {
591
+ const firstKey = this.splitByColorCache.keys().next().value;
592
+ this.splitByColorCache.delete(firstKey);
593
+ }
594
+ return colors;
595
+ }
596
+ /**
597
+ * Helper method to check if an aggregate is the only visible one
598
+ */
599
+ static isOnlyVisibleAggregate(displayState, aggKey) {
600
+ for (const currAgg in displayState) {
601
+ if (currAgg !== aggKey && displayState[currAgg]?.visible !== false) {
602
+ return false;
603
+ }
604
+ }
605
+ return true;
606
+ }
607
+ /**
608
+ * Helper method to generate color variations for split-bys
609
+ */
610
+ static generateSplitByColorVariations(baseColor, count) {
611
+ const baseHcl = d3.hcl(baseColor);
612
+ const interpolateColor = d3.scaleLinear()
613
+ .domain([0, count])
614
+ .range([baseHcl.darker().l, baseHcl.brighter().l]);
615
+ const colors = new Array(count);
616
+ for (let i = 0; i < count; i++) {
617
+ const newColor = d3.hcl(baseColor);
574
618
  newColor.l = interpolateColor(i);
575
- colors.push(newColor.formatHex());
619
+ colors[i] = newColor.formatHex();
576
620
  }
577
621
  return colors;
578
622
  }
623
+ /**
624
+ * Clears the split-by color cache (useful when display state changes significantly)
625
+ */
626
+ static clearSplitByColorCache() {
627
+ this.splitByColorCache.clear();
628
+ }
579
629
  static colorSplitBy(displayState, splitByIndex, aggKey, ignoreIsOnlyAgg = false) {
580
- if (Object.keys(displayState[aggKey]["splitBys"]).length == 1)
581
- return displayState[aggKey].color;
582
- var isOnlyAgg = Object.keys(displayState).reduce((accum, currAgg) => {
583
- if (currAgg == aggKey)
584
- return accum;
585
- if (displayState[currAgg]["visible"] == false)
586
- return accum && true;
587
- return false;
588
- }, true);
589
- if (isOnlyAgg && !ignoreIsOnlyAgg) {
590
- var splitByColors = this.generateColors(Object.keys(displayState[aggKey]["splitBys"]).length);
591
- return splitByColors[splitByIndex];
630
+ const colors = this.createSplitByColors(displayState, aggKey, ignoreIsOnlyAgg);
631
+ if (typeof splitByIndex === 'number' &&
632
+ Number.isInteger(splitByIndex) &&
633
+ splitByIndex >= 0 &&
634
+ splitByIndex < colors.length) {
635
+ return colors[splitByIndex];
592
636
  }
593
- var aggColor = displayState[aggKey].color;
594
- var interpolateColor = d3.scaleLinear().domain([0, Object.keys(displayState[aggKey]["splitBys"]).length])
595
- .range([d3.hcl(aggColor).darker().l, d3.hcl(aggColor).brighter().l]);
596
- const newColor = d3.hcl(aggColor);
597
- newColor.l = interpolateColor(splitByIndex);
598
- return newColor.formatHex();
637
+ return displayState[aggKey]?.color || '#000000';
599
638
  }
600
639
  static getTheme(theme) {
601
640
  return theme ? 'tsi-' + theme : 'tsi-dark';
@@ -1019,6 +1058,7 @@ class Utils {
1019
1058
  }
1020
1059
  }
1021
1060
  Utils.guidForNullTSID = Utils.guid();
1061
+ Utils.splitByColorCache = new Map();
1022
1062
  Utils.equalToEventTarget = (function (current, event) {
1023
1063
  return (current == event.target);
1024
1064
  });
@@ -3437,6 +3477,8 @@ class ContextMenu extends Component {
3437
3477
  this.drawChart = drawChart;
3438
3478
  this.contextMenuElement = d3.select(renderTarget).insert("div", ":first-child")
3439
3479
  .attr("class", "tsi-contextMenu")
3480
+ .attr("aria-label", "Context Menu")
3481
+ .attr("role", "menu")
3440
3482
  .style("left", "0px")
3441
3483
  .style("top", "0px");
3442
3484
  }
@@ -3525,6 +3567,7 @@ class ContextMenu extends Component {
3525
3567
  var actionElementsEntered = actionElements.enter()
3526
3568
  .append("div")
3527
3569
  .attr("class", `tsi-actionElement`)
3570
+ .attr("role", "menuitem")
3528
3571
  .classed('tsi-hasSubMenu', d => d.isNested)
3529
3572
  .merge(actionElements)
3530
3573
  .text(d => d.name)
@@ -3651,6 +3694,7 @@ class Tooltip extends Component {
3651
3694
  }).data([theme]);
3652
3695
  this.tooltipDiv = tooltip.enter().append('div')
3653
3696
  .attr('class', 'tsi-tooltip')
3697
+ .attr('role', 'tooltip')
3654
3698
  .merge(tooltip)
3655
3699
  .each(function (d) {
3656
3700
  d3.select(this).selectAll("*").remove();
@@ -6256,6 +6300,8 @@ class LineChart extends TemporalXAxisComponent {
6256
6300
  label.enter()
6257
6301
  .append("text")
6258
6302
  .attr("class", (d) => `tsi-swimLaneLabel-${lane} tsi-swimLaneLabel ${onClickPresentAndValid(d) ? 'tsi-boldOnHover' : ''}`)
6303
+ .attr("role", "heading")
6304
+ .attr("aria-level", "3")
6259
6305
  .merge(label)
6260
6306
  .style("text-anchor", "middle")
6261
6307
  .attr("transform", d => `translate(${(-this.horizontalLabelOffset + swimlaneLabelConstants.labelLeftPadding)},${(d.offset + d.height / 2)}) rotate(-90)`)
@@ -6280,13 +6326,12 @@ class LineChart extends TemporalXAxisComponent {
6280
6326
  });
6281
6327
  }
6282
6328
  render(data, options, aggregateExpressionOptions) {
6283
- console.log('LineChart render called a');
6284
6329
  super.render(data, options, aggregateExpressionOptions);
6285
6330
  this.originalSwimLanes = this.aggregateExpressionOptions.map((aEO) => {
6286
6331
  return aEO.swimLane;
6287
6332
  });
6288
6333
  this.originalSwimLaneOptions = options.swimLaneOptions;
6289
- this.hasBrush = options && (options.brushMoveAction || options.brushMoveEndAction || options.brushContextMenuActions);
6334
+ this.hasBrush = !!(options && (options.brushMoveAction || options.brushMoveEndAction || options.brushContextMenuActions));
6290
6335
  this.chartOptions.setOptions(options);
6291
6336
  this.chartMargins.right = this.chartOptions.labelSeriesWithMarker ? (SERIESLABELWIDTH + 8) : LINECHARTCHARTMARGINS.right;
6292
6337
  this.width = this.getWidth();
@@ -6335,6 +6380,7 @@ class LineChart extends TemporalXAxisComponent {
6335
6380
  .attr("type", "button")
6336
6381
  .on("click", function () {
6337
6382
  self.overwriteSwimLanes();
6383
+ // cast to any to avoid TS incompatibility when spreading chartOptions instance into ILineChartOptions
6338
6384
  self.render(self.data, { ...self.chartOptions, yAxisState: self.nextStackedState() }, self.aggregateExpressionOptions);
6339
6385
  d3.select(this).attr("aria-label", () => self.getString("set axis state to") + ' ' + self.nextStackedState());
6340
6386
  setTimeout(() => d3.select(this).node().focus(), 200);
@@ -6361,6 +6407,7 @@ class LineChart extends TemporalXAxisComponent {
6361
6407
  this.svgSelection = this.targetElement.append("svg")
6362
6408
  .attr("class", "tsi-lineChartSVG tsi-chartSVG")
6363
6409
  .attr('title', this.getString('Line chart'))
6410
+ .attr("role", "img")
6364
6411
  .attr("height", this.height);
6365
6412
  var g = this.svgSelection.append("g")
6366
6413
  .classed("svgGroup", true)
@@ -6746,6 +6793,54 @@ class LineChart extends TemporalXAxisComponent {
6746
6793
  }
6747
6794
  }
6748
6795
 
6796
+ class TimezonePicker extends ChartComponent {
6797
+ constructor(renderTarget) {
6798
+ super(renderTarget);
6799
+ this.timeZones = ["Local", "UTC", "Africa/Algiers", "Africa/Cairo", "Africa/Casablanca", "Africa/Harare", "Africa/Johannesburg", "Africa/Lagos", "Africa/Nairobi", "Africa/Windhoek", "America/Anchorage", "America/Bogota", "America/Buenos Aires", "America/Caracas", "America/Chicago", "America/Chihuahua", "America/Denver", "America/Edmonton", "America/Godthab", "America/Guatemala", "America/Halifax", "America/Indiana/Indianapolis", "America/Los Angeles", "America/Manaus", "America/Mexico City", "America/Montevideo", "America/New York", "America/Phoenix", "America/Santiago", "America/Sao Paulo", "America/St Johns", "America/Tijuana", "America/Toronto", "America/Vancouver", "America/Winnipeg", "Asia/Amman", "Asia/Beirut", "Asia/Baghdad", "Asia/Baku", "Asia/Bangkok", "Asia/Calcutta", "Asia/Colombo", "Asia/Dhaka", "Asia/Dubai", "Asia/Ho Chi Minh", "Asia/Hong Kong", "Asia/Irkutsk", "Asia/Istanbul", "Asia/Jakarta", "Asia/Jerusalem", "Asia/Kabul", "Asia/Karachi", "Asia/Kathmandu", "Asia/Krasnoyarsk", "Asia/Kuala Lumpur", "Asia/Kuwait", "Asia/Magadan", "Asia/Muscat", "Asia/Novosibirsk", "Asia/Qatar", "Asia/Rangoon", "Asia/Seoul", "Asia/Shanghai", "Asia/Singapore", "Asia/Taipei", "Asia/Tbilisi", "Asia/Tehran", "Asia/Tokyo", "Asia/Vladivostok", "Asia/Yakutsk", "Asia/Yekaterinburg", "Asia/Yerevan", "Atlantic/Azores", "Atlantic/Cape Verde", "Atlantic/South Georgia", "Australia/Adelaide", "Australia/Brisbane", "Australia/Canberra", "Australia/Darwin", "Australia/Hobart", "Australia/Melbourne", "Australia/Perth", "Australia/Queensland", "Australia/Sydney", "Europe/Amsterdam", "Europe/Andorra", "Europe/Athens", "Europe/Belfast", "Europe/Belgrade", "Europe/Berlin", "Europe/Brussels", "Europe/Budapest", "Europe/Dublin", "Europe/Helsinki", "Europe/Kiev", "Europe/Lisbon", "Europe/London", "Europe/Luxembourg", "Europe/Madrid", "Europe/Minsk", "Europe/Monaco", "Europe/Moscow", "Europe/Oslo", "Europe/Paris", "Europe/Rome", "Europe/Stockholm", "Europe/Vienna", "Europe/Warsaw", "Europe/Zurich", "Pacific/Auckland", "Pacific/Fiji", "Pacific/Guam", "Pacific/Honolulu", "Pacific/Midway", "Pacific/Tongatapu"];
6800
+ }
6801
+ sortTimezones() {
6802
+ let filteredTimezones = this.timeZones.filter((tz) => {
6803
+ return !(tz.toLowerCase() == 'local' || tz == 'UTC');
6804
+ });
6805
+ filteredTimezones.sort((a, b) => {
6806
+ let aOffset = moment.tz(new Date(), a.split(' ').join('_')).utcOffset();
6807
+ let bOffset = moment.tz(new Date(), b.split(' ').join('_')).utcOffset();
6808
+ if (aOffset < bOffset) {
6809
+ return -1;
6810
+ }
6811
+ if (aOffset > bOffset) {
6812
+ return 1;
6813
+ }
6814
+ return 0;
6815
+ });
6816
+ this.timeZones = ['Local', 'UTC'].concat(filteredTimezones);
6817
+ }
6818
+ render(onTimezoneSelect, defaultTimeZone = null) {
6819
+ this.targetElement = d3.select(this.renderTarget)
6820
+ .classed("tsi-timezonePicker", true);
6821
+ var timezoneSelection = this.targetElement.append("select")
6822
+ .attr("class", "tsi-timezonePicker tsi-select");
6823
+ this.sortTimezones();
6824
+ var options = timezoneSelection.selectAll("option")
6825
+ .data(this.timeZones)
6826
+ .enter()
6827
+ .append("option")
6828
+ .attr('value', d => d)
6829
+ .text((tz) => Utils.convertTimezoneToLabel(tz, this.getString('Local')));
6830
+ timezoneSelection.on("change", function (d) {
6831
+ var timezone = d3.select(this).node().value.replace(/\s/g, "_");
6832
+ onTimezoneSelect(timezone);
6833
+ });
6834
+ defaultTimeZone = defaultTimeZone.replace(/_/g, " ");
6835
+ if (defaultTimeZone != null) {
6836
+ options.filter((d) => d == defaultTimeZone).attr("selected", true);
6837
+ }
6838
+ return;
6839
+ }
6840
+ }
6841
+
6842
+ var commonjsGlobal = typeof globalThis !== 'undefined' ? globalThis : typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {};
6843
+
6749
6844
  function getDefaultExportFromCjs (x) {
6750
6845
  return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, 'default') ? x['default'] : x;
6751
6846
  }
@@ -6765,1231 +6860,1177 @@ function requirePikaday () {
6765
6860
  if (hasRequiredPikaday) return pikaday$1.exports;
6766
6861
  hasRequiredPikaday = 1;
6767
6862
  (function (module, exports) {
6768
- (function (root, factory)
6769
- {
6863
+ (function (root, factory) {
6770
6864
 
6771
6865
  var moment;
6772
6866
  {
6773
6867
  // CommonJS module
6774
6868
  // Load moment.js as an optional dependency
6775
- try { moment = require('moment'); } catch (e) {}
6869
+ try { moment = require('moment'); } catch (e) { moment = (typeof window !== 'undefined' && window.moment) || undefined; }
6776
6870
  module.exports = factory(moment);
6777
6871
  }
6778
- }(pikaday, function (moment)
6779
- {
6872
+ }(typeof self !== 'undefined' ? self :
6873
+ typeof window !== 'undefined' ? window :
6874
+ typeof commonjsGlobal !== 'undefined' ? commonjsGlobal :
6875
+ pikaday, function (moment) {
6780
6876
 
6781
- /**
6782
- * feature detection and helper functions
6783
- */
6784
- var hasMoment = typeof moment === 'function',
6877
+ /**
6878
+ * feature detection and helper functions
6879
+ */
6880
+ var hasMoment = typeof moment === 'function' || (moment && typeof moment.version === 'string'),
6785
6881
 
6786
- hasEventListeners = !!window.addEventListener,
6882
+ hasEventListeners = !!window.addEventListener,
6787
6883
 
6788
- document = window.document,
6884
+ document = window.document,
6789
6885
 
6790
- sto = window.setTimeout,
6886
+ sto = window.setTimeout,
6791
6887
 
6792
- addEvent = function(el, e, callback, capture)
6793
- {
6794
- if (hasEventListeners) {
6795
- el.addEventListener(e, callback, !!capture);
6796
- } else {
6797
- el.attachEvent('on' + e, callback);
6798
- }
6799
- },
6800
-
6801
- removeEvent = function(el, e, callback, capture)
6802
- {
6803
- if (hasEventListeners) {
6804
- el.removeEventListener(e, callback, !!capture);
6805
- } else {
6806
- el.detachEvent('on' + e, callback);
6807
- }
6808
- },
6809
-
6810
- trim = function(str)
6811
- {
6812
- return str.trim ? str.trim() : str.replace(/^\s+|\s+$/g,'');
6813
- },
6888
+ addEvent = function (el, e, callback, capture) {
6889
+ if (hasEventListeners) {
6890
+ el.addEventListener(e, callback, !!capture);
6891
+ } else {
6892
+ el.attachEvent('on' + e, callback);
6893
+ }
6894
+ },
6814
6895
 
6815
- hasClass = function(el, cn)
6816
- {
6817
- return (' ' + el.className + ' ').indexOf(' ' + cn + ' ') !== -1;
6818
- },
6896
+ removeEvent = function (el, e, callback, capture) {
6897
+ if (hasEventListeners) {
6898
+ el.removeEventListener(e, callback, !!capture);
6899
+ } else {
6900
+ el.detachEvent('on' + e, callback);
6901
+ }
6902
+ },
6819
6903
 
6820
- addClass = function(el, cn)
6821
- {
6822
- if (!hasClass(el, cn)) {
6823
- el.className = (el.className === '') ? cn : el.className + ' ' + cn;
6824
- }
6825
- },
6904
+ trim = function (str) {
6905
+ return str.trim ? str.trim() : str.replace(/^\s+|\s+$/g, '');
6906
+ },
6826
6907
 
6827
- removeClass = function(el, cn)
6828
- {
6829
- el.className = trim((' ' + el.className + ' ').replace(' ' + cn + ' ', ' '));
6830
- },
6908
+ hasClass = function (el, cn) {
6909
+ return (' ' + el.className + ' ').indexOf(' ' + cn + ' ') !== -1;
6910
+ },
6831
6911
 
6832
- isArray = function(obj)
6833
- {
6834
- return (/Array/).test(Object.prototype.toString.call(obj));
6835
- },
6912
+ addClass = function (el, cn) {
6913
+ if (!hasClass(el, cn)) {
6914
+ el.className = (el.className === '') ? cn : el.className + ' ' + cn;
6915
+ }
6916
+ },
6917
+
6918
+ removeClass = function (el, cn) {
6919
+ el.className = trim((' ' + el.className + ' ').replace(' ' + cn + ' ', ' '));
6920
+ },
6921
+
6922
+ isArray = function (obj) {
6923
+ return (/Array/).test(Object.prototype.toString.call(obj));
6924
+ },
6925
+
6926
+ isDate = function (obj) {
6927
+ return (/Date/).test(Object.prototype.toString.call(obj)) && !isNaN(obj.getTime());
6928
+ },
6929
+
6930
+ isWeekend = function (date) {
6931
+ var day = date.getDay();
6932
+ return day === 0 || day === 6;
6933
+ },
6934
+
6935
+ isLeapYear = function (year) {
6936
+ // solution by Matti Virkkunen: http://stackoverflow.com/a/4881951
6937
+ return year % 4 === 0 && year % 100 !== 0 || year % 400 === 0;
6938
+ },
6939
+
6940
+ getDaysInMonth = function (year, month) {
6941
+ return [31, isLeapYear(year) ? 29 : 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31][month];
6942
+ },
6943
+
6944
+ setToStartOfDay = function (date) {
6945
+ if (isDate(date)) date.setHours(0, 0, 0, 0);
6946
+ },
6947
+
6948
+ compareDates = function (a, b) {
6949
+ // weak date comparison (use setToStartOfDay(date) to ensure correct result)
6950
+ return a.getTime() === b.getTime();
6951
+ },
6952
+
6953
+ extend = function (to, from, overwrite) {
6954
+ var prop, hasProp;
6955
+ for (prop in from) {
6956
+ hasProp = to[prop] !== undefined;
6957
+ if (hasProp && typeof from[prop] === 'object' && from[prop] !== null && from[prop].nodeName === undefined) {
6958
+ if (isDate(from[prop])) {
6959
+ if (overwrite) {
6960
+ to[prop] = new Date(from[prop].getTime());
6961
+ }
6962
+ }
6963
+ else if (isArray(from[prop])) {
6964
+ if (overwrite) {
6965
+ to[prop] = from[prop].slice(0);
6966
+ }
6967
+ } else {
6968
+ to[prop] = extend({}, from[prop], overwrite);
6969
+ }
6970
+ } else if (overwrite || !hasProp) {
6971
+ to[prop] = from[prop];
6972
+ }
6973
+ }
6974
+ return to;
6975
+ },
6976
+
6977
+ fireEvent = function (el, eventName, data) {
6978
+ var ev;
6979
+
6980
+ if (document.createEvent) {
6981
+ ev = document.createEvent('HTMLEvents');
6982
+ ev.initEvent(eventName, true, false);
6983
+ ev = extend(ev, data);
6984
+ el.dispatchEvent(ev);
6985
+ } else if (document.createEventObject) {
6986
+ ev = document.createEventObject();
6987
+ ev = extend(ev, data);
6988
+ el.fireEvent('on' + eventName, ev);
6989
+ }
6990
+ },
6836
6991
 
6837
- isDate = function(obj)
6838
- {
6839
- return (/Date/).test(Object.prototype.toString.call(obj)) && !isNaN(obj.getTime());
6840
- },
6992
+ adjustCalendar = function (calendar) {
6993
+ if (calendar.month < 0) {
6994
+ calendar.year -= Math.ceil(Math.abs(calendar.month) / 12);
6995
+ calendar.month += 12;
6996
+ }
6997
+ if (calendar.month > 11) {
6998
+ calendar.year += Math.floor(Math.abs(calendar.month) / 12);
6999
+ calendar.month -= 12;
7000
+ }
7001
+ return calendar;
7002
+ },
6841
7003
 
6842
- isWeekend = function(date)
6843
- {
6844
- var day = date.getDay();
6845
- return day === 0 || day === 6;
6846
- },
7004
+ /**
7005
+ * defaults and localisation
7006
+ */
7007
+ defaults = {
6847
7008
 
6848
- isLeapYear = function(year)
6849
- {
6850
- // solution by Matti Virkkunen: http://stackoverflow.com/a/4881951
6851
- return year % 4 === 0 && year % 100 !== 0 || year % 400 === 0;
6852
- },
7009
+ // bind the picker to a form field
7010
+ field: null,
6853
7011
 
6854
- getDaysInMonth = function(year, month)
6855
- {
6856
- return [31, isLeapYear(year) ? 29 : 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31][month];
6857
- },
7012
+ // automatically show/hide the picker on `field` focus (default `true` if `field` is set)
7013
+ bound: undefined,
6858
7014
 
6859
- setToStartOfDay = function(date)
6860
- {
6861
- if (isDate(date)) date.setHours(0,0,0,0);
6862
- },
7015
+ // position of the datepicker, relative to the field (default to bottom & left)
7016
+ // ('bottom' & 'left' keywords are not used, 'top' & 'right' are modifier on the bottom/left position)
7017
+ position: 'bottom left',
6863
7018
 
6864
- compareDates = function(a,b)
6865
- {
6866
- // weak date comparison (use setToStartOfDay(date) to ensure correct result)
6867
- return a.getTime() === b.getTime();
6868
- },
7019
+ // automatically fit in the viewport even if it means repositioning from the position option
7020
+ reposition: true,
6869
7021
 
6870
- extend = function(to, from, overwrite)
6871
- {
6872
- var prop, hasProp;
6873
- for (prop in from) {
6874
- hasProp = to[prop] !== undefined;
6875
- if (hasProp && typeof from[prop] === 'object' && from[prop] !== null && from[prop].nodeName === undefined) {
6876
- if (isDate(from[prop])) {
6877
- if (overwrite) {
6878
- to[prop] = new Date(from[prop].getTime());
6879
- }
6880
- }
6881
- else if (isArray(from[prop])) {
6882
- if (overwrite) {
6883
- to[prop] = from[prop].slice(0);
6884
- }
6885
- } else {
6886
- to[prop] = extend({}, from[prop], overwrite);
6887
- }
6888
- } else if (overwrite || !hasProp) {
6889
- to[prop] = from[prop];
6890
- }
6891
- }
6892
- return to;
6893
- },
6894
-
6895
- fireEvent = function(el, eventName, data)
6896
- {
6897
- var ev;
7022
+ // the default output format for `.toString()` and `field` value
7023
+ format: 'YYYY-MM-DD',
6898
7024
 
6899
- if (document.createEvent) {
6900
- ev = document.createEvent('HTMLEvents');
6901
- ev.initEvent(eventName, true, false);
6902
- ev = extend(ev, data);
6903
- el.dispatchEvent(ev);
6904
- } else if (document.createEventObject) {
6905
- ev = document.createEventObject();
6906
- ev = extend(ev, data);
6907
- el.fireEvent('on' + eventName, ev);
6908
- }
6909
- },
7025
+ // the toString function which gets passed a current date object and format
7026
+ // and returns a string
7027
+ toString: null,
6910
7028
 
6911
- adjustCalendar = function(calendar) {
6912
- if (calendar.month < 0) {
6913
- calendar.year -= Math.ceil(Math.abs(calendar.month)/12);
6914
- calendar.month += 12;
6915
- }
6916
- if (calendar.month > 11) {
6917
- calendar.year += Math.floor(Math.abs(calendar.month)/12);
6918
- calendar.month -= 12;
6919
- }
6920
- return calendar;
6921
- },
7029
+ // used to create date object from current input string
7030
+ parse: null,
6922
7031
 
6923
- /**
6924
- * defaults and localisation
6925
- */
6926
- defaults = {
7032
+ // the initial date to view when first opened
7033
+ defaultDate: null,
6927
7034
 
6928
- // bind the picker to a form field
6929
- field: null,
7035
+ // make the `defaultDate` the initial selected value
7036
+ setDefaultDate: false,
6930
7037
 
6931
- // automatically show/hide the picker on `field` focus (default `true` if `field` is set)
6932
- bound: undefined,
7038
+ // first day of week (0: Sunday, 1: Monday etc)
7039
+ firstDay: 0,
6933
7040
 
6934
- // position of the datepicker, relative to the field (default to bottom & left)
6935
- // ('bottom' & 'left' keywords are not used, 'top' & 'right' are modifier on the bottom/left position)
6936
- position: 'bottom left',
7041
+ // the default flag for moment's strict date parsing
7042
+ formatStrict: false,
6937
7043
 
6938
- // automatically fit in the viewport even if it means repositioning from the position option
6939
- reposition: true,
7044
+ // the minimum/earliest date that can be selected
7045
+ minDate: null,
7046
+ // the maximum/latest date that can be selected
7047
+ maxDate: null,
6940
7048
 
6941
- // the default output format for `.toString()` and `field` value
6942
- format: 'YYYY-MM-DD',
7049
+ // number of years either side, or array of upper/lower range
7050
+ yearRange: 10,
6943
7051
 
6944
- // the toString function which gets passed a current date object and format
6945
- // and returns a string
6946
- toString: null,
7052
+ // show week numbers at head of row
7053
+ showWeekNumber: false,
6947
7054
 
6948
- // used to create date object from current input string
6949
- parse: null,
7055
+ // Week picker mode
7056
+ pickWholeWeek: false,
6950
7057
 
6951
- // the initial date to view when first opened
6952
- defaultDate: null,
7058
+ // used internally (don't config outside)
7059
+ minYear: 0,
7060
+ maxYear: 9999,
7061
+ minMonth: undefined,
7062
+ maxMonth: undefined,
6953
7063
 
6954
- // make the `defaultDate` the initial selected value
6955
- setDefaultDate: false,
7064
+ startRange: null,
7065
+ endRange: null,
6956
7066
 
6957
- // first day of week (0: Sunday, 1: Monday etc)
6958
- firstDay: 0,
7067
+ isRTL: false,
6959
7068
 
6960
- // the default flag for moment's strict date parsing
6961
- formatStrict: false,
7069
+ // Additional text to append to the year in the calendar title
7070
+ yearSuffix: '',
6962
7071
 
6963
- // the minimum/earliest date that can be selected
6964
- minDate: null,
6965
- // the maximum/latest date that can be selected
6966
- maxDate: null,
7072
+ // Render the month after year in the calendar title
7073
+ showMonthAfterYear: false,
6967
7074
 
6968
- // number of years either side, or array of upper/lower range
6969
- yearRange: 10,
7075
+ // Render days of the calendar grid that fall in the next or previous month
7076
+ showDaysInNextAndPreviousMonths: false,
6970
7077
 
6971
- // show week numbers at head of row
6972
- showWeekNumber: false,
7078
+ // Allows user to select days that fall in the next or previous month
7079
+ enableSelectionDaysInNextAndPreviousMonths: false,
6973
7080
 
6974
- // Week picker mode
6975
- pickWholeWeek: false,
7081
+ // how many months are visible
7082
+ numberOfMonths: 1,
6976
7083
 
6977
- // used internally (don't config outside)
6978
- minYear: 0,
6979
- maxYear: 9999,
6980
- minMonth: undefined,
6981
- maxMonth: undefined,
7084
+ // when numberOfMonths is used, this will help you to choose where the main calendar will be (default `left`, can be set to `right`)
7085
+ // only used for the first display or when a selected date is not visible
7086
+ mainCalendar: 'left',
6982
7087
 
6983
- startRange: null,
6984
- endRange: null,
7088
+ // Specify a DOM element to render the calendar in
7089
+ container: undefined,
6985
7090
 
6986
- isRTL: false,
7091
+ // Blur field when date is selected
7092
+ blurFieldOnSelect: true,
6987
7093
 
6988
- // Additional text to append to the year in the calendar title
6989
- yearSuffix: '',
7094
+ // internationalization
7095
+ i18n: {
7096
+ previousMonth: 'Previous Month',
7097
+ nextMonth: 'Next Month',
7098
+ months: ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'],
7099
+ weekdays: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'],
7100
+ weekdaysShort: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat']
7101
+ },
6990
7102
 
6991
- // Render the month after year in the calendar title
6992
- showMonthAfterYear: false,
7103
+ // Theme Classname
7104
+ theme: null,
6993
7105
 
6994
- // Render days of the calendar grid that fall in the next or previous month
6995
- showDaysInNextAndPreviousMonths: false,
7106
+ // events array
7107
+ events: [],
6996
7108
 
6997
- // Allows user to select days that fall in the next or previous month
6998
- enableSelectionDaysInNextAndPreviousMonths: false,
6999
-
7000
- // how many months are visible
7001
- numberOfMonths: 1,
7109
+ // callback function
7110
+ onSelect: null,
7111
+ onOpen: null,
7112
+ onClose: null,
7113
+ onDraw: null,
7002
7114
 
7003
- // when numberOfMonths is used, this will help you to choose where the main calendar will be (default `left`, can be set to `right`)
7004
- // only used for the first display or when a selected date is not visible
7005
- mainCalendar: 'left',
7115
+ // Enable keyboard input
7116
+ keyboardInput: true
7117
+ },
7006
7118
 
7007
- // Specify a DOM element to render the calendar in
7008
- container: undefined,
7009
7119
 
7010
- // Blur field when date is selected
7011
- blurFieldOnSelect : true,
7120
+ /**
7121
+ * templating functions to abstract HTML rendering
7122
+ */
7123
+ renderDayName = function (opts, day, abbr) {
7124
+ day += opts.firstDay;
7125
+ while (day >= 7) {
7126
+ day -= 7;
7127
+ }
7128
+ return abbr ? opts.i18n.weekdaysShort[day] : opts.i18n.weekdays[day];
7129
+ },
7130
+
7131
+ renderDay = function (opts) {
7132
+ var arr = [];
7133
+ var ariaSelected = 'false';
7134
+ if (opts.isEmpty) {
7135
+ if (opts.showDaysInNextAndPreviousMonths) {
7136
+ arr.push('is-outside-current-month');
7137
+
7138
+ if (!opts.enableSelectionDaysInNextAndPreviousMonths) {
7139
+ arr.push('is-selection-disabled');
7140
+ }
7141
+
7142
+ } else {
7143
+ return '<td class="is-empty"></td>';
7144
+ }
7145
+ }
7146
+ if (opts.isDisabled) {
7147
+ arr.push('is-disabled');
7148
+ }
7149
+ if (opts.isToday) {
7150
+ arr.push('is-today');
7151
+ }
7152
+ if (opts.isSelected) {
7153
+ arr.push('is-selected');
7154
+ ariaSelected = 'true';
7155
+ }
7156
+ if (opts.hasEvent) {
7157
+ arr.push('has-event');
7158
+ }
7159
+ if (opts.isInRange) {
7160
+ arr.push('is-inrange');
7161
+ }
7162
+ if (opts.isStartRange) {
7163
+ arr.push('is-startrange');
7164
+ }
7165
+ if (opts.isEndRange) {
7166
+ arr.push('is-endrange');
7167
+ }
7168
+ return '<td data-day="' + opts.day + '" class="' + arr.join(' ') + '" aria-selected="' + ariaSelected + '">' +
7169
+ '<button tabIndex="-1" class="pika-button pika-day" type="button" ' +
7170
+ 'data-pika-year="' + opts.year + '" data-pika-month="' + opts.month + '" data-pika-day="' + opts.day + '">' +
7171
+ opts.day +
7172
+ '</button>' +
7173
+ '</td>';
7174
+ },
7175
+
7176
+ renderWeek = function (d, m, y) {
7177
+ // Lifted from http://javascript.about.com/library/blweekyear.htm, lightly modified.
7178
+ var onejan = new Date(y, 0, 1),
7179
+ weekNum = Math.ceil((((new Date(y, m, d) - onejan) / 86400000) + onejan.getDay() + 1) / 7);
7180
+ return '<td class="pika-week">' + weekNum + '</td>';
7181
+ },
7182
+
7183
+ renderRow = function (days, isRTL, pickWholeWeek, isRowSelected) {
7184
+ return '<tr class="pika-row' + (pickWholeWeek ? ' pick-whole-week' : '') + (isRowSelected ? ' is-selected' : '') + '">' + (isRTL ? days.reverse() : days).join('') + '</tr>';
7185
+ },
7186
+
7187
+ renderBody = function (rows) {
7188
+ return '<tbody>' + rows.join('') + '</tbody>';
7189
+ },
7190
+
7191
+ renderHead = function (opts) {
7192
+ var i, arr = [];
7193
+ if (opts.showWeekNumber) {
7194
+ arr.push('<th></th>');
7195
+ }
7196
+ for (i = 0; i < 7; i++) {
7197
+ arr.push('<th scope="col"><abbr title="' + renderDayName(opts, i) + '">' + renderDayName(opts, i, true) + '</abbr></th>');
7198
+ }
7199
+ return '<thead><tr>' + (opts.isRTL ? arr.reverse() : arr).join('') + '</tr></thead>';
7200
+ },
7201
+
7202
+ renderTitle = function (instance, c, year, month, refYear, randId) {
7203
+ var i, j, arr,
7204
+ opts = instance._o,
7205
+ isMinYear = year === opts.minYear,
7206
+ isMaxYear = year === opts.maxYear,
7207
+ html = '<div id="' + randId + '" class="pika-title">',
7208
+ monthHtml,
7209
+ yearHtml,
7210
+ prev = true,
7211
+ next = true;
7212
+
7213
+ for (arr = [], i = 0; i < 12; i++) {
7214
+ arr.push('<option value="' + (year === refYear ? i - c : 12 + i - c) + '"' +
7215
+ (i === month ? ' selected="selected"' : '') +
7216
+ ((isMinYear && i < opts.minMonth) || (isMaxYear && i > opts.maxMonth) ? 'disabled="disabled"' : '') + '>' +
7217
+ opts.i18n.months[i] + '</option>');
7218
+ }
7012
7219
 
7013
- // internationalization
7014
- i18n: {
7015
- previousMonth : 'Previous Month',
7016
- nextMonth : 'Next Month',
7017
- months : ['January','February','March','April','May','June','July','August','September','October','November','December'],
7018
- weekdays : ['Sunday','Monday','Tuesday','Wednesday','Thursday','Friday','Saturday'],
7019
- weekdaysShort : ['Sun','Mon','Tue','Wed','Thu','Fri','Sat']
7020
- },
7220
+ monthHtml = '<div class="pika-label">' + opts.i18n.months[month] + '<select aria-label="select month" class="pika-select pika-select-month" tabindex="-1">' + arr.join('') + '</select></div>';
7021
7221
 
7022
- // Theme Classname
7023
- theme: null,
7222
+ if (isArray(opts.yearRange)) {
7223
+ i = opts.yearRange[0];
7224
+ j = opts.yearRange[1] + 1;
7225
+ } else {
7226
+ i = year - opts.yearRange;
7227
+ j = 1 + year + opts.yearRange;
7228
+ }
7024
7229
 
7025
- // events array
7026
- events: [],
7230
+ for (arr = []; i < j && i <= opts.maxYear; i++) {
7231
+ if (i >= opts.minYear) {
7232
+ arr.push('<option value="' + i + '"' + (i === year ? ' selected="selected"' : '') + '>' + (i) + '</option>');
7233
+ }
7234
+ }
7235
+ yearHtml = '<div class="pika-label">' + year + opts.yearSuffix + '<select aria-label="select year" class="pika-select pika-select-year" tabindex="-1">' + arr.join('') + '</select></div>';
7027
7236
 
7028
- // callback function
7029
- onSelect: null,
7030
- onOpen: null,
7031
- onClose: null,
7032
- onDraw: null,
7237
+ if (opts.showMonthAfterYear) {
7238
+ html += yearHtml + monthHtml;
7239
+ } else {
7240
+ html += monthHtml + yearHtml;
7241
+ }
7033
7242
 
7034
- // Enable keyboard input
7035
- keyboardInput: true
7036
- },
7243
+ if (isMinYear && (month === 0 || opts.minMonth >= month)) {
7244
+ prev = false;
7245
+ }
7037
7246
 
7247
+ if (isMaxYear && (month === 11 || opts.maxMonth <= month)) {
7248
+ next = false;
7249
+ }
7038
7250
 
7039
- /**
7040
- * templating functions to abstract HTML rendering
7041
- */
7042
- renderDayName = function(opts, day, abbr)
7043
- {
7044
- day += opts.firstDay;
7045
- while (day >= 7) {
7046
- day -= 7;
7047
- }
7048
- return abbr ? opts.i18n.weekdaysShort[day] : opts.i18n.weekdays[day];
7049
- },
7050
-
7051
- renderDay = function(opts)
7052
- {
7053
- var arr = [];
7054
- var ariaSelected = 'false';
7055
- if (opts.isEmpty) {
7056
- if (opts.showDaysInNextAndPreviousMonths) {
7057
- arr.push('is-outside-current-month');
7058
-
7059
- if(!opts.enableSelectionDaysInNextAndPreviousMonths) {
7060
- arr.push('is-selection-disabled');
7061
- }
7062
-
7063
- } else {
7064
- return '<td class="is-empty"></td>';
7065
- }
7066
- }
7067
- if (opts.isDisabled) {
7068
- arr.push('is-disabled');
7069
- }
7070
- if (opts.isToday) {
7071
- arr.push('is-today');
7072
- }
7073
- if (opts.isSelected) {
7074
- arr.push('is-selected');
7075
- ariaSelected = 'true';
7076
- }
7077
- if (opts.hasEvent) {
7078
- arr.push('has-event');
7079
- }
7080
- if (opts.isInRange) {
7081
- arr.push('is-inrange');
7082
- }
7083
- if (opts.isStartRange) {
7084
- arr.push('is-startrange');
7085
- }
7086
- if (opts.isEndRange) {
7087
- arr.push('is-endrange');
7088
- }
7089
- return '<td data-day="' + opts.day + '" class="' + arr.join(' ') + '" aria-selected="' + ariaSelected + '">' +
7090
- '<button tabIndex="-1" class="pika-button pika-day" type="button" ' +
7091
- 'data-pika-year="' + opts.year + '" data-pika-month="' + opts.month + '" data-pika-day="' + opts.day + '">' +
7092
- opts.day +
7093
- '</button>' +
7094
- '</td>';
7095
- },
7096
-
7097
- renderWeek = function (d, m, y) {
7098
- // Lifted from http://javascript.about.com/library/blweekyear.htm, lightly modified.
7099
- var onejan = new Date(y, 0, 1),
7100
- weekNum = Math.ceil((((new Date(y, m, d) - onejan) / 86400000) + onejan.getDay()+1)/7);
7101
- return '<td class="pika-week">' + weekNum + '</td>';
7102
- },
7103
-
7104
- renderRow = function(days, isRTL, pickWholeWeek, isRowSelected)
7105
- {
7106
- return '<tr class="pika-row' + (pickWholeWeek ? ' pick-whole-week' : '') + (isRowSelected ? ' is-selected' : '') + '">' + (isRTL ? days.reverse() : days).join('') + '</tr>';
7107
- },
7251
+ if (c === 0) {
7252
+ html += '<button tabIndex="-1" class="pika-prev' + (prev ? '' : ' is-disabled') + '" type="button">' + opts.i18n.previousMonth + '</button>';
7253
+ }
7254
+ if (c === (instance._o.numberOfMonths - 1)) {
7255
+ html += '<button tabIndex="-1" class="pika-next' + (next ? '' : ' is-disabled') + '" type="button">' + opts.i18n.nextMonth + '</button>';
7256
+ }
7108
7257
 
7109
- renderBody = function(rows)
7110
- {
7111
- return '<tbody>' + rows.join('') + '</tbody>';
7112
- },
7258
+ return html += '</div>';
7259
+ },
7113
7260
 
7114
- renderHead = function(opts)
7115
- {
7116
- var i, arr = [];
7117
- if (opts.showWeekNumber) {
7118
- arr.push('<th></th>');
7119
- }
7120
- for (i = 0; i < 7; i++) {
7121
- arr.push('<th scope="col"><abbr title="' + renderDayName(opts, i) + '">' + renderDayName(opts, i, true) + '</abbr></th>');
7122
- }
7123
- return '<thead><tr>' + (opts.isRTL ? arr.reverse() : arr).join('') + '</tr></thead>';
7124
- },
7125
-
7126
- renderTitle = function(instance, c, year, month, refYear, randId)
7127
- {
7128
- var i, j, arr,
7129
- opts = instance._o,
7130
- isMinYear = year === opts.minYear,
7131
- isMaxYear = year === opts.maxYear,
7132
- html = '<div id="' + randId + '" class="pika-title">',
7133
- monthHtml,
7134
- yearHtml,
7135
- prev = true,
7136
- next = true;
7137
-
7138
- for (arr = [], i = 0; i < 12; i++) {
7139
- arr.push('<option value="' + (year === refYear ? i - c : 12 + i - c) + '"' +
7140
- (i === month ? ' selected="selected"': '') +
7141
- ((isMinYear && i < opts.minMonth) || (isMaxYear && i > opts.maxMonth) ? 'disabled="disabled"' : '') + '>' +
7142
- opts.i18n.months[i] + '</option>');
7143
- }
7144
-
7145
- monthHtml = '<div class="pika-label">' + opts.i18n.months[month] + '<select aria-label="select month" class="pika-select pika-select-month" tabindex="-1">' + arr.join('') + '</select></div>';
7146
-
7147
- if (isArray(opts.yearRange)) {
7148
- i = opts.yearRange[0];
7149
- j = opts.yearRange[1] + 1;
7150
- } else {
7151
- i = year - opts.yearRange;
7152
- j = 1 + year + opts.yearRange;
7153
- }
7154
-
7155
- for (arr = []; i < j && i <= opts.maxYear; i++) {
7156
- if (i >= opts.minYear) {
7157
- arr.push('<option value="' + i + '"' + (i === year ? ' selected="selected"': '') + '>' + (i) + '</option>');
7158
- }
7159
- }
7160
- yearHtml = '<div class="pika-label">' + year + opts.yearSuffix + '<select aria-label="select year" class="pika-select pika-select-year" tabindex="-1">' + arr.join('') + '</select></div>';
7161
-
7162
- if (opts.showMonthAfterYear) {
7163
- html += yearHtml + monthHtml;
7164
- } else {
7165
- html += monthHtml + yearHtml;
7166
- }
7167
-
7168
- if (isMinYear && (month === 0 || opts.minMonth >= month)) {
7169
- prev = false;
7170
- }
7171
-
7172
- if (isMaxYear && (month === 11 || opts.maxMonth <= month)) {
7173
- next = false;
7174
- }
7175
-
7176
- if (c === 0) {
7177
- html += '<button tabIndex="-1" class="pika-prev' + (prev ? '' : ' is-disabled') + '" type="button">' + opts.i18n.previousMonth + '</button>';
7178
- }
7179
- if (c === (instance._o.numberOfMonths - 1) ) {
7180
- html += '<button tabIndex="-1" class="pika-next' + (next ? '' : ' is-disabled') + '" type="button">' + opts.i18n.nextMonth + '</button>';
7181
- }
7182
-
7183
- return html += '</div>';
7184
- },
7185
-
7186
- renderTable = function(opts, data, randId)
7187
- {
7188
- return '<table cellpadding="0" cellspacing="0" class="pika-table" role="grid" aria-labelledby="' + randId + '">' + renderHead(opts) + renderBody(data) + '</table>';
7189
- },
7261
+ renderTable = function (opts, data, randId) {
7262
+ return '<table cellpadding="0" cellspacing="0" class="pika-table" role="grid" aria-labelledby="' + randId + '">' + renderHead(opts) + renderBody(data) + '</table>';
7263
+ },
7190
7264
 
7191
7265
 
7192
- /**
7193
- * Pikaday constructor
7194
- */
7195
- Pikaday = function(options)
7196
- {
7197
- var self = this,
7198
- opts = self.config(options);
7199
-
7200
- self._onMouseDown = function(e)
7201
- {
7202
- if (!self._v) {
7203
- return;
7204
- }
7205
- e = e || window.event;
7206
- var target = e.target || e.srcElement;
7207
- if (!target) {
7208
- return;
7209
- }
7210
-
7211
- if (!hasClass(target, 'is-disabled')) {
7212
- if (hasClass(target, 'pika-button') && !hasClass(target, 'is-empty') && !hasClass(target.parentNode, 'is-disabled')) {
7213
- self.setDate(new Date(target.getAttribute('data-pika-year'), target.getAttribute('data-pika-month'), target.getAttribute('data-pika-day')));
7214
- if (opts.bound) {
7215
- sto(function() {
7216
- self.hide();
7217
- if (opts.blurFieldOnSelect && opts.field) {
7218
- opts.field.blur();
7266
+ /**
7267
+ * Pikaday constructor
7268
+ */
7269
+ Pikaday = function (options) {
7270
+ var self = this,
7271
+ opts = self.config(options);
7272
+
7273
+ self._onMouseDown = function (e) {
7274
+ if (!self._v) {
7275
+ return;
7219
7276
  }
7220
- }, 100);
7221
- }
7222
- }
7223
- else if (hasClass(target, 'pika-prev')) {
7224
- self.prevMonth();
7225
- }
7226
- else if (hasClass(target, 'pika-next')) {
7227
- self.nextMonth();
7228
- }
7229
- }
7230
- if (!hasClass(target, 'pika-select')) {
7231
- // if this is touch event prevent mouse events emulation
7232
- if (e.preventDefault) {
7233
- e.preventDefault();
7234
- } else {
7235
- e.returnValue = false;
7236
- return false;
7237
- }
7238
- } else {
7239
- self._c = true;
7240
- }
7241
- };
7242
-
7243
- self._onChange = function(e)
7244
- {
7245
- e = e || window.event;
7246
- var target = e.target || e.srcElement;
7247
- if (!target) {
7248
- return;
7249
- }
7250
- if (hasClass(target, 'pika-select-month')) {
7251
- self.gotoMonth(target.value);
7252
- }
7253
- else if (hasClass(target, 'pika-select-year')) {
7254
- self.gotoYear(target.value);
7255
- }
7256
- };
7257
-
7258
- self._onKeyChange = function(e)
7259
- {
7260
- e = e || window.event;
7261
- // ignore if event comes from input box
7262
- if (self.isVisible() && e.target && e.target.type !== 'text') {
7263
-
7264
- switch(e.keyCode){
7265
- case 13:
7266
- case 27:
7277
+ e = e || window.event;
7278
+ var target = e.target || e.srcElement;
7279
+ if (!target) {
7280
+ return;
7281
+ }
7282
+
7283
+ if (!hasClass(target, 'is-disabled')) {
7284
+ if (hasClass(target, 'pika-button') && !hasClass(target, 'is-empty') && !hasClass(target.parentNode, 'is-disabled')) {
7285
+ self.setDate(new Date(target.getAttribute('data-pika-year'), target.getAttribute('data-pika-month'), target.getAttribute('data-pika-day')));
7286
+ if (opts.bound) {
7287
+ sto(function () {
7288
+ self.hide();
7289
+ if (opts.blurFieldOnSelect && opts.field) {
7290
+ opts.field.blur();
7291
+ }
7292
+ }, 100);
7293
+ }
7294
+ }
7295
+ else if (hasClass(target, 'pika-prev')) {
7296
+ self.prevMonth();
7297
+ }
7298
+ else if (hasClass(target, 'pika-next')) {
7299
+ self.nextMonth();
7300
+ }
7301
+ }
7302
+ if (!hasClass(target, 'pika-select')) {
7303
+ // if this is touch event prevent mouse events emulation
7304
+ if (e.preventDefault) {
7305
+ e.preventDefault();
7306
+ } else {
7307
+ e.returnValue = false;
7308
+ return false;
7309
+ }
7310
+ } else {
7311
+ self._c = true;
7312
+ }
7313
+ };
7314
+
7315
+ self._onChange = function (e) {
7316
+ e = e || window.event;
7317
+ var target = e.target || e.srcElement;
7318
+ if (!target) {
7319
+ return;
7320
+ }
7321
+ if (hasClass(target, 'pika-select-month')) {
7322
+ self.gotoMonth(target.value);
7323
+ }
7324
+ else if (hasClass(target, 'pika-select-year')) {
7325
+ self.gotoYear(target.value);
7326
+ }
7327
+ };
7328
+
7329
+ self._onKeyChange = function (e) {
7330
+ e = e || window.event;
7331
+ // ignore if event comes from input box
7332
+ if (self.isVisible() && e.target && e.target.type !== 'text') {
7333
+
7334
+ switch (e.keyCode) {
7335
+ case 13:
7336
+ case 27:
7337
+ if (opts.field) {
7338
+ opts.field.blur();
7339
+ }
7340
+ break;
7341
+ case 37:
7342
+ e.preventDefault();
7343
+ self.adjustDate('subtract', 1);
7344
+ break;
7345
+ case 38:
7346
+ self.adjustDate('subtract', 7);
7347
+ break;
7348
+ case 39:
7349
+ self.adjustDate('add', 1);
7350
+ break;
7351
+ case 40:
7352
+ self.adjustDate('add', 7);
7353
+ break;
7354
+ }
7355
+ }
7356
+ };
7357
+
7358
+ self._onInputChange = function (e) {
7359
+ var date;
7360
+
7361
+ if (e.firedBy === self) {
7362
+ return;
7363
+ }
7364
+ if (opts.parse) {
7365
+ date = opts.parse(opts.field.value, opts.format);
7366
+ } else if (hasMoment) {
7367
+ date = moment(opts.field.value, opts.format, opts.formatStrict);
7368
+ date = (date && date.isValid()) ? date.toDate() : null;
7369
+ }
7370
+ else {
7371
+ date = new Date(Date.parse(opts.field.value));
7372
+ }
7373
+ // if (isDate(date)) {
7374
+ // self.setDate(date);
7375
+ // }
7376
+ // if (!self._v) {
7377
+ // self.show();
7378
+ // }
7379
+ };
7380
+
7381
+ self._onInputFocus = function () {
7382
+ self.show();
7383
+ };
7384
+
7385
+ self._onInputClick = function () {
7386
+ self.show();
7387
+ };
7388
+
7389
+ self._onInputBlur = function () {
7390
+ // IE allows pika div to gain focus; catch blur the input field
7391
+ var pEl = document.activeElement;
7392
+ do {
7393
+ if (hasClass(pEl, 'pika-single')) {
7394
+ return;
7395
+ }
7396
+ }
7397
+ while ((pEl = pEl.parentNode));
7398
+
7399
+ if (!self._c) {
7400
+ self._b = sto(function () {
7401
+ self.hide();
7402
+ }, 50);
7403
+ }
7404
+ self._c = false;
7405
+ };
7406
+
7407
+ self._onClick = function (e) {
7408
+ e = e || window.event;
7409
+ var target = e.target || e.srcElement,
7410
+ pEl = target;
7411
+ if (!target) {
7412
+ return;
7413
+ }
7414
+ if (!hasEventListeners && hasClass(target, 'pika-select')) {
7415
+ if (!target.onchange) {
7416
+ target.setAttribute('onchange', 'return;');
7417
+ addEvent(target, 'change', self._onChange);
7418
+ }
7419
+ }
7420
+ do {
7421
+ if (hasClass(pEl, 'pika-single') || pEl === opts.trigger) {
7422
+ return;
7423
+ }
7424
+ }
7425
+ while ((pEl = pEl.parentNode));
7426
+ if (self._v && target !== opts.trigger && pEl !== opts.trigger) {
7427
+ self.hide();
7428
+ }
7429
+ };
7430
+
7431
+ self.el = document.createElement('div');
7432
+ self.el.className = 'pika-single' + (opts.isRTL ? ' is-rtl' : '') + (opts.theme ? ' ' + opts.theme : '');
7433
+
7434
+ addEvent(self.el, 'mousedown', self._onMouseDown, true);
7435
+ addEvent(self.el, 'touchend', self._onMouseDown, true);
7436
+ addEvent(self.el, 'change', self._onChange);
7437
+
7438
+ if (opts.keyboardInput) {
7439
+ addEvent(document, 'keydown', self._onKeyChange);
7440
+ }
7441
+
7267
7442
  if (opts.field) {
7268
- opts.field.blur();
7443
+ if (opts.container) {
7444
+ opts.container.appendChild(self.el);
7445
+ } else if (opts.bound) {
7446
+ document.body.appendChild(self.el);
7447
+ } else {
7448
+ opts.field.parentNode.insertBefore(self.el, opts.field.nextSibling);
7449
+ }
7450
+ addEvent(opts.field, 'change', self._onInputChange);
7451
+
7452
+ if (!opts.defaultDate) {
7453
+ if (hasMoment && opts.field.value) {
7454
+ opts.defaultDate = moment(opts.field.value, opts.format).toDate();
7455
+ } else {
7456
+ opts.defaultDate = new Date(Date.parse(opts.field.value));
7457
+ }
7458
+ opts.setDefaultDate = true;
7459
+ }
7460
+ }
7461
+
7462
+ var defDate = opts.defaultDate;
7463
+
7464
+ if (isDate(defDate)) {
7465
+ if (opts.setDefaultDate) {
7466
+ self.setDate(defDate, true);
7467
+ } else {
7468
+ self.gotoDate(defDate);
7469
+ }
7470
+ } else {
7471
+ self.gotoDate(new Date());
7472
+ }
7473
+
7474
+ if (opts.bound) {
7475
+ this.hide();
7476
+ self.el.className += ' is-bound';
7477
+ addEvent(opts.trigger, 'click', self._onInputClick);
7478
+ addEvent(opts.trigger, 'focus', self._onInputFocus);
7479
+ addEvent(opts.trigger, 'blur', self._onInputBlur);
7480
+ } else {
7481
+ this.show();
7269
7482
  }
7270
- break;
7271
- case 37:
7272
- e.preventDefault();
7273
- self.adjustDate('subtract', 1);
7274
- break;
7275
- case 38:
7276
- self.adjustDate('subtract', 7);
7277
- break;
7278
- case 39:
7279
- self.adjustDate('add', 1);
7280
- break;
7281
- case 40:
7282
- self.adjustDate('add', 7);
7283
- break;
7284
- }
7285
- }
7286
- };
7287
-
7288
- self._onInputChange = function(e)
7289
- {
7290
- var date;
7291
-
7292
- if (e.firedBy === self) {
7293
- return;
7294
- }
7295
- if (opts.parse) {
7296
- date = opts.parse(opts.field.value, opts.format);
7297
- } else if (hasMoment) {
7298
- date = moment(opts.field.value, opts.format, opts.formatStrict);
7299
- date = (date && date.isValid()) ? date.toDate() : null;
7300
- }
7301
- else {
7302
- date = new Date(Date.parse(opts.field.value));
7303
- }
7304
- // if (isDate(date)) {
7305
- // self.setDate(date);
7306
- // }
7307
- // if (!self._v) {
7308
- // self.show();
7309
- // }
7310
- };
7311
-
7312
- self._onInputFocus = function()
7313
- {
7314
- self.show();
7315
- };
7316
-
7317
- self._onInputClick = function()
7318
- {
7319
- self.show();
7320
- };
7321
-
7322
- self._onInputBlur = function()
7323
- {
7324
- // IE allows pika div to gain focus; catch blur the input field
7325
- var pEl = document.activeElement;
7326
- do {
7327
- if (hasClass(pEl, 'pika-single')) {
7328
- return;
7329
- }
7330
- }
7331
- while ((pEl = pEl.parentNode));
7332
-
7333
- if (!self._c) {
7334
- self._b = sto(function() {
7335
- self.hide();
7336
- }, 50);
7337
- }
7338
- self._c = false;
7339
- };
7340
-
7341
- self._onClick = function(e)
7342
- {
7343
- e = e || window.event;
7344
- var target = e.target || e.srcElement,
7345
- pEl = target;
7346
- if (!target) {
7347
- return;
7348
- }
7349
- if (!hasEventListeners && hasClass(target, 'pika-select')) {
7350
- if (!target.onchange) {
7351
- target.setAttribute('onchange', 'return;');
7352
- addEvent(target, 'change', self._onChange);
7353
- }
7354
- }
7355
- do {
7356
- if (hasClass(pEl, 'pika-single') || pEl === opts.trigger) {
7357
- return;
7358
- }
7359
- }
7360
- while ((pEl = pEl.parentNode));
7361
- if (self._v && target !== opts.trigger && pEl !== opts.trigger) {
7362
- self.hide();
7363
- }
7364
- };
7365
-
7366
- self.el = document.createElement('div');
7367
- self.el.className = 'pika-single' + (opts.isRTL ? ' is-rtl' : '') + (opts.theme ? ' ' + opts.theme : '');
7368
-
7369
- addEvent(self.el, 'mousedown', self._onMouseDown, true);
7370
- addEvent(self.el, 'touchend', self._onMouseDown, true);
7371
- addEvent(self.el, 'change', self._onChange);
7372
-
7373
- if (opts.keyboardInput) {
7374
- addEvent(document, 'keydown', self._onKeyChange);
7375
- }
7376
-
7377
- if (opts.field) {
7378
- if (opts.container) {
7379
- opts.container.appendChild(self.el);
7380
- } else if (opts.bound) {
7381
- document.body.appendChild(self.el);
7382
- } else {
7383
- opts.field.parentNode.insertBefore(self.el, opts.field.nextSibling);
7384
- }
7385
- addEvent(opts.field, 'change', self._onInputChange);
7386
-
7387
- if (!opts.defaultDate) {
7388
- if (hasMoment && opts.field.value) {
7389
- opts.defaultDate = moment(opts.field.value, opts.format).toDate();
7390
- } else {
7391
- opts.defaultDate = new Date(Date.parse(opts.field.value));
7392
- }
7393
- opts.setDefaultDate = true;
7394
- }
7395
- }
7396
-
7397
- var defDate = opts.defaultDate;
7398
-
7399
- if (isDate(defDate)) {
7400
- if (opts.setDefaultDate) {
7401
- self.setDate(defDate, true);
7402
- } else {
7403
- self.gotoDate(defDate);
7404
- }
7405
- } else {
7406
- self.gotoDate(new Date());
7407
- }
7408
-
7409
- if (opts.bound) {
7410
- this.hide();
7411
- self.el.className += ' is-bound';
7412
- addEvent(opts.trigger, 'click', self._onInputClick);
7413
- addEvent(opts.trigger, 'focus', self._onInputFocus);
7414
- addEvent(opts.trigger, 'blur', self._onInputBlur);
7415
- } else {
7416
- this.show();
7417
- }
7418
- };
7419
-
7420
-
7421
- /**
7422
- * public Pikaday API
7423
- */
7424
- Pikaday.prototype = {
7425
-
7426
-
7427
- /**
7428
- * configure functionality
7429
- */
7430
- config: function(options)
7431
- {
7432
- if (!this._o) {
7433
- this._o = extend({}, defaults, true);
7434
- }
7435
-
7436
- var opts = extend(this._o, options, true);
7437
-
7438
- opts.isRTL = !!opts.isRTL;
7439
-
7440
- opts.field = (opts.field && opts.field.nodeName) ? opts.field : null;
7441
-
7442
- opts.theme = (typeof opts.theme) === 'string' && opts.theme ? opts.theme : null;
7443
-
7444
- opts.bound = !!(opts.bound !== undefined ? opts.field && opts.bound : opts.field);
7445
-
7446
- opts.trigger = (opts.trigger && opts.trigger.nodeName) ? opts.trigger : opts.field;
7447
-
7448
- opts.disableWeekends = !!opts.disableWeekends;
7449
-
7450
- opts.disableDayFn = (typeof opts.disableDayFn) === 'function' ? opts.disableDayFn : null;
7451
-
7452
- var nom = parseInt(opts.numberOfMonths, 10) || 1;
7453
- opts.numberOfMonths = nom > 4 ? 4 : nom;
7454
-
7455
- if (!isDate(opts.minDate)) {
7456
- opts.minDate = false;
7457
- }
7458
- if (!isDate(opts.maxDate)) {
7459
- opts.maxDate = false;
7460
- }
7461
- if ((opts.minDate && opts.maxDate) && opts.maxDate < opts.minDate) {
7462
- opts.maxDate = opts.minDate = false;
7463
- }
7464
- if (opts.minDate) {
7465
- this.setMinDate(opts.minDate);
7466
- }
7467
- if (opts.maxDate) {
7468
- this.setMaxDate(opts.maxDate);
7469
- }
7470
-
7471
- if (isArray(opts.yearRange)) {
7472
- var fallback = new Date().getFullYear() - 10;
7473
- opts.yearRange[0] = parseInt(opts.yearRange[0], 10) || fallback;
7474
- opts.yearRange[1] = parseInt(opts.yearRange[1], 10) || fallback;
7475
- } else {
7476
- opts.yearRange = Math.abs(parseInt(opts.yearRange, 10)) || defaults.yearRange;
7477
- if (opts.yearRange > 100) {
7478
- opts.yearRange = 100;
7479
- }
7480
- }
7481
-
7482
- return opts;
7483
- },
7484
-
7485
- /**
7486
- * return a formatted string of the current selection (using Moment.js if available)
7487
- */
7488
- toString: function(format)
7489
- {
7490
- format = format || this._o.format;
7491
- if (!isDate(this._d)) {
7492
- return '';
7493
- }
7494
- if (this._o.toString) {
7495
- return this._o.toString(this._d, format);
7496
- }
7497
- if (hasMoment) {
7498
- return moment(this._d).format(format);
7499
- }
7500
- return this._d.toDateString();
7501
- },
7502
-
7503
- /**
7504
- * return a Moment.js object of the current selection (if available)
7505
- */
7506
- getMoment: function()
7507
- {
7508
- return hasMoment ? moment(this._d) : null;
7509
- },
7510
-
7511
- /**
7512
- * set the current selection from a Moment.js object (if available)
7513
- */
7514
- setMoment: function(date, preventOnSelect)
7515
- {
7516
- if (hasMoment && moment.isMoment(date)) {
7517
- this.setDate(date.toDate(), preventOnSelect);
7518
- }
7519
- },
7520
-
7521
- /**
7522
- * return a Date object of the current selection
7523
- */
7524
- getDate: function()
7525
- {
7526
- return isDate(this._d) ? new Date(this._d.getTime()) : null;
7527
- },
7528
-
7529
- /**
7530
- * set the current selection
7531
- */
7532
- setDate: function(date, preventOnSelect)
7533
- {
7534
- if (!date) {
7535
- this._d = null;
7536
-
7537
- if (this._o.field) {
7538
- this._o.field.value = '';
7539
- fireEvent(this._o.field, 'change', { firedBy: this });
7540
- }
7541
-
7542
- return this.draw();
7543
- }
7544
- if (typeof date === 'string') {
7545
- date = new Date(Date.parse(date));
7546
- }
7547
- if (!isDate(date)) {
7548
- return;
7549
- }
7550
-
7551
- var min = this._o.minDate,
7552
- max = this._o.maxDate;
7553
-
7554
- if (isDate(min) && date < min) {
7555
- date = min;
7556
- } else if (isDate(max) && date > max) {
7557
- date = max;
7558
- }
7559
-
7560
- this._d = new Date(date.getTime());
7561
- setToStartOfDay(this._d);
7562
- this.gotoDate(this._d);
7563
-
7564
- if (this._o.field) {
7565
- this._o.field.value = this.toString();
7566
- fireEvent(this._o.field, 'change', { firedBy: this });
7567
- }
7568
- if (!preventOnSelect && typeof this._o.onSelect === 'function') {
7569
- this._o.onSelect.call(this, this.getDate());
7570
- }
7571
- },
7572
-
7573
- /**
7574
- * change view to a specific date
7575
- */
7576
- gotoDate: function(date)
7577
- {
7578
- var newCalendar = true;
7579
-
7580
- if (!isDate(date)) {
7581
- return;
7582
- }
7583
-
7584
- if (this.calendars) {
7585
- var firstVisibleDate = new Date(this.calendars[0].year, this.calendars[0].month, 1),
7586
- lastVisibleDate = new Date(this.calendars[this.calendars.length-1].year, this.calendars[this.calendars.length-1].month, 1),
7587
- visibleDate = date.getTime();
7588
- // get the end of the month
7589
- lastVisibleDate.setMonth(lastVisibleDate.getMonth()+1);
7590
- lastVisibleDate.setDate(lastVisibleDate.getDate()-1);
7591
- newCalendar = (visibleDate < firstVisibleDate.getTime() || lastVisibleDate.getTime() < visibleDate);
7592
- }
7593
-
7594
- if (newCalendar) {
7595
- this.calendars = [{
7596
- month: date.getMonth(),
7597
- year: date.getFullYear()
7598
- }];
7599
- if (this._o.mainCalendar === 'right') {
7600
- this.calendars[0].month += 1 - this._o.numberOfMonths;
7601
- }
7602
- }
7603
-
7604
- this.adjustCalendars();
7605
- },
7606
-
7607
- adjustDate: function(sign, days) {
7608
-
7609
- var day = this.getDate() || new Date();
7610
- var difference = parseInt(days)*24*60*60*1000;
7611
-
7612
- var newDay;
7613
-
7614
- if (sign === 'add') {
7615
- newDay = new Date(day.valueOf() + difference);
7616
- } else if (sign === 'subtract') {
7617
- newDay = new Date(day.valueOf() - difference);
7618
- }
7619
-
7620
- this.setDate(newDay);
7621
- },
7622
-
7623
- adjustCalendars: function() {
7624
- this.calendars[0] = adjustCalendar(this.calendars[0]);
7625
- for (var c = 1; c < this._o.numberOfMonths; c++) {
7626
- this.calendars[c] = adjustCalendar({
7627
- month: this.calendars[0].month + c,
7628
- year: this.calendars[0].year
7629
- });
7630
- }
7631
- this.draw();
7632
- },
7633
-
7634
- gotoToday: function()
7635
- {
7636
- this.gotoDate(new Date());
7637
- },
7638
-
7639
- /**
7640
- * change view to a specific month (zero-index, e.g. 0: January)
7641
- */
7642
- gotoMonth: function(month)
7643
- {
7644
- if (!isNaN(month)) {
7645
- this.calendars[0].month = parseInt(month, 10);
7646
- this.adjustCalendars();
7647
- }
7648
- },
7649
-
7650
- nextMonth: function()
7651
- {
7652
- this.calendars[0].month++;
7653
- this.adjustCalendars();
7654
- },
7655
-
7656
- prevMonth: function()
7657
- {
7658
- this.calendars[0].month--;
7659
- this.adjustCalendars();
7660
- },
7661
-
7662
- /**
7663
- * change view to a specific full year (e.g. "2012")
7664
- */
7665
- gotoYear: function(year)
7666
- {
7667
- if (!isNaN(year)) {
7668
- this.calendars[0].year = parseInt(year, 10);
7669
- this.adjustCalendars();
7670
- }
7671
- },
7672
-
7673
- /**
7674
- * change the minDate
7675
- */
7676
- setMinDate: function(value)
7677
- {
7678
- if(value instanceof Date) {
7679
- setToStartOfDay(value);
7680
- this._o.minDate = value;
7681
- this._o.minYear = value.getFullYear();
7682
- this._o.minMonth = value.getMonth();
7683
- } else {
7684
- this._o.minDate = defaults.minDate;
7685
- this._o.minYear = defaults.minYear;
7686
- this._o.minMonth = defaults.minMonth;
7687
- this._o.startRange = defaults.startRange;
7688
- }
7689
-
7690
- this.draw();
7691
- },
7692
-
7693
- /**
7694
- * change the maxDate
7695
- */
7696
- setMaxDate: function(value)
7697
- {
7698
- if(value instanceof Date) {
7699
- setToStartOfDay(value);
7700
- this._o.maxDate = value;
7701
- this._o.maxYear = value.getFullYear();
7702
- this._o.maxMonth = value.getMonth();
7703
- } else {
7704
- this._o.maxDate = defaults.maxDate;
7705
- this._o.maxYear = defaults.maxYear;
7706
- this._o.maxMonth = defaults.maxMonth;
7707
- this._o.endRange = defaults.endRange;
7708
- }
7709
-
7710
- this.draw();
7711
- },
7712
-
7713
- setStartRange: function(value)
7714
- {
7715
- this._o.startRange = value;
7716
- },
7717
-
7718
- setEndRange: function(value)
7719
- {
7720
- this._o.endRange = value;
7721
- },
7722
-
7723
- /**
7724
- * refresh the HTML
7725
- */
7726
- draw: function(force)
7727
- {
7728
- if (!this._v && !force) {
7729
- return;
7730
- }
7731
- var opts = this._o,
7732
- minYear = opts.minYear,
7733
- maxYear = opts.maxYear,
7734
- minMonth = opts.minMonth,
7735
- maxMonth = opts.maxMonth,
7736
- html = '',
7737
- randId;
7738
-
7739
- if (this._y <= minYear) {
7740
- this._y = minYear;
7741
- if (!isNaN(minMonth) && this._m < minMonth) {
7742
- this._m = minMonth;
7743
- }
7744
- }
7745
- if (this._y >= maxYear) {
7746
- this._y = maxYear;
7747
- if (!isNaN(maxMonth) && this._m > maxMonth) {
7748
- this._m = maxMonth;
7749
- }
7750
- }
7751
-
7752
- for (var c = 0; c < opts.numberOfMonths; c++) {
7753
- randId = 'pika-title-' + Math.random().toString(36).replace(/[^a-z]+/g, '').substr(0, 2);
7754
- html += '<div class="pika-lendar">' + renderTitle(this, c, this.calendars[c].year, this.calendars[c].month, this.calendars[0].year, randId) + this.render(this.calendars[c].year, this.calendars[c].month, randId) + '</div>';
7755
- }
7756
-
7757
- this.el.innerHTML = html;
7758
-
7759
- if (opts.bound) {
7760
- if(opts.field.type !== 'hidden') {
7761
- sto(function() {
7762
- opts.trigger.focus();
7763
- }, 1);
7764
- }
7765
- }
7766
-
7767
- if (typeof this._o.onDraw === 'function') {
7768
- this._o.onDraw(this);
7769
- }
7770
-
7771
- if (opts.bound) {
7772
- // let the screen reader user know to use arrow keys
7773
- opts.field.setAttribute('aria-label', 'Use the arrow keys to pick a date');
7774
- }
7775
- },
7776
-
7777
- adjustPosition: function()
7778
- {
7779
- var field, pEl, width, height, viewportWidth, viewportHeight, scrollTop, left, top, clientRect;
7780
-
7781
- if (this._o.container) return;
7782
-
7783
- this.el.style.position = 'absolute';
7784
-
7785
- field = this._o.trigger;
7786
- pEl = field;
7787
- width = this.el.offsetWidth;
7788
- height = this.el.offsetHeight;
7789
- viewportWidth = window.innerWidth || document.documentElement.clientWidth;
7790
- viewportHeight = window.innerHeight || document.documentElement.clientHeight;
7791
- scrollTop = window.pageYOffset || document.body.scrollTop || document.documentElement.scrollTop;
7792
-
7793
- if (typeof field.getBoundingClientRect === 'function') {
7794
- clientRect = field.getBoundingClientRect();
7795
- left = clientRect.left + window.pageXOffset;
7796
- top = clientRect.bottom + window.pageYOffset;
7797
- } else {
7798
- left = pEl.offsetLeft;
7799
- top = pEl.offsetTop + pEl.offsetHeight;
7800
- while((pEl = pEl.offsetParent)) {
7801
- left += pEl.offsetLeft;
7802
- top += pEl.offsetTop;
7803
- }
7804
- }
7805
-
7806
- // default position is bottom & left
7807
- if ((this._o.reposition && left + width > viewportWidth) ||
7808
- (
7809
- this._o.position.indexOf('right') > -1 &&
7810
- left - width + field.offsetWidth > 0
7811
- )
7812
- ) {
7813
- left = left - width + field.offsetWidth;
7814
- }
7815
- if ((this._o.reposition && top + height > viewportHeight + scrollTop) ||
7816
- (
7817
- this._o.position.indexOf('top') > -1 &&
7818
- top - height - field.offsetHeight > 0
7819
- )
7820
- ) {
7821
- top = top - height - field.offsetHeight;
7822
- }
7823
-
7824
- this.el.style.left = left + 'px';
7825
- this.el.style.top = top + 'px';
7826
- },
7827
-
7828
- /**
7829
- * render HTML for a particular month
7830
- */
7831
- render: function(year, month, randId)
7832
- {
7833
- var opts = this._o,
7834
- now = new Date(),
7835
- days = getDaysInMonth(year, month),
7836
- before = new Date(year, month, 1).getDay(),
7837
- data = [],
7838
- row = [];
7839
- setToStartOfDay(now);
7840
- if (opts.firstDay > 0) {
7841
- before -= opts.firstDay;
7842
- if (before < 0) {
7843
- before += 7;
7844
- }
7845
- }
7846
- var previousMonth = month === 0 ? 11 : month - 1,
7847
- nextMonth = month === 11 ? 0 : month + 1,
7848
- yearOfPreviousMonth = month === 0 ? year - 1 : year,
7849
- yearOfNextMonth = month === 11 ? year + 1 : year,
7850
- daysInPreviousMonth = getDaysInMonth(yearOfPreviousMonth, previousMonth);
7851
- var cells = days + before,
7852
- after = cells;
7853
- while(after > 7) {
7854
- after -= 7;
7855
- }
7856
- cells += 7 - after;
7857
- var isWeekSelected = false;
7858
- for (var i = 0, r = 0; i < cells; i++)
7859
- {
7860
- var day = new Date(year, month, 1 + (i - before)),
7861
- isSelected = isDate(this._d) ? compareDates(day, this._d) : false,
7862
- isToday = compareDates(day, now),
7863
- hasEvent = opts.events.indexOf(day.toDateString()) !== -1 ? true : false,
7864
- isEmpty = i < before || i >= (days + before),
7865
- dayNumber = 1 + (i - before),
7866
- monthNumber = month,
7867
- yearNumber = year,
7868
- isStartRange = opts.startRange && compareDates(opts.startRange, day),
7869
- isEndRange = opts.endRange && compareDates(opts.endRange, day),
7870
- isInRange = opts.startRange && opts.endRange && opts.startRange < day && day < opts.endRange,
7871
- isDisabled = (opts.minDate && day < opts.minDate) ||
7872
- (opts.maxDate && day > opts.maxDate) ||
7873
- (opts.disableWeekends && isWeekend(day)) ||
7874
- (opts.disableDayFn && opts.disableDayFn(day));
7875
-
7876
- if (isEmpty) {
7877
- if (i < before) {
7878
- dayNumber = daysInPreviousMonth + dayNumber;
7879
- monthNumber = previousMonth;
7880
- yearNumber = yearOfPreviousMonth;
7881
- } else {
7882
- dayNumber = dayNumber - days;
7883
- monthNumber = nextMonth;
7884
- yearNumber = yearOfNextMonth;
7885
- }
7886
- }
7887
-
7888
- var dayConfig = {
7889
- day: dayNumber,
7890
- month: monthNumber,
7891
- year: yearNumber,
7892
- hasEvent: hasEvent,
7893
- isSelected: isSelected,
7894
- isToday: isToday,
7895
- isDisabled: isDisabled,
7896
- isEmpty: isEmpty,
7897
- isStartRange: isStartRange,
7898
- isEndRange: isEndRange,
7899
- isInRange: isInRange,
7900
- showDaysInNextAndPreviousMonths: opts.showDaysInNextAndPreviousMonths,
7901
- enableSelectionDaysInNextAndPreviousMonths: opts.enableSelectionDaysInNextAndPreviousMonths
7902
7483
  };
7903
7484
 
7904
- if (opts.pickWholeWeek && isSelected) {
7905
- isWeekSelected = true;
7906
- }
7907
7485
 
7908
- row.push(renderDay(dayConfig));
7486
+ /**
7487
+ * public Pikaday API
7488
+ */
7489
+ Pikaday.prototype = {
7909
7490
 
7910
- if (++r === 7) {
7911
- if (opts.showWeekNumber) {
7912
- row.unshift(renderWeek(i - before, month, year));
7491
+
7492
+ /**
7493
+ * configure functionality
7494
+ */
7495
+ config: function (options) {
7496
+ if (!this._o) {
7497
+ this._o = extend({}, defaults, true);
7498
+ }
7499
+
7500
+ var opts = extend(this._o, options, true);
7501
+
7502
+ opts.isRTL = !!opts.isRTL;
7503
+
7504
+ opts.field = (opts.field && opts.field.nodeName) ? opts.field : null;
7505
+
7506
+ opts.theme = (typeof opts.theme) === 'string' && opts.theme ? opts.theme : null;
7507
+
7508
+ opts.bound = !!(opts.bound !== undefined ? opts.field && opts.bound : opts.field);
7509
+
7510
+ opts.trigger = (opts.trigger && opts.trigger.nodeName) ? opts.trigger : opts.field;
7511
+
7512
+ opts.disableWeekends = !!opts.disableWeekends;
7513
+
7514
+ opts.disableDayFn = (typeof opts.disableDayFn) === 'function' ? opts.disableDayFn : null;
7515
+
7516
+ var nom = parseInt(opts.numberOfMonths, 10) || 1;
7517
+ opts.numberOfMonths = nom > 4 ? 4 : nom;
7518
+
7519
+ if (!isDate(opts.minDate)) {
7520
+ opts.minDate = false;
7521
+ }
7522
+ if (!isDate(opts.maxDate)) {
7523
+ opts.maxDate = false;
7524
+ }
7525
+ if ((opts.minDate && opts.maxDate) && opts.maxDate < opts.minDate) {
7526
+ opts.maxDate = opts.minDate = false;
7527
+ }
7528
+ if (opts.minDate) {
7529
+ this.setMinDate(opts.minDate);
7530
+ }
7531
+ if (opts.maxDate) {
7532
+ this.setMaxDate(opts.maxDate);
7533
+ }
7534
+
7535
+ if (isArray(opts.yearRange)) {
7536
+ var fallback = new Date().getFullYear() - 10;
7537
+ opts.yearRange[0] = parseInt(opts.yearRange[0], 10) || fallback;
7538
+ opts.yearRange[1] = parseInt(opts.yearRange[1], 10) || fallback;
7539
+ } else {
7540
+ opts.yearRange = Math.abs(parseInt(opts.yearRange, 10)) || defaults.yearRange;
7541
+ if (opts.yearRange > 100) {
7542
+ opts.yearRange = 100;
7543
+ }
7544
+ }
7545
+
7546
+ return opts;
7547
+ },
7548
+
7549
+ /**
7550
+ * return a formatted string of the current selection (using Moment.js if available)
7551
+ */
7552
+ toString: function (format) {
7553
+ format = format || this._o.format;
7554
+ if (!isDate(this._d)) {
7555
+ return '';
7556
+ }
7557
+ if (this._o.toString) {
7558
+ return this._o.toString(this._d, format);
7559
+ }
7560
+ if (hasMoment) {
7561
+ return moment(this._d).format(format);
7562
+ }
7563
+ return this._d.toDateString();
7564
+ },
7565
+
7566
+ /**
7567
+ * return a Moment.js object of the current selection (if available)
7568
+ */
7569
+ getMoment: function () {
7570
+ return hasMoment ? moment(this._d) : null;
7571
+ },
7572
+
7573
+ /**
7574
+ * set the current selection from a Moment.js object (if available)
7575
+ */
7576
+ setMoment: function (date, preventOnSelect) {
7577
+ if (hasMoment && moment.isMoment(date)) {
7578
+ this.setDate(date.toDate(), preventOnSelect);
7579
+ }
7580
+ },
7581
+
7582
+ /**
7583
+ * return a Date object of the current selection
7584
+ */
7585
+ getDate: function () {
7586
+ return isDate(this._d) ? new Date(this._d.getTime()) : null;
7587
+ },
7588
+
7589
+ /**
7590
+ * set the current selection
7591
+ */
7592
+ setDate: function (date, preventOnSelect) {
7593
+ if (!date) {
7594
+ this._d = null;
7595
+
7596
+ if (this._o.field) {
7597
+ this._o.field.value = '';
7598
+ fireEvent(this._o.field, 'change', { firedBy: this });
7599
+ }
7600
+
7601
+ return this.draw();
7602
+ }
7603
+ if (typeof date === 'string') {
7604
+ date = new Date(Date.parse(date));
7605
+ }
7606
+ if (!isDate(date)) {
7607
+ return;
7608
+ }
7609
+
7610
+ var min = this._o.minDate,
7611
+ max = this._o.maxDate;
7612
+
7613
+ if (isDate(min) && date < min) {
7614
+ date = min;
7615
+ } else if (isDate(max) && date > max) {
7616
+ date = max;
7617
+ }
7618
+
7619
+ this._d = new Date(date.getTime());
7620
+ setToStartOfDay(this._d);
7621
+ this.gotoDate(this._d);
7622
+
7623
+ if (this._o.field) {
7624
+ this._o.field.value = this.toString();
7625
+ fireEvent(this._o.field, 'change', { firedBy: this });
7626
+ }
7627
+ if (!preventOnSelect && typeof this._o.onSelect === 'function') {
7628
+ this._o.onSelect.call(this, this.getDate());
7629
+ }
7630
+ },
7631
+
7632
+ /**
7633
+ * change view to a specific date
7634
+ */
7635
+ gotoDate: function (date) {
7636
+ var newCalendar = true;
7637
+
7638
+ if (!isDate(date)) {
7639
+ return;
7640
+ }
7641
+
7642
+ if (this.calendars) {
7643
+ var firstVisibleDate = new Date(this.calendars[0].year, this.calendars[0].month, 1),
7644
+ lastVisibleDate = new Date(this.calendars[this.calendars.length - 1].year, this.calendars[this.calendars.length - 1].month, 1),
7645
+ visibleDate = date.getTime();
7646
+ // get the end of the month
7647
+ lastVisibleDate.setMonth(lastVisibleDate.getMonth() + 1);
7648
+ lastVisibleDate.setDate(lastVisibleDate.getDate() - 1);
7649
+ newCalendar = (visibleDate < firstVisibleDate.getTime() || lastVisibleDate.getTime() < visibleDate);
7650
+ }
7651
+
7652
+ if (newCalendar) {
7653
+ this.calendars = [{
7654
+ month: date.getMonth(),
7655
+ year: date.getFullYear()
7656
+ }];
7657
+ if (this._o.mainCalendar === 'right') {
7658
+ this.calendars[0].month += 1 - this._o.numberOfMonths;
7659
+ }
7660
+ }
7661
+
7662
+ this.adjustCalendars();
7663
+ },
7664
+
7665
+ adjustDate: function (sign, days) {
7666
+
7667
+ var day = this.getDate() || new Date();
7668
+ var difference = parseInt(days) * 24 * 60 * 60 * 1000;
7669
+
7670
+ var newDay;
7671
+
7672
+ if (sign === 'add') {
7673
+ newDay = new Date(day.valueOf() + difference);
7674
+ } else if (sign === 'subtract') {
7675
+ newDay = new Date(day.valueOf() - difference);
7676
+ }
7677
+
7678
+ this.setDate(newDay);
7679
+ },
7680
+
7681
+ adjustCalendars: function () {
7682
+ this.calendars[0] = adjustCalendar(this.calendars[0]);
7683
+ for (var c = 1; c < this._o.numberOfMonths; c++) {
7684
+ this.calendars[c] = adjustCalendar({
7685
+ month: this.calendars[0].month + c,
7686
+ year: this.calendars[0].year
7687
+ });
7688
+ }
7689
+ this.draw();
7690
+ },
7691
+
7692
+ gotoToday: function () {
7693
+ this.gotoDate(new Date());
7694
+ },
7695
+
7696
+ /**
7697
+ * change view to a specific month (zero-index, e.g. 0: January)
7698
+ */
7699
+ gotoMonth: function (month) {
7700
+ if (!isNaN(month)) {
7701
+ this.calendars[0].month = parseInt(month, 10);
7702
+ this.adjustCalendars();
7703
+ }
7704
+ },
7705
+
7706
+ nextMonth: function () {
7707
+ this.calendars[0].month++;
7708
+ this.adjustCalendars();
7709
+ },
7710
+
7711
+ prevMonth: function () {
7712
+ this.calendars[0].month--;
7713
+ this.adjustCalendars();
7714
+ },
7715
+
7716
+ /**
7717
+ * change view to a specific full year (e.g. "2012")
7718
+ */
7719
+ gotoYear: function (year) {
7720
+ if (!isNaN(year)) {
7721
+ this.calendars[0].year = parseInt(year, 10);
7722
+ this.adjustCalendars();
7723
+ }
7724
+ },
7725
+
7726
+ /**
7727
+ * change the minDate
7728
+ */
7729
+ setMinDate: function (value) {
7730
+ if (value instanceof Date) {
7731
+ setToStartOfDay(value);
7732
+ this._o.minDate = value;
7733
+ this._o.minYear = value.getFullYear();
7734
+ this._o.minMonth = value.getMonth();
7735
+ } else {
7736
+ this._o.minDate = defaults.minDate;
7737
+ this._o.minYear = defaults.minYear;
7738
+ this._o.minMonth = defaults.minMonth;
7739
+ this._o.startRange = defaults.startRange;
7740
+ }
7741
+
7742
+ this.draw();
7743
+ },
7744
+
7745
+ /**
7746
+ * change the maxDate
7747
+ */
7748
+ setMaxDate: function (value) {
7749
+ if (value instanceof Date) {
7750
+ setToStartOfDay(value);
7751
+ this._o.maxDate = value;
7752
+ this._o.maxYear = value.getFullYear();
7753
+ this._o.maxMonth = value.getMonth();
7754
+ } else {
7755
+ this._o.maxDate = defaults.maxDate;
7756
+ this._o.maxYear = defaults.maxYear;
7757
+ this._o.maxMonth = defaults.maxMonth;
7758
+ this._o.endRange = defaults.endRange;
7759
+ }
7760
+
7761
+ this.draw();
7762
+ },
7763
+
7764
+ setStartRange: function (value) {
7765
+ this._o.startRange = value;
7766
+ },
7767
+
7768
+ setEndRange: function (value) {
7769
+ this._o.endRange = value;
7770
+ },
7771
+
7772
+ /**
7773
+ * refresh the HTML
7774
+ */
7775
+ draw: function (force) {
7776
+ if (!this._v && !force) {
7777
+ return;
7778
+ }
7779
+ var opts = this._o,
7780
+ minYear = opts.minYear,
7781
+ maxYear = opts.maxYear,
7782
+ minMonth = opts.minMonth,
7783
+ maxMonth = opts.maxMonth,
7784
+ html = '',
7785
+ randId;
7786
+
7787
+ if (this._y <= minYear) {
7788
+ this._y = minYear;
7789
+ if (!isNaN(minMonth) && this._m < minMonth) {
7790
+ this._m = minMonth;
7791
+ }
7792
+ }
7793
+ if (this._y >= maxYear) {
7794
+ this._y = maxYear;
7795
+ if (!isNaN(maxMonth) && this._m > maxMonth) {
7796
+ this._m = maxMonth;
7797
+ }
7798
+ }
7799
+
7800
+ for (var c = 0; c < opts.numberOfMonths; c++) {
7801
+ randId = 'pika-title-' + Math.random().toString(36).replace(/[^a-z]+/g, '').substr(0, 2);
7802
+ html += '<div class="pika-lendar">' + renderTitle(this, c, this.calendars[c].year, this.calendars[c].month, this.calendars[0].year, randId) + this.render(this.calendars[c].year, this.calendars[c].month, randId) + '</div>';
7803
+ }
7804
+
7805
+ this.el.innerHTML = html;
7806
+
7807
+ if (opts.bound) {
7808
+ if (opts.field.type !== 'hidden') {
7809
+ sto(function () {
7810
+ opts.trigger.focus();
7811
+ }, 1);
7812
+ }
7813
+ }
7814
+
7815
+ if (typeof this._o.onDraw === 'function') {
7816
+ this._o.onDraw(this);
7817
+ }
7818
+
7819
+ if (opts.bound) {
7820
+ // let the screen reader user know to use arrow keys
7821
+ opts.field.setAttribute('aria-label', 'Use the arrow keys to pick a date');
7822
+ }
7823
+ },
7824
+
7825
+ adjustPosition: function () {
7826
+ var field, pEl, width, height, viewportWidth, viewportHeight, scrollTop, left, top, clientRect;
7827
+
7828
+ if (this._o.container) return;
7829
+
7830
+ this.el.style.position = 'absolute';
7831
+
7832
+ field = this._o.trigger;
7833
+ pEl = field;
7834
+ width = this.el.offsetWidth;
7835
+ height = this.el.offsetHeight;
7836
+ viewportWidth = window.innerWidth || document.documentElement.clientWidth;
7837
+ viewportHeight = window.innerHeight || document.documentElement.clientHeight;
7838
+ scrollTop = window.pageYOffset || document.body.scrollTop || document.documentElement.scrollTop;
7839
+
7840
+ if (typeof field.getBoundingClientRect === 'function') {
7841
+ clientRect = field.getBoundingClientRect();
7842
+ left = clientRect.left + window.pageXOffset;
7843
+ top = clientRect.bottom + window.pageYOffset;
7844
+ } else {
7845
+ left = pEl.offsetLeft;
7846
+ top = pEl.offsetTop + pEl.offsetHeight;
7847
+ while ((pEl = pEl.offsetParent)) {
7848
+ left += pEl.offsetLeft;
7849
+ top += pEl.offsetTop;
7850
+ }
7851
+ }
7852
+
7853
+ // default position is bottom & left
7854
+ if ((this._o.reposition && left + width > viewportWidth) ||
7855
+ (
7856
+ this._o.position.indexOf('right') > -1 &&
7857
+ left - width + field.offsetWidth > 0
7858
+ )
7859
+ ) {
7860
+ left = left - width + field.offsetWidth;
7861
+ }
7862
+ if ((this._o.reposition && top + height > viewportHeight + scrollTop) ||
7863
+ (
7864
+ this._o.position.indexOf('top') > -1 &&
7865
+ top - height - field.offsetHeight > 0
7866
+ )
7867
+ ) {
7868
+ top = top - height - field.offsetHeight;
7869
+ }
7870
+
7871
+ this.el.style.left = left + 'px';
7872
+ this.el.style.top = top + 'px';
7873
+ },
7874
+
7875
+ /**
7876
+ * render HTML for a particular month
7877
+ */
7878
+ render: function (year, month, randId) {
7879
+ var opts = this._o,
7880
+ now = new Date(),
7881
+ days = getDaysInMonth(year, month),
7882
+ before = new Date(year, month, 1).getDay(),
7883
+ data = [],
7884
+ row = [];
7885
+ setToStartOfDay(now);
7886
+ if (opts.firstDay > 0) {
7887
+ before -= opts.firstDay;
7888
+ if (before < 0) {
7889
+ before += 7;
7890
+ }
7891
+ }
7892
+ var previousMonth = month === 0 ? 11 : month - 1,
7893
+ nextMonth = month === 11 ? 0 : month + 1,
7894
+ yearOfPreviousMonth = month === 0 ? year - 1 : year,
7895
+ yearOfNextMonth = month === 11 ? year + 1 : year,
7896
+ daysInPreviousMonth = getDaysInMonth(yearOfPreviousMonth, previousMonth);
7897
+ var cells = days + before,
7898
+ after = cells;
7899
+ while (after > 7) {
7900
+ after -= 7;
7901
+ }
7902
+ cells += 7 - after;
7903
+ var isWeekSelected = false;
7904
+ for (var i = 0, r = 0; i < cells; i++) {
7905
+ var day = new Date(year, month, 1 + (i - before)),
7906
+ isSelected = isDate(this._d) ? compareDates(day, this._d) : false,
7907
+ isToday = compareDates(day, now),
7908
+ hasEvent = opts.events.indexOf(day.toDateString()) !== -1 ? true : false,
7909
+ isEmpty = i < before || i >= (days + before),
7910
+ dayNumber = 1 + (i - before),
7911
+ monthNumber = month,
7912
+ yearNumber = year,
7913
+ isStartRange = opts.startRange && compareDates(opts.startRange, day),
7914
+ isEndRange = opts.endRange && compareDates(opts.endRange, day),
7915
+ isInRange = opts.startRange && opts.endRange && opts.startRange < day && day < opts.endRange,
7916
+ isDisabled = (opts.minDate && day < opts.minDate) ||
7917
+ (opts.maxDate && day > opts.maxDate) ||
7918
+ (opts.disableWeekends && isWeekend(day)) ||
7919
+ (opts.disableDayFn && opts.disableDayFn(day));
7920
+
7921
+ if (isEmpty) {
7922
+ if (i < before) {
7923
+ dayNumber = daysInPreviousMonth + dayNumber;
7924
+ monthNumber = previousMonth;
7925
+ yearNumber = yearOfPreviousMonth;
7926
+ } else {
7927
+ dayNumber = dayNumber - days;
7928
+ monthNumber = nextMonth;
7929
+ yearNumber = yearOfNextMonth;
7930
+ }
7931
+ }
7932
+
7933
+ var dayConfig = {
7934
+ day: dayNumber,
7935
+ month: monthNumber,
7936
+ year: yearNumber,
7937
+ hasEvent: hasEvent,
7938
+ isSelected: isSelected,
7939
+ isToday: isToday,
7940
+ isDisabled: isDisabled,
7941
+ isEmpty: isEmpty,
7942
+ isStartRange: isStartRange,
7943
+ isEndRange: isEndRange,
7944
+ isInRange: isInRange,
7945
+ showDaysInNextAndPreviousMonths: opts.showDaysInNextAndPreviousMonths,
7946
+ enableSelectionDaysInNextAndPreviousMonths: opts.enableSelectionDaysInNextAndPreviousMonths
7947
+ };
7948
+
7949
+ if (opts.pickWholeWeek && isSelected) {
7950
+ isWeekSelected = true;
7951
+ }
7952
+
7953
+ row.push(renderDay(dayConfig));
7954
+
7955
+ if (++r === 7) {
7956
+ if (opts.showWeekNumber) {
7957
+ row.unshift(renderWeek(i - before, month, year));
7958
+ }
7959
+ data.push(renderRow(row, opts.isRTL, opts.pickWholeWeek, isWeekSelected));
7960
+ row = [];
7961
+ r = 0;
7962
+ isWeekSelected = false;
7963
+ }
7964
+ }
7965
+ return renderTable(opts, data, randId);
7966
+ },
7967
+
7968
+ isVisible: function () {
7969
+ return this._v;
7970
+ },
7971
+
7972
+ show: function () {
7973
+ if (!this.isVisible()) {
7974
+ this._v = true;
7975
+ this.draw();
7976
+ removeClass(this.el, 'is-hidden');
7977
+ if (this._o.bound) {
7978
+ addEvent(document, 'click', this._onClick);
7979
+ this.adjustPosition();
7980
+ }
7981
+ if (typeof this._o.onOpen === 'function') {
7982
+ this._o.onOpen.call(this);
7983
+ }
7984
+ }
7985
+ },
7986
+
7987
+ hide: function () {
7988
+ var v = this._v;
7989
+ if (v !== false) {
7990
+ if (this._o.bound) {
7991
+ removeEvent(document, 'click', this._onClick);
7992
+ }
7993
+ this.el.style.position = 'static'; // reset
7994
+ this.el.style.left = 'auto';
7995
+ this.el.style.top = 'auto';
7996
+ addClass(this.el, 'is-hidden');
7997
+ this._v = false;
7998
+ if (v !== undefined && typeof this._o.onClose === 'function') {
7999
+ this._o.onClose.call(this);
8000
+ }
8001
+ }
8002
+ },
8003
+
8004
+ /**
8005
+ * GAME OVER
8006
+ */
8007
+ destroy: function () {
8008
+ var opts = this._o;
8009
+
8010
+ this.hide();
8011
+ removeEvent(this.el, 'mousedown', this._onMouseDown, true);
8012
+ removeEvent(this.el, 'touchend', this._onMouseDown, true);
8013
+ removeEvent(this.el, 'change', this._onChange);
8014
+ if (opts.keyboardInput) {
8015
+ removeEvent(document, 'keydown', this._onKeyChange);
8016
+ }
8017
+ if (opts.field) {
8018
+ removeEvent(opts.field, 'change', this._onInputChange);
8019
+ if (opts.bound) {
8020
+ removeEvent(opts.trigger, 'click', this._onInputClick);
8021
+ removeEvent(opts.trigger, 'focus', this._onInputFocus);
8022
+ removeEvent(opts.trigger, 'blur', this._onInputBlur);
8023
+ }
8024
+ }
8025
+ if (this.el.parentNode) {
8026
+ this.el.parentNode.removeChild(this.el);
8027
+ }
7913
8028
  }
7914
- data.push(renderRow(row, opts.isRTL, opts.pickWholeWeek, isWeekSelected));
7915
- row = [];
7916
- r = 0;
7917
- isWeekSelected = false;
7918
- }
7919
- }
7920
- return renderTable(opts, data, randId);
7921
- },
7922
-
7923
- isVisible: function()
7924
- {
7925
- return this._v;
7926
- },
7927
-
7928
- show: function()
7929
- {
7930
- if (!this.isVisible()) {
7931
- this._v = true;
7932
- this.draw();
7933
- removeClass(this.el, 'is-hidden');
7934
- if (this._o.bound) {
7935
- addEvent(document, 'click', this._onClick);
7936
- this.adjustPosition();
7937
- }
7938
- if (typeof this._o.onOpen === 'function') {
7939
- this._o.onOpen.call(this);
7940
- }
7941
- }
7942
- },
7943
-
7944
- hide: function()
7945
- {
7946
- var v = this._v;
7947
- if (v !== false) {
7948
- if (this._o.bound) {
7949
- removeEvent(document, 'click', this._onClick);
7950
- }
7951
- this.el.style.position = 'static'; // reset
7952
- this.el.style.left = 'auto';
7953
- this.el.style.top = 'auto';
7954
- addClass(this.el, 'is-hidden');
7955
- this._v = false;
7956
- if (v !== undefined && typeof this._o.onClose === 'function') {
7957
- this._o.onClose.call(this);
7958
- }
7959
- }
7960
- },
7961
-
7962
- /**
7963
- * GAME OVER
7964
- */
7965
- destroy: function()
7966
- {
7967
- var opts = this._o;
7968
-
7969
- this.hide();
7970
- removeEvent(this.el, 'mousedown', this._onMouseDown, true);
7971
- removeEvent(this.el, 'touchend', this._onMouseDown, true);
7972
- removeEvent(this.el, 'change', this._onChange);
7973
- if (opts.keyboardInput) {
7974
- removeEvent(document, 'keydown', this._onKeyChange);
7975
- }
7976
- if (opts.field) {
7977
- removeEvent(opts.field, 'change', this._onInputChange);
7978
- if (opts.bound) {
7979
- removeEvent(opts.trigger, 'click', this._onInputClick);
7980
- removeEvent(opts.trigger, 'focus', this._onInputFocus);
7981
- removeEvent(opts.trigger, 'blur', this._onInputBlur);
7982
- }
7983
- }
7984
- if (this.el.parentNode) {
7985
- this.el.parentNode.removeChild(this.el);
7986
- }
7987
- }
7988
-
7989
- };
7990
-
7991
- return Pikaday;
7992
- }));
8029
+
8030
+ };
8031
+
8032
+ return Pikaday;
8033
+ }));
7993
8034
  } (pikaday$1));
7994
8035
  return pikaday$1.exports;
7995
8036
  }
@@ -7997,50 +8038,26 @@ function requirePikaday () {
7997
8038
  var pikadayExports = /*@__PURE__*/ requirePikaday();
7998
8039
  var Pikaday = /*@__PURE__*/getDefaultExportFromCjs(pikadayExports);
7999
8040
 
8000
- class TimezonePicker extends ChartComponent {
8001
- constructor(renderTarget) {
8002
- super(renderTarget);
8003
- this.timeZones = ["Local", "UTC", "Africa/Algiers", "Africa/Cairo", "Africa/Casablanca", "Africa/Harare", "Africa/Johannesburg", "Africa/Lagos", "Africa/Nairobi", "Africa/Windhoek", "America/Anchorage", "America/Bogota", "America/Buenos Aires", "America/Caracas", "America/Chicago", "America/Chihuahua", "America/Denver", "America/Edmonton", "America/Godthab", "America/Guatemala", "America/Halifax", "America/Indiana/Indianapolis", "America/Los Angeles", "America/Manaus", "America/Mexico City", "America/Montevideo", "America/New York", "America/Phoenix", "America/Santiago", "America/Sao Paulo", "America/St Johns", "America/Tijuana", "America/Toronto", "America/Vancouver", "America/Winnipeg", "Asia/Amman", "Asia/Beirut", "Asia/Baghdad", "Asia/Baku", "Asia/Bangkok", "Asia/Calcutta", "Asia/Colombo", "Asia/Dhaka", "Asia/Dubai", "Asia/Ho Chi Minh", "Asia/Hong Kong", "Asia/Irkutsk", "Asia/Istanbul", "Asia/Jakarta", "Asia/Jerusalem", "Asia/Kabul", "Asia/Karachi", "Asia/Kathmandu", "Asia/Krasnoyarsk", "Asia/Kuala Lumpur", "Asia/Kuwait", "Asia/Magadan", "Asia/Muscat", "Asia/Novosibirsk", "Asia/Qatar", "Asia/Rangoon", "Asia/Seoul", "Asia/Shanghai", "Asia/Singapore", "Asia/Taipei", "Asia/Tbilisi", "Asia/Tehran", "Asia/Tokyo", "Asia/Vladivostok", "Asia/Yakutsk", "Asia/Yekaterinburg", "Asia/Yerevan", "Atlantic/Azores", "Atlantic/Cape Verde", "Atlantic/South Georgia", "Australia/Adelaide", "Australia/Brisbane", "Australia/Canberra", "Australia/Darwin", "Australia/Hobart", "Australia/Melbourne", "Australia/Perth", "Australia/Queensland", "Australia/Sydney", "Europe/Amsterdam", "Europe/Andorra", "Europe/Athens", "Europe/Belfast", "Europe/Belgrade", "Europe/Berlin", "Europe/Brussels", "Europe/Budapest", "Europe/Dublin", "Europe/Helsinki", "Europe/Kiev", "Europe/Lisbon", "Europe/London", "Europe/Luxembourg", "Europe/Madrid", "Europe/Minsk", "Europe/Monaco", "Europe/Moscow", "Europe/Oslo", "Europe/Paris", "Europe/Rome", "Europe/Stockholm", "Europe/Vienna", "Europe/Warsaw", "Europe/Zurich", "Pacific/Auckland", "Pacific/Fiji", "Pacific/Guam", "Pacific/Honolulu", "Pacific/Midway", "Pacific/Tongatapu"];
8041
+ // Ensure moment is available globally for Pikaday
8042
+ if (typeof window !== 'undefined') {
8043
+ window.moment = moment$1;
8044
+ }
8045
+ // Export a function to safely create Pikaday instances
8046
+ function createPikaday(options) {
8047
+ if (typeof window === 'undefined') {
8048
+ console.warn('Pikaday requires a browser environment');
8049
+ return null;
8004
8050
  }
8005
- sortTimezones() {
8006
- let filteredTimezones = this.timeZones.filter((tz) => {
8007
- return !(tz.toLowerCase() == 'local' || tz == 'UTC');
8008
- });
8009
- filteredTimezones.sort((a, b) => {
8010
- let aOffset = moment.tz(new Date(), a.split(' ').join('_')).utcOffset();
8011
- let bOffset = moment.tz(new Date(), b.split(' ').join('_')).utcOffset();
8012
- if (aOffset < bOffset) {
8013
- return -1;
8014
- }
8015
- if (aOffset > bOffset) {
8016
- return 1;
8017
- }
8018
- return 0;
8019
- });
8020
- this.timeZones = ['Local', 'UTC'].concat(filteredTimezones);
8051
+ const Pikaday = window.Pikaday;
8052
+ if (!Pikaday) {
8053
+ console.error('Pikaday not available. Make sure pikaday.js is loaded.');
8054
+ return null;
8021
8055
  }
8022
- render(onTimezoneSelect, defaultTimeZone = null) {
8023
- this.targetElement = d3.select(this.renderTarget)
8024
- .classed("tsi-timezonePicker", true);
8025
- var timezoneSelection = this.targetElement.append("select")
8026
- .attr("class", "tsi-timezonePicker tsi-select");
8027
- this.sortTimezones();
8028
- var options = timezoneSelection.selectAll("option")
8029
- .data(this.timeZones)
8030
- .enter()
8031
- .append("option")
8032
- .attr('value', d => d)
8033
- .text((tz) => Utils.convertTimezoneToLabel(tz, this.getString('Local')));
8034
- timezoneSelection.on("change", function (d) {
8035
- var timezone = d3.select(this).node().value.replace(/\s/g, "_");
8036
- onTimezoneSelect(timezone);
8037
- });
8038
- defaultTimeZone = defaultTimeZone.replace(/_/g, " ");
8039
- if (defaultTimeZone != null) {
8040
- options.filter((d) => d == defaultTimeZone).attr("selected", true);
8041
- }
8042
- return;
8056
+ if (!moment$1 || !window.moment) {
8057
+ console.error('Moment.js not available. Pikaday requires moment.js.');
8058
+ return null;
8043
8059
  }
8060
+ return new Pikaday(options);
8044
8061
  }
8045
8062
 
8046
8063
  class DateTimePicker extends ChartComponent {
@@ -8313,8 +8330,8 @@ class DateTimePicker extends ChartComponent {
8313
8330
  weekdays: moment$1.localeData().weekdays(),
8314
8331
  weekdaysShort: moment$1.localeData().weekdaysMin()
8315
8332
  };
8316
- //@ts-ignore
8317
- this.calendarPicker = new Pikaday({
8333
+ // Use the safe Pikaday wrapper
8334
+ this.calendarPicker = createPikaday({
8318
8335
  bound: false,
8319
8336
  container: this.calendar.node(),
8320
8337
  field: this.calendar.node(),
@@ -8350,6 +8367,11 @@ class DateTimePicker extends ChartComponent {
8350
8367
  maxDate: this.convertToCalendarDate(this.maxMillis),
8351
8368
  defaultDate: Utils.adjustDateFromTimezoneOffset(new Date(this.fromMillis))
8352
8369
  });
8370
+ // Check if Pikaday was created successfully
8371
+ if (!this.calendarPicker) {
8372
+ console.error('Failed to create Pikaday calendar. Check moment.js availability.');
8373
+ return;
8374
+ }
8353
8375
  }
8354
8376
  setSelectedQuickTimes() {
8355
8377
  let isSelected = d => {
@@ -8758,6 +8780,7 @@ class AvailabilityChart extends ChartComponent {
8758
8780
  }
8759
8781
  //transformation of buckets created by the UX client to buckets for the availabilityChart
8760
8782
  createDisplayBuckets(fromMillis, toMillis) {
8783
+ //TODO: "" key is confusing, should be "count" or something similar
8761
8784
  var keysInRange = Object.keys(this.transformedAvailability[0].availabilityCount[""]).reduce((inRangeObj, timestamp, i, timestamps) => {
8762
8785
  var currTSMillis = (new Date(timestamp)).valueOf();
8763
8786
  var nextTSMillis = currTSMillis + this.bucketSize;
@@ -8810,6 +8833,7 @@ class AvailabilityChart extends ChartComponent {
8810
8833
  this.bucketSize = null;
8811
8834
  }
8812
8835
  }
8836
+ //TODO: should have proper types for parameters
8813
8837
  render(transformedAvailability, chartOptions, rawAvailability = {}) {
8814
8838
  this.setChartOptions(chartOptions);
8815
8839
  this.rawAvailability = rawAvailability;
@@ -13973,6 +13997,10 @@ class GeoProcessGraphic extends HistoryPlayback {
13973
13997
  }
13974
13998
  }
13975
13999
 
14000
+ // Ensure moment is available globally for Pikaday and other components
14001
+ if (typeof window !== 'undefined') {
14002
+ window.moment = moment$1;
14003
+ }
13976
14004
  class UXClient {
13977
14005
  constructor() {
13978
14006
  // Public facing components have class constructors exposed as public UXClient members.