1,804 articles and 14,446 comments as of Monday, January 3rd, 2011

EndUserSharePoint has combined resources with NothingButSharePoint.com. You can now find End User (Mark Miller), Developer (Jeremy Thake) and IT Pro SharePoint (Joel Oleson) content all in one place!

This site is a historical archive and is no longer being updated. Please update your favorites, bookmarks and RSS feeds.

NothingButSharePoint.com
Friday, January 23, 2009

JQuery for Everyone: Replacing [Today]

The [Today] thing gives people fits. It just doesn’t work in calculated columns like you want it to.

Here’s a slick way around it using some jQuery. To test this example for yourself, place the code sample in a Content Editor Web Part on the same page as a standard Discussion List view.

Two things to note here:

  1. This script can dynamically find the correct column to calculate when you give it a name.
  2. If your column is not called “Last Updated” you need to change the str parameter below.
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.2.6/jquery.min.js" type="text/javascript"></script>
<script type="text/javascript">
$(function() {
	var str = "Last Updated"; //change this based on col header
	var today = new Date();
	today = Date.parse(today)/1000;
	var a=0;
	var headers = $("table.ms-listviewtable:first> tbody> tr:first th").get();
	$.each(headers, function(i,e){
		x = $(e).contents().find("a[title*='"+str+"']").length;
		a = x > 0 && i > a ? i : a;
	});
	var dArray = $("table.ms-listviewtable:first> tbody> tr:gt(0)").find(">td:eq("+a+")").get()
	$.each(dArray, function(i,e){
		var d1 = Date.parse($(e).text())/1000;
		var dd = (today-d1)/86400;
		var dh = (dd-Math.floor(dd))*24;
		var dm = (dh-Math.floor(dh))*60;
		var time = ((Math.floor(dd) > 0 ? Math.floor(dd) +" days, " : "")+
					(Math.floor(dh) > 0 ? Math.floor(dh)+" hrs, " : "")+
					(Math.floor(dm)+" min"));
		$(e).text(time);
	});
});
</script>

Paul Grenier

View all entries in this series: PaulGrenier-JQuery for Everyone»
Entries in this series:
  1. JQuery for Everyone: Accordion Left Nav
  2. JQuery for Everyone: Print (Any) Web Part
  3. JQuery for Everyone: HTML Calculated Column
  4. JQuery for Everyone: Dressing-up Links Pt1
  5. JQuery for Everyone: Dressing-up Links Pt2
  6. JQuery for Everyone: Dressing-up Links Pt3
  7. JQuery for Everyone: Cleaning Windows Pt1
  8. JQuery for Everyone: Cleaning Windows Pt2
  9. JQuery for Everyone: Fixing the Gantt View
  10. JQuery for Everyone: Dynamically Sizing Excel Web Parts
  11. JQuery for Everyone: Manually Resizing Web Parts
  12. JQuery for Everyone: Total Calculated Columns
  13. JQuery for Everyone: Total of Time Differences
  14. JQuery for Everyone: Fixing Configured Web Part Height
  15. JQuery for Everyone: Expand/Collapse All Groups
  16. JQuery for Everyone: Preview Pane for Multiple Lists
  17. JQuery for Everyone: Preview Pane for Calendar View
  18. JQuery for Everyone: Degrading Dynamic Script Loader
  19. JQuery for Everyone: Force Checkout
  20. JQuery for Everyone: Replacing [Today]
  21. JQuery for Everyone: Whether They Want It Or Not
  22. JQuery for Everyone: Linking the Attachment Icon
  23. JQuery for Everyone: Aspect-Oriented Programming with jQuery
  24. JQuery for Everyone: AOP in Action - loadTip Gone Wild
  25. JQuery for Everyone: Wiki Outbound Links
  26. JQuery for Everyone: Collapse Text in List View
  27. JQuery for Everyone: AOP in Action - Clone List Header
  28. JQuery for Everyone: $.grep and calcHTML Revisited
  29. JQuery for Everyone: Evolution of the Preview
  30. JQuery for Everyone: Create a Client-Side Object Model
  31. JQuery for Everyone: Print (Any) Web Part(s) Plugin
  32. JQuery for Everyone: Minimal AOP and Elegant Modularity
  33. JQuery for Everyone: Cookies and Plugins
  34. JQuery for Everyone: Live Events vs. AOP
  35. JQuery for Everyone: Live Preview Pane
  36. JQuery for Everyone: Pre-populate Form Fields
  37. JQuery for Everyone: Get XML List Data with OWSSVR.DLL (RPC)
  38. Use Firebug in IE
  39. JQuery for Everyone: Extending OWS API for Calculated Columns
  40. JQuery for Everyone: Accordion Left-nav with Cookies Speed Test
  41. JQuery for Everyone: Email a List of People with OWS
  42. JQuery for Everyone: Faster than Document.Ready
  43. jQuery for Everyone: Collapse or Prepopulate Form Fields
  44. jQuery for Everyone: Hourly Summary Web Part
  45. jQuery for Everyone: "Read More..." On a Blog Site
  46. jQuery for Everyone: Slick Speed Test
  47. jQuery for Everyone: The SharePoint Game Changer
  48. JQuery For Everyone: Live LoadTip
 

Please Join the Discussion

50 Responses to “JQuery for Everyone: Replacing [Today]”
  1. Charlie Epes says:

    Hi Paul:
    This is very cool… sets my head spinning thinking of other ways to incorporate or tweak it for other list date fields.

    This is a slight departure from other time tweaks since refreshing the entire (F5) web page changes ALL the [Last Updated] entries, not just the one that was modified.

    Hmmm….

    Charlie Epes

  2. AutoSponge says:

    @Charlie,

    Thanks for pointing out the mistake. I updated the script, it should be “a = x > 0 && i > a ? i : a;” not “a = x > 0 && i > a ? i : 0;”.

    It’s still designed to replace a column. Targeting another column introduces a lot more logic which just hurts my head.

    ~Paul

  3. Iain Munro says:

    Hi Paul

    Thanks again for some great code.

    I want to check this out for other projects I have been struggling with, but get NaN Min in the column.

    I tried the new column as text and date with both the same result – Any Ideas?

    Iain

  4. AutoSponge says:

    @Iain,

    The column should be Date & Time. But I think your issue may be something I forgot to mention for other lists.

    This script searches for the Title of the header’s link, so for Modified, the Title=”Sort by Modified”.

    Only on headers without sorting will it appear normally.

    I think it’s a problem with the $= operator I’ve noticed in jQuery 1.3. So, you can either change the title to “Sort by Modified” or change the operator to *= in line 10.

    Both ways should work.

  5. AutoSponge says:

    I think I’m going to change the operator in my script so fewer people have issues.

    The rest of the logic holds (but was not explained in the article for brevity). If you have two columns with the word ‘Modified’ the changes will only apply to the last one (farthest to the right).

  6. Iain Munro says:

    Hi Paul

    I think I have done what you suggested, but nothing has changed.

    Iain

  7. Brad says:

    Dear Readers,

    How are you guys? Thanks for this code BUT I have a little issue I would like to correct.

    I would like to know how I could plug this code into the Desired Field in a list. Only thing it seems to change is the title. (Which I know is what you wanted to change, but I was considering to change the title of an internal list name?)

    Let me see if I can explain this.

    I have a List.

    8 Different Properties ( Housing Property 1,2,3,4,5,etc )

    Each of these display on 1 page with a +/- and inside there is basically like a issue log.

    I need to know how I could populate a Today or Last Update down in the list, and not at the title.

    If I can get the function for the list to give me at least todays date, I can write the code for the rest.

    http://www.myocdns.com/Screen_Sharepoint.png

    The following above is a picture of what I am saying, the blue is the area I need to fill.

    Thanks,
    Brad

  8. Wanda says:

    Hi Paul, I would like to show “days since last updated” for a task list. This would be today-modified expressed in days.
    I used the clunky fake-Today column, but I don’t like having to update that everyday.
    I would like to use this script, but it isn’t working for me. I have copied the jquery to a library on my parent site, and changed the script scr to reference this. (e.g.: /sites/xx/scripts/jquery.min.js)

    I changed the str to =”Modified”;

    what else do i need to do?

  9. AutoSponge says:

    @Wanda,

    Since we’re matching with a wildcard, we always take the last column header with “Modified.” Make sure your “Modified” column is the last one (left to right) appearing with that word.

    If you only want to see the time in days, change the last variable line to this:

    var time = (Math.floor(dd) > 0 ? Math.floor(dd) +" days" : "Today");
    

    Let me know how it goes.

  10. AutoSponge says:

    @Brad,

    If you’re trying to put Today() in a column so you can do calculations on it–well, that’s the problem–you can’t. That’s why I introduced this “hack.”

    By putting the relevant data on the screen (in this case Last Modified), we can use the client’s current time (basically Today) to make some calculations and update the screen’s display–WE’RE NOT CHANGING LIST DATA. Which is what you need to do calculations in calculated columns and the like.

    I hope that answers your question–even if it’s not the answer you were hoping for.

  11. Wanda says:

    Hi Paul

    no luck tonight. I’ll try again tomorrow. thanks.

  12. Brad says:

    Hey thanks. I found something that helps me out a little more then this hack.

    http://www.sharepointblogs.com/dez/archive/2008/07/31/dynamically-updating-a-sharepoint-calculated-column-containing-a-quot-today-quot-reference.aspx

    I just compiled the Source and run the scheduled task nightly. It uses a external XML file that you can set up and assign to a task list of your needs.

    Just set up the -Today- Function like the typical hacking way and use this to keep it going nightly.

    I enjoyed this code, but I needed something that helps the client out using the basic sharepoint commands so they don’t need to come back to me every 5 minutes and ask ” how do you do -this- with the code setup on the sharepoint site.”

    I appreciate your time and energy, but as they say if there is a “WILL” there is a “WAY” :]

    @wanda
    It seems you are trying to do something like I am, just not wording it the same way. This might help you out in the way you are seeking.

    P.S.To All: If you don’t have a copy of Visual Studio I will be more than happy to email or post the code in a zip (Compiled and non-compiled) so you can plug it into your site.

    Thanks,
    - Brad

    • Steve says:

      Brad,

      Did you ever upload the console application up somewhere?

      I would like to get the code as I do not have visual studio.

      Thanks,
      -Steve

      • Ceyda says:

        Hi Brad

        Is it possible for you to share the code please?

        Is there a website we can get it from?

        Thank you

  13. Jorgen says:

    Hi Paul,

    Regarding this code, I’ve got the same problem as Iain – NaN min occurs in the “last updated” col. Will the language of the installation have any impact on this code (my SP installation is in Norwegian) or date/time formatting?

    PS: I’ve tried out some of your jQuery snippets, and I really like them! I find the EUSP site perfect for my non-excisting programming level (working hard for SP super star level)!

  14. AutoSponge says:

    @Jorgen,

    You asked some great questions. I have no idea what Norwegian looks like to my code, but here are some ideas for troubleshooting:

    1. NaN means ‘not a number’ so chances are the script found a column with character data or a date format it did not recognize. First check that whatever you set “var str” to is the LAST column (left-to-right) with those exact words. For instance if you have var str = ‘Modified’; then the columns Modified and Modified By, Modified By will try to apply the script.

    2. I use Date.parse($(e).text()) to turn a formatted date into an epoch date. If the local date format is not recognized by JavaScript, you may need to add a custom function to parse the date.

  15. Lance says:

    What if I want to apply this to a Data View Web Part on the page? I have tried giving my DVWP a table ID and then changing table.ms-listviewtable to #nameoftable but this then seems to only change the first column item in the table.

    Any thoughts on how to do this?

  16. Kat says:

    I can’t recall who blogged about this originally, but there is a quick workaround for using [today] in a calculated column. Simply create a column in your list, and call it “Today”. Then set your calculated column up and use [today] the way you really want to. Once you have everything else set up and finalized, you can delete your “Today” column. Voila! The calculated column (so long as you don’t go back in to edit it) now works and is referencing the real “today”. It’s a nice trick for anyone who wants to do this quickly and who doesn’t plan to often/ever change any settings for that particular calculated column.

    Sorry I can’t remember the name of the blogger who suggested this originally. I didn’t create this workaround- I just use it all the time.

  17. Christophe says:

    Kat: many bloggers published the trick you are talking about, and it just doesn’t work.
    More details here:
    http://pathtosharepoint.wordpress.com/2008/08/14/calculated-columns-the-useless-today-trick/

  18. Marc says:

    Hi Paul, thanks for sharing this script. It works great if you are in the same time zone as where the SharePoint server is located. I want to use this to determine the age of a document since it was created.

    This script compares the created date of the SharePoint doc (American time in my case) to my local PC time (Central European time). So as a default age I get 6 hours. Somebody in Singapore will even get a higher number. If I change my PC to the same time zone as the SharePoint server then it shows the correct age. Is there a way to compare the server time instead of the local pc time?

    Many thanks,

    Marc

  19. AutoSponge says:

    Marc,

    You have to adjust both the client’s time and the server’s representation to GMT. For the client, try this:

    var today = new Date();
    var clOff = today.getTimezoneOffset();
    today = Date.parse(today)/1000;
    today = today-clOff;
    

    Then for the server (hard-coded to the server’s timezone), try:

    var d1 = Date.parse($(e).text())/1000;
    var svrOff = 6*60; //GMT offset in minutes
    d1 = d1-svrOff;
    
  20. Christophe says:

    Marc, this is “by design” as JavaScript will run on your PC.
    If you need the same time reference for everybody, you’d better pick the current time on the server side. You could for example use a Data View Web Part and xsl timestamp functions for that.

  21. Carlos says:

    HEllo EVERYONE.
    I just copy the code, change the search column and the code is almost working fine, but the count it’s made is not correctly.
    I use a column that has the following: “18/07/2009 18:16″ and it should show the difference between this date and the now time, that is 20/07/2009 11:34″ but it is showing just 17 hrs, 16 min. It should be 1 day 17 hrs, 16 min. What is wrong? thanks

  22. Maxx says:

    Hi everyone

    Regarding this code, I’ve got the same problem as Iain and Jorgen – NaN min occurs in the “last updated” col. I did everything you said but still got same result. I wonder if Jorgen or Iain have solved their problem? Maybe you guys could share your wisdom if you solved the mistery? How to fix this “Nan min” showing in the last column.

  23. Maxx says:

    Hi again, I just checked if time format could adress my problem and it did, seems like time format 24hours is not gonna work with this script, as soon as I changed to 12 hour format it started working, I was wondering if there is some workaround for this problem?

  24. AutoSponge says:

    @Maxx,

    Try changing this line:

    var d1 = Date.parse($(e).text())/1000;

    to this:

    var d1 = UTC.parse($(e).text())/1000;

  25. Rob Chisholm says:

    It only works if there is no grouping being used? I’m trying to show how long projects have been open. It works fine until I group by Project Status. Any ideas? Thank you.

  26. AutoSponge says:

    @Rob,

    It still works but it will only total for individual OPEN groups, not the entire list.

  27. David Petersen says:

    I’ve been trying to do the same thing and came across your code. The problem I have is that I am trying to create an “aging” field that shows how many days have expired since a particular date. The date field is called [StartDate] and the calculated field [Aging] should reflect the result of a formula Today – [StartDate].

    Has anyone done any work towards this? I would assume that you would find the value of the [StartDate] for each item in your list and then calculate the aging field similar to your above code. Any ideas?

  28. I solved my own problem. I made the [Aging] field a DateTime calculated field =[StartDate]. Then I used the javascript code to modify the [Aging] field. I modified the javascript so that it would only calculate Days since that is all I needed. The result is that my Aging field now reflects the number of days from [StartDate].

  29. Adam says:

    Found a great solution to this problem in MOSS 2007 –

    1. Create a new column called ‘Today’. Make it a single line of text.

    2. Create a new calculated field called ‘Aging’. Give it a formula of ‘DATEDIF([Modified],[Today],”D”)’. Have it be a number with 0 decimals.

    3. Go to the edit page of the ‘Today’ column and delete it.

    See here for the reference:
    http://blogs.officezealot.com/mauro/archive/2008/06/04/21062.aspx

    Just did this on our Fab 40 Helpdesk template for service requests, and it works GREAT!!

    Hope this helps, and requires NO coding.

  30. David says:

    Adam,
    There are many posts online that explain why the [Today] trick is useless. Someone on this discussion list aleady pointed to one such post…

    http://pathtosharepoint.wordpress.com/2008/08/14/calculated-columns-the-useless-today-trick/

    Just use “modified” for the same behavior…

  31. Caroline says:

    Hi Paul,

    I’m having trouble finding the code you posted, it doesn’t look like there is a “Read More” to click anywhere.

    Please let me know if you can re-post it or if I’m missing it.

    Thanks,
    Caroline

  32. Vijay says:

    Hi,

    I’m making a mess when trying to update this code so that it works for us folk in the UK (dd/mm/yyyy).

    Please can someone help update the code so it is compatible for the UK?

    Cheers!

  33. Hank says:

    I am using this script to calculate the duration of a web application outage. I’ve created a calculated field and the calculation is “=START_TIME”.

    How can the script be edited to execute the script only on items with no value in the “END_TIME” column?

    But would like it to calculate the duration between START_TIME and END_TIME, if the END_TIME exists.

    Thanks,

    Hank

  34. Ryan says:

    Hi Paul, thanks for the great tutorial. I was able to make it work to show the number of days since the date given in another column. However, the script doesn’t work quite right if I add grouping to my list. Basically, the calculation still works, but it gets displayed in the wrong column. I’m grouping by two other columns, and the calculation gets displayed one column left of where it should be displayed.

    Any suggestions?

  35. Chris says:

    This is great help. Glad I found this.

    I created a Calculated Column called Last Modified, set it to =[Modified], set the “The data type returned from this formula is:” to ‘Date and Time’ and “Date and Time Format:” to ‘Date & Time’.

    In the script I change line 4 to var str = “Sort by Last Modified”;

    It shows perfectly the correct time. If you have current list items and they show “Nam min” it is more then likely you have not enter in a Date and Time. BUT, setting up a calculated column and pointing it to Modified fixes that problem.

  36. Jonathan says:

    Hello, I realize this is an old post, but was hoping for some help or guidance. I have added the discussion as a web part on a page. How can I tweak the script to update the Last Updated field? Is this possible?

  37. Shawn White says:

    This is great! I am still relativally new to working with JavaScript and more so with JQuery. I have gotten this work just fine with calculating the “Modified” column; however, I’d like to have it caculated based upon the “Created” column. This way, I can view the “age” of a list item.

    I am unsure what needs to change in this script. Can someone enlighten me?

    Thanks!

    • Shawn White says:

      I figured it out! Just change “var a=0;” to “var a=1;”. I should have figured this out before even posting this. Doh!

    • Caroline says:

      Hi Shawn,

      I have created a column called “today” that defaults to today’s date when the item is created. Then this is the code I have for days outstanding that includes some tweaks to Paul’s code.

      I hope this helps!

      $(function() {

      var str = “Days Outstanding”; //change this based on col header

      var today = new Date();

      today = Date.parse(today)/1000;

      var a=0;

      var headers = $(”table.ms-listviewtable:first> tbody> tr:first th”).get();

      $.each(headers, function(i,e){

      x = $(e).contents().find(”a[title*='"+str+"']“).length;

      a = x > 0 && i > a ? i : a;

      });

      var dArray = $(”table.ms-listviewtable:first> tbody> tr:gt(0)”).find(”>td:eq(”+a+”)”).get()

      $.each(dArray, function(i,e){

      var d1 = Date.parse($(e).text())/1000;

      var dd = (today-d1)/86400;

      var dh = (dd-Math.floor(dd))*24;

      var dm = (dh-Math.floor(dh))*60;

      var time =(Math.floor(dd) > 0 ? Math.floor(dd) +” ” : “Today”);

      $(e).text(time);

      });

      });

      • Caroline says:

        Sorry, all the code wasn’t copied. Also “days outstanding” is my column name.

        $(function() {

        var str = “Days Outstanding”; //change this based on col header

        var today = new Date();

        today = Date.parse(today)/1000;

        var a=0;

        var headers = $(”table.ms-listviewtable:first> tbody> tr:first th”).get();

        $.each(headers, function(i,e){

        x = $(e).contents().find(”a[title*='"+str+"']“).length;

        a = x > 0 && i > a ? i : a;

        });

        var dArray = $(”table.ms-listviewtable:first> tbody> tr:gt(0)”).find(”>td:eq(”+a+”)”).get()

        $.each(dArray, function(i,e){

        var d1 = Date.parse($(e).text())/1000;

        var dd = (today-d1)/86400;

        var dh = (dd-Math.floor(dd))*24;

        var dm = (dh-Math.floor(dh))*60;

        var time =(Math.floor(dd) > 0 ? Math.floor(dd) +” ” : “Today”);

        $(e).text(time);

        });

        });

  38. AutoSponge says:

    @Shawn,

    I don’t really maintain this script anymore, but the comment in line 4 should have given you the clue :P

    var str = “Last Updated”; //change this based on col header

    Change it to the column header you want to use. The script counts how many cells in that header is then uses that column for the rest of the table body to work with the date info.

  39. Shawn says:

    So…I eventually got this working for a few months. Then we upgraded to SP2010 and now I get the infamous “NaNmin” text in the column. The only way I have been able to correct this is by putting my column, “Age” in the farest left column. When I do, it calculates and displays fine. I am still digging into this…

  40. Anvesh says:

    Thanks a lot, Paul. You helped me solve my problem.

Trackbacks

Check out what others are saying about this post...
  1. Calculated Time Left columns in SharePoint with jQuery…

    A current project I’m working on in SharePoint is an online auction. I’ll post more info about this and…

  2. Calculated Time Left columns in SharePoint with jQuery…

    A current project I’m working on in SharePoint is an online auction. I’ll post more info…

  3. [...] He has written a series entitled jQuery for Everyone and one of his articles was on Replacing [Today].  In his article, Paul talks about replacing a DateTime field with an Aging calculation. His [...]




Notify me of comments to this article:


Speak and you will be heard.

We check comments hourly.
If you want a pic to show with your comment, go get a gravatar!