fullcalendar current time line on week view and day view

21,379

Solution 1

function setTimeline(view) {
    var parentDiv = jQuery(".fc-agenda-slots:visible").parent();
    var timeline = parentDiv.children(".timeline");
    if (timeline.length == 0) { //if timeline isn't there, add it
        timeline = jQuery("<hr>").addClass("timeline");
        parentDiv.prepend(timeline);
    }

    var curTime = new Date();

    var curCalView = jQuery("#calendar").fullCalendar('getView');
    if (curCalView.visStart < curTime && curCalView.visEnd > curTime) {
        timeline.show();
    } else {
        timeline.hide();
        return;
    }

    var curSeconds = (curTime.getHours() * 60 * 60) + (curTime.getMinutes() * 60) + curTime.getSeconds();
    var percentOfDay = curSeconds / 86400; //24 * 60 * 60 = 86400, # of seconds in a day
    var topLoc = Math.floor(parentDiv.height() * percentOfDay);

    timeline.css("top", topLoc + "px");

    if (curCalView.name == "agendaWeek") { //week view, don't want the timeline to go the whole way across
        var dayCol = jQuery(".fc-today:visible");
        var left = dayCol.position().left + 1;
        var width = dayCol.width()-2;
        timeline.css({
            left: left + "px",
            width: width + "px"
        });
    }

}

And then in the setup:

viewDisplay: function(view) {
        try {
            setTimeline();
        } catch(err) {}
    },

and in the css:

.timeline {
    position: absolute;
    left: 59px;
    border: none;
    border-top: 1px solid red;
    width: 100%;
    margin: 0;
    padding: 0;
    z-index: 999;
}

Only tried this on week-view since that's all I use.

Good luck.

Edit:

To get the timeline to update during the day you could try something like this in the viewDisplay:

viewDisplay: function(view) {
            if(first){
                first = false;
            }else {
                window.clearInterval(timelineInterval);
            }
            timelineInterval = window.setInterval(setTimeline, 300000);
            try {
                setTimeline();
            } catch(err) {}
        },

You will need to set first=true in the top of the tag. This will move the timeline every 300 second = 5 minutes. You can lower it if you need it more smooth..

Solution 2

It has been solved in the new version of FullCalendar (2.6.0)

http://fullcalendar.io/docs/current_date/nowIndicator/

$('#calendar').fullCalendar({       
    nowIndicator: true
});

nowIndicator

Solution 3

Magnus Winter's solution works very well, but it doesn't consider fullcalender options minTime and maxTime. If they are set then the timeline is misplaced.

To fix this replace the definition of curSeconds and percentOfDay in Magnus Winter's code with:

var curSeconds = ((curTime.getHours() - curCalView.opt("minTime")) * 60 * 60) + (curTime.getMinutes() * 60) + curTime.getSeconds();
var percentOfDay = curSeconds / ((curCalView.opt("maxTime") - curCalView.opt("minTime")) * 3600); // 60 * 60 = 3600, # of seconds in a hour

Solution 4

Great solution, accumulated all the changes in the thread to get this working for fullcalendar-2.1.0-beta1 and made some minor changes so it would work for me.

var timelineInterval;

$calendar.fullCalendar({
  ...,
  viewRender: function(view) {              
    if(typeof(timelineInterval) != 'undefined'){
      window.clearInterval(timelineInterval); 
    }
    timelineInterval = window.setInterval(setTimeline, 300000);
    try {
      setTimeline();
    } catch(err) {}
  },
  ...
});

function setTimeline(view) {
  var parentDiv = $('.fc-slats:visible').parent();
  var timeline = parentDiv.children(".timeline");
  if (timeline.length == 0) { //if timeline isn't there, add it
    timeline = $("<hr>").addClass("timeline");
    parentDiv.prepend(timeline);
  }

  var curTime = new Date();

  var curCalView = $("#calendar").fullCalendar('getView');
  if (curCalView.intervalStart < curTime && curCalView.intervalEnd > curTime) {
    timeline.show();
  } else {
    timeline.hide();
    return;
  }
  var calMinTimeInMinutes = strTimeToMinutes(curCalView.opt("minTime"));
  var calMaxTimeInMinutes = strTimeToMinutes(curCalView.opt("maxTime"));
  var curSeconds = (( ((curTime.getHours() * 60) + curTime.getMinutes()) - calMinTimeInMinutes) * 60) + curTime.getSeconds();
  var percentOfDay = curSeconds / ((calMaxTimeInMinutes - calMinTimeInMinutes) * 60);

  var topLoc = Math.floor(parentDiv.height() * percentOfDay);
  var timeCol = $('.fc-time:visible');
  timeline.css({top: topLoc + "px", left: (timeCol.outerWidth(true))+"px"});

  if (curCalView.name == "agendaWeek") { //week view, don't want the timeline to go the whole way across
    var dayCol = $(".fc-today:visible");
    var left = dayCol.position().left + 1;
    var width = dayCol.width() + 1;
    timeline.css({left: left + "px", width: width + "px"});
  }
}

function strTimeToMinutes(str_time) {
  var arr_time = str_time.split(":");
  var hour = parseInt(arr_time[0]);
  var minutes = parseInt(arr_time[1]);
  return((hour * 60) + minutes);
}

My changes

Had to change

var parentDiv = jQuery(".fc-agenda-slots:visible").parent();

to

var parentDiv = jQuery(".fc-slats:visible").parent();

Otherwise no timeline would be rendered at all. Guess Full Calendar changed this.


Then I had an issue with the left pos of the line in day view so I changed

timeline.css("top", topLoc + "px");

to

var timeCol = $('.fc-time:visible');
timeline.css({top: topLoc + "px", left: (timeCol.outerWidth(true))+"px"});

Also the timeline width in agendaWeek came out wrong so i changed

var width = dayCol.width() - 2;

to

var width = dayCol.width() + 1;

Didn't go into why this was, just changed it so it would look right.

Solution 5

Martin Pabst made a good point, but it doesn't work if you set min and max time as strings (ex. "07:30").

To solve that:

function strTimeToMinutes(str_time) {
  var arr_time = str_time.split(":");
  var hour = parseInt(arr_time[0]);
  var minutes = parseInt(arr_time[1]);
  return((hour * 60) + minutes);
}

And replace his definitions with:

var calMinTimeInMinutes = strTimeToMinutes(curCalView.opt("minTime"));
var calMaxTimeInMinutes = strTimeToMinutes(curCalView.opt("maxTime"));

var curSeconds = (( ((curTime.getHours() * 60) + curTime.getMinutes()) - calMinTimeInMinutes) * 60) + curTime.getSeconds();                       
var percentOfDay = curSeconds / ((calMaxTimeInMinutes - calMinTimeInMinutes) * 60);
Share:
21,379
RussellHarrower
Author by

RussellHarrower

Self taught PHP, HTML, CSS, JAVASCRIPT developer.

Updated on July 09, 2022

Comments

  • RussellHarrower
    RussellHarrower almost 2 years

    I understand that according to this issue ticket on google code http://code.google.com/p/fullcalendar/issues/detail?id=143 that there is a soloution floating around, however I cant seem to find it.

    I am wondering if anyone knows how to show a red solid line on the current time on the calendar

  • RussellHarrower
    RussellHarrower over 12 years
    Thank you, that worked a charm, will this get updated as the day goes on if the user stays on the same page or will it just stay at the current time it was loaded.
  • RussellHarrower
    RussellHarrower over 12 years
    The only thing that did not work is the time zone, it things it is 3:22pm when right now is 4:22
  • Magnus Winter
    Magnus Winter over 12 years
    Not sure about the time zone thing, if new Date() gives you the correct time you should be allright I guess?!
  • Zalaboza
    Zalaboza about 11 years
    working great. but there is a problem with timezone :( not sure how to fix that
  • Dragomir Ivanov
    Dragomir Ivanov almost 9 years
    I want to use your solution, but I am new to angular, can you paste here some simple usage example. Thanks.
  • Vladimír Gorej
    Vladimír Gorej almost 9 years
    First of all I updated the timeline generation with current code. Sorry Dragomir but there is no simple usage example. I would have to paste entire directive, which is proprietary software, so I cannot do that. Simply said, you have to have all requirements injected into your controller that this function uses e.g. moment, $interval and others. Then in fullcalendar viewRender event, just call this function.
  • Dragomir Ivanov
    Dragomir Ivanov almost 9 years
    Okay, understood. Thanks a lot Vladimir.
  • GONeale
    GONeale almost 9 years
    For angular users, this is the best solution. @VladimírGorej I had to change timeline.css({ top: topLoc, left: timeCol.outerWidth(true) }); to timeline.css({ top: topLoc + 'px', left: timeCol.outerWidth(true) + 'px' }); for Chrome compatibility.
  • hitautodestruct
    hitautodestruct over 7 years
    This has been solved in version 2.6.0 nowIndicator
  • hitautodestruct
    hitautodestruct over 7 years
    This is the correct answer for the most current version of fullcalendar.
  • Praveen
    Praveen over 7 years
    hi @Silvestre, how can i set sun, mon tue on left and 10am, 11am, 12pm on top? I mean the reversed view of this.