Skip to content

Commit

Permalink
Add some support for custom chart elements
Browse files Browse the repository at this point in the history
- Add vMinDate, vMaxDate options to extend chart surface
- Add `chartRowDateToX` method to GanttChart
  • Loading branch information
nidu committed Jul 13, 2019
1 parent 7677dcb commit 020ab2e
Show file tree
Hide file tree
Showing 8 changed files with 134 additions and 29 deletions.
11 changes: 11 additions & 0 deletions Documentation.md
Original file line number Diff line number Diff line change
Expand Up @@ -238,6 +238,15 @@ After adding or removing tasks a call to "g.Draw()" must be made to redraw the c
This method will clear al the tasks from the list and after that you have to call "g.Draw()".
## Drawing custom elements on the chart ##
If you want to draw something custom in addition to task bars you may find following useful:
1. Put your drawing call in `afterDraw` callback. It's called in the end of each `Draw` call so view will mostly stay in sync. There you can get task row elements with `g.getList()[...].getChildRow()` and add HTML you need.
2. Use `g.chartRowDateToX(date)` to get X coordinate for a date.
3. If custom drawings go beyond min/max task dates - extend chart range with `vMinDate`/`vMaxDate` chart options.
4. See example in demo with *Custom elements* flag.
# Options #
You can set Options as an object, following the example:
Expand Down Expand Up @@ -285,6 +294,8 @@ The following options take a single numeric parameter; a value of 1 will enable
|_setEventsChange():_ |Controls events when a task row is cliked. Pass a function to execute ex.: `{ taskname: function(task, event, cell, column){ console.log(task, event, cell, column); } }`|
|_setAdditionalHeaders:_ |Set object with headers values for additional columns . ex : `{ category: { title: 'Category' }` }|
|_setResources():_ |Set the list of possible resources, must be an array of objects, ex: `[{ id: 1, name: 'Mario' } , { id: 2, name: 'Henrique' }]`|
|_setMinDate():_ |Set minimum date further than minimum task date. It doesn't trim any task if it starts before this minimum date, but can extend the chart to the left. This may be useful if you want to draw some custom elements on the chart or want to fix the time range regardless of the content|
|_setMaxDate():_ |Similar to _setMinDate()_|
|_setEditable():_ |Set with true if you want to edit values in the data table, will show inputs instead of texts|
|_setDebug():_ |Set with true if you want to see debug in console|
Expand Down
26 changes: 26 additions & 0 deletions docs/demo.html
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,19 @@
.row {
width: 100%
}

.space {
display: inline-block;
width: 30px;
}

.deadline-line {
position: absolute;
top: 0;
width: 1px;
height: 22px;
background: #777777;
}
</style>
<!-- External resources -->
<!-- jQuery + Ajax [required by Bootstrap] -->
Expand Down Expand Up @@ -157,6 +170,19 @@ <h3 class="row">Hide and Show Properties</h3>
<label>Configure sortTasks:</label>
<input type="checkbox" id="sort" onchange="start(event)" />
</span>

<br />

<span>
<label>Custom elements (black lines for deadlines):</label>
<input type="checkbox" id="customElements" checked onchange="start(event)" />
<div class="space"></div>
<label>Min Date:</label>
<input type="date" id="vMinDate" onchange="start(event)" />
<div class="space"></div>
<label>Max Date:</label>
<input type="date" id="vMaxDate" onchange="start(event)" />
</span>

<br />

Expand Down
13 changes: 8 additions & 5 deletions docs/fixes/data.json
Original file line number Diff line number Diff line change
Expand Up @@ -72,8 +72,8 @@
"pDepend": "",
"pCaption": "",
"pNotes": "",
"pDuration": "3 days"

"pDuration": "3 days",
"deadline": "2018-07-01"
},
{
"pID": 122,
Expand All @@ -92,7 +92,8 @@
"pOpen": 1,
"pDepend": 121,
"pCaption": "",
"pNotes": ""
"pNotes": "",
"deadline": "2018-07-10"
},
{
"pID": 123,
Expand Down Expand Up @@ -130,7 +131,8 @@
"pDepend": "123SS",
"pCaption": "This is a caption",
"pNotes": null,
"pCost": 34
"pCost": 34,
"deadline": "2018-07-05"
},
{
"pID": 2,
Expand Down Expand Up @@ -353,6 +355,7 @@
"pOpen": 1,
"pDepend": "333",
"pCaption": "",
"pNotes": ""
"pNotes": "",
"deadline": "2019-02-01"
}
]
27 changes: 26 additions & 1 deletion docs/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,9 @@ function start(e) {
vShowTaskInfoLink = document.querySelector('#vShowTaskInfoLink:checked') ? 1 : 0;
vShowEndWeekDate = document.querySelector('#vShowEndWeekDate:checked') ? 1 : 0;

vMinDate = document.querySelector('#vMinDate').value;
vMaxDate = document.querySelector('#vMaxDate').value;

vAdditionalHeaders = {
category: {
title: 'Category'
Expand Down Expand Up @@ -68,6 +71,8 @@ function start(e) {
vShowPlanStartDate,
vShowPlanEndDate,
vAdditionalHeaders,
vMinDate,
vMaxDate,
vEvents: {
taskname: console.log,
res: console.log,
Expand All @@ -79,7 +84,12 @@ function start(e) {
planend: console.log,
cost: console.log,
beforeDraw: ()=>console.log('before draw listener'),
afterDraw: ()=>console.log('before after listener')
afterDraw: ()=> {
console.log('before after listener');
if (document.querySelector("#customElements:checked")) {
drawCustomElements(g);
}
}
},
vEventsChange: {
taskname: editValue.bind(this, jsonObj),
Expand Down Expand Up @@ -169,4 +179,19 @@ function editValue(list, task, event, cell, column) {
found[column] = event ? event.target.value : '';
}
}

function drawCustomElements(g) {
for (const item of g.getList()) {
if (item.getDataObject().deadline) {
const x = g.chartRowDateToX(new Date(item.getDataObject().deadline));
const td = item.getChildRow().querySelector('td');
td.style.position = 'relative';
const div = document.createElement('div');
div.style.left = `${x}px`;
div.classList.add('deadline-line');
td.appendChild(div);
}
}
}

start('pt')
42 changes: 31 additions & 11 deletions docs/jsgantt.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.JSGantt = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.JSGantt = f()}})(function(){var define,module,exports;return (function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i<t.length;i++)o(t[i]);return o}return r})()({1:[function(require,module,exports){
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var jsGantt = require("./src/jsgantt");
Expand Down Expand Up @@ -123,6 +123,8 @@ exports.GanttChart = function (pDiv, pFormat) {
this.vTimer = 20;
this.vTooltipDelay = 1500;
this.vTooltipTemplate = null;
this.vMinDate = null;
this.vMaxDate = null;
this.includeGetSet = options_1.includeGetSet.bind(this);
this.includeGetSet();
this.mouseOver = events_1.mouseOver;
Expand Down Expand Up @@ -343,8 +345,8 @@ exports.GanttChart = function (pDiv, pFormat) {
task_1.processRows(this.vTaskList, 0, -1, 1, 1, this.getUseSort(), this.vDebug);
this.vProcessNeeded = false;
// get overall min/max dates plus padding
vMinDate = utils_1.getMinDate(this.vTaskList, this.vFormat);
vMaxDate = utils_1.getMaxDate(this.vTaskList, this.vFormat);
vMinDate = utils_1.getMinDate(this.vTaskList, this.vFormat, this.getMinDate() && utils_1.coerceDate(this.getMinDate()));
vMaxDate = utils_1.getMaxDate(this.vTaskList, this.vFormat, this.getMaxDate() && utils_1.coerceDate(this.getMaxDate()));
// Calculate chart width variables.
if (this.vFormat == 'day')
vColWidth = this.vDayColWidth;
Expand Down Expand Up @@ -1008,6 +1010,9 @@ exports.GanttChart = function (pDiv, pFormat) {
var ad = new Date();
console.log('after draw', ad, (ad.getTime() - bd.getTime()));
}
this.chartRowDateToX = function (date) {
return utils_1.getOffset(vMinDate, date, vColWidth, this.vFormat);
};
if (this.vEvents && this.vEvents.afterDraw) {
this.vEvents.afterDraw();
}
Expand Down Expand Up @@ -2519,6 +2524,8 @@ exports.includeGetSet = function () {
this.setTimer = function (pVal) { this.vTimer = pVal * 1; };
this.setTooltipDelay = function (pVal) { this.vTooltipDelay = pVal * 1; };
this.setTooltipTemplate = function (pVal) { this.vTooltipTemplate = pVal; };
this.setMinDate = function (pVal) { this.vMinDate = pVal; };
this.setMaxDate = function (pVal) { this.vMaxDate = pVal; };
this.addLang = function (pLang, pVals) {
if (!this.vLangs[pLang]) {
this.vLangs[pLang] = new Object();
Expand Down Expand Up @@ -2591,6 +2598,8 @@ exports.includeGetSet = function () {
this.getChartTable = function () { return this.vChartTable; };
this.getLines = function () { return this.vLines; };
this.getTimer = function () { return this.vTimer; };
this.getMinDate = function () { return this.vMinDate; };
this.getMaxDate = function () { return this.vMaxDate; };
this.getTooltipDelay = function () { return this.vTooltipDelay; };
this.getList = function () { return this.vTaskList; };
this.getEventsClickCell = function () { return this.vEvents; };
Expand Down Expand Up @@ -3357,12 +3366,12 @@ exports.internalPropertiesLang = {
'pPlanStart': 'planstartdate',
'pPlanEnd': 'planenddate'
};
exports.getMinDate = function (pList, pFormat) {
exports.getMinDate = function (pList, pFormat, pMinDate) {
var vDate = new Date();
if (pList.length <= 0)
return vDate;
vDate.setTime(pList[0].getStart().getTime());
// Parse all Task End dates to find min
return pMinDate || vDate;
vDate.setTime((pMinDate && pMinDate.getTime()) || pList[0].getStart().getTime());
// Parse all Task Start dates to find min
for (var i = 0; i < pList.length; i++) {
if (pList[i].getStart().getTime() < vDate.getTime())
vDate.setTime(pList[i].getStart().getTime());
Expand Down Expand Up @@ -3405,11 +3414,11 @@ exports.getMinDate = function (pList, pFormat) {
vDate.setHours(0, 0, 0);
return (vDate);
};
exports.getMaxDate = function (pList, pFormat) {
exports.getMaxDate = function (pList, pFormat, pMaxDate) {
var vDate = new Date();
if (pList.length <= 0)
return vDate;
vDate.setTime(pList[0].getEnd().getTime());
return pMaxDate || vDate;
vDate.setTime((pMaxDate && pMaxDate.getTime()) || pList[0].getEnd().getTime());
// Parse all Task End dates to find max
for (var i = 0; i < pList.length; i++) {
if (pList[i].getEnd().getTime() > vDate.getTime())
Expand Down Expand Up @@ -3468,6 +3477,17 @@ exports.changeFormat = function (pFormat, ganttObj) {
else
alert('Chart undefined');
};
exports.coerceDate = function (date) {
if (date instanceof Date) {
return date;
}
else {
var temp = new Date(date);
if (temp instanceof Date && !isNaN(temp.valueOf())) {
return temp;
}
}
};
exports.parseDateStr = function (pDateStr, pFormatStr) {
var vDate = new Date();
var vDateParts = pDateStr.split(/[^0-9]/);
Expand Down Expand Up @@ -4176,4 +4196,4 @@ exports.getXMLTask = function (pID, pIdx) {
};

},{"./task":8,"./utils":9}]},{},[1])(1)
});
});
15 changes: 10 additions & 5 deletions src/draw.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import {
} from "./events";
import {
parseDateFormatStr, formatDateStr, getOffset, parseDateStr, getZoomFactor,
getScrollPositions, getMaxDate, getMinDate
getScrollPositions, getMaxDate, getMinDate, coerceDate
} from './utils';
import { createTaskInfo, AddTaskItem, AddTaskItemObject, RemoveTaskItem, processRows, ClearTasks } from './task';
import { includeGetSet } from './options';
Expand Down Expand Up @@ -121,6 +121,8 @@ export const GanttChart = function (pDiv, pFormat) {
this.vTimer = 20;
this.vTooltipDelay = 1500;
this.vTooltipTemplate = null;
this.vMinDate = null;
this.vMaxDate = null;
this.includeGetSet = includeGetSet.bind(this);
this.includeGetSet();

Expand Down Expand Up @@ -165,8 +167,6 @@ export const GanttChart = function (pDiv, pFormat) {





this.clearDependencies = function () {
let parent = this.getLines();
while (parent.hasChildNodes()) parent.removeChild(parent.firstChild);
Expand Down Expand Up @@ -347,8 +347,8 @@ export const GanttChart = function (pDiv, pFormat) {
this.vProcessNeeded = false;

// get overall min/max dates plus padding
vMinDate = getMinDate(this.vTaskList, this.vFormat);
vMaxDate = getMaxDate(this.vTaskList, this.vFormat);
vMinDate = getMinDate(this.vTaskList, this.vFormat, this.getMinDate() && coerceDate(this.getMinDate()));
vMaxDate = getMaxDate(this.vTaskList, this.vFormat, this.getMaxDate() && coerceDate(this.getMaxDate()));

// Calculate chart width variables.
if (this.vFormat == 'day') vColWidth = this.vDayColWidth;
Expand Down Expand Up @@ -1031,6 +1031,11 @@ export const GanttChart = function (pDiv, pFormat) {
const ad = new Date();
console.log('after draw', ad, (ad.getTime() - bd.getTime()));
}

this.chartRowDateToX = function (date) {
return getOffset(vMinDate, date, vColWidth, this.vFormat);
}

if (this.vEvents && this.vEvents.afterDraw) {
this.vEvents.afterDraw()
}
Expand Down
4 changes: 4 additions & 0 deletions src/options.ts
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,8 @@ export const includeGetSet = function () {
this.setTimer = function (pVal) { this.vTimer = pVal * 1; };
this.setTooltipDelay = function (pVal) { this.vTooltipDelay = pVal * 1; };
this.setTooltipTemplate = function (pVal) { this.vTooltipTemplate = pVal; };
this.setMinDate = function (pVal) { this.vMinDate = pVal; };
this.setMaxDate = function (pVal) { this.vMaxDate = pVal; };
this.addLang = function (pLang, pVals) {
if (!this.vLangs[pLang]) {
this.vLangs[pLang] = new Object();
Expand Down Expand Up @@ -176,6 +178,8 @@ export const includeGetSet = function () {
this.getChartTable = function () { return this.vChartTable; };
this.getLines = function () { return this.vLines; };
this.getTimer = function () { return this.vTimer; };
this.getMinDate = function () { return this.vMinDate; };
this.getMaxDate = function () { return this.vMaxDate; };
this.getTooltipDelay = function () { return this.vTooltipDelay; };
this.getList = function () { return this.vTaskList; };
this.getEventsClickCell = function () { return this.vEvents; };
Expand Down
25 changes: 18 additions & 7 deletions src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,14 +22,14 @@ export const internalPropertiesLang = {
'pPlanEnd': 'planenddate'
};

export const getMinDate = function (pList, pFormat) {
export const getMinDate = function (pList, pFormat, pMinDate) {
let vDate = new Date();

if (pList.length <= 0) return vDate;
if (pList.length <= 0) return pMinDate || vDate;

vDate.setTime(pList[0].getStart().getTime());
vDate.setTime((pMinDate && pMinDate.getTime()) || pList[0].getStart().getTime());

// Parse all Task End dates to find min
// Parse all Task Start dates to find min
for (let i = 0; i < pList.length; i++) {
if (pList[i].getStart().getTime() < vDate.getTime()) vDate.setTime(pList[i].getStart().getTime());
}
Expand Down Expand Up @@ -68,12 +68,12 @@ export const getMinDate = function (pList, pFormat) {
return (vDate);
};

export const getMaxDate = function (pList, pFormat) {
export const getMaxDate = function (pList, pFormat, pMaxDate) {
let vDate = new Date();

if (pList.length <= 0) return vDate;
if (pList.length <= 0) return pMaxDate || vDate;

vDate.setTime(pList[0].getEnd().getTime());
vDate.setTime((pMaxDate && pMaxDate.getTime()) || pList[0].getEnd().getTime());

// Parse all Task End dates to find max
for (let i = 0; i < pList.length; i++) {
Expand Down Expand Up @@ -130,6 +130,17 @@ export const changeFormat = function (pFormat, ganttObj) {
else alert('Chart undefined');
};

export const coerceDate = function (date) {
if (date instanceof Date) {
return date;
} else {
const temp = new Date(date);
if (temp instanceof Date && !isNaN(temp.valueOf())) {
return temp;
}
}
}

export const parseDateStr = function (pDateStr, pFormatStr) {
let vDate = new Date();
let vDateParts = pDateStr.split(/[^0-9]/);
Expand Down

0 comments on commit 020ab2e

Please sign in to comment.