From 2e8dc72f7a84012cabe2669c51175dbcc8f3a73c Mon Sep 17 00:00:00 2001 From: DJ Gallagher Date: Fri, 17 Jan 2014 13:42:00 -0500 Subject: [PATCH 1/5] Adds "showFractionalHours" as a chart option. When set to true, charts zoomed in to the scale of hours can depict fractional hour values for start and end time. --- js/jquery.fn.gantt.js | 25 +++++++--- tests/test02.html | 103 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 122 insertions(+), 6 deletions(-) mode change 100644 => 100755 js/jquery.fn.gantt.js create mode 100644 tests/test02.html diff --git a/js/jquery.fn.gantt.js b/js/jquery.fn.gantt.js old mode 100644 new mode 100755 index 686b420..4c86058 --- a/js/jquery.fn.gantt.js +++ b/js/jquery.fn.gantt.js @@ -44,7 +44,8 @@ onItemClick: function (data) { return; }, onAddClick: function (data) { return; }, onRender: function() { return; }, - scrollToToday: true + scrollToToday: true, + showFractionalHours: false }; /** @@ -506,7 +507,7 @@ } hoursInDay++; - horArr.push('
' + '
' + rday.getWeekOfYear() + '
'); } @@ -644,7 +645,7 @@ daysInYear = 0; } daysInYear++; - monthArr.push('
' + (1 + rday.getMonth()) + '
'); + monthArr.push('
' + (1 + rday.getMonth()) + '
'); } @@ -1013,14 +1014,23 @@ switch (settings.scale) { // **Hourly data** case "hours": + // In fractional hour aware charts, this determines the pixel delta of d_from and d_to relative to the hour tick-mark + var pixelOffsetFactor = tools.getCellSize() / (3600000.0*element.scaleStep); + var dFrom = tools.genId(tools.dateDeserialize(day.from).getTime(), element.scaleStep); + var dFromDelta = settings.showFractionalHours ? + (tools.dateDeserialize(day.from).getTime() - dFrom) * pixelOffsetFactor : + 0; var from = $(element).find('#dh-' + dFrom); var dTo = tools.genId(tools.dateDeserialize(day.to).getTime(), element.scaleStep); + var dToDelta = settings.showFractionalHours ? + (tools.dateDeserialize(day.to).getTime() - dTo) * pixelOffsetFactor : + 0; var to = $(element).find('#dh-' + dTo); - var cFrom = from.attr("offset"); - var cTo = to.attr("offset"); + var cFrom = parseInt(from.attr("offset")) + dFromDelta; + var cTo = parseInt(to.attr("offset")) + dToDelta; var dl = Math.floor((cTo - cFrom) / tools.getCellSize()) + 1; _bar = core.createProgressBar( @@ -1487,6 +1497,9 @@ case "hours": minDate.setHours(Math.floor((minDate.getHours()) / element.scaleStep) * element.scaleStep); minDate.setHours(minDate.getHours() - element.scaleStep * 3); + minDate.setMinutes(0); + minDate.setSeconds(0); + minDate.setMilliseconds(0); break; case "weeks": var bd = new Date(minDate.getTime()); diff --git a/tests/test02.html b/tests/test02.html new file mode 100644 index 0000000..bacacb8 --- /dev/null +++ b/tests/test02.html @@ -0,0 +1,103 @@ + + + + jQuery.Gantt - Test Suite 02 + + + + + + + + + +
+ +

+ jQuery.Gantt + — Test Suite 02 +

+ +

+ Expected behaviour: Gantt bar should run from "now" until 2.5 hours from now. Both bars should be offset from the hour mark according to the number of minutes past. It fails when all the bars are docked left at the hour view. +

+ +

+ Manual validation: +

+

+ +
+ + + + + + + + + + \ No newline at end of file From fde707ec19a1f6be625a68288e8b3328c64bfb47 Mon Sep 17 00:00:00 2001 From: DJ Gallagher Date: Fri, 17 Jan 2014 14:02:47 -0500 Subject: [PATCH 2/5] Minified file --- js/jquery.fn.gantt.min.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/js/jquery.fn.gantt.min.js b/js/jquery.fn.gantt.min.js index 1d4430a..c1ccec9 100644 --- a/js/jquery.fn.gantt.min.js +++ b/js/jquery.fn.gantt.min.js @@ -1 +1 @@ -(function(e,t){"use strict";e.fn.gantt=function(n){function o(e,t){for(var n=1;;n++){var r=new Date(e);r.setHours(e.getHours()+t*n);if(r.getTime()!==e.getTime()){return r}}}var r="jquery.fn.gantt";var i=["hours","days","weeks","months"];var s={source:null,itemsPerPage:7,months:["January","February","March","April","May","June","July","August","September","October","November","December"],dow:["S","M","T","W","T","F","S"],navigate:"buttons",scale:"days",useCookie:false,maxScale:"months",minScale:"hours",waitText:"Please wait...",onItemClick:function(e){return},onAddClick:function(e){return},onRender:function(){return},scrollToToday:true};if(n){e.extend(s,n)}s.useCookie=s.useCookie&&e.isFunction(e.cookie);e.extend(e.expr[":"],{findday:function(t,n,r){var i=new Date(parseInt(r[3],10));var s=e(t).attr("id");s=s?s:"";var o=s.indexOf("-")+1;var u=new Date(parseInt(s.substring(o,s.length),10));i=new Date(i.getFullYear(),i.getMonth(),i.getDate());u=new Date(u.getFullYear(),u.getMonth(),u.getDate());return i.getTime()===u.getTime()}});e.extend(e.expr[":"],{findweek:function(t,n,r){var i=new Date(parseInt(r[3],10));var s=e(t).attr("id");s=s?s:"";var o=s.indexOf("-")+1;i=i.getFullYear()+"-"+i.getDayForWeek().getWeekOfYear();var u=s.substring(o,s.length);return i===u}});e.extend(e.expr[":"],{findmonth:function(t,n,r){var i=new Date(parseInt(r[3],10));i=i.getFullYear()+"-"+i.getMonth();var s=e(t).attr("id");s=s?s:"";var o=s.indexOf("-")+1;var u=s.substring(o,s.length);return i===u}});Date.prototype.getWeekId=function(){var e=this.getFullYear();var t=this.getDayForWeek().getWeekOfYear();var n=this.getMonth();if(n===11&&t===1){e++}return"dh-"+e+"-"+t};Date.prototype.genRepDate=function(){switch(s.scale){case"hours":return this.getTime();case"weeks":return this.getDayForWeek().getTime();case"months":return(new Date(this.getFullYear(),this.getMonth(),1)).getTime();default:return this.getTime()}};Date.prototype.getDayOfYear=function(){var e=new Date(this.getFullYear(),0,0);var t=new Date(this.getFullYear(),this.getMonth(),this.getDate());return Math.ceil((t-e)/864e5)};Date.prototype.getWeekOfYear=function(){var e=new Date(this.getFullYear(),0,1);var t=new Date(this.getFullYear(),this.getMonth(),this.getDate());if(e.getDay()>3){e=new Date(t.getFullYear(),0,7-e.getDay())}var n=t.getDayOfYear()-e.getDayOfYear();return Math.ceil(n/7)};Date.prototype.getDaysInMonth=function(){return 32-(new Date(this.getFullYear(),this.getMonth(),32)).getDate()};Date.prototype.hasWeek=function(){var e=new Date(this.valueOf());e.setDate(e.getDate()-e.getDay());var t=new Date(this.valueOf());t.setDate(t.getDate()+(6-t.getDay()));if(e.getMonth()===t.getMonth()){return true}else{return e.getMonth()===this.getMonth()&&t.getDate()<4||e.getMonth()!==this.getMonth()&&t.getDate()>=4}};Date.prototype.getDayForWeek=function(){var e=new Date(this.valueOf());e.setDate(e.getDate()-e.getDay());var t=new Date(this.valueOf());t.setDate(t.getDate()+(6-t.getDay()));if(e.getMonth()===t.getMonth()||e.getMonth()!==t.getMonth()&&t.getDate()>=4){return new Date(t.setDate(t.getDate()-3))}else{return new Date(e.setDate(e.getDate()+3))}};var u={elementFromPoint:function(t,n){if(!e.support.boxModel){t-=e(document).scrollLeft();n-=e(document).scrollTop()}else{t-=window.pageXOffset;n-=window.pageYOffset}return document.elementFromPoint(t,n)},create:function(t){if(typeof s.source!=="string"){t.data=s.source;u.init(t)}else{e.getJSON(s.source,function(e){t.data=e;u.init(t)})}},init:function(e){e.rowsNum=e.data.length;e.pageCount=Math.ceil(e.rowsNum/s.itemsPerPage);e.rowsOnLastPage=e.rowsNum-Math.floor(e.rowsNum/s.itemsPerPage)*s.itemsPerPage;e.dateStart=a.getMinDate(e);e.dateEnd=a.getMaxDate(e);u.waitToggle(e,true,function(){u.render(e)})},render:function(t){var n=e('
');var r=u.leftPanel(t);n.append(r);var i=u.rightPanel(t,r);var o,a;n.append(i);n.append(u.navigation(t));var f=i.find(".dataPanel");t.gantt=e('
').append(n);e(t).html(t.gantt);t.scrollNavigation.panelMargin=parseInt(f.css("margin-left").replace("px",""),10);t.scrollNavigation.panelMaxPos=f.width()-i.width();t.scrollNavigation.canScroll=f.width()>i.width();u.markNow(t);u.fillData(t,f,r);if(s.useCookie){var l=e.cookie(this.cookieKey+"ScrollPos");if(l){t.hPosition=l}}if(s.scrollToToday){u.navigateTo(t,"now");u.scrollPanel(t,0)}else{if(t.hPosition!==0){if(t.scaleOldWidth){o=f.width()-i.width();a=o*t.hPosition/t.scaleOldWidth;a=a>0?0:a;f.css({"margin-left":a+"px"});t.scrollNavigation.panelMargin=a;t.hPosition=a;t.scaleOldWidth=null}else{f.css({"margin-left":t.hPosition+"px"});t.scrollNavigation.panelMargin=t.hPosition}u.repositionLabel(t)}else{u.repositionLabel(t)}}f.css({height:r.height()});u.waitToggle(t,false);s.onRender()},leftPanel:function(t){var n=e('
').append(e('
').css("height",a.getCellSize()*t.headerRows+"px").css("width","100%"));var r=[];e.each(t.data,function(e,n){if(e>=t.pageNum*s.itemsPerPage&&e');r.push(''+n.name+"");r.push("
");if(n.desc){r.push('
');r.push(''+n.desc+"");r.push("
")}}});n.append(r.join(""));return n},dataPanel:function(n,r){var i=e('
');var o="onwheel"in n?"wheel":document.onmousewheel!==t?"mousewheel":"DOMMouseScroll";e(n).on(o,function(e){u.wheelScroll(n,e)});i.click(function(t){t.stopPropagation();var r,i;var o=e(n).find(".fn-gantt .leftPanel");var f=e(n).find(".fn-gantt .dataPanel");switch(s.scale){case"weeks":i=a.getCellSize()*2;break;case"months":i=a.getCellSize();break;case"hours":i=a.getCellSize()*4;break;case"days":i=a.getCellSize()*3;break;default:i=a.getCellSize()*2;break}var l=u.elementFromPoint(t.pageX,f.offset().top+i);if(l.className==="fn-label"){l=e(l.parentNode)}else{l=e(l)}var c=l.attr("repdate");var h=u.elementFromPoint(o.offset().left+o.width()-10,t.pageY);if(h.className.indexOf("fn-label")===0){h=e(h.parentNode)}else{h=e(h)}var p=h.data().id;s.onAddClick(c,p)});return i},rightPanel:function(t,n){var r=null;var i=[" sn"," wd"," wd"," wd"," wd"," wd"," sa"];var f=['
'];var l=0;var c=['
'];var h=0;var p=[];var d=0;var v=[];var m=[];var g=new Date;g=new Date(g.getFullYear(),g.getMonth(),g.getDate());var y=s.holidays?s.holidays.join():"";switch(s.scale){case"hours":r=a.parseTimeRange(t.dateStart,t.dateEnd,t.scaleStep);var b=r[0].getFullYear();var w=r[0].getMonth();var E=r[0];for(var S=0;S
'+b+"
");b=T;l=0}l++;var N=x.getMonth();if(N!==w){c.push('
'+s.months[w]+"
");w=N;h=0}h++;var C=x.getDay();var k=E.getDay();var L=i[C];var A=E.getTime();if(y.indexOf((new Date(x.getFullYear(),x.getMonth(),x.getDate())).getTime())>-1){L="holiday"}if(C!==k){var O=g-E===0?" today":y.indexOf(A)>-1?"holiday":i[k];p.push('
'+'
'+E.getDate()+"
");v.push('
'+'
'+s.dow[k]+"
");E=x;d=0}d++;m.push('
'+x.getHours()+"
")}f.push('
'+b+"
");c.push('
'+s.months[w]+"
");var L=i[E.getDay()];if(y.indexOf((new Date(E.getFullYear(),E.getMonth(),E.getDate())).getTime())>-1){L="holiday"}p.push('
'+'
'+E.getDate()+"
");v.push('
'+'
'+s.dow[E.getDay()]+"
");var M=u.dataPanel(t,r.length*a.getCellSize());M.append(f.join(""));M.append(c.join(""));M.append(e('
').html(p.join("")));M.append(e('
').html(v.join("")));M.append(e('
').html(m.join("")));break;case"weeks":r=a.parseWeeksRange(t.dateStart,t.dateEnd);f=['
'];c=['
'];var b=r[0].getFullYear();var w=r[0].getMonth();var E=r[0];for(var S=0;S
'+b+"
");b=x.getFullYear();l=0}l++;if(x.getMonth()!==w){c.push('
'+s.months[w]+"
");w=x.getMonth();h=0}h++;p.push('
'+'
'+x.getWeekOfYear()+"
")}f.push('
'+b+"
");c.push('
'+s.months[w]+"
");var M=u.dataPanel(t,r.length*a.getCellSize());M.append(f.join("")+c.join("")+p.join("")+v.join(""));break;case"months":r=a.parseMonthsRange(t.dateStart,t.dateEnd);var b=r[0].getFullYear();var w=r[0].getMonth();var E=r[0];for(var S=0;S
'+b+"
");b=x.getFullYear();l=0}l++;c.push('
'+(1+x.getMonth())+"
")}f.push('
'+b+"
");c.push('
"
'+s.months[w]+"
");var M=u.dataPanel(t,r.length*a.getCellSize());M.append(f.join(""));M.append(c.join(""));M.append(e('
').html(p.join("")));M.append(e('
').html(v.join("")));break;default:r=a.parseDateRange(t.dateStart,t.dateEnd);var _=o(r[0],-1);var b=_.getFullYear();var w=_.getMonth();var E=_;for(var S=0;S
'+b+"
");b=x.getFullYear();l=0}l++;if(x.getMonth()!==w){c.push('
'+s.months[w]+"
");w=x.getMonth();h=0}h++;var k=x.getDay();var L=i[k];if(y.indexOf((new Date(x.getFullYear(),x.getMonth(),x.getDate())).getTime())>-1){L="holiday"}p.push('
'+'
'+x.getDate()+"
");v.push('
'+'
'+s.dow[k]+"
")}f.push('
'+b+"
");c.push('
'+s.months[w]+"
");var M=u.dataPanel(t,r.length*a.getCellSize());M.append(f.join(""));M.append(c.join(""));M.append(e('
').html(p.join("")));M.append(e('
').html(v.join("")));break}return e('
').append(M)},navigation:function(t){var n=null;if(s.navigate==="scroll"){n=e('