class BBTimelineBackgroundCanvas extends BBTimelineCanvas { constructor(parentEl, el) { super(parentEl, el); } initialiseOptions() { super.initialiseOptions(); const a = this; 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() { super.initialiseComponents(); const a = this; a.Invalidate(); } get GraphRectangle() { const a = this; if (a.Options.XAxis.Position == 'top') { return { X: a.ClientRectangle.X, Y: (a.ClientRectangle.Y + a.XAxisHeight), W: a.ClientRectangle.W, H: (a.ClientRectangle.H - a.XAxisHeight) }; } else { return { X: a.ClientRectangle.X, Y: a.ClientRectangle.Y, W: a.ClientRectangle.W, H: (a.ClientRectangle.H - a.XAxisHeight) }; } } get XAxisHeight() { const a = this; const labelSize = a.measureText(a.Options.Axis.Font, "0"); return labelSize.H + a.Options.Axis.LabelSpacing + (a.Options.XAxis.DayLineHeight * 2); } get XAxisPositions() { const a = this; const endPosX = (a.GraphRectangle.X + a.GraphRectangle.W); let result = []; let x = a.GraphRectangle.X; let date = a.Parent.ConvertToDate(a.Parent.ShowDate); // Rollback one day date.setDate(date.getDate() - 1); while (true) { if (x >= endPosX) { break; } result.push({ Date: a.Parent.DateToInternalString(date), X: x }); x += (a.Options.XAxis.HourLineSpace * a.Options.XAxis.NoPartPerDay); date.setDate(date.getDate() + 1); } return result; } Invalidate() { const a = this; a.Clear(); a.drawAxis(); a.drawXAxisTicks(); a.drawXAxisLabels(); if (a.Parent.Debug) a.drawRectangle(a.ClientRectangle, "red"); if (a.Parent.Debug) a.drawRectangle(a.GraphRectangle, "red"); } drawAxis() { const a = this; a.CTX.beginPath(); 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); } else { a.CTX.moveTo(a.GraphRectangle.X, a.GraphRectangle.Y); a.CTX.lineTo(a.GraphRectangle.X, (a.GraphRectangle.Y +a.GraphRectangle.H)); a.CTX.lineTo((a.GraphRectangle.X + a.GraphRectangle.W), (a.GraphRectangle.Y + a.GraphRectangle.H)); } 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.Options.Axis.Font, "0"); let posY = 0; let posDayY = 0; let posMonthY = 0; 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.Options.Axis.LineWidth; posDayY = (posY + a.Options.XAxis.DayLineHeight); posMonthY = (posDayY + labelSize.H + a.Options.Axis.LabelSpacing); } a.XAxisPositions.forEach(function(e, i) { const date = a.Parent.ConvertToDate(e.Date); let writeLabel = false; if ((i == 0)) { // Don't label first entry if too close to the next month if (date.getDate() < 25) { writeLabel = true; } } else if (date.getDate() == 1) { writeLabel = true; } // if (i == 0) { // // Don't write first date // } else { // Write date (dd) 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.Options.Axis.Font, a.Options.Axis.LabelColour, "left"); } }); } drawXAxisTicks() { const a = this; let startPosX = a.GraphRectangle.X; const endPosX = (a.GraphRectangle.X + a.GraphRectangle.W); let posY = 0; let posDayY = 0; let posHourY = 0; 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.Options.Axis.LineWidth; posDayY = (posY + a.Options.XAxis.DayLineHeight); posHourY = (posY + a.Options.XAxis.HourLineHeight); } let i = 0; while (true) { if (startPosX >= endPosX) { break; } a.CTX.beginPath(); a.CTX.moveTo(startPosX, posY); if ((i % a.Options.XAxis.NoPartPerDay) == 0) { a.CTX.lineTo(startPosX, posDayY); a.CTX.strokeStyle = a.Options.XAxis.DayLineColour; } else { a.CTX.lineTo(startPosX, posHourY); a.CTX.strokeStyle = a.Options.XAxis.HourLineColour; } a.CTX.lineWidth = a.Options.Axis.LineWidth; a.CTX.stroke(); startPosX += a.Options.XAxis.HourLineSpace; i++; } } }