Added collision avoidance and marker methods

This commit is contained in:
Ray 2023-10-02 23:42:08 +01:00
parent 00c38a5e00
commit f935d337d6
3 changed files with 412 additions and 158 deletions

View File

View File

@ -36,16 +36,21 @@ class BBTimeline {
BorderColour: "#3A5D9C", BorderColour: "#3A5D9C",
BorderWidth: 2, BorderWidth: 2,
BackColour: "#D4DEEF", BackColour: "#D4DEEF",
Width: 10 Width: 10,
ForeColour: "#3A5D9C",
Font: "9pt Arial",
LabelCollisionMargin: 4
}; };
a.HighlightLine = { a.HighlightLine = {
Colour: "#A6A6A6", Colour: "#A6A6A6",
Width: 1, Width: 1,
}; };
a.Events = []; a.Events = [];
a.StartDate = new Date(); a.StartDate = a.DateToString(new Date(), "yyyy-MM-dd");
a.ClientRectangle = a.getClientRectangle(); a.ShowDate = a.StartDate;
a.GraphRectangle = a.calcGraphArea();
a.Enabled = false; a.Enabled = false;
a.Debug = false;
a.ctx = a.Container.getContext("2d"); a.ctx = a.Container.getContext("2d");
a.ctx.canvas.width = a.Size.Width; a.ctx.canvas.width = a.Size.Width;
@ -54,32 +59,50 @@ class BBTimeline {
a.initialiseComponents(); a.initialiseComponents();
} }
Load(startDate) { AddEvent(date, label, options) {
const a = this; const a = this;
a.StartDate = ((typeof(startDate) == "undefined") ? new Date() : startDate); const _options = Object.assign(a.GetEventItem(), options);
a.invalidate(true); let event = a.FindEvent(date);
if (event == null) {
a.Events.push(a.GetEvent(date));
a.Enabled = true; event = a.FindEvent(date);
} }
Clear(all) { if (label != null) {
event.Label = label;
}
event.Events.push(_options);
}
Clear() {
const a = this; const a = this;
if (all) {
a.ctx.clearRect(0, 0, a.ctx.canvas.width, a.ctx.canvas.height); a.ctx.clearRect(0, 0, a.ctx.canvas.width, a.ctx.canvas.height);
a.Events = []; a.StartDate = a.DateToString(new Date(), "yyyy-MM-dd");
a.ShowDate = a.StartDate;
a.Enabled = false; a.Enabled = false;
} else { a.Events = [];
const rect = a.getClientCoords(); }
a.ctx.clearRect((rect.X1 + a.Axis.LineWidth), rect.Y1, (rect.X2 - rect.X1 - a.Axis.LineWidth), (rect.Y2 - rect.Y1 - a.Axis.LineWidth)); DeleteMarker(date)
{
const a = this;
for (let i=0; i<a.Events.length; i++) {
if (a.Events[i].Date != date) {
continue;
}
a.Events.splice(i, 1);
} }
} }
FindDate(date) { FindDatePosition(date) {
const a = this; const a = this;
const points = a.getXAxis(); const points = a.getXAxis();
@ -92,11 +115,46 @@ class BBTimeline {
return null; return null;
} }
FindEventByCoords(x, y) { FindVisibleEvents() {
const a = this;
let result = [];
const availableX = a.getXAxis();
availableX.forEach(function (e) {
const event = a.FindEvent(e.Date);
if (event == null) {
return;
}
// Set offsetX on current view
event.Position.X = e.X;
result.push(event);
});
return result;
}
FindEvent(date) {
const a = this; const a = this;
for (let i=0; i<a.Events.length; i++) { for (let i=0; i<a.Events.length; i++) {
const e = a.Events[i].Rectangle; if (a.Events[i].Date == date) {
return a.Events[i];
}
}
return null;
}
FindEventsByCoords(x, y) {
const a = this;
for (let i=0; i<a.Events.length; i++) {
const e = a.Events[i].HitBox;
if (a.Events[i].HitBox == null) {
continue;
}
if ((x >= e.X1) && (x <= e.X2) && (y >= e.Y1) && (y <= e.Y2)){ if ((x >= e.X1) && (x <= e.X2) && (y >= e.Y1) && (y <= e.Y2)){
return a.Events[i]; return a.Events[i];
@ -106,77 +164,265 @@ class BBTimeline {
return null; return null;
} }
AddEvent(date, title, description, link) { Load(startDate) {
const a = this; const a = this;
a.Events.push({ a.StartDate = startDate;
Date: date,
Title: title,
Description: description,
Link: link
});
a.invalidate(false); a.Show(startDate);
} }
Show(date) {
const a = this;
if (a.stringToDate(date) < a.stringToDate(a.StartDate)) {
date = a.StartDate;
}
a.ShowDate = date;
a.Enabled = true;
a.Invalidate(true, true);
}
ShowNext() {
const a = this;
let date = a.stringToDate(a.ShowDate);
date.setMonth(date.getMonth() + 1);
a.Show(a.DateToString(date, "yyyy-MM-dd"));
}
ShowPrevious() {
const a = this;
let date = a.stringToDate(a.ShowDate);
date.setMonth(date.getMonth() - 1);
a.Show(a.DateToString(date, "yyyy-MM-dd"));
}
UpdateLabel(date, label) {
const a = this;
let event = a.FindEvent(date);
if (event == null) {
return;
}
event.Label = label;
a.Invalidate(false, true);
}
UpdateMarker(date, borderColour, backColour) {
const a = this;
let event = a.FindEvent(date);
if (event == null) {
return;
}
event.BorderColour = borderColour;
event.BackColour = backColour;
a.Invalidate(false, true);
}
initialiseComponents() { initialiseComponents() {
const a = this; const a = this;
const coords = a.getClientCoords(); const coords = a.getClientCoords();
// Vertical highlight line
// a.ctx.canvas.addEventListener('mousemove', function (e) {
// if (!a.Enabled) {
// return;
// }
// a.invalidate(false);
// if ((e.offsetX > (coords.X1 + a.Axis.LineWidth)) && (e.offsetX < coords.X2) && (e.offsetY >= coords.Y1) && (e.offsetY < (coords.Y2 - a.Axis.LineWidth))){
// a.drawVerticalLine(e.offsetX);
// }
// });
a.ctx.canvas.addEventListener('mousedown', function (e) { a.ctx.canvas.addEventListener('mousedown', function (e) {
if (!a.Enabled) { if (!a.Enabled) {
return; return;
} }
var event = a.FindEventByCoords(e.offsetX, e.offsetY); var event = a.FindEventsByCoords(e.offsetX, e.offsetY);
if (event == null) {
return;
}
console.log(event); if (a.Debug) console.log(event);
// console.log(e); a.OnEventClick(event);
}); });
} }
invalidate(all) { Invalidate(redrawAxis, redrawMarkers) {
const a = this; const a = this;
a.Clear(all); if (redrawAxis) {
a.ctx.clearRect(0, 0, a.ctx.canvas.width, a.ctx.canvas.height);
if (all) {
a.drawAxis(); a.drawAxis();
a.drawXAxis(); a.drawXAxis();
a.drawXAxisLabels(); a.drawXAxisLabels();
} else { }
if (redrawMarkers) {
a.clearChart();
const visibleEvents = a.FindVisibleEvents();
const coords = a.getClientCoords(); const coords = a.getClientCoords();
coords.Y1 += a.Marker.Width; coords.Y1 += a.Marker.Width;
for (let i=0; i<a.Events.length; i++) { if (a.Debug) console.log(visibleEvents);
const event = a.FindDate(a.Events[i].Date);
a.drawVerticalLine(event.X, coords.Y1); visibleEvents.forEach(function (e, i) {
// Calculate Y position
let posY = a.calcMarkerPosition(e.Position.X, coords.Y1);
const rect = a.drawMarker(event.X, coords.Y1); a.drawVerticalLine(e.Position.X, posY);
a.Events[i].Rectangle = rect; const markerCoords = a.drawMarker(e.Position.X, posY, e.BorderColour, e.BackColour);
} const labelSize = a.drawText((markerCoords.X2 + a.GraphRectangle.Margin), markerCoords.Y1, e.Label, a.Marker.Font, a.Marker.ForeColour, "left");
console.log(a.Events); e.Position = { X: e.Position.X, Y: posY };
e.HitBox = {
X1: markerCoords.X1,
Y1: markerCoords.Y1,
X2: (markerCoords.X2 + a.GraphRectangle.Margin + labelSize.Width),
Y2: markerCoords.Y2
};
if (a.Debug) a.drawRectangle(e.HitBox);
if (a.Debug) console.log(e);
});
} }
} }
GetEvent(date) {
const a = this;
return {
Date: date,
Label: "",
Position: { X: 0, Y: 0 },
Events: [],
HitBox: null,
BorderColour: a.Marker.BorderColour,
BackColour: a.Marker.BackColour
};
}
GetEventItem() {
return {
Title: "",
Description: "",
Link: "",
Tag: null
};
}
DateToString(date, pattern) {
let result = pattern;
result = result.replace("fffffff", date.getMilliseconds().toString().padStart(7, '0'));
result = result.replace("ffffff", date.getMilliseconds().toString().padStart(6, '0'));
result = result.replace("fffff", date.getMilliseconds().toString().padStart(5, '0'));
result = result.replace("yyyy", date.getFullYear().toString().padStart(4, '0'));
result = result.replace("MMMM", "{1}");
result = result.replace("dddd", "{2}");
result = result.replace("ffff", date.getMilliseconds().toString().padStart(4, '0'));
result = result.replace("yyy", date.getFullYear().toString().padStart(3, '0'));
result = result.replace("MMM", "{3}");
result = result.replace("ddd", "{4}");
result = result.replace("fff", date.getMilliseconds().toString().padStart(3, '0'));
result = result.replace("zzz", "");
result = result.replace("yy", date.getFullYear().toString().slice(-2));
result = result.replace("MM", (date.getMonth() + 1).toString().padStart(2, '0'));
result = result.replace("dd", date.getDate().toString().padStart(2, '0'));
result = result.replace("HH", date.getHours().toString().padStart(2, '0'));
result = result.replace("hh", (date.getHours() > 12 ? (date.getHours() - 12) : date.getHours()).toString().padStart(2, '0'));
result = result.replace("mm", date.getMinutes().toString().padStart(2, '0'));
result = result.replace("ss", date.getSeconds().toString().padStart(2, '0'));
result = result.replace("ff", date.getMilliseconds().toString().padStart(2, '0'));
result = result.replace("tt", "{5}");
result = result.replace("zz", "");
result = result.replace("y", date.getFullYear().toString());
result = result.replace("M", (date.getMonth() + 1).toString());
result = result.replace("d", date.getDate().toString());
result = result.replace("H", date.getHours().toString());
result = result.replace("h", (date.getHours() > 12 ? (date.getHours() - 12) : date.getHours()).toString());
result = result.replace("m", date.getMinutes().toString());
result = result.replace("s", date.getSeconds().toString());
result = result.replace("z", "");
result = result.replace("t", "{6}");
result = result.replace("Z", "");
result = result.replace("{1}", date.toLocaleString('default', { month: 'long' }));
result = result.replace("{2}", date.toLocaleString('default', { weekday: 'long' }));
result = result.replace("{3}", date.toLocaleString('default', { month: 'short' }));
result = result.replace("{4}", date.toLocaleString('default', { weekday: 'short' }));
result = result.replace("{5}", (date.getHours() >= 12 ? "PM" : "AM"));
result = result.replace("{6}", (date.getHours() >= 12 ? "P" : "A"));
return result;
}
OnEventClick(event) {
}
calcGraphArea() {
const a = this;
let result = {
X: a.Padding.Left,
Y: a.Padding.Top,
Width: (a.Size.Width - a.Padding.Right),
Height: (a.Size.Height - a.Padding.Bottom),
Margin: (a.Marker.BorderWidth * 2)
};
result.StepHeight = a.Marker.Width + result.Margin;
result.NoStep = Math.floor(result.Height / result.StepHeight);
return result;
}
calcMarkerPosition(x, y) {
const a = this;
// Calculate Y position
let hasMoved = false;
let posY = y;
for (let i=0; i<a.GraphRectangle.NoStep; i++)
{
posY = y + (a.GraphRectangle.StepHeight * i);
var clippedEvent = a.FindEventsByCoords(x, posY);
if (clippedEvent == null) {
hasMoved = true;
break;
}
}
if (!hasMoved) {
posY = y;
}
return posY;
}
clearChart() {
const a = this;
const rect = a.getClientCoords();
a.ctx.clearRect((rect.X1 + a.Axis.LineWidth), rect.Y1, (rect.X2 - rect.X1 - a.Axis.LineWidth), (rect.Y2 - rect.Y1 - a.Axis.LineWidth));
// Clear marker positions
const visibleEvents = a.FindVisibleEvents();
visibleEvents.forEach(function (e, i) {
e.Position = { X: 0, Y: 0 };
e.HitBox = null;
});
}
drawAxis() { drawAxis() {
const a = this; const a = this;
const coords = a.getClientCoords(); const coords = a.getClientCoords();
@ -191,6 +437,8 @@ class BBTimeline {
a.ctx.lineWidth = a.Axis.LineWidth; a.ctx.lineWidth = a.Axis.LineWidth;
a.ctx.strokeStyle = a.Axis.LineColour1; a.ctx.strokeStyle = a.Axis.LineColour1;
a.ctx.stroke(); a.ctx.stroke();
if (a.Debug) a.drawRectangle(coords);
} }
drawXAxis() { drawXAxis() {
@ -258,17 +506,17 @@ class BBTimeline {
// return; // return;
// } // }
const labelSize = a.drawText(e.X, (y + a.Axis.X.DayLineHeight), a.dateToString(date, "dd"), "center"); const labelSize = a.drawText(e.X, (y + a.Axis.X.DayLineHeight), a.DateToString(date, "dd"), a.Axis.Font, a.Axis.LabelColour, "center");
const label2Spacing = 6; const label2Spacing = 6;
// Write month on first of the month // Write month on first of the month
if (writeLabel) { if (writeLabel) {
a.drawText(e.X, (y + a.Axis.X.DayLineHeight + labelSize.Height + label2Spacing), a.dateToString(date, "MMMM yyyy"), "left"); a.drawText(e.X, (y + a.Axis.X.DayLineHeight + labelSize.Height + label2Spacing), a.DateToString(date, "MMMM yyyy"), a.Axis.Font, a.Axis.LabelColour, "left");
} }
}); });
} }
drawMarker(x, y) { drawMarker(x, y, borderColour, backColour) {
const a = this; const a = this;
const coords = a.getClientCoords(); const coords = a.getClientCoords();
if (coords == null) { if (coords == null) {
@ -279,39 +527,22 @@ class BBTimeline {
a.ctx.beginPath(); a.ctx.beginPath();
a.ctx.arc(x, y, width, 0, 2 * Math.PI, false); a.ctx.arc(x, y, width, 0, 2 * Math.PI, false);
a.ctx.fillStyle = a.Marker.BackColour; a.ctx.fillStyle = backColour;
a.ctx.fill(); a.ctx.fill();
a.ctx.lineWidth = a.Marker.BorderWidth; a.ctx.lineWidth = a.Marker.BorderWidth;
a.ctx.strokeStyle = a.Marker.BorderColour; a.ctx.strokeStyle = borderColour;
a.ctx.stroke(); a.ctx.stroke();
const offset = a.half(a.Marker.Width); return a.measureMarker(x, y);
const result = {
X1: x - (offset + a.Marker.BorderWidth),
Y1: y - (offset + a.Marker.BorderWidth),
X2: x + (offset + a.Marker.BorderWidth),
Y2: y + (offset + a.Marker.BorderWidth)
};
// a.ctx.beginPath();
// a.ctx.rect(result.X1, result.Y1, (result.X2 - result.X1), (result.Y2 - result.Y1));
// a.ctx.fillStyle = 'yellow';
// a.ctx.fill();
// a.ctx.lineWidth = 1;
// a.ctx.strokeStyle = 'black';
// a.ctx.stroke();
return result;
} }
drawText(x, y, label, align) { drawText(x, y, label, font, foreColour, align) {
const a = this; const a = this;
a.ctx.font = a.Axis.Font; a.ctx.font = font;
a.ctx.fillStyle = a.Axis.LabelColour; a.ctx.fillStyle = foreColour;
const size = a.measureText(label); const size = a.measureText(font, label);
switch (align) { switch (align) {
case "center": case "center":
@ -331,6 +562,18 @@ class BBTimeline {
return size; return size;
} }
drawRectangle(coords) {
const a = this;
a.ctx.beginPath();
a.ctx.rect(coords.X1, coords.Y1, (coords.X2 - coords.X1), (coords.Y2 - coords.Y1));
//a.ctx.fillStyle = 'yellow';
//a.ctx.fill();
a.ctx.lineWidth = 1;
a.ctx.strokeStyle = 'red';
a.ctx.stroke();
}
drawVerticalLine(x, y) { drawVerticalLine(x, y) {
const a = this; const a = this;
const coords = a.getClientCoords(); const coords = a.getClientCoords();
@ -353,26 +596,15 @@ class BBTimeline {
getClientCoords() { getClientCoords() {
const a = this; const a = this;
if (a.ClientRectangle == null) { if (a.GraphRectangle == null) {
return null; return null;
} }
return { return {
X1: a.ClientRectangle.X, X1: a.GraphRectangle.X,
Y1: a.ClientRectangle.Y, Y1: a.GraphRectangle.Y,
X2: (a.ClientRectangle.Width - a.ClientRectangle.X), X2: (a.GraphRectangle.Width - a.GraphRectangle.X),
Y2: (a.ClientRectangle.Height - a.ClientRectangle.Y) Y2: (a.GraphRectangle.Height - a.GraphRectangle.Y)
};
}
getClientRectangle() {
const a = this;
return {
X: a.Padding.Left,
Y: a.Padding.Top,
Width: (a.Size.Width - a.Padding.Right),
Height: (a.Size.Height - a.Padding.Bottom)
}; };
} }
@ -385,7 +617,7 @@ class BBTimeline {
let result = []; let result = [];
let x = coords.X1; let x = coords.X1;
let date = a.stringToDate(a.dateToString(a.StartDate, "yyyy-MM-dd")); let date = a.stringToDate(a.ShowDate);
// Rollback one day // Rollback one day
date.setDate(date.getDate() - 1); date.setDate(date.getDate() - 1);
@ -396,7 +628,7 @@ class BBTimeline {
} }
result.push({ result.push({
Date: a.dateToString(date, "yyyy-MM-dd"), Date: a.DateToString(date, "yyyy-MM-dd"),
X: x X: x
}); });
@ -411,9 +643,24 @@ class BBTimeline {
return (value / 2); return (value / 2);
} }
measureText(value) { measureMarker(x, y) {
const a = this;
const offset = a.half(a.Marker.Width);
const result = {
X1: x - (offset + a.Marker.BorderWidth),
Y1: y - (offset + a.Marker.BorderWidth),
X2: x + (offset + a.Marker.BorderWidth),
Y2: y + (offset + a.Marker.BorderWidth)
};
return result;
}
measureText(font, value) {
const a = this; const a = this;
a.ctx.font = font;
const size = a.ctx.measureText(value); const size = a.ctx.measureText(value);
return { return {
@ -424,52 +671,6 @@ class BBTimeline {
}; };
} }
dateToString(date, pattern) {
let result = pattern;
result = result.replace("fffffff", date.getMilliseconds().toString().padStart(7, '0'));
result = result.replace("ffffff", date.getMilliseconds().toString().padStart(6, '0'));
result = result.replace("fffff", date.getMilliseconds().toString().padStart(5, '0'));
result = result.replace("yyyy", date.getFullYear().toString().padStart(4, '0'));
result = result.replace("MMMM", "{1}");
result = result.replace("dddd", "{2}");
result = result.replace("ffff", date.getMilliseconds().toString().padStart(4, '0'));
result = result.replace("yyy", date.getFullYear().toString().padStart(3, '0'));
result = result.replace("MMM", "{3}");
result = result.replace("ddd", "{4}");
result = result.replace("fff", date.getMilliseconds().toString().padStart(3, '0'));
result = result.replace("zzz", "");
result = result.replace("yy", date.getFullYear().toString().slice(-2));
result = result.replace("MM", (date.getMonth() + 1).toString().padStart(2, '0'));
result = result.replace("dd", date.getDate().toString().padStart(2, '0'));
result = result.replace("HH", date.getHours().toString().padStart(2, '0'));
result = result.replace("hh", (date.getHours() > 12 ? (date.getHours() - 12) : date.getHours()).toString().padStart(2, '0'));
result = result.replace("mm", date.getMinutes().toString().padStart(2, '0'));
result = result.replace("ss", date.getSeconds().toString().padStart(2, '0'));
result = result.replace("ff", date.getMilliseconds().toString().padStart(2, '0'));
result = result.replace("tt", "{5}");
result = result.replace("zz", "");
result = result.replace("y", date.getFullYear().toString());
result = result.replace("M", (date.getMonth() + 1).toString());
result = result.replace("d", date.getDate().toString());
result = result.replace("H", date.getHours().toString());
result = result.replace("h", (date.getHours() > 12 ? (date.getHours() - 12) : date.getHours()).toString());
result = result.replace("m", date.getMinutes().toString());
result = result.replace("s", date.getSeconds().toString());
result = result.replace("z", "");
result = result.replace("t", "{6}");
result = result.replace("Z", "");
result = result.replace("{1}", date.toLocaleString('default', { month: 'long' }));
result = result.replace("{2}", date.toLocaleString('default', { weekday: 'long' }));
result = result.replace("{3}", date.toLocaleString('default', { month: 'short' }));
result = result.replace("{4}", date.toLocaleString('default', { weekday: 'short' }));
result = result.replace("{5}", (date.getHours() >= 12 ? "PM" : "AM"));
result = result.replace("{6}", (date.getHours() >= 12 ? "P" : "A"));
return result;
}
stringToDate(value) { stringToDate(value) {
return new Date(Date.parse(value)); return new Date(Date.parse(value));
} }

View File

@ -10,9 +10,7 @@
<!-- <script src="http://cdn.hiimray.co.uk/8206c600-707c-469e-8d49-a76ae35782af/bootstrap/5.3.0/dist/js/bootstrap.bundle.min.js"></script> --> <!-- <script src="http://cdn.hiimray.co.uk/8206c600-707c-469e-8d49-a76ae35782af/bootstrap/5.3.0/dist/js/bootstrap.bundle.min.js"></script> -->
<!-- <link href="http://cdn.hiimray.co.uk/8206c600-707c-469e-8d49-a76ae35782af/bootstrap/5.3.0/dist/css/bootstrap.min.css" rel="stylesheet" /> --> <!-- <link href="http://cdn.hiimray.co.uk/8206c600-707c-469e-8d49-a76ae35782af/bootstrap/5.3.0/dist/css/bootstrap.min.css" rel="stylesheet" /> -->
<link href="bbtimeline.css" rel="stylesheet" />
<script src="bbtimeline.js"></script> <script src="bbtimeline.js"></script>
<!-- <link href="bbtimeline.min.css" rel="stylesheet" /> -->
<!-- <script src="bbtimeline.min.js"></script> --> <!-- <script src="bbtimeline.min.js"></script> -->
<title></title> <title></title>
@ -23,9 +21,18 @@
<p> <p>
<button onclick="Clear()">Clear</button> <button onclick="Clear()">Clear</button>
<button onclick="LoadToday()">Load Today</button> <button onclick="LoadDemo()">Load Demo Events</button>
<button onclick="LoadNext()">Load Next Month</button> <button onclick="ToggleDebug()">Toggle Debug</button>
</p>
<p>
<button onclick="LoadToday()">Show Today</button>
<button onclick="LoadPrevious()">Show Previous Month</button>
<button onclick="LoadNext()">Show Next Month</button>
</p>
<p>
<button onclick="UpdateLabel()">Update Label</button>
<button onclick="UpdateMarker()">Update Marker</button>
<button onclick="DeleteMarker()">Delete Marker</button>
</p> </p>
<style> <style>
@ -49,11 +56,13 @@ canvas {
<script> <script>
var timeline1 = new BBTimeline("myCanvas"); var timeline1 = new BBTimeline("myCanvas");
timeline1.OnEventClick = function(e) {
// console.log(e);
}
LoadDemo();
LoadToday();
timeline1.Load();
timeline1.AddEvent("2023-10-05", "title", "description", "link");
timeline1.AddEvent("2023-10-06", "title", "description", "link");
timeline1.AddEvent("2023-10-16", "title", "description", "link");
@ -63,17 +72,61 @@ function Clear()
timeline1.Clear(true); timeline1.Clear(true);
} }
function LoadDemo()
{
timeline1.AddEvent("2023-10-05", "hello", { Title: Math.random(), Description: Math.random() });
timeline1.AddEvent("2023-10-06", "hello", { Title: Math.random(), Description: Math.random() });
timeline1.AddEvent("2023-10-06", null, { Title: Math.random(), Description: Math.random() });
timeline1.AddEvent("2023-10-16", "hello", { Title: Math.random(), Description: Math.random() });
timeline1.AddEvent("2023-10-06", "hello 2", { Title: Math.random(), Description: Math.random() });
timeline1.AddEvent("2023-10-06", null, { Title: Math.random(), Description: Math.random() });
timeline1.AddEvent("2023-10-20", "hello hello hello", { Title: Math.random(), Description: Math.random() });
timeline1.AddEvent("2023-10-21", "hello", { Title: Math.random(), Description: Math.random() });
timeline1.AddEvent("2023-10-23", "hello", { Title: Math.random(), Description: Math.random() });
timeline1.AddEvent("2023-10-26", "hello", { Title: Math.random(), Description: Math.random() });
LoadToday();
timeline1.Invalidate(false, true);
}
function ToggleDebug()
{
timeline1.Debug = !timeline1.Debug;
timeline1.Invalidate(true, true);
}
function LoadToday() function LoadToday()
{ {
timeline1.Load(new Date()); const date = timeline1.DateToString(new Date(), "yyyy-MM-dd");
timeline1.Load(date);
}
function LoadPrevious()
{
timeline1.ShowPrevious();
} }
function LoadNext() function LoadNext()
{ {
let date = timeline1.StartDate; timeline1.ShowNext();
date.setMonth(date.getMonth() + 1); }
timeline1.Load(date); function UpdateLabel()
{
timeline1.UpdateLabel("2023-10-21", "hello world");
}
function UpdateMarker()
{
timeline1.UpdateMarker("2023-10-21", "#E68422", "#FAE7D3");
}
function DeleteMarker()
{
timeline1.DeleteMarker("2023-10-06");
timeline1.Invalidate(false, true);
} }
</script> </script>