JQuery for Everyone: Fixing the Gantt View
This question came in from Stump The Panel:
Does anyone know how to freeze the Title column in Project Task list Gantt chart view?
Since I want to get better using jQuery, and tweaking the UI will be easier than fixing the web part, I went after it.
Instead of freezing the Title column, I decided to drop the x-axis scrollbar and add labels to the ends of each activity.
Since the header rows also disappear when you scroll down on the inner scrollbar, I froze the date header by moving it out of the chart area.

But I couldn’t stop there. I don’t always need the Task List View below my chart and sometimes I need to see more of the chart at once. I decided to add some buttons to the toolbar that control the List View display and Gantt View height.

Check out the results of these tweaks in this screencast:
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.2.6/jquery.min.js" type="text/javascript"></script> <script type="text/javascript"> $(function() { //capture variables var div=$("div[class^='ms-ganttDiv']:eq(0)"); var tlv=$("table.ms-listviewtable:eq(0)"); var w = $("#GanttTable").width(); var a = "img[src='/_layouts/images/EndNormal.gif']" var b = "img[src='/_layouts/images/MileStone.gif']" //build new html from header rows var html="<table class='ms-ganttInnerTable' cellspacing='0' cellpadding='0' style='table-layout:fixed' width='"+w+"'>"+ "<col width='222px'></col>"+ "<tbody><tr>"+ $("#GanttTable tr:eq(0)").html()+ "</tr><tr class='ms-ganttDetailTimeUnitRow'>"+ $("#GanttTable tr:eq(1)").html()+ "</tr></tbody></table>"; //build toggle buttons var bt1="<input id='tlv0' class='ms-ButtonHeightWidth' type='button' target='_self' value='Toggle List' name='togglelv'/>"; var bt2="<input id='div100' class='ms-ButtonHeightWidth' type='button' target='_self' value='Full Gantt' name='div100'/>"; var bt3="<input id='div272' class='ms-ButtonHeightWidth' type='button' target='_self' value='Min Gantt' name='div100'/>"; //DOM manipulation $("#GanttTable").prepend("<col width='222px'></col>"); $("table.ms-menutoolbar:eq(0)").after(html); //insert html $("td.ms-toolbar[width='99%']").append(bt1).append(bt2).append(bt3);//add buttons $("#tlv0").click(function() {$(tlv).toggle()}); //add toggle fn $("#div100").click(function() { $(div).height("100%"); $(div).css({"overflow-y": "visible", position: "relative"}); }); //add 100% fn $("#div272").click(function() { $(div).height("272"); $(div).css({"overflow-y": "auto"}); }); //add 272 fn $("#GanttTable tr:lt(2)").replaceWith("<th></th>"); //replace original rows $(a+", "+b).each(function(i,e) { //add labels var title = $(e).parent().siblings("th").text(); $(e).parent().next().html("<div style='position:relative;z-index:99;white-space: nowrap'>"+title+"</div>"); }); //css fixes $("#GanttTable").css({"table-layout":"fixed","word-wrap":"normal",width:w}); $("table.ms-listviewtable > tbody > tr[class='']").css("background-color","#fff"); $(div).css({"overflow-y": "auto", "overflow-x": "hidden"}); }); </script> <style type="text/css"> body {background-color:#83B0EC} .ms-main {height:97%} .ms-globalTitleArea {background-color:#fff} .ms-bodyareapagemargin {border-top:1px solid #83B0EC} .ms-bodyareaframe {background:none transparent} .ms-ganttInnerTable {background-color:#fff} .ms-bodyareacell {background-color:#83B0EC} </style>
- JQuery for Everyone: Accordion Left Nav
- JQuery for Everyone: Print (Any) Web Part
- JQuery for Everyone: HTML Calculated Column
- JQuery for Everyone: Dressing-up Links Pt1
- JQuery for Everyone: Dressing-up Links Pt2
- JQuery for Everyone: Dressing-up Links Pt3
- JQuery for Everyone: Cleaning Windows Pt1
- JQuery for Everyone: Cleaning Windows Pt2
- JQuery for Everyone: Fixing the Gantt View
- JQuery for Everyone: Dynamically Sizing Excel Web Parts
- JQuery for Everyone: Manually Resizing Web Parts
- JQuery for Everyone: Total Calculated Columns
- JQuery for Everyone: Total of Time Differences
- JQuery for Everyone: Fixing Configured Web Part Height
- JQuery for Everyone: Expand/Collapse All Groups
- JQuery for Everyone: Preview Pane for Multiple Lists
- JQuery for Everyone: Preview Pane for Calendar View
- JQuery for Everyone: Degrading Dynamic Script Loader
- JQuery for Everyone: Force Checkout
- JQuery for Everyone: Replacing [Today]
- JQuery for Everyone: Whether They Want It Or Not
- JQuery for Everyone: Linking the Attachment Icon
- JQuery for Everyone: Aspect-Oriented Programming with jQuery
- JQuery for Everyone: AOP in Action - loadTip Gone Wild
- JQuery for Everyone: Wiki Outbound Links
- JQuery for Everyone: Collapse Text in List View
- JQuery for Everyone: AOP in Action - Clone List Header
- JQuery for Everyone: $.grep and calcHTML Revisited
- JQuery for Everyone: Evolution of the Preview
- JQuery for Everyone: Create a Client-Side Object Model
- JQuery for Everyone: Print (Any) Web Part(s) Plugin
- JQuery for Everyone: Minimal AOP and Elegant Modularity
- JQuery for Everyone: Cookies and Plugins
- JQuery for Everyone: Live Events vs. AOP
- JQuery for Everyone: Live Preview Pane
- JQuery for Everyone: Pre-populate Form Fields
- JQuery for Everyone: Get XML List Data with OWSSVR.DLL (RPC)
- Use Firebug in IE
- JQuery for Everyone: Extending OWS API for Calculated Columns
- JQuery for Everyone: Accordion Left-nav with Cookies Speed Test
- JQuery for Everyone: Email a List of People with OWS
- JQuery for Everyone: Faster than Document.Ready
- jQuery for Everyone: Collapse or Prepopulate Form Fields
- jQuery for Everyone: Hourly Summary Web Part
- jQuery for Everyone: "Read More..." On a Blog Site
- jQuery for Everyone: Slick Speed Test
- jQuery for Everyone: The SharePoint Game Changer
- JQuery For Everyone: Live LoadTip
Looks excellent!
Thanks for all the great ideas. :)
Paul,
Xmas came early for me.
This works splendidly. Thanks for working on this and finding an excellent solution.
Stump
Paul – I have to agree with Stump on this one… Christmas came early. The Gantt view has such obvious short comings, your work around makes it actually usable. — Mark
Paul,
Great articles! Do you have any plans to use jQuery to help modify the width of list columns?
I want audio! :-P
Paul,
I successfully implemented your solution and would like to thank you for this posting.
@Robin,
I’ll add that to the idea hat :)
~Paul
Paul – I agree with Robin. Managing the width of columns is almost always the first request as people try to manage the interface of a list or library. Count me in… Mark
Paul,
I just implemented this for a few project sites and noticed that the task name only appends when the task is not complete. Was that intended? Is there a way to show it regardgless of whether the task is complete or not?
Thanks
Stump
@Stump,
I can’t replicate that in IE or FF. In my site, all Task statuses appear the same.
In the script, var a and b(milestone) are images that make up the activity “bar.” On the line with the comment “add labels” I tell jQuery to find a+”, “+b, then loop through adding the Title.
Check your Gantt charts. If you have a different ending .gif for your completed Tasks, you can modify the code with a third variable (c) and a selector like: a+”, “+b+” ,”+c.
I will certainly try that.
Thanks
Stump.
Any ideas on how to change the date format columns from week/day to month/week?
@Dean,
Just so I’m certain what you mean–are you suggesting a more “macro” view of the data so it displays activities lasting weeks instead of months?
~Paul
Paul, what I’m suggesting is being able to change the Time Scale like we can in MS Project. I’d like to be able to change the top units to months or quarters or years and the bottom units to weeks or months. If tasks are long, it is good to be able to see their entire duration on one screen without having to scroll way to the right.
Dean
Paul,
Thanks for all you effort getting this jquery code out there – it is much appreciated! Once question, though – this works for the list view page. What would need to change to get this fix to work on the project task list that is added to a site page?
Thanks in advance.
@Chris,
First, the width would need to be changed. In IE especially, the Web Part’s div will not extend to 100% of the content area.
Second, without the toolbar, there is no place to put the Title bar, so you’d need to create an element there to hold it.
I changed the background color in my script. That doesn’t look as hot when the web part is smaller than the content area, so you might need to do some CSS changes.
I love the update Gantt chart – but is there a way to restrict the width, and add a scroll bar at the bottom? Some of my projects go on for years, and the default screen width just isn’t wide enough.
@Cami
I’m not sure I understand. This change makes the web part as large as it needs to be to display the entire Gantt chart. The scroll bar appears at the bottom of the browser.
This is so very close. I don’t like how the full view expands the whole page, I would like the scroll bar for horizontal scrolling back at the bottom of the gannt view where it was before. It must be too late for me to not be able to figure this out on my own.
@Scrapperchick,
To get the week/day header to stay put, I placed it in the toolbar.
If put the inner scrollbar back in the Gantt view, the week/day header in the toolbar gets crunched to the Gantt width.
It probably could be done but there’s a lot more fancy scripting involved to sync the toolbar and Gantt’s scrolling.
Since I try to keep my published solutions “short,” that wasn’t an option for this article.
But thanks for the ideas, keep them coming!
~Paul
I would like to reiterate Scrapperchick on January 21st, 2009 8:19 pm comment about the horizontal scrollbar being much more useful at the bottom of the gantt chart. If I had to choose if the week/day header staying put or the scrollbar at the bottom of the gantt chart, I would choose the the scrollbar. Let me know if you plan to add it to a future release of the script. Thanks!
Great Script. However, the labels aren’t appearing next to images on chart. Odd. Any ideas? I am using custom css and master pages. The gifs point to the right ones as listed in the code as well. Thanks in advance and thank you for you contribution!!
Found my solution. Odd really. I had to put the entire URL to gifs in place of Directory URL. Regardless, it works like a champ!!!! Thanks!!!
thanks for the solution, had thought about implementing it myself too. one note: when using SSL/HTTPS you can replace the beginning of the javascript loading url with “https://ajax.googleapis.com/..” to avoid browser warning that some parts of the page are insecure.
@martin
I tried that when I first started messing with jQuery and it didn’t work. Now it does! That’s great.
I’m having a problem getting this enhanced Gantt to work properly with Christophe’s slider. I find the Gantt more useful if I can change the date scale, which is what Christope’s slider does.
I can get them on the same page, but I lose the laod tips, and the slider behavior is peculiar. And perfomance seems to be impacted.
Have you tried this? Suggestions?
Great script, I was looking for this and here i found it.
Have you had a chance to review what “Dean on January 8th, 2009 10:55 am” was suggesting?
I wanted to do something similiar, infact exactly the same. I appreciate your help in this regard.
thanks
@Wanda
I have not tried that, I’ll take a look and see if the two scripts are compatible.
@cloudno9
I think this is related to Wanda’s comments. I’ll look into it.
thx for response. christpophe slider still maintain the same date scale. all it does it removes Weeks/days and change it with months.
I wanted to do similar what dean said “I’d like to be able to change the top units to months or quarters or years and the bottom units to weeks or months. If tasks are long, it is good to be able to see their entire duration on one screen without having to scroll way to the right.”
Thanks
Hi Paul,
This is fantastic!
Do you have a similar trick for freezing column headings on sharepoint lists?
@Carolyn
Good idea.
Hi paul
Very nice post! I like it so much tat I have this question: Is there a way to make the the “Full Gant” and the “Toggle List” the default view? So that these functions are already activated when you visit the page and you wont have to click on it each time you go to the page.
Charlotte
@Charlotte
Try replacing the last two lines of the JavaScript portion with this:
Re my Feb 18th question on integrating this code with Christophe’s slider. Any luck? Or any alterntive for changing the view from days to weeks, or months or quarters?
How would you fix the Title column, so when you scroll to the right, it stays put?
Like others have said, having the scroll bar at the bottom of the Gantt would be an ideal solution, along with the fixed date headers.
@AutoSponge, works perfectly!
Hi Paul, any ideas on how to implement what Dean was asking for in comment 15? Your jquery works like a charm, with the option to change the timeline it would be perfected.
Yes, I have a similar need in that I need to change it out even further
from Month/Day
to Quarters/Months
Any ideas?
Very nice, thanks for sharing.
Has anyone looked at how to group the “Title” field? I have all the titles listed but would like them to display in the same grouping I have in the list view.
I’m not near a good enough scripter/programmer to figure it out on myown.
Thanks!
I have the same need to Grouping By Title in the header area, and haven’t been successful doing it yet.
This is really awesome! I’m having a problem making this work with my branding – I have a fixed width design, and the Gantt chart really shouldn’t be wider than about 751px. When I use this code, the html changes cause the Gantt chart to push the browser window way out there. Is there a way to avoid this?
I’ve tried manipulating this code, and the only thing I can think of is that this part:
var w = $(”#GanttTable”).width();
That w is setting the width rather high (in my environment, this var returns >1600). When I take out the code that’s manipulating the DOM html fragment, the date header (I think this might be handled by the ms-ganttDetailTimeUnitRow class) disappears.
Any ideas?
@Eric,
$(”#GanttTable”).css({”table-layout”:”fixed”,”word-wrap”:”normal”,width:w});
That link actually changes the width of the chart. However, if you leave the default, it will break the “sticky header.” Also, the default only appears page-width in IE, FireFox lets the chart grow.
I figured out a fix for my problem. After examining the CSS and tweaking that in-browser a bit, I realized that the width can be explicitly set by grabbing the width of the TABLE element whose class is “ms-ganttOuterTable” and applying that to the parent div. So, my fix is to grab the calculated width of this table on render, and apply that to the DIV whose class is “ms-ganttDiv” that you’re setting as the var “div”:
In the “//capture variables” section, add:
var outerTableWidth = $(”table[class^='ms-ganttOuterTable']:eq(0)”).width();
And at the bottom in the “//DOM manipulation”, add:
$(div).width(outerTableWidth);
That fixes it for me, anyway – hopefully that helps someone else out there!
Actually, I take that back – it fixes the width issue, but now the buttons don’t appear anymore, and neither do the dates. Something is conflicting with the “//css fixes” section – back to the drawing board .
Thanks for the excellent post. I am attempting to take this a step further and add the Assigned To field from the List view to the text after the bar on the Gantt. So far no luck, but if I figure it out I’ll post it up!
Humm… the Full Gantt and Min Gantt buttons aren’t working on my site… but the Toggle List does…
Got it. Well, a dirty bodge, but it seems to work if anyone is interested. I am sure there must be a more elegant solution than this, but hey ho.
// define array
var usrTxt = [];
// scan through thepage for elements of ms-vb-user class. Bung each one into an array for use later on.
$(”.ms-vb-user”).each(function() { usrTxt.push($(this).text()) });
// Juggle these about a bit, as it always seems to screw the order up
usrTxt.push(usrTxt.shift());
—-
And then just add this + usrTxt[count] + to the line that puts the title after the Gantt line – remembering that it is an array so you’ll need to maintain a count.
PS. Walter – I had the same problem as you – for “some” reason when I copy & pasted the example here to my site it changed some values – specifically the names of the 272 and 100 functions, so take a look to make sure that what you thought you copied is actually what you got!
I implemented the original suggestion, and it moves the scroll bar to the bottom of the page instead of of right below the Gantt, which causes me to not be able to view the entire project list without scrolling. Anyway to only add the titles to the Gannt points, but keep everything else as is? I don’t need the button either. Thanks!
Thanks for usefull post. it works very well.
In addition to the title showing at the right of the bar in the gantt chart, I would like a comment stored in another column in the list to show.
Is this possible?
I guess this is some of the same that Mat on May 6th, 2009 10:46 am and Mat on May 7th, 2009 7:08 am found a solution to, but i can’t get it to work.