From e062f56b656131f0e53dd5cb1efb69b35ca3b206 Mon Sep 17 00:00:00 2001 From: Ray Date: Sun, 7 Jan 2024 00:13:44 +0000 Subject: [PATCH] Refactored to avoid ES6 as bundler will not handle private modifiers Added build script for project Added canvas to js-extensions --- build-ryzjsext.bat | 1 + build-ryzproj.bat | 38 ++ build/ryzjsext.min.js | 16 +- build/ryzproj.bundle.min.js | 24 + build/ryzproj.min.js | 14 + canvas.js | 544 ------------------ ...st.html => demo-javascript-extensions.html | 2 - ryzproj.css => demo-project.css | 3 +- ryzproj-test.html => demo-project.html | 13 +- javascript-extensions/canvas.js | 540 +++++++++++++++++ javascript-extensions/version.txt | 2 +- .../gantt-chart.js | 101 ++-- ryzproj.js => project/project.js | 38 +- project-taskgrid.js => project/task-grid.js | 18 +- project/version-bundle.txt | 4 + 15 files changed, 724 insertions(+), 634 deletions(-) create mode 100644 build-ryzproj.bat create mode 100644 build/ryzproj.bundle.min.js create mode 100644 build/ryzproj.min.js delete mode 100644 canvas.js rename ryzjsext-test.html => demo-javascript-extensions.html (91%) rename ryzproj.css => demo-project.css (96%) rename ryzproj-test.html => demo-project.html (92%) create mode 100644 javascript-extensions/canvas.js rename project-ganttchart.js => project/gantt-chart.js (67%) rename ryzproj.js => project/project.js (91%) rename project-taskgrid.js => project/task-grid.js (89%) create mode 100644 project/version-bundle.txt diff --git a/build-ryzjsext.bat b/build-ryzjsext.bat index 8f59d8d..8bf9e72 100644 --- a/build-ryzjsext.bat +++ b/build-ryzjsext.bat @@ -1,5 +1,6 @@ del ryzjsext.min.js del ryzjsext.min.tmp +del build/ryzjsext.min.js cd javascript-extensions diff --git a/build-ryzproj.bat b/build-ryzproj.bat new file mode 100644 index 0000000..d5d9eed --- /dev/null +++ b/build-ryzproj.bat @@ -0,0 +1,38 @@ +del ryzproj.min.js +del ryzproj.min.tmp +del build/ryzproj.min.js + +cd project + +type version.txt >> ../ryzproj.min.js + +"C:\B\Portable Files (dev)\Google Closure Compiler\closure-compiler-v20231112.jar" --js project.js --js_output_file ../ryzproj.min.tmp + +cd.. + +type ryzproj.min.tmp >> ryzproj.min.js + +move ryzproj.min.js build/ryzproj.min.js + +del ryzproj.min.tmp + + + + +del ryzproj.bundle.min.js +del ryzproj.bundle.min.tmp +del ryzproj.bundle.min.js + +cd project + +type version-bundle.txt >> ../ryzproj.bundle.min.js + +"C:\B\Portable Files (dev)\Google Closure Compiler\closure-compiler-v20231112.jar" --js *.js --js_output_file ../ryzproj.bundle.min.tmp + +cd.. + +type ryzproj.bundle.min.tmp >> ryzproj.bundle.min.js + +move ryzproj.bundle.min.js build/ryzproj.bundle.min.js + +del ryzproj.bundle.min.tmp diff --git a/build/ryzjsext.min.js b/build/ryzjsext.min.js index 6c62c1a..a6df19e 100644 --- a/build/ryzjsext.min.js +++ b/build/ryzjsext.min.js @@ -1,13 +1,25 @@ /** * Ray's JavaScript Extension - * @version v0.1.0.071 (2023/12/27 1551) + * @version v0.1.0.088 (2024/01/06 1933) */ Array.toFlatten=function(a,b,c){for(let d=0;d{b+=this.count(c.propName,c.value)});return b};Array.prototype.flatten=function(a){let b=[];Array.toFlatten(this,a,b);return b};Array.prototype.index=function(a,b){for(let c=0;ca?this.splice(0,0,b):a>=this.length?this.push(b):this.splice(a,0,b);return this}; Array.prototype.joinIfNotNullOrWhitespace=function(a){let b="";for(let c=0;c=this[c][a].length||!1!==this[c][a].forEachTree(a,b));c++);}; Array.prototype.indexes=function(a,b){let c=[];for(let d=0;dc[a]?1:0});return this};Array.prototype.orderByDesc=function(a){this.sort(function(b,c){return b[a]c[a]?-1:0});return this}; Array.prototype.remove=function(a){let b=[];for(let c=0;ca||a>=this.length)return this;this.splice(a,1);return this};Array.prototype.removeRange=function(a){for(let b=0;b{b=b.select(c.propName,c.value)});return b};Array.prototype.toList=function(a){let b=[];this.forEach(c=>{b.push(c[a])});return b};Array.prototype.sortTree=function(a,b){this.orderBy(b);for(let c=0;c=this[c][a].length||this[c][a].orderBy(b)};Boolean.isFalse=function(a){return String.isNullOrUndefined(a)?!0:a.toString().containsCI("false","f","y","0","x")};Boolean.isTrue=function(a){return String.isNullOrUndefined(a)?!1:a.toString().containsCI("true","t","n","1","o")};Boolean.ifTrue=function(a,b,c){return Boolean.isTrue(a)?b:c};Date.addDays=function(a,b){a=new Date(a);a.addDays(b);return a};Date.addMonths=function(a,b){a=new Date(a);a.addMonths(b);return a};Date.addYears=function(a,b){a=new Date(a);a.addYears(b);return a};Date.max=function(a,b){return null==a?b:null==b?a:new Date(a)<=new Date(b)?new Date(b):new Date(a)};Date.min=function(a,b){return null==a?b:null==b?a:new Date(a)<=new Date(b)?new Date(a):new Date(b)};Date.diffDays=function(a,b){return Math.ceil(((new Date(b)).getTime()-(new Date(a)).getTime())/864E5)}; +Array.prototype.selectMany=function(...a){let b=this;a.forEach(c=>{b=b.select(c.propName,c.value)});return b};Array.prototype.toList=function(a){let b=[];this.forEach(c=>{b.push(c[a])});return b};Array.prototype.sortTree=function(a,b){this.orderBy(b);for(let c=0;c=this[c][a].length||this[c][a].orderBy(b)};Boolean.isFalse=function(a){return String.isNullOrUndefined(a)?!0:a.toString().containsCI("false","f","y","0","x")};Boolean.isTrue=function(a){return String.isNullOrUndefined(a)?!1:a.toString().containsCI("true","t","n","1","o")};Boolean.ifTrue=function(a,b,c){return Boolean.isTrue(a)?b:c};class Canvas{constructor(a){this.container=a;this.canvasContainer=this.flowContainer=this.ctx=null;this.autoSize=!0;this.padding={Top:0,Right:0,Bottom:0,Left:0};this.initialiseComponents()}initialiseComponents(){null!=this.container&&(this.container.innerHTML="
",null!=this.container&&(this.container.style.width="100%",this.container.style.height="100%",this.flowContainer=this.container.getElementsByTagName("div")[0],this.canvasContainer=this.flowContainer.getElementsByTagName("canvas")[0], +this.ctx=this.canvasContainer.getContext("2d")),this.AutoSize=this.AutoSize,this.Width=this.Width,this.Height=this.Height,this.Clear())}get AutoSize(){return this.autoSize}set AutoSize(a){this.autoSize=a;null!=this.flowContainer&&(1==a?this.flowContainer.style.overflow="hidden":(this.flowContainer.style.overflowX=this.Width>=this.ClientWidth?"hidden":"auto",this.flowContainer.style.overflowY=this.Height>=this.ClientHeight?"hidden":"auto"))}get ClientHeight(){return null==this.canvasContainer?0:this.getHeight(this.canvasContainer)}set ClientHeight(a){null!= +this.canvasContainer&&(this.canvasContainer.style.height=a+"px");null!=this.ctx&&(this.ctx.canvas.height=a)}get ClientWidth(){return null==this.canvasContainer?0:this.getWidth(this.canvasContainer)}set ClientWidth(a){null!=this.canvasContainer&&(this.canvasContainer.style.width=a+"px");null!=this.ctx&&(this.ctx.canvas.width=a)}get Height(){return null==this.container?0:this.getHeight(this.container)}set Height(a){null!=this.container&&(this.container.style.height=a+"px");null!=this.flowContainer&& +(this.flowContainer.style.height=a+"px");1==this.AutoSize&&(this.ClientHeight=a)}get Width(){return null==this.container?0:this.getWidth(this.container)}set Width(a){null!=this.container&&(this.container.style.width=a+"px");null!=this.flowContainer&&(this.flowContainer.style.width=a+"px");1==this.AutoSize&&(this.ClientWidth=a)}get Size(){return{W:this.Width,H:this.Height}}get ClientRectangle(){return{X:this.padding.Left,Y:this.padding.Top,W:this.Width-(this.padding.Left+this.padding.Right),H:this.Height- +(this.padding.Top+this.padding.Bottom)}}get Rectangle(){return{X:0,Y:0,W:this.Width,H:this.Height}}Clear(){null!=this.ctx&&this.ctx.clearRect(0,0,this.ctx.canvas.width,this.ctx.canvas.height)}DrawArrowS(a,b,c){null!=this.ctx&&(c=Object.assign({LineWidth:1,LineDash:[],FillColour:null},c),a.X+=.5,a.Y+=.5,a.W-=c.LineWidth,a.H-=c.LineWidth,this.ctx.beginPath(),this.ctx.strokeStyle=b,this.ctx.lineWidth=c.LineWidth,this.ctx.setLineDash(c.LineDash),this.ctx.moveTo(a.X,a.Y),this.ctx.lineTo(a.X+a.W,a.Y),this.ctx.lineTo(a.X+ +Math.half(a.W),a.Y+a.H),this.ctx.closePath(),null!=c.FillColour&&(this.ctx.fillStyle=c.FillColour,this.ctx.fill()),this.ctx.stroke())}DrawCircle(a,b,c,d,e){if(null!=this.ctx){e=Object.assign({LineWidth:1,LineDash:[],FillColour:null},e);a+=Math.half(c);b+=Math.half(c);var f=Math.half(c);Math.half(c);a+=.5;b+=.5;f-=Math.half(e.LineWidth);Math.half(e.LineWidth);this.ctx.beginPath();this.ctx.strokeStyle=d;this.ctx.lineWidth=e.LineWidth;this.ctx.setLineDash(e.LineDash);this.ctx.arc(a,b,f,0,2*Math.PI,!1); +this.ctx.closePath();null!=e.FillColour&&(this.ctx.fillStyle=e.FillColour,this.ctx.fill());this.ctx.stroke()}}DrawDiamond(a,b,c){null!=this.ctx&&(c=Object.assign({LineWidth:1,LineDash:[],FillColour:null},c),a.X+=.5,a.Y+=.5,a.W-=c.LineWidth,a.H-=c.LineWidth,this.ctx.beginPath(),this.ctx.strokeStyle=b,this.ctx.lineWidth=c.LineWidth,this.ctx.setLineDash(c.LineDash),this.ctx.moveTo(a.X+Math.half(a.W),a.Y),this.ctx.lineTo(a.X+a.W,a.Y+Math.half(a.H)),this.ctx.lineTo(a.X+Math.half(a.W),a.Y+a.H),this.ctx.lineTo(a.X, +a.Y+Math.half(a.H)),this.ctx.closePath(),null!=c.FillColour&&(this.ctx.fillStyle=c.FillColour,this.ctx.fill()),this.ctx.stroke())}DrawRectangle(a,b,c){null!=this.ctx&&(c=Object.assign({LineWidth:1,LineDash:[],FillColour:null},c),a.X+=.5,a.Y+=.5,a.W-=c.LineWidth,a.H-=c.LineWidth,this.ctx.beginPath(),this.ctx.strokeStyle=b,this.ctx.lineWidth=c.LineWidth,this.ctx.setLineDash(c.LineDash),this.ctx.rect(a.X,a.Y,a.W,a.H),null!=c.FillColour&&(this.ctx.fillStyle=c.FillColour,this.ctx.fill()),this.ctx.closePath(), +this.ctx.stroke())}DrawLine(a,b,c,d,e,f){null!=this.ctx&&(f=Object.assign({LineWidth:1,LineDash:[]},f),b-=.5,this.ctx.beginPath(),this.ctx.strokeStyle=e,this.ctx.lineWidth=f.LineWidth,this.ctx.setLineDash(f.LineDash),this.ctx.moveTo(a,b),this.ctx.lineTo(c,d),this.ctx.stroke())}DrawLines(a,b,c){if(null!=this.ctx&&null!=a&&!(0>=a.length)){c=Object.assign({LineWidth:1,LineDash:[]},c);this.ctx.beginPath();this.ctx.strokeStyle=b;this.ctx.lineWidth=c.LineWidth;this.ctx.setLineDash(c.LineDash);this.ctx.moveTo(a[0].X, +a[0].Y);for(b=1;b=b[a].Duration?this.Canvas.DrawDiamond(e,c.BorderColour,{FillColour:c.FillColour}):this.Canvas.DrawRectangle(e,c.BorderColour,{FillColour:c.FillColour})}}drawLines(b){for(let e=0;e=b.Duration?(b={X:this.Options.DayWidth*(Date.diffDays(this.StartDate,b.StartDate)+1),Y:this.HeaderHeight+this.Options.Row.Height*c+a.PaddingTop,W:a.Height,H:a.Height},b.X-=Math.half(b.W)):b={X:this.Options.DayWidth*(Date.diffDays(this.StartDate,b.StartDate)+1),Y:this.HeaderHeight+ +this.Options.Row.Height*c+a.PaddingTop,W:this.Options.DayWidth*b.Duration,H:a.Height};return b}};class RyzProject{constructor(b){this.Project=Object.assign(this.newProject,b);this.Tasks=[];this.initialiseComponents()}initialiseComponents(){}get NewTask(){return{ID:null,Name:"",Description:"",Tag:null,StartDelay:0,Duration:1,PredecessorTaskID:null,IsCollated:!1,CollatedTaskID:null,ActuWorkHours:null,Progress:0,Resources:[]}}get StartDate(){return new Date(this.Project.StartDate)}get FinishDate(){let b=new Date(this.Project.StartDate);this.ExportTasks().forEach(a=>{null!=a.FinishDate&&(b=Date.max(b, +a.FinishDate))});return b}get Duration(){return Date.diffDays(this.StartDate,this.FinishDate)}get newProject(){return{Name:"",Description:"",StartDate:Date.today(),Tag:null,StartOfWeek:1,WorkHours:[0,7.5,7.5,7.5,7.5,7.5,0]}}get newTaskNode(){return{Order:null,ID:null,Name:"",Description:"",Tag:null,StartDate:null,FinishDate:null,StartDelay:0,Duration:1,PredecessorTaskID:null,IsCollated:!1,CollatedTaskID:null,CalcWorkHours:0,ActuWorkHours:null,Progress:0,Resources:[],Level:0,PredecessorTaskNo:null, +Tasks:[]}}AddTask(b){b=Object.assign(this.NewTask,b);b=Object.assign(this.newTaskNode,b);if(null==b.PredecessorTaskID&&null==b.CollatedTaskID)this.Tasks.push(b);else if(null!=b.PredecessorTaskID){var a=this.FindTask(b.PredecessorTaskID);null!=a?a.Tasks.push(b):this.log("Task not found ("+b.PredecessorTaskID+")")}else null!=b.CollatedTaskID?(a=this.FindTask(b.CollatedTaskID),null!=a?a.Tasks.push(b):this.log("Task not found ("+b.CollatedTaskID+")")):this.log("Task not found ("+b.ID+")")}ClearTasks(){this.Tasks= +[]}ExportTasks(){let b=this.Tasks.copy().flatten("Tasks");for(var a=0;ae;e++){if(0>=a.copy().countMany({propName:"StartDate",value:null},{propName:"FinishDate",value:null})){b=!0;break}this.log("Round "+ +(e+1));for(c=0;c=b[a].Duration)continue;let c=0,e=new Date(b[a].StartDate);for(let d=0;d=c.length)return b[a].Duration=0,new Date(b[a].StartDate);if(c.any("FinishDate",null))return b[a].Duration=0,null;let e=new Date(b[a].StartDate);c.forEach(d=>{d.FinishDate>e&&(e=d.FinishDate)});b[a].Progress=Math.average(c.toList("Progress")); +b[a].FinishDate=new Date(e);b[a].Duration=Date.diffDays(b[a].StartDate,b[a].FinishDate)}};class ProjectTaskGrid{constructor(b){this.Container=b;this.Columns=[null,null,"Task Name","Duration","Start","Finish","Predecessor","Resource Names",null];this.initialiseComponents()}initialiseComponents(){let b;b=""+this.renderTHead();b=b+""+this.renderPlaceholder();this.Container.innerHTML=b+"
"}Render(b){const a=this;let c="";c+="";c+=a.renderTHead();c+="";b.forEach(e=>{c+=a.renderRow(e)});c+="";c+="
"; +a.Container.innerHTML=c}renderTHead(){let b="";b+="";b+="";this.Columns.forEach(a=>{b+=""+(a??"")+""});b+="";return b+=""}renderPlaceholder(){return"Loading...")}renderRow(b){let a="";a=1==b.IsCollated?a+"":a+"";a+=""+b.Order+"";a+="";for(let c=0;c";a+=b.Name;a=a+""+(b.Duration+" day"+(1==parseInt(b.Duration)? +"":"s")+"");a+=""+(new Date(b.StartDate)).toLocaleDateString()+"";a+=""+(new Date(b.FinishDate)).toLocaleDateString()+"";a+=""+(b.PredecessorTaskNo??"")+"";return a+""}}; diff --git a/build/ryzproj.min.js b/build/ryzproj.min.js new file mode 100644 index 0000000..73a5c5e --- /dev/null +++ b/build/ryzproj.min.js @@ -0,0 +1,14 @@ +/** + * Ray's Projects + * @version v0.1.0.104 (2023/12/27 1051) + */ +class RyzProject{constructor(b){this.Project=Object.assign(this.newProject,b);this.Tasks=[];this.initialiseComponents()}initialiseComponents(){}get NewTask(){return{ID:null,Name:"",Description:"",Tag:null,StartDelay:0,Duration:1,PredecessorTaskID:null,IsCollated:!1,CollatedTaskID:null,ActuWorkHours:null,Progress:0,Resources:[]}}get StartDate(){return new Date(this.Project.StartDate)}get FinishDate(){let b=new Date(this.Project.StartDate);this.ExportTasks().forEach(a=>{null!=a.FinishDate&&(b=Date.max(b, +a.FinishDate))});return b}get Duration(){return Date.diffDays(this.StartDate,this.FinishDate)}get newProject(){return{Name:"",Description:"",StartDate:Date.today(),Tag:null,StartOfWeek:1,WorkHours:[0,7.5,7.5,7.5,7.5,7.5,0]}}get newTaskNode(){return{Order:null,ID:null,Name:"",Description:"",Tag:null,StartDate:null,FinishDate:null,StartDelay:0,Duration:1,PredecessorTaskID:null,IsCollated:!1,CollatedTaskID:null,CalcWorkHours:0,ActuWorkHours:null,Progress:0,Resources:[],Level:0,PredecessorTaskNo:null, +Tasks:[]}}AddTask(b){b=Object.assign(this.NewTask,b);b=Object.assign(this.newTaskNode,b);if(null==b.PredecessorTaskID&&null==b.CollatedTaskID)this.Tasks.push(b);else if(null!=b.PredecessorTaskID){var a=this.FindTask(b.PredecessorTaskID);null!=a?a.Tasks.push(b):this.log("Task not found ("+b.PredecessorTaskID+")")}else null!=b.CollatedTaskID?(a=this.FindTask(b.CollatedTaskID),null!=a?a.Tasks.push(b):this.log("Task not found ("+b.CollatedTaskID+")")):this.log("Task not found ("+b.ID+")")}ClearTasks(){this.Tasks= +[]}ExportTasks(){let b=this.Tasks.copy().flatten("Tasks");for(var a=0;ae;e++){if(0>=a.copy().countMany({propName:"StartDate",value:null},{propName:"FinishDate",value:null})){b=!0;break}this.log("Round "+ +(e+1));for(c=0;c=b[a].Duration)continue;let c=0,e=new Date(b[a].StartDate);for(let d=0;d=c.length)return b[a].Duration=0,new Date(b[a].StartDate);if(c.any("FinishDate",null))return b[a].Duration=0,null;let e=new Date(b[a].StartDate);c.forEach(d=>{d.FinishDate>e&&(e=d.FinishDate)});b[a].Progress=Math.average(c.toList("Progress")); +b[a].FinishDate=new Date(e);b[a].Duration=Date.diffDays(b[a].StartDate,b[a].FinishDate)}}; diff --git a/canvas.js b/canvas.js deleted file mode 100644 index cfc80ab..0000000 --- a/canvas.js +++ /dev/null @@ -1,544 +0,0 @@ -class Canvas { - _container = null; - _flowContainer = null; - _canvasContainer = null; - _ctx = null; - - _autoSize = true; - _padding = { - Top: 0, - Right: 0, - Bottom: 0, - Left: 0 - }; - - - constructor(el) { - const a = this; - - a._container = el; - a._ctx = null; - - a.#initialiseComponents(); - } - - #initialiseComponents() { - const a = this; - - if (a._container == null) { - return; - } - - a._container.innerHTML = "
"; - - if (a._container != null) { - a._container.style.width = "100%"; - a._container.style.height = "100%"; - - a._flowContainer = a._container.getElementsByTagName("div")[0]; - a._canvasContainer = a._flowContainer.getElementsByTagName("canvas")[0]; - a._ctx = a._canvasContainer.getContext("2d"); - } - - a.AutoSize = a.AutoSize; - a.Width = a.Width; - a.Height = a.Height; - - a.Clear(); - } - - - get AutoSize() { - return this._autoSize; - } - - set AutoSize(value) { - const a = this; - - a._autoSize = value; - - if (a._flowContainer != null) { - if (value == true) { - a._flowContainer.style.overflow = "hidden"; - } else { - a._flowContainer.style.overflowX = ((a.Width >= a.ClientWidth) ? "hidden" : "auto"); - a._flowContainer.style.overflowY = ((a.Height >= a.ClientHeight) ? "hidden" : "auto"); - } - } - } - - get ClientHeight() { - const a = this; - - if (a._canvasContainer == null) { - return 0; - } - - return a.#getHeight(a._canvasContainer); - } - - set ClientHeight(value) { - const a = this; - - if (a._canvasContainer != null) a._canvasContainer.style.height = value + "px"; - if (a._ctx != null) a._ctx.canvas.height = value; - } - - get ClientWidth() { - const a = this; - - if (a._canvasContainer == null) { - return 0; - } - - return a.#getWidth(a._canvasContainer); - } - - set ClientWidth(value) { - const a = this; - - if (a._canvasContainer != null) a._canvasContainer.style.width = value + "px"; - if (a._ctx != null) a._ctx.canvas.width = value; - } - - get Height() { - const a = this; - - if (a._container == null) { - return 0; - } - - return a.#getHeight(a._container); - } - - set Height(value) { - const a = this; - - if (a._container != null) a._container.style.height = value + "px"; - if (a._flowContainer != null) a._flowContainer.style.height = value + "px"; - - if (a.AutoSize == true) { - a.ClientHeight = value; - } - } - - get Width() { - const a = this; - - if (a._container == null) { - return 0; - } - - return a.#getWidth(a._container); - } - - set Width(value) { - const a = this; - - if (a._container != null) a._container.style.width = value + "px"; - if (a._flowContainer != null) a._flowContainer.style.width = value + "px"; - - if (a.AutoSize == true) { - a.ClientWidth = value; - } - } - - get Size() { - const a = this; - - return { - W: a.Width, - H: a.Height - }; - } - - get ClientRectangle() { - const a = this; - - return { - X: a._padding.Left, - Y: a._padding.Top, - W: (a.Width - (a._padding.Left + a._padding.Right)), - H: (a.Height - (a._padding.Top + a._padding.Bottom)) - }; - } - - get Rectangle() { - const a = this; - - return { - X: 0, - Y: 0, - W: a.Width, - H: a.Height - }; - } - - - Clear() { - const a = this; - - if (a._ctx == null) { - return; - } - - a._ctx.clearRect(0, 0, a._ctx.canvas.width, a._ctx.canvas.height); - } - - DrawArrowS(rectangle, penColour, options) { - const a = this; - - if (a._ctx == null) { - return; - } - - const opt = Object.assign({ - LineWidth: 1, - LineDash: [], - FillColour: null - }, options); - - // Adjust for pen discrepancy - rectangle.X += 0.5; - rectangle.Y += 0.5; - rectangle.W -= opt.LineWidth; - rectangle.H -= opt.LineWidth; - - a._ctx.beginPath(); - a._ctx.strokeStyle = penColour; - a._ctx.lineWidth = opt.LineWidth; - a._ctx.setLineDash(opt.LineDash); - - a._ctx.moveTo(rectangle.X, rectangle.Y); - a._ctx.lineTo((rectangle.X + rectangle.W), rectangle.Y); - a._ctx.lineTo((rectangle.X + Math.half(rectangle.W)), (rectangle.Y + rectangle.H)); - - a._ctx.closePath(); - - if (opt.FillColour != null) { - a._ctx.fillStyle = opt.FillColour; - a._ctx.fill(); - } - - a._ctx.stroke(); - } - - DrawCircle(x, y, width, penColour, options) { - const a = this; - - if (a._ctx == null) { - return; - } - - const opt = Object.assign({ - LineWidth: 1, - LineDash: [], - FillColour: null - }, options); - - let rectangle = { - X: x + Math.half(width), - Y: y + Math.half(width), - W: Math.half(width), - H: Math.half(width) - }; - - // Adjust for pen discrepancy - rectangle.X += 0.5; - rectangle.Y += 0.5; - rectangle.W -= Math.half(opt.LineWidth); - rectangle.H -= Math.half(opt.LineWidth); - - a._ctx.beginPath(); - a._ctx.strokeStyle = penColour; - a._ctx.lineWidth = opt.LineWidth; - a._ctx.setLineDash(opt.LineDash); - - a._ctx.arc(rectangle.X, rectangle.Y, rectangle.W, 0, 2 * Math.PI, false); - - a._ctx.closePath(); - - if (opt.FillColour != null) { - a._ctx.fillStyle = opt.FillColour; - a._ctx.fill(); - } - - a._ctx.stroke(); - } - - DrawDiamond(rectangle, penColour, options) { - const a = this; - - if (a._ctx == null) { - return; - } - - const opt = Object.assign({ - LineWidth: 1, - LineDash: [], - FillColour: null - }, options); - - // Adjust for pen discrepancy - rectangle.X += 0.5; - rectangle.Y += 0.5; - rectangle.W -= opt.LineWidth; - rectangle.H -= opt.LineWidth; - - a._ctx.beginPath(); - a._ctx.strokeStyle = penColour; - a._ctx.lineWidth = opt.LineWidth; - a._ctx.setLineDash(opt.LineDash); - - a._ctx.moveTo((rectangle.X + Math.half(rectangle.W)), rectangle.Y); - a._ctx.lineTo((rectangle.X + rectangle.W), (rectangle.Y + Math.half(rectangle.H))); - a._ctx.lineTo((rectangle.X + Math.half(rectangle.W)), (rectangle.Y + rectangle.H)); - a._ctx.lineTo(rectangle.X, (rectangle.Y + Math.half(rectangle.H))); - - a._ctx.closePath(); - - if (opt.FillColour != null) { - a._ctx.fillStyle = opt.FillColour; - a._ctx.fill(); - } - - a._ctx.stroke(); - } - - DrawRectangle(rectangle, penColour, options) { - const a = this; - - if (a._ctx == null) { - return; - } - - const opt = Object.assign({ - LineWidth: 1, - LineDash: [], - FillColour: null - }, options); - - // Adjust for pen discrepancy - rectangle.X += 0.5; - rectangle.Y += 0.5; - rectangle.W -= opt.LineWidth; - rectangle.H -= opt.LineWidth; - - a._ctx.beginPath(); - a._ctx.strokeStyle = penColour; - a._ctx.lineWidth = opt.LineWidth; - a._ctx.setLineDash(opt.LineDash); - a._ctx.rect(rectangle.X, rectangle.Y, rectangle.W, rectangle.H); - - if (opt.FillColour != null) { - a._ctx.fillStyle = opt.FillColour; - a._ctx.fill(); - } - - a._ctx.closePath(); - a._ctx.stroke(); - - return rectangle; - } - - DrawLine(startX, startY, finishX, finishY, penColour, options) { - const a = this; - - if (a._ctx == null) { - return; - } - - const opt = Object.assign({ - LineWidth: 1, - LineDash: [] - }, options); - - startY -= 0.5; - // y -= penWidth; - - a._ctx.beginPath(); - a._ctx.strokeStyle = penColour; - a._ctx.lineWidth = opt.LineWidth; - a._ctx.setLineDash(opt.LineDash); - a._ctx.moveTo(startX, startY); - a._ctx.lineTo(finishX, finishY); - a._ctx.stroke(); - } - - DrawLines(points, penColour, options) { - const a = this; - - if (a._ctx == null) { - return; - } - - if (points == null) { - return; - } - - if (points.length <= 0) { - return; - } - - const opt = Object.assign({ - LineWidth: 1, - LineDash: [] - }, options); - - a._ctx.beginPath(); - a._ctx.strokeStyle = penColour; - a._ctx.lineWidth = opt.LineWidth; - a._ctx.setLineDash(opt.LineDash); - - a._ctx.moveTo(points[0].X, points[0].Y); - - for (let i=1; i - - + - - - - + + + + @@ -152,7 +151,6 @@ body { project1.Invalidate(); console.log(new Date(project1.StartDate).toLocaleDateString() + " - " + new Date(project1.FinishDate).toLocaleDateString() + " [" + project1.Duration + "]"); - const taskData = project1.ExportTasks(); if (taskGrid1 == null) taskGrid1 = new ProjectTaskGrid(document.getElementById("taskGrid1")); @@ -161,7 +159,6 @@ body { if (ganttChart1 == null) ganttChart1 = new RyzGanttChart(document.getElementById("ganttChart1"), {}); ganttChart1.Load(project1); - }); diff --git a/javascript-extensions/canvas.js b/javascript-extensions/canvas.js new file mode 100644 index 0000000..bd6dfb8 --- /dev/null +++ b/javascript-extensions/canvas.js @@ -0,0 +1,540 @@ +class Canvas { + + constructor(el) { + const a = this; + + a.container = el; + a.ctx = null; + + a.flowContainer = null; + a.canvasContainer = null; + + a.autoSize = true; + a.padding = { + Top: 0, + Right: 0, + Bottom: 0, + Left: 0 + }; + + a.initialiseComponents(); + } + + initialiseComponents() { + const a = this; + + if (a.container == null) { + return; + } + + a.container.innerHTML = "
"; + + if (a.container != null) { + a.container.style.width = "100%"; + a.container.style.height = "100%"; + + a.flowContainer = a.container.getElementsByTagName("div")[0]; + a.canvasContainer = a.flowContainer.getElementsByTagName("canvas")[0]; + a.ctx = a.canvasContainer.getContext("2d"); + } + + a.AutoSize = a.AutoSize; + a.Width = a.Width; + a.Height = a.Height; + + a.Clear(); + } + + + get AutoSize() { + return this.autoSize; + } + + set AutoSize(value) { + const a = this; + + a.autoSize = value; + + if (a.flowContainer != null) { + if (value == true) { + a.flowContainer.style.overflow = "hidden"; + } else { + a.flowContainer.style.overflowX = ((a.Width >= a.ClientWidth) ? "hidden" : "auto"); + a.flowContainer.style.overflowY = ((a.Height >= a.ClientHeight) ? "hidden" : "auto"); + } + } + } + + get ClientHeight() { + const a = this; + + if (a.canvasContainer == null) { + return 0; + } + + return a.getHeight(a.canvasContainer); + } + + set ClientHeight(value) { + const a = this; + + if (a.canvasContainer != null) a.canvasContainer.style.height = value + "px"; + if (a.ctx != null) a.ctx.canvas.height = value; + } + + get ClientWidth() { + const a = this; + + if (a.canvasContainer == null) { + return 0; + } + + return a.getWidth(a.canvasContainer); + } + + set ClientWidth(value) { + const a = this; + + if (a.canvasContainer != null) a.canvasContainer.style.width = value + "px"; + if (a.ctx != null) a.ctx.canvas.width = value; + } + + get Height() { + const a = this; + + if (a.container == null) { + return 0; + } + + return a.getHeight(a.container); + } + + set Height(value) { + const a = this; + + if (a.container != null) a.container.style.height = value + "px"; + if (a.flowContainer != null) a.flowContainer.style.height = value + "px"; + + if (a.AutoSize == true) { + a.ClientHeight = value; + } + } + + get Width() { + const a = this; + + if (a.container == null) { + return 0; + } + + return a.getWidth(a.container); + } + + set Width(value) { + const a = this; + + if (a.container != null) a.container.style.width = value + "px"; + if (a.flowContainer != null) a.flowContainer.style.width = value + "px"; + + if (a.AutoSize == true) { + a.ClientWidth = value; + } + } + + get Size() { + const a = this; + + return { + W: a.Width, + H: a.Height + }; + } + + get ClientRectangle() { + const a = this; + + return { + X: a.padding.Left, + Y: a.padding.Top, + W: (a.Width - (a.padding.Left + a.padding.Right)), + H: (a.Height - (a.padding.Top + a.padding.Bottom)) + }; + } + + get Rectangle() { + const a = this; + + return { + X: 0, + Y: 0, + W: a.Width, + H: a.Height + }; + } + + + Clear() { + const a = this; + + if (a.ctx == null) { + return; + } + + a.ctx.clearRect(0, 0, a.ctx.canvas.width, a.ctx.canvas.height); + } + + DrawArrowS(rectangle, penColour, options) { + const a = this; + + if (a.ctx == null) { + return; + } + + const opt = Object.assign({ + LineWidth: 1, + LineDash: [], + FillColour: null + }, options); + + // Adjust for pen discrepancy + rectangle.X += 0.5; + rectangle.Y += 0.5; + rectangle.W -= opt.LineWidth; + rectangle.H -= opt.LineWidth; + + a.ctx.beginPath(); + a.ctx.strokeStyle = penColour; + a.ctx.lineWidth = opt.LineWidth; + a.ctx.setLineDash(opt.LineDash); + + a.ctx.moveTo(rectangle.X, rectangle.Y); + a.ctx.lineTo((rectangle.X + rectangle.W), rectangle.Y); + a.ctx.lineTo((rectangle.X + Math.half(rectangle.W)), (rectangle.Y + rectangle.H)); + + a.ctx.closePath(); + + if (opt.FillColour != null) { + a.ctx.fillStyle = opt.FillColour; + a.ctx.fill(); + } + + a.ctx.stroke(); + } + + DrawCircle(x, y, width, penColour, options) { + const a = this; + + if (a.ctx == null) { + return; + } + + const opt = Object.assign({ + LineWidth: 1, + LineDash: [], + FillColour: null + }, options); + + let rectangle = { + X: x + Math.half(width), + Y: y + Math.half(width), + W: Math.half(width), + H: Math.half(width) + }; + + // Adjust for pen discrepancy + rectangle.X += 0.5; + rectangle.Y += 0.5; + rectangle.W -= Math.half(opt.LineWidth); + rectangle.H -= Math.half(opt.LineWidth); + + a.ctx.beginPath(); + a.ctx.strokeStyle = penColour; + a.ctx.lineWidth = opt.LineWidth; + a.ctx.setLineDash(opt.LineDash); + + a.ctx.arc(rectangle.X, rectangle.Y, rectangle.W, 0, 2 * Math.PI, false); + + a.ctx.closePath(); + + if (opt.FillColour != null) { + a.ctx.fillStyle = opt.FillColour; + a.ctx.fill(); + } + + a.ctx.stroke(); + } + + DrawDiamond(rectangle, penColour, options) { + const a = this; + + if (a.ctx == null) { + return; + } + + const opt = Object.assign({ + LineWidth: 1, + LineDash: [], + FillColour: null + }, options); + + // Adjust for pen discrepancy + rectangle.X += 0.5; + rectangle.Y += 0.5; + rectangle.W -= opt.LineWidth; + rectangle.H -= opt.LineWidth; + + a.ctx.beginPath(); + a.ctx.strokeStyle = penColour; + a.ctx.lineWidth = opt.LineWidth; + a.ctx.setLineDash(opt.LineDash); + + a.ctx.moveTo((rectangle.X + Math.half(rectangle.W)), rectangle.Y); + a.ctx.lineTo((rectangle.X + rectangle.W), (rectangle.Y + Math.half(rectangle.H))); + a.ctx.lineTo((rectangle.X + Math.half(rectangle.W)), (rectangle.Y + rectangle.H)); + a.ctx.lineTo(rectangle.X, (rectangle.Y + Math.half(rectangle.H))); + + a.ctx.closePath(); + + if (opt.FillColour != null) { + a.ctx.fillStyle = opt.FillColour; + a.ctx.fill(); + } + + a.ctx.stroke(); + } + + DrawRectangle(rectangle, penColour, options) { + const a = this; + + if (a.ctx == null) { + return; + } + + const opt = Object.assign({ + LineWidth: 1, + LineDash: [], + FillColour: null + }, options); + + // Adjust for pen discrepancy + rectangle.X += 0.5; + rectangle.Y += 0.5; + rectangle.W -= opt.LineWidth; + rectangle.H -= opt.LineWidth; + + a.ctx.beginPath(); + a.ctx.strokeStyle = penColour; + a.ctx.lineWidth = opt.LineWidth; + a.ctx.setLineDash(opt.LineDash); + a.ctx.rect(rectangle.X, rectangle.Y, rectangle.W, rectangle.H); + + if (opt.FillColour != null) { + a.ctx.fillStyle = opt.FillColour; + a.ctx.fill(); + } + + a.ctx.closePath(); + a.ctx.stroke(); + } + + DrawLine(startX, startY, finishX, finishY, penColour, options) { + const a = this; + + if (a.ctx == null) { + return; + } + + const opt = Object.assign({ + LineWidth: 1, + LineDash: [] + }, options); + + startY -= 0.5; + // y -= penWidth; + + a.ctx.beginPath(); + a.ctx.strokeStyle = penColour; + a.ctx.lineWidth = opt.LineWidth; + a.ctx.setLineDash(opt.LineDash); + a.ctx.moveTo(startX, startY); + a.ctx.lineTo(finishX, finishY); + a.ctx.stroke(); + } + + DrawLines(points, penColour, options) { + const a = this; + + if (a.ctx == null) { + return; + } + + if (points == null) { + return; + } + + if (points.length <= 0) { + return; + } + + const opt = Object.assign({ + LineWidth: 1, + LineDash: [] + }, options); + + a.ctx.beginPath(); + a.ctx.strokeStyle = penColour; + a.ctx.lineWidth = opt.LineWidth; + a.ctx.setLineDash(opt.LineDash); + + a.ctx.moveTo(points[0].X, points[0].Y); + + for (let i=1; i { - htmlContent += a.#renderRow(e); + htmlContent += a.renderRow(e); }); htmlContent += ""; @@ -53,7 +53,7 @@ class ProjectTaskGrid { } - #renderTHead() { + renderTHead() { const a = this; let htmlContent = ""; @@ -70,7 +70,7 @@ class ProjectTaskGrid { return htmlContent; } - #renderPlaceholder() { + renderPlaceholder() { const a = this; let htmlContent = ""; @@ -82,7 +82,7 @@ class ProjectTaskGrid { return htmlContent; } - #renderRow(e) { + renderRow(e) { const a = this; let htmlContent = ""; diff --git a/project/version-bundle.txt b/project/version-bundle.txt new file mode 100644 index 0000000..6338d19 --- /dev/null +++ b/project/version-bundle.txt @@ -0,0 +1,4 @@ +/** + * Ray's Projects (Bundled with TaskGrid and GanttChart) + * @version v0.1.0.104 (2023/12/27 1051) + */