initial commit
This commit is contained in:
512
node_modules/vis/lib/timeline/DateUtil.js
generated
vendored
Normal file
512
node_modules/vis/lib/timeline/DateUtil.js
generated
vendored
Normal file
@@ -0,0 +1,512 @@
|
||||
|
||||
/**
|
||||
* used in Core to convert the options into a volatile variable
|
||||
*
|
||||
* @param {function} moment
|
||||
* @param {Object} body
|
||||
* @param {Array | Object} hiddenDates
|
||||
* @returns {number}
|
||||
*/
|
||||
exports.convertHiddenOptions = function(moment, body, hiddenDates) {
|
||||
if (hiddenDates && !Array.isArray(hiddenDates)) {
|
||||
return exports.convertHiddenOptions(moment, body, [hiddenDates])
|
||||
}
|
||||
|
||||
body.hiddenDates = [];
|
||||
if (hiddenDates) {
|
||||
if (Array.isArray(hiddenDates) == true) {
|
||||
for (var i = 0; i < hiddenDates.length; i++) {
|
||||
if (hiddenDates[i].repeat === undefined) {
|
||||
var dateItem = {};
|
||||
dateItem.start = moment(hiddenDates[i].start).toDate().valueOf();
|
||||
dateItem.end = moment(hiddenDates[i].end).toDate().valueOf();
|
||||
body.hiddenDates.push(dateItem);
|
||||
}
|
||||
}
|
||||
body.hiddenDates.sort(function (a, b) {
|
||||
return a.start - b.start;
|
||||
}); // sort by start time
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* create new entrees for the repeating hidden dates
|
||||
*
|
||||
* @param {function} moment
|
||||
* @param {Object} body
|
||||
* @param {Array | Object} hiddenDates
|
||||
* @returns {null}
|
||||
*/
|
||||
exports.updateHiddenDates = function (moment, body, hiddenDates) {
|
||||
if (hiddenDates && !Array.isArray(hiddenDates)) {
|
||||
return exports.updateHiddenDates(moment, body, [hiddenDates])
|
||||
}
|
||||
|
||||
if (hiddenDates && body.domProps.centerContainer.width !== undefined) {
|
||||
exports.convertHiddenOptions(moment, body, hiddenDates);
|
||||
|
||||
var start = moment(body.range.start);
|
||||
var end = moment(body.range.end);
|
||||
|
||||
var totalRange = (body.range.end - body.range.start);
|
||||
var pixelTime = totalRange / body.domProps.centerContainer.width;
|
||||
|
||||
for (var i = 0; i < hiddenDates.length; i++) {
|
||||
if (hiddenDates[i].repeat !== undefined) {
|
||||
var startDate = moment(hiddenDates[i].start);
|
||||
var endDate = moment(hiddenDates[i].end);
|
||||
|
||||
if (startDate._d == "Invalid Date") {
|
||||
throw new Error("Supplied start date is not valid: " + hiddenDates[i].start);
|
||||
}
|
||||
if (endDate._d == "Invalid Date") {
|
||||
throw new Error("Supplied end date is not valid: " + hiddenDates[i].end);
|
||||
}
|
||||
|
||||
var duration = endDate - startDate;
|
||||
if (duration >= 4 * pixelTime) {
|
||||
|
||||
var offset = 0;
|
||||
var runUntil = end.clone();
|
||||
switch (hiddenDates[i].repeat) {
|
||||
case "daily": // case of time
|
||||
if (startDate.day() != endDate.day()) {
|
||||
offset = 1;
|
||||
}
|
||||
startDate.dayOfYear(start.dayOfYear());
|
||||
startDate.year(start.year());
|
||||
startDate.subtract(7,'days');
|
||||
|
||||
endDate.dayOfYear(start.dayOfYear());
|
||||
endDate.year(start.year());
|
||||
endDate.subtract(7 - offset,'days');
|
||||
|
||||
runUntil.add(1, 'weeks');
|
||||
break;
|
||||
case "weekly":
|
||||
var dayOffset = endDate.diff(startDate,'days');
|
||||
var day = startDate.day();
|
||||
|
||||
// set the start date to the range.start
|
||||
startDate.date(start.date());
|
||||
startDate.month(start.month());
|
||||
startDate.year(start.year());
|
||||
endDate = startDate.clone();
|
||||
|
||||
// force
|
||||
startDate.day(day);
|
||||
endDate.day(day);
|
||||
endDate.add(dayOffset,'days');
|
||||
|
||||
startDate.subtract(1,'weeks');
|
||||
endDate.subtract(1,'weeks');
|
||||
|
||||
runUntil.add(1, 'weeks');
|
||||
break;
|
||||
case "monthly":
|
||||
if (startDate.month() != endDate.month()) {
|
||||
offset = 1;
|
||||
}
|
||||
startDate.month(start.month());
|
||||
startDate.year(start.year());
|
||||
startDate.subtract(1,'months');
|
||||
|
||||
endDate.month(start.month());
|
||||
endDate.year(start.year());
|
||||
endDate.subtract(1,'months');
|
||||
endDate.add(offset,'months');
|
||||
|
||||
runUntil.add(1, 'months');
|
||||
break;
|
||||
case "yearly":
|
||||
if (startDate.year() != endDate.year()) {
|
||||
offset = 1;
|
||||
}
|
||||
startDate.year(start.year());
|
||||
startDate.subtract(1,'years');
|
||||
endDate.year(start.year());
|
||||
endDate.subtract(1,'years');
|
||||
endDate.add(offset,'years');
|
||||
|
||||
runUntil.add(1, 'years');
|
||||
break;
|
||||
default:
|
||||
console.log("Wrong repeat format, allowed are: daily, weekly, monthly, yearly. Given:", hiddenDates[i].repeat);
|
||||
return;
|
||||
}
|
||||
while (startDate < runUntil) {
|
||||
body.hiddenDates.push({start: startDate.valueOf(), end: endDate.valueOf()});
|
||||
switch (hiddenDates[i].repeat) {
|
||||
case "daily":
|
||||
startDate.add(1, 'days');
|
||||
endDate.add(1, 'days');
|
||||
break;
|
||||
case "weekly":
|
||||
startDate.add(1, 'weeks');
|
||||
endDate.add(1, 'weeks');
|
||||
break;
|
||||
case "monthly":
|
||||
startDate.add(1, 'months');
|
||||
endDate.add(1, 'months');
|
||||
break;
|
||||
case "yearly":
|
||||
startDate.add(1, 'y');
|
||||
endDate.add(1, 'y');
|
||||
break;
|
||||
default:
|
||||
console.log("Wrong repeat format, allowed are: daily, weekly, monthly, yearly. Given:", hiddenDates[i].repeat);
|
||||
return;
|
||||
}
|
||||
}
|
||||
body.hiddenDates.push({start: startDate.valueOf(), end: endDate.valueOf()});
|
||||
}
|
||||
}
|
||||
}
|
||||
// remove duplicates, merge where possible
|
||||
exports.removeDuplicates(body);
|
||||
// ensure the new positions are not on hidden dates
|
||||
var startHidden = exports.isHidden(body.range.start, body.hiddenDates);
|
||||
var endHidden = exports.isHidden(body.range.end,body.hiddenDates);
|
||||
var rangeStart = body.range.start;
|
||||
var rangeEnd = body.range.end;
|
||||
if (startHidden.hidden == true) {rangeStart = body.range.startToFront == true ? startHidden.startDate - 1 : startHidden.endDate + 1;}
|
||||
if (endHidden.hidden == true) {rangeEnd = body.range.endToFront == true ? endHidden.startDate - 1 : endHidden.endDate + 1;}
|
||||
if (startHidden.hidden == true || endHidden.hidden == true) {
|
||||
body.range._applyRange(rangeStart, rangeEnd);
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* remove duplicates from the hidden dates list. Duplicates are evil. They mess everything up.
|
||||
* Scales with N^2
|
||||
*
|
||||
* @param {Object} body
|
||||
*/
|
||||
exports.removeDuplicates = function(body) {
|
||||
var hiddenDates = body.hiddenDates;
|
||||
var safeDates = [];
|
||||
for (var i = 0; i < hiddenDates.length; i++) {
|
||||
for (var j = 0; j < hiddenDates.length; j++) {
|
||||
if (i != j && hiddenDates[j].remove != true && hiddenDates[i].remove != true) {
|
||||
// j inside i
|
||||
if (hiddenDates[j].start >= hiddenDates[i].start && hiddenDates[j].end <= hiddenDates[i].end) {
|
||||
hiddenDates[j].remove = true;
|
||||
}
|
||||
// j start inside i
|
||||
else if (hiddenDates[j].start >= hiddenDates[i].start && hiddenDates[j].start <= hiddenDates[i].end) {
|
||||
hiddenDates[i].end = hiddenDates[j].end;
|
||||
hiddenDates[j].remove = true;
|
||||
}
|
||||
// j end inside i
|
||||
else if (hiddenDates[j].end >= hiddenDates[i].start && hiddenDates[j].end <= hiddenDates[i].end) {
|
||||
hiddenDates[i].start = hiddenDates[j].start;
|
||||
hiddenDates[j].remove = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < hiddenDates.length; i++) {
|
||||
if (hiddenDates[i].remove !== true) {
|
||||
safeDates.push(hiddenDates[i]);
|
||||
}
|
||||
}
|
||||
|
||||
body.hiddenDates = safeDates;
|
||||
body.hiddenDates.sort(function (a, b) {
|
||||
return a.start - b.start;
|
||||
}); // sort by start time
|
||||
};
|
||||
|
||||
exports.printDates = function(dates) {
|
||||
for (var i =0; i < dates.length; i++) {
|
||||
console.log(i, new Date(dates[i].start),new Date(dates[i].end), dates[i].start, dates[i].end, dates[i].remove);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Used in TimeStep to avoid the hidden times.
|
||||
* @param {function} moment
|
||||
* @param {TimeStep} timeStep
|
||||
* @param {Date} previousTime
|
||||
*/
|
||||
exports.stepOverHiddenDates = function(moment, timeStep, previousTime) {
|
||||
var stepInHidden = false;
|
||||
var currentValue = timeStep.current.valueOf();
|
||||
for (var i = 0; i < timeStep.hiddenDates.length; i++) {
|
||||
var startDate = timeStep.hiddenDates[i].start;
|
||||
var endDate = timeStep.hiddenDates[i].end;
|
||||
if (currentValue >= startDate && currentValue < endDate) {
|
||||
stepInHidden = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (stepInHidden == true && currentValue < timeStep._end.valueOf() && currentValue != previousTime) {
|
||||
var prevValue = moment(previousTime);
|
||||
var newValue = moment(endDate);
|
||||
//check if the next step should be major
|
||||
if (prevValue.year() != newValue.year()) {timeStep.switchedYear = true;}
|
||||
else if (prevValue.month() != newValue.month()) {timeStep.switchedMonth = true;}
|
||||
else if (prevValue.dayOfYear() != newValue.dayOfYear()) {timeStep.switchedDay = true;}
|
||||
|
||||
timeStep.current = newValue;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
///**
|
||||
// * Used in TimeStep to avoid the hidden times.
|
||||
// * @param timeStep
|
||||
// * @param previousTime
|
||||
// */
|
||||
//exports.checkFirstStep = function(timeStep) {
|
||||
// var stepInHidden = false;
|
||||
// var currentValue = timeStep.current.valueOf();
|
||||
// for (var i = 0; i < timeStep.hiddenDates.length; i++) {
|
||||
// var startDate = timeStep.hiddenDates[i].start;
|
||||
// var endDate = timeStep.hiddenDates[i].end;
|
||||
// if (currentValue >= startDate && currentValue < endDate) {
|
||||
// stepInHidden = true;
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// if (stepInHidden == true && currentValue <= timeStep._end.valueOf()) {
|
||||
// var newValue = moment(endDate);
|
||||
// timeStep.current = newValue.toDate();
|
||||
// }
|
||||
//};
|
||||
|
||||
/**
|
||||
* replaces the Core toScreen methods
|
||||
*
|
||||
* @param {vis.Core} Core
|
||||
* @param {Date} time
|
||||
* @param {number} width
|
||||
* @returns {number}
|
||||
*/
|
||||
exports.toScreen = function (Core, time, width) {
|
||||
var conversion;
|
||||
if (Core.body.hiddenDates.length == 0) {
|
||||
conversion = Core.range.conversion(width);
|
||||
return (time.valueOf() - conversion.offset) * conversion.scale;
|
||||
} else {
|
||||
var hidden = exports.isHidden(time, Core.body.hiddenDates);
|
||||
if (hidden.hidden == true) {
|
||||
time = hidden.startDate;
|
||||
}
|
||||
|
||||
var duration = exports.getHiddenDurationBetween(Core.body.hiddenDates, Core.range.start, Core.range.end);
|
||||
if (time < Core.range.start) {
|
||||
conversion = Core.range.conversion(width, duration);
|
||||
var hiddenBeforeStart = exports.getHiddenDurationBeforeStart(Core.body.hiddenDates, time, conversion.offset);
|
||||
time = Core.options.moment(time).toDate().valueOf();
|
||||
time = time + hiddenBeforeStart;
|
||||
return -(conversion.offset - time.valueOf()) * conversion.scale;
|
||||
|
||||
} else if (time > Core.range.end) {
|
||||
var rangeAfterEnd = {start: Core.range.start, end: time};
|
||||
time = exports.correctTimeForHidden(Core.options.moment, Core.body.hiddenDates, rangeAfterEnd, time);
|
||||
conversion = Core.range.conversion(width, duration);
|
||||
return (time.valueOf() - conversion.offset) * conversion.scale;
|
||||
|
||||
} else {
|
||||
time = exports.correctTimeForHidden(Core.options.moment, Core.body.hiddenDates, Core.range, time);
|
||||
conversion = Core.range.conversion(width, duration);
|
||||
return (time.valueOf() - conversion.offset) * conversion.scale;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Replaces the core toTime methods
|
||||
*
|
||||
* @param {vis.Core} Core
|
||||
* @param {number} x
|
||||
* @param {number} width
|
||||
* @returns {Date}
|
||||
*/
|
||||
exports.toTime = function(Core, x, width) {
|
||||
if (Core.body.hiddenDates.length == 0) {
|
||||
var conversion = Core.range.conversion(width);
|
||||
return new Date(x / conversion.scale + conversion.offset);
|
||||
}
|
||||
else {
|
||||
var hiddenDuration = exports.getHiddenDurationBetween(Core.body.hiddenDates, Core.range.start, Core.range.end);
|
||||
var totalDuration = Core.range.end - Core.range.start - hiddenDuration;
|
||||
var partialDuration = totalDuration * x / width;
|
||||
var accumulatedHiddenDuration = exports.getAccumulatedHiddenDuration(Core.body.hiddenDates, Core.range, partialDuration);
|
||||
|
||||
return new Date(accumulatedHiddenDuration + partialDuration + Core.range.start);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Support function
|
||||
*
|
||||
* @param {Array.<{start: Window.start, end: *}>} hiddenDates
|
||||
* @param {number} start
|
||||
* @param {number} end
|
||||
* @returns {number}
|
||||
*/
|
||||
exports.getHiddenDurationBetween = function(hiddenDates, start, end) {
|
||||
var duration = 0;
|
||||
for (var i = 0; i < hiddenDates.length; i++) {
|
||||
var startDate = hiddenDates[i].start;
|
||||
var endDate = hiddenDates[i].end;
|
||||
// if time after the cutout, and the
|
||||
if (startDate >= start && endDate < end) {
|
||||
duration += endDate - startDate;
|
||||
}
|
||||
}
|
||||
return duration;
|
||||
};
|
||||
|
||||
/**
|
||||
* Support function
|
||||
*
|
||||
* @param {Array.<{start: Window.start, end: *}>} hiddenDates
|
||||
* @param {number} start
|
||||
* @param {number} end
|
||||
* @returns {number}
|
||||
*/
|
||||
exports.getHiddenDurationBeforeStart = function (hiddenDates, start, end) {
|
||||
var duration = 0;
|
||||
for (var i = 0; i < hiddenDates.length; i++) {
|
||||
var startDate = hiddenDates[i].start;
|
||||
var endDate = hiddenDates[i].end;
|
||||
|
||||
if (startDate >= start && endDate <= end) {
|
||||
duration += endDate - startDate;
|
||||
}
|
||||
}
|
||||
return duration;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Support function
|
||||
* @param {function} moment
|
||||
* @param {Array.<{start: Window.start, end: *}>} hiddenDates
|
||||
* @param {{start: number, end: number}} range
|
||||
* @param {Date} time
|
||||
* @returns {number}
|
||||
*/
|
||||
exports.correctTimeForHidden = function(moment, hiddenDates, range, time) {
|
||||
time = moment(time).toDate().valueOf();
|
||||
time -= exports.getHiddenDurationBefore(moment, hiddenDates,range,time);
|
||||
return time;
|
||||
};
|
||||
|
||||
exports.getHiddenDurationBefore = function(moment, hiddenDates, range, time) {
|
||||
var timeOffset = 0;
|
||||
time = moment(time).toDate().valueOf();
|
||||
|
||||
for (var i = 0; i < hiddenDates.length; i++) {
|
||||
var startDate = hiddenDates[i].start;
|
||||
var endDate = hiddenDates[i].end;
|
||||
// if time after the cutout, and the
|
||||
if (startDate >= range.start && endDate < range.end) {
|
||||
if (time >= endDate) {
|
||||
timeOffset += (endDate - startDate);
|
||||
}
|
||||
}
|
||||
}
|
||||
return timeOffset;
|
||||
};
|
||||
|
||||
/**
|
||||
* sum the duration from start to finish, including the hidden duration,
|
||||
* until the required amount has been reached, return the accumulated hidden duration
|
||||
* @param {Array.<{start: Window.start, end: *}>} hiddenDates
|
||||
* @param {{start: number, end: number}} range
|
||||
* @param {number} [requiredDuration=0]
|
||||
* @returns {number}
|
||||
*/
|
||||
exports.getAccumulatedHiddenDuration = function(hiddenDates, range, requiredDuration) {
|
||||
var hiddenDuration = 0;
|
||||
var duration = 0;
|
||||
var previousPoint = range.start;
|
||||
//exports.printDates(hiddenDates)
|
||||
for (var i = 0; i < hiddenDates.length; i++) {
|
||||
var startDate = hiddenDates[i].start;
|
||||
var endDate = hiddenDates[i].end;
|
||||
// if time after the cutout, and the
|
||||
if (startDate >= range.start && endDate < range.end) {
|
||||
duration += startDate - previousPoint;
|
||||
previousPoint = endDate;
|
||||
if (duration >= requiredDuration) {
|
||||
break;
|
||||
}
|
||||
else {
|
||||
hiddenDuration += endDate - startDate;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return hiddenDuration;
|
||||
};
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* used to step over to either side of a hidden block. Correction is disabled on tablets, might be set to true
|
||||
* @param {Array.<{start: Window.start, end: *}>} hiddenDates
|
||||
* @param {Date} time
|
||||
* @param {number} direction
|
||||
* @param {boolean} correctionEnabled
|
||||
* @returns {Date|number}
|
||||
*/
|
||||
exports.snapAwayFromHidden = function(hiddenDates, time, direction, correctionEnabled) {
|
||||
var isHidden = exports.isHidden(time, hiddenDates);
|
||||
if (isHidden.hidden == true) {
|
||||
if (direction < 0) {
|
||||
if (correctionEnabled == true) {
|
||||
return isHidden.startDate - (isHidden.endDate - time) - 1;
|
||||
}
|
||||
else {
|
||||
return isHidden.startDate - 1;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (correctionEnabled == true) {
|
||||
return isHidden.endDate + (time - isHidden.startDate) + 1;
|
||||
}
|
||||
else {
|
||||
return isHidden.endDate + 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
return time;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Check if a time is hidden
|
||||
*
|
||||
* @param {Date} time
|
||||
* @param {Array.<{start: Window.start, end: *}>} hiddenDates
|
||||
* @returns {{hidden: boolean, startDate: Window.start, endDate: *}}
|
||||
*/
|
||||
exports.isHidden = function(time, hiddenDates) {
|
||||
for (var i = 0; i < hiddenDates.length; i++) {
|
||||
var startDate = hiddenDates[i].start;
|
||||
var endDate = hiddenDates[i].end;
|
||||
|
||||
if (time >= startDate && time < endDate) { // if the start is entering a hidden zone
|
||||
return {hidden: true, startDate: startDate, endDate: endDate};
|
||||
}
|
||||
}
|
||||
return {hidden: false, startDate: startDate, endDate: endDate};
|
||||
};
|
||||
Reference in New Issue
Block a user