From ae12b4040c09d3130921bfc5a1bbcbece103f3c5 Mon Sep 17 00:00:00 2001 From: Ray Date: Sun, 12 Nov 2023 01:13:17 +0000 Subject: [PATCH 1/2] Refactor to move properties to options in layers --- bbtimeline-background-canvas.js | 89 +++++++++++++++++++-------------- bbtimeline-canvas.js | 5 ++ bbtimeline-flourish-canvas.js | 5 +- bbtimeline-foreground-canvas.js | 57 ++++++++++++++------- bbtimeline.js | 82 +++++++++++------------------- bbtimeline.min.js | 4 -- demo-test.html | 10 ++-- 7 files changed, 133 insertions(+), 119 deletions(-) diff --git a/bbtimeline-background-canvas.js b/bbtimeline-background-canvas.js index 9f6a859..c40adee 100644 --- a/bbtimeline-background-canvas.js +++ b/bbtimeline-background-canvas.js @@ -1,14 +1,31 @@ class BBTimelineBackgroundCanvas extends BBTimelineCanvas { constructor(parentEl, el) { super(parentEl, el); + } + + initialiseOptions() { + super.initialiseOptions(); const a = this; - a.Margin = 0; - a.StepHeight = 0; - a.NoStep = 0; - - a.initialiseComponents(); + a.Options = { + Axis: { + LineColour1: "#000000", + LineWidth: 1, + Font: "8pt Arial", + LabelColour: "#000000", + LabelSpacing: 6 + }, + XAxis: { + NoPartPerDay: 4, + HourLineSpace: 6, + HourLineHeight: 10, + HourLineColour: "#EAEAEA", + DayLineHeight: 20, + DayLineColour: "#9E9E9E", + Position: 'bottom' + } + }; } initialiseComponents() { @@ -16,10 +33,6 @@ class BBTimelineBackgroundCanvas extends BBTimelineCanvas { const a = this; - a.Margin = (a.Parent.Marker.BorderWidth * 2); - a.StepHeight = a.Parent.Marker.Width + a.Margin; - a.NoStep = Math.floor(a.GraphRectangle.H / a.StepHeight); - a.Invalidate(); } @@ -27,7 +40,7 @@ class BBTimelineBackgroundCanvas extends BBTimelineCanvas { get GraphRectangle() { const a = this; - if (a.Parent.XAxis.Position == 'top') { + if (a.Options.XAxis.Position == 'top') { return { X: a.ClientRectangle.X, Y: (a.ClientRectangle.Y + a.XAxisHeight), @@ -46,9 +59,9 @@ class BBTimelineBackgroundCanvas extends BBTimelineCanvas { get XAxisHeight() { const a = this; - const labelSize = a.measureText(a.Parent.Axis.Font, "0"); + const labelSize = a.measureText(a.Options.Axis.Font, "0"); - return labelSize.H + a.Parent.Axis.LabelSpacing + (a.Parent.XAxis.DayLineHeight * 2); + return labelSize.H + a.Options.Axis.LabelSpacing + (a.Options.XAxis.DayLineHeight * 2); } get XAxisPositions() { @@ -72,7 +85,7 @@ class BBTimelineBackgroundCanvas extends BBTimelineCanvas { X: x }); - x += (a.Parent.XAxis.HourLineSpace * a.Parent.XAxis.NoPartPerDay); + x += (a.Options.XAxis.HourLineSpace * a.Options.XAxis.NoPartPerDay); date.setDate(date.getDate() + 1); } @@ -99,7 +112,7 @@ class BBTimelineBackgroundCanvas extends BBTimelineCanvas { a.CTX.beginPath(); - if (a.Parent.XAxis.Position == 'top') { + if (a.Options.XAxis.Position == 'top') { a.CTX.moveTo(a.GraphRectangle.X, (a.GraphRectangle.Y + a.GraphRectangle.H)); a.CTX.lineTo(a.GraphRectangle.X, a.GraphRectangle.Y); a.CTX.lineTo((a.GraphRectangle.X + a.GraphRectangle.W), a.GraphRectangle.Y); @@ -109,27 +122,27 @@ class BBTimelineBackgroundCanvas extends BBTimelineCanvas { a.CTX.lineTo((a.GraphRectangle.X + a.GraphRectangle.W), (a.GraphRectangle.Y + a.GraphRectangle.H)); } - a.CTX.lineWidth = a.Parent.Axis.LineWidth; - a.CTX.strokeStyle = a.Parent.Axis.LineColour1; + a.CTX.lineWidth = a.Options.Axis.LineWidth; + a.CTX.strokeStyle = a.Options.Axis.LineColour1; a.CTX.stroke(); } drawXAxisLabels() { const a = this; - const labelSize = a.measureText(a.Parent.Axis.Font, "0"); + const labelSize = a.measureText(a.Options.Axis.Font, "0"); let posY = 0; let posDayY = 0; let posMonthY = 0; - if (a.Parent.XAxis.Position == 'top') { - posY = (a.GraphRectangle.Y - a.Parent.Axis.LineWidth) - 2; - posDayY = (posY - (labelSize.H + a.Parent.XAxis.DayLineHeight)); - posMonthY = (posDayY - (labelSize.H + a.Parent.Axis.LabelSpacing)); + if (a.Options.XAxis.Position == 'top') { + posY = (a.GraphRectangle.Y - a.Options.Axis.LineWidth) - 2; + posDayY = (posY - (labelSize.H + a.Options.XAxis.DayLineHeight)); + posMonthY = (posDayY - (labelSize.H + a.Options.Axis.LabelSpacing)); } else { - posY = (a.GraphRectangle.Y + a.GraphRectangle.H) + a.Parent.Axis.LineWidth; - posDayY = (posY + a.Parent.XAxis.DayLineHeight); - posMonthY = (posDayY + labelSize.H + a.Parent.Axis.LabelSpacing); + posY = (a.GraphRectangle.Y + a.GraphRectangle.H) + a.Options.Axis.LineWidth; + posDayY = (posY + a.Options.XAxis.DayLineHeight); + posMonthY = (posDayY + labelSize.H + a.Options.Axis.LabelSpacing); } a.XAxisPositions.forEach(function(e, i) { @@ -149,12 +162,12 @@ class BBTimelineBackgroundCanvas extends BBTimelineCanvas { // // Don't write first date // } else { // Write date (dd) - a.drawText(e.X, posDayY, a.Parent.DateToString(date, "dd"), a.Parent.Axis.Font, a.Parent.Axis.LabelColour, "center"); + a.drawText(e.X, posDayY, a.Parent.DateToString(date, "dd"), a.Options.Axis.Font, a.Options.Axis.LabelColour, "center"); // } // Write month (MMMM) on first of the month if (writeLabel) { - a.drawText(e.X, posMonthY, a.Parent.DateToString(date, "MMMM yyyy"), a.Parent.Axis.Font, a.Parent.Axis.LabelColour, "left"); + a.drawText(e.X, posMonthY, a.Parent.DateToString(date, "MMMM yyyy"), a.Options.Axis.Font, a.Options.Axis.LabelColour, "left"); } }); } @@ -168,14 +181,14 @@ class BBTimelineBackgroundCanvas extends BBTimelineCanvas { let posDayY = 0; let posHourY = 0; - if (a.Parent.XAxis.Position == 'top') { - posY = (a.GraphRectangle.Y - a.Parent.Axis.LineWidth); - posDayY = (posY - a.Parent.XAxis.DayLineHeight); - posHourY = (posY - a.Parent.XAxis.HourLineHeight); + if (a.Options.XAxis.Position == 'top') { + posY = (a.GraphRectangle.Y - a.Options.Axis.LineWidth); + posDayY = (posY - a.Options.XAxis.DayLineHeight); + posHourY = (posY - a.Options.XAxis.HourLineHeight); } else { - posY = (a.GraphRectangle.Y + a.GraphRectangle.H) + a.Parent.Axis.LineWidth; - posDayY = (posY + a.Parent.XAxis.DayLineHeight); - posHourY = (posY + a.Parent.XAxis.HourLineHeight); + posY = (a.GraphRectangle.Y + a.GraphRectangle.H) + a.Options.Axis.LineWidth; + posDayY = (posY + a.Options.XAxis.DayLineHeight); + posHourY = (posY + a.Options.XAxis.HourLineHeight); } let i = 0; @@ -188,18 +201,18 @@ class BBTimelineBackgroundCanvas extends BBTimelineCanvas { a.CTX.beginPath(); a.CTX.moveTo(startPosX, posY); - if ((i % a.Parent.XAxis.NoPartPerDay) == 0) { + if ((i % a.Options.XAxis.NoPartPerDay) == 0) { a.CTX.lineTo(startPosX, posDayY); - a.CTX.strokeStyle = a.Parent.XAxis.DayLineColour; + a.CTX.strokeStyle = a.Options.XAxis.DayLineColour; } else { a.CTX.lineTo(startPosX, posHourY); - a.CTX.strokeStyle = a.Parent.XAxis.HourLineColour; + a.CTX.strokeStyle = a.Options.XAxis.HourLineColour; } - a.CTX.lineWidth = a.Parent.Axis.LineWidth; + a.CTX.lineWidth = a.Options.Axis.LineWidth; a.CTX.stroke(); - startPosX += a.Parent.XAxis.HourLineSpace; + startPosX += a.Options.XAxis.HourLineSpace; i++; } diff --git a/bbtimeline-canvas.js b/bbtimeline-canvas.js index adeeaa2..f53be16 100644 --- a/bbtimeline-canvas.js +++ b/bbtimeline-canvas.js @@ -6,9 +6,14 @@ class BBTimelineCanvas { a.Container = el; a.CTX = a.Container.getContext("2d"); + a.initialiseOptions(); a.initialiseComponents(); } + initialiseOptions() { + // Inherit + } + initialiseComponents() { const a = this; diff --git a/bbtimeline-flourish-canvas.js b/bbtimeline-flourish-canvas.js index 8b0cc7e..5e3c12f 100644 --- a/bbtimeline-flourish-canvas.js +++ b/bbtimeline-flourish-canvas.js @@ -1,6 +1,10 @@ class BBTimelineFlourishCanvas extends BBTimelineCanvas { constructor(parentEl, el) { super(parentEl, el); + } + + initialiseOptions() { + super.initialiseOptions(); const a = this; @@ -27,7 +31,6 @@ class BBTimelineFlourishCanvas extends BBTimelineCanvas { a.drawCircle(a.XPos, posY, a.Parent.HotTrack.Width, 0, a.Parent.HotTrack.Colour, a.Parent.HotTrack.Colour); } - } } \ No newline at end of file diff --git a/bbtimeline-foreground-canvas.js b/bbtimeline-foreground-canvas.js index 1649e92..82be438 100644 --- a/bbtimeline-foreground-canvas.js +++ b/bbtimeline-foreground-canvas.js @@ -1,10 +1,33 @@ class BBTimelineForegroundCanvas extends BBTimelineCanvas { constructor(parentEl, el) { super(parentEl, el); + } + + initialiseOptions() { + super.initialiseOptions(); const a = this; - // a.initialiseComponents(); + a.Options = { + Marker: { + BorderColour: "#3A5D9C", + BorderWidth: 2, + BackColour: "#D4DEEF", + Width: 10 + }, + Label: { + Colour: "#3A5D9C", + Font: "9pt Arial", + Margin: { + X: 2, + Y: 10 + }, + Line: { + Colour: "#A6A6A6", + Width: 1, + } + } + }; } initialiseComponents() { @@ -17,7 +40,7 @@ class BBTimelineForegroundCanvas extends BBTimelineCanvas { return; } - var event = a.Parent.FindEventsByCoords(e.offsetX, e.offsetY); + var event = a.Parent.FindEventsByCoords(e.offsetX, e.offsetY, false); if (event == null) { return; } @@ -32,7 +55,7 @@ class BBTimelineForegroundCanvas extends BBTimelineCanvas { return; } - var event = a.Parent.FindEventsByCoords(e.offsetX, e.offsetY); + var event = a.Parent.FindEventsByCoords(e.offsetX, e.offsetY, false); if (event == null) { return; } @@ -47,7 +70,7 @@ class BBTimelineForegroundCanvas extends BBTimelineCanvas { return; } - var event = a.Parent.FindEventsByCoords(e.offsetX, e.offsetY); + var event = a.Parent.FindEventsByCoords(e.offsetX, e.offsetY, false); if (event == null) { return; } @@ -63,7 +86,7 @@ class BBTimelineForegroundCanvas extends BBTimelineCanvas { return; } - var event = a.Parent.FindEventsByCoords(e.offsetX, e.offsetY); + var event = a.Parent.FindEventsByCoords(e.offsetX, e.offsetY, false); if (event != null) { a.Container.style.cursor = 'pointer'; } else { @@ -96,7 +119,6 @@ class BBTimelineForegroundCanvas extends BBTimelineCanvas { Invalidate() { const a = this; const rect = a.Parent.Layer.Background.GraphRectangle; - const margin = a.Parent.Layer.Background.Margin; a.Clear(); @@ -104,9 +126,9 @@ class BBTimelineForegroundCanvas extends BBTimelineCanvas { const visibleEvents = a.Parent.VisibleEvents; if (a.Parent.XAxis.Position == 'top') { - startPosY = (rect.Y + a.Parent.Marker.Width + 20); + startPosY = (rect.Y + a.Options.Marker.Width + 20); } else { - startPosY = (rect.Y + a.Parent.Marker.Width); + startPosY = (rect.Y + a.Options.Marker.Width); } // Clear for collisions detection @@ -125,17 +147,16 @@ class BBTimelineForegroundCanvas extends BBTimelineCanvas { posY2 = (a.Parent.Layer.Background.GraphRectangle.Y + a.Parent.Layer.Background.GraphRectangle.H); } - if (a.Parent.MarkerLabel.Line.Width > 0) { - a.drawVerticalLine(e.Position.X, posY, posY2, a.Parent.MarkerLabel.Line.Width, a.Parent.MarkerLabel.Line.Colour); + if (a.Options.Label.Line.Width > 0) { + a.drawVerticalLine(e.Position.X, posY, posY2, a.Options.Label.Line.Width, a.Options.Label.Line.Colour); } - const markerRectangle = a.drawCircle(e.Position.X, posY, a.Parent.Marker.Width, a.Parent.Marker.BorderWidth, e.BorderColour, e.BackColour); + const markerRectangle = a.drawCircle(e.Position.X, posY, a.Options.Marker.Width, a.Options.Marker.BorderWidth, e.BorderColour, e.BackColour); e.Position = { X: e.Position.X, Y: posY }; if (a.Parent.ShowMarkerLabel) { - const labelRectangle = a.drawText((markerRectangle.X + markerRectangle.W + margin), markerRectangle.Y, e.Label, a.Parent.MarkerLabel.Font, a.Parent.MarkerLabel.Colour, "left"); - labelRectangle.W += a.Parent.MarkerLabel.Margin; + const labelRectangle = a.drawText((markerRectangle.X + markerRectangle.W + a.Options.Label.Margin.X), markerRectangle.Y, e.Label, a.Options.Label.Font, a.Options.Label.Colour, "left"); e.HitBox = a.combineRectangle(markerRectangle, labelRectangle); } else { @@ -152,14 +173,13 @@ class BBTimelineForegroundCanvas extends BBTimelineCanvas { return; } - var event = a.Parent.FindEventsByCoords(e.offsetX, e.offsetY); + var event = a.Parent.FindEventsByCoords(e.offsetX, e.offsetY, false); if (event == null) { return; } if (a.Parent.Debug) console.log(event); - console.log("!"); a.Parent.OnMouseDown(this, e, event); } @@ -167,14 +187,13 @@ class BBTimelineForegroundCanvas extends BBTimelineCanvas { const a = this; const rect = a.Parent.Layer.Background.GraphRectangle; - // Calculate Y position let hasMoved = false; let posY = y; - for (let i=0; i= e.X) && (x <= x2) && (y >= e.Y) && (y <= y2)){ return a.Events[i]; @@ -383,18 +373,4 @@ class BBTimeline { OnDblClick(sender, e, event) { /* delegate */ } - - initialiseComponents() { - const a = this; - - a.Container.innerHTML = ""; - - const canvasList = a.Container.getElementsByTagName("canvas"); - - a.Layer.Background = new BBTimelineBackgroundCanvas(a, canvasList[0]); - a.Layer.Flourish = new BBTimelineFlourishCanvas(a, canvasList[1]); - a.Layer.Markers = new BBTimelineForegroundCanvas(a, canvasList[2]); - - } - } \ No newline at end of file diff --git a/bbtimeline.min.js b/bbtimeline.min.js index 2d55388..e69de29 100644 --- a/bbtimeline.min.js +++ b/bbtimeline.min.js @@ -1,4 +0,0 @@ -/** - * BBTimeline - * @version v0.1.1.121 beta (2023/10/18 2058) - */ diff --git a/demo-test.html b/demo-test.html index 128ed04..ca55f19 100644 --- a/demo-test.html +++ b/demo-test.html @@ -197,12 +197,13 @@ function ToggleShowLabel() { } function ToggleXAxisPosition() { - if (timeline1.XAxis.Position == 'top') { - timeline1.XAxis.Position = 'bottom'; + const xAxis = timeline1.Layer.Background.Options.XAxis; + if (xAxis.Position == 'top') { + xAxis.Position = 'bottom'; timeline1.Padding.Top = 20; timeline1.Padding.Bottom = 0; } else { - timeline1.XAxis.Position = 'top'; + xAxis.Position = 'top'; timeline1.Padding.Top = 0; timeline1.Padding.Bottom = 20; } @@ -211,7 +212,8 @@ function ToggleXAxisPosition() { } function ToggleMarkerTail() { - timeline1.MarkerLabel.Line.Width = ((timeline1.MarkerLabel.Line.Width <= 0) ? 1 : 0); + + timeline1.Layer.Markers.Options.Label.Line.Width = ((timeline1.Layer.Markers.Options.Label.Line.Width <= 0) ? 1 : 0); timeline1.Invalidate(true, true); } From 501bab98ec684a5c10b158e4ea9d560d3d7f555f Mon Sep 17 00:00:00 2001 From: Ray Date: Sun, 12 Nov 2023 14:13:12 +0000 Subject: [PATCH 2/2] Added minified file --- bbtimeline.min.js | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/bbtimeline.min.js b/bbtimeline.min.js index e69de29..90219f0 100644 --- a/bbtimeline.min.js +++ b/bbtimeline.min.js @@ -0,0 +1,13 @@ +/** + * BBTimeline + * @version v0.1.1.277 apha (2023/11/12 0106) + */ +class BBTimeline{constructor(e){const t=this;t.Container=document.getElementById(e),t.Padding={Left:20,Top:20,Right:20,Bottom:0},t.Size={W:t.Container.innerWidth||t.Container.clientWidth,H:t.Container.innerHeight||t.Container.clientHeight},t.Layer={Background:null,Flourish:null,Markers:null},t.DateParsePattern="yyyy-MM-dd",t.HotTrack={Colour:"#F57C00",Width:3},t.Events=[],t.StartDate=t.DateToInternalString(new Date),t.ShowDate=t.StartDate,t.ShowMarkerLabel=!0,t.Enabled=!1,t.Debug=!1,t.EnableHotTracking=!0,t.initialiseComponents()}initialiseComponents(){const e=this;e.Container.innerHTML="";const t=e.Container.getElementsByTagName("canvas");e.Layer.Background=new BBTimelineBackgroundCanvas(e,t[0]),e.Layer.Flourish=new BBTimelineFlourishCanvas(e,t[1]),e.Layer.Markers=new BBTimelineForegroundCanvas(e,t[2])}get CTX(){return a.Layer.Markers.CTX}get NewEvent(){return{Date:"",Label:"",Position:{X:0,Y:0},Events:[],HitBox:null,BorderColour:this.Layer.Markers.Options.Marker.BorderColour,BackColour:this.Layer.Markers.Options.Marker.BackColour}}get NewEventItem(){return{Title:"",Description:"",Link:"",Tag:null}}get VisibleDays(){const e=this,t=e.Size.W-(e.Padding.Left+e.Padding.Right);return Math.floor(t/(e.XAxis.NoPartPerDay*e.XAxis.HourLineSpace))}get VisibleStartDate(){return this.ConvertToDate(this.ShowDate)}get VisibleEndDate(){const e=this;let t=e.ConvertToDate(e.ShowDate);return t.setDate(t.getDate()+e.VisibleDays),t.setDate(t.getDate()-1),e.DateToString(t,e.DateParsePattern)}get VisibleEvents(){const e=this;let t=[];return e.Layer.Background.XAxisPositions.forEach((function(a){const r=e.FindEvent(a.Date);null!=r&&(r.Position.X=a.X,t.push(r))})),t}get XAxis(){return this.Layer.Background.Options.XAxis}AddEvent(e,t,a){const r=this,n=Object.assign(r.NewEventItem,a);let i=r.FindEvent(e);if(null==i){let t=r.NewEvent;t.Date=e,r.Events.push(t),i=r.FindEvent(e)}null!=t&&(i.Label=t),i.Events.push(n)}Clear(){const e=this;e.Layer.Background.Clear(),e.Layer.Flourish.Clear(),e.Layer.Markers.Clear(),e.StartDate=e.DateToInternalString(new Date),e.ShowDate=e.StartDate,e.Enabled=!1,e.Events=[]}DeleteMarker(e){const t=this;for(let a=0;a=i.X&&e<=o&&t>=i.Y&&t<=l)return r.Events[n]}return null}Load(e){this.StartDate=e,this.Show(e)}Show(e){const t=this;t.ConvertToDate(e)12?e.getHours()-12:e.getHours()).toString().padStart(2,"0")),a=a.replace("mm",e.getMinutes().toString().padStart(2,"0")),a=a.replace("ss",e.getSeconds().toString().padStart(2,"0")),a=a.replace("ff",e.getMilliseconds().toString().padStart(2,"0")),a=a.replace("tt","{5}"),a=a.replace("zz",""),a=a.replace("y",e.getFullYear().toString()),a=a.replace("M",(e.getMonth()+1).toString()),a=a.replace("d",e.getDate().toString()),a=a.replace("H",e.getHours().toString()),a=a.replace("h",(e.getHours()>12?e.getHours()-12:e.getHours()).toString()),a=a.replace("m",e.getMinutes().toString()),a=a.replace("s",e.getSeconds().toString()),a=a.replace("z",""),a=a.replace("t","{6}"),a=a.replace("Z",""),a=a.replace("{1}",e.toLocaleString("default",{month:"long"})),a=a.replace("{2}",e.toLocaleString("default",{weekday:"long"})),a=a.replace("{3}",e.toLocaleString("default",{month:"short"})),a=a.replace("{4}",e.toLocaleString("default",{weekday:"short"})),a=a.replace("{5}",e.getHours()>=12?"PM":"AM"),a=a.replace("{6}",e.getHours()>=12?"P":"A"),a}DateToInternalString(e){return this.DateToString(e,this.DateParsePattern)}ConvertToDate(e){return new Date(Date.parse(e))}OnMouseDown(e,t,a){}OnMouseMove(e,t,a){}OnClick(e,t,a){}OnDblClick(e,t,a){}} + +class BBTimelineCanvas{constructor(t,e){const n=this;n.Parent=t,n.Container=e,n.CTX=n.Container.getContext("2d"),n.initialiseOptions(),n.initialiseComponents()}initialiseOptions(){}initialiseComponents(){const t=this;t.Container.style.width=t.Parent.Size.W+"px",t.Container.style.height=t.Parent.Size.H+"px",t.Container.style.position="absolute",t.Container.style.border="none",t.CTX.canvas.width=t.Parent.Size.W,t.CTX.canvas.height=t.Parent.Size.H,t.Clear()}get ClientRectangle(){const t=this;return{X:t.Parent.Padding.Left,Y:t.Parent.Padding.Top,W:t.Parent.Size.W-(t.Parent.Padding.Left+t.Parent.Padding.Right),H:t.Parent.Size.H-(t.Parent.Padding.Top+t.Parent.Padding.Bottom)}}Clear(){const t=this;t.CTX.clearRect(0,0,t.CTX.canvas.width,t.CTX.canvas.height)}Invalidate(){}drawCircle(t,e,n,i,a,r){const s=this,o=2*i,X=n-o,l=s.half(n);s.CTX.beginPath(),s.CTX.arc(t,e,X,0,2*Math.PI,!1),s.CTX.fillStyle=r,s.CTX.fill(),s.CTX.lineWidth=i,s.CTX.strokeStyle=a,s.CTX.stroke();return{X:t-(l+i),Y:e-(l+i),W:n+o,H:n+o}}drawRectangle(t,e){const n=this;return n.CTX.beginPath(),n.CTX.rect(t.X,t.Y,t.W,t.H),n.CTX.lineWidth=1,n.CTX.strokeStyle=e,n.CTX.stroke(),t}drawText(t,e,n,i,a,r){const s=this;s.CTX.font=i,s.CTX.fillStyle=a;let o=s.measureText(i,n);switch(o.Y=e,r){case"center":o.X=t-o.X;break;case"right":o.X=t-o.W;break;default:o.X=t}return s.CTX.fillText(n,o.X,o.Y+o.H),o}drawVerticalLine(t,e,n,i,a){const r=this;r.CTX.beginPath(),r.CTX.moveTo(t,e),r.CTX.lineTo(t,n-i),r.CTX.lineWidth=i,r.CTX.strokeStyle=a,r.CTX.stroke();return{X:t,Y:e,W:i,H:n-e}}half(t){return t/2}measureText(t,e){const n=this;n.CTX.font=t;const i=n.CTX.measureText(e);return{W:i.width,H:i.fontBoundingBoxAscent,X:n.half(i.width),Y:n.half(i.fontBoundingBoxAscent)}}isPointInRectangle(t,e){const n=t.X+t.W,i=t.Y+t.H;return e.X>=t.X&&e.X<=n&&e.Y>=t.Y&&e.Y<=i}combineRectangle(t,e){const n=Math.max(t.X+t.W,e.X+e.W),i=Math.max(t.Y+t.H,e.Y+e.H),a={X:Math.min(t.X,e.X),Y:Math.min(t.Y,e.Y),W:0,H:0};return a.W=n-a.X,a.H=i-a.Y,a}} + +class BBTimelineBackgroundCanvas extends BBTimelineCanvas{constructor(e,t){super(e,t)}initialiseOptions(){super.initialiseOptions();this.Options={Axis:{LineColour1:"#000000",LineWidth:1,Font:"8pt Arial",LabelColour:"#000000",LabelSpacing:6},XAxis:{NoPartPerDay:4,HourLineSpace:6,HourLineHeight:10,HourLineColour:"#EAEAEA",DayLineHeight:20,DayLineColour:"#9E9E9E",Position:"bottom"}}}initialiseComponents(){super.initialiseComponents();this.Invalidate()}get GraphRectangle(){const e=this;return"top"==e.Options.XAxis.Position?{X:e.ClientRectangle.X,Y:e.ClientRectangle.Y+e.XAxisHeight,W:e.ClientRectangle.W,H:e.ClientRectangle.H-e.XAxisHeight}:{X:e.ClientRectangle.X,Y:e.ClientRectangle.Y,W:e.ClientRectangle.W,H:e.ClientRectangle.H-e.XAxisHeight}}get XAxisHeight(){const e=this;return e.measureText(e.Options.Axis.Font,"0").H+e.Options.Axis.LabelSpacing+2*e.Options.XAxis.DayLineHeight}get XAxisPositions(){const e=this,t=e.GraphRectangle.X+e.GraphRectangle.W;let i=[],n=e.GraphRectangle.X,a=e.Parent.ConvertToDate(e.Parent.ShowDate);for(a.setDate(a.getDate()-1);!(n>=t);)i.push({Date:e.Parent.DateToInternalString(a),X:n}),n+=e.Options.XAxis.HourLineSpace*e.Options.XAxis.NoPartPerDay,a.setDate(a.getDate()+1);return i}Invalidate(){const e=this;e.Clear(),e.drawAxis(),e.drawXAxisTicks(),e.drawXAxisLabels(),e.Parent.Debug&&e.drawRectangle(e.ClientRectangle,"red"),e.Parent.Debug&&e.drawRectangle(e.GraphRectangle,"red")}drawAxis(){const e=this;e.CTX.beginPath(),"top"==e.Options.XAxis.Position?(e.CTX.moveTo(e.GraphRectangle.X,e.GraphRectangle.Y+e.GraphRectangle.H),e.CTX.lineTo(e.GraphRectangle.X,e.GraphRectangle.Y),e.CTX.lineTo(e.GraphRectangle.X+e.GraphRectangle.W,e.GraphRectangle.Y)):(e.CTX.moveTo(e.GraphRectangle.X,e.GraphRectangle.Y),e.CTX.lineTo(e.GraphRectangle.X,e.GraphRectangle.Y+e.GraphRectangle.H),e.CTX.lineTo(e.GraphRectangle.X+e.GraphRectangle.W,e.GraphRectangle.Y+e.GraphRectangle.H)),e.CTX.lineWidth=e.Options.Axis.LineWidth,e.CTX.strokeStyle=e.Options.Axis.LineColour1,e.CTX.stroke()}drawXAxisLabels(){const e=this,t=e.measureText(e.Options.Axis.Font,"0");let i=0,n=0,a=0;"top"==e.Options.XAxis.Position?(i=e.GraphRectangle.Y-e.Options.Axis.LineWidth-2,n=i-(t.H+e.Options.XAxis.DayLineHeight),a=n-(t.H+e.Options.Axis.LabelSpacing)):(i=e.GraphRectangle.Y+e.GraphRectangle.H+e.Options.Axis.LineWidth,n=i+e.Options.XAxis.DayLineHeight,a=n+t.H+e.Options.Axis.LabelSpacing),e.XAxisPositions.forEach((function(t,i){const s=e.Parent.ConvertToDate(t.Date);let o=!1;0==i?s.getDate()<25&&(o=!0):1==s.getDate()&&(o=!0),e.drawText(t.X,n,e.Parent.DateToString(s,"dd"),e.Options.Axis.Font,e.Options.Axis.LabelColour,"center"),o&&e.drawText(t.X,a,e.Parent.DateToString(s,"MMMM yyyy"),e.Options.Axis.Font,e.Options.Axis.LabelColour,"left")}))}drawXAxisTicks(){const e=this;let t=e.GraphRectangle.X;const i=e.GraphRectangle.X+e.GraphRectangle.W;let n=0,a=0,s=0;"top"==e.Options.XAxis.Position?(n=e.GraphRectangle.Y-e.Options.Axis.LineWidth,a=n-e.Options.XAxis.DayLineHeight,s=n-e.Options.XAxis.HourLineHeight):(n=e.GraphRectangle.Y+e.GraphRectangle.H+e.Options.Axis.LineWidth,a=n+e.Options.XAxis.DayLineHeight,s=n+e.Options.XAxis.HourLineHeight);let o=0;for(;!(t>=i);)e.CTX.beginPath(),e.CTX.moveTo(t,n),o%e.Options.XAxis.NoPartPerDay==0?(e.CTX.lineTo(t,a),e.CTX.strokeStyle=e.Options.XAxis.DayLineColour):(e.CTX.lineTo(t,s),e.CTX.strokeStyle=e.Options.XAxis.HourLineColour),e.CTX.lineWidth=e.Options.Axis.LineWidth,e.CTX.stroke(),t+=e.Options.XAxis.HourLineSpace,o++}} + +class BBTimelineFlourishCanvas extends BBTimelineCanvas{constructor(a,e){super(a,e)}initialiseOptions(){super.initialiseOptions();this.XPos=-1}Invalidate(){const a=this;if(a.Clear(),a.XPos<0)a.Clear();else{let e=0;e="top"==a.Parent.XAxis.Position?a.Parent.Layer.Background.GraphRectangle.Y:a.Parent.Layer.Background.GraphRectangle.Y+a.Parent.Layer.Background.GraphRectangle.H,a.drawCircle(a.XPos,e,a.Parent.HotTrack.Width,0,a.Parent.HotTrack.Colour,a.Parent.HotTrack.Colour)}}} + +class BBTimelineForegroundCanvas extends BBTimelineCanvas{constructor(e,n){super(e,n)}initialiseOptions(){super.initialiseOptions();this.Options={Marker:{BorderColour:"#3A5D9C",BorderWidth:2,BackColour:"#D4DEEF",Width:10},Label:{Colour:"#3A5D9C",Font:"9pt Arial",Margin:{X:2,Y:10},Line:{Colour:"#A6A6A6",Width:1}}}}initialiseComponents(){super.initialiseComponents();const e=this;e.CTX.canvas.addEventListener("mousedown",(function(n){if(e.Parent.Enabled){var t=e.Parent.FindEventsByCoords(n.offsetX,n.offsetY,!1);null!=t&&(e.Parent.Debug&&console.log(t),e.Parent.OnMouseDown(this,n,t))}})),e.CTX.canvas.addEventListener("click",(function(n){if(e.Parent.Enabled){var t=e.Parent.FindEventsByCoords(n.offsetX,n.offsetY,!1);null!=t&&(e.Parent.Debug&&console.log(t),e.Parent.OnClick(this,n,t))}})),e.CTX.canvas.addEventListener("dblclick",(function(n){if(e.Parent.Enabled){var t=e.Parent.FindEventsByCoords(n.offsetX,n.offsetY,!1);null!=t&&(e.Parent.Debug&&console.log(t),e.Parent.OnDblClick(this,n,t))}})),e.Parent.EnableHotTracking&&e.CTX.canvas.addEventListener("mousemove",(function(n){if(e.Parent.Enabled){var t=e.Parent.FindEventsByCoords(n.offsetX,n.offsetY,!1);if(e.Container.style.cursor=null!=t?"pointer":"default",e.Parent.EnableHotTracking){const o={X:n.offsetX,Y:n.offsetY};e.isPointInRectangle(e.Parent.Layer.Background.GraphRectangle,o)?(e.Parent.Debug&&console.log(o),e.Parent.Layer.Flourish.XPos=o.X,e.Parent.OnMouseMove(this,n,t)):e.Parent.Layer.Flourish.XPos=-1,e.Parent.Layer.Flourish.Invalidate()}}})),e.Invalidate()}Invalidate(){const e=this,n=e.Parent.Layer.Background.GraphRectangle;e.Clear();let t=0;const o=e.Parent.VisibleEvents;t="top"==e.Parent.XAxis.Position?n.Y+e.Options.Marker.Width+20:n.Y+e.Options.Marker.Width,o.forEach((function(e,n){e.HitBox={X:0,Y:0,W:0,H:0}})),o.forEach((function(n,o){let a=e.calcMarkerPosition(n.Position.X,t),r=0;r="top"==e.Parent.XAxis.Position?e.Parent.Layer.Background.GraphRectangle.Y:e.Parent.Layer.Background.GraphRectangle.Y+e.Parent.Layer.Background.GraphRectangle.H,e.Options.Label.Line.Width>0&&e.drawVerticalLine(n.Position.X,a,r,e.Options.Label.Line.Width,e.Options.Label.Line.Colour);const i=e.drawCircle(n.Position.X,a,e.Options.Marker.Width,e.Options.Marker.BorderWidth,n.BorderColour,n.BackColour);if(n.Position={X:n.Position.X,Y:a},e.Parent.ShowMarkerLabel){const t=e.drawText(i.X+i.W+e.Options.Label.Margin.X,i.Y,n.Label,e.Options.Label.Font,e.Options.Label.Colour,"left");n.HitBox=e.combineRectangle(i,t)}else n.HitBox=i;e.Parent.Debug&&e.drawRectangle(n.HitBox,"red"),e.Parent.Debug&&console.log(n)}))}OnMouseDown(e){if(a.Parent.Enabled){var n=a.Parent.FindEventsByCoords(e.offsetX,e.offsetY,!1);null!=n&&(a.Parent.Debug&&console.log(n),a.Parent.OnMouseDown(this,e,n))}}calcMarkerPosition(e,n){const t=this,o=t.Parent.Layer.Background.GraphRectangle;let a=!1,r=n;for(let n=o.Y;n