Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

FullCalendar Horizontal Time Range Selection

Can someone tell me how to achieve something like below image. How can I select particular time range in selected days.

Notice that the selection spans multiple days. It's a horizontal selection across multiple days (as opposed to a continuous one).

I am using fullCalendar jquery library.

intended result

like image 869
user3796642 Avatar asked May 06 '15 03:05

user3796642


2 Answers

So, the exact thing you need to do isn't quite possible unless you want to heavily modify FC. But you can do something quite close:

horizontal FC selection

JSFiddle

Basic Algorithm

  • Turn on selectHelper so that FC will attempt to render it as an event.
  • In eventRender, stop the helper from actually rendering. Instead, take its start and end dates and chunk them into one event per day.
  • Render the chunked events.

Chunking and Rendering

// Chunks a multiday event into an array of events
// i.e. From {start:"2015-05-06T11:00",end:"2015-05-08T15:00"}
//      into [ {start:"2015-05-06T11:00",end:"2015-05-07T15:00"},
//             {start:"2015-05-07T11:00",end:"2015-05-08T15:00"} ]
var chunk = function (event,type) {
    var chunked = [];
        //diff = moment.duration(event.end.diff(event.start));
    if (event.start.format('HHmm') > event.end.format('HHmm')) {
        return false; //Can't chunk, starttime > endtime
    }
    for (var day = event.start.clone(); !day.isAfter(event.end,'day'); day.add(1,'day')) {
        chunked.push({
            start:day.clone(),
            end:day.clone().hour(event.end.hour()).minute(event.end.minute()),
            id:"chunked-"+type //Used as a flag in the render function
        })
    }
    return chunked;
};
// Takes an event and renders it chunked. Also remove the previous chunked-helper.
// Runs after a timeout and only once.
var renderChunkedHelper = (function(){
    var id = 0;
    return function(event){
        window.clearTimeout(id);
        id = window.setTimeout(function(){
            var chunked = chunk(event,"helper");
            eventToChunk = null;
            $("#calendar").fullCalendar( "removeEvents", "chunked-helper");
            for(var i = 0; i < chunked.length; i++){
                $("#calendar").fullCalendar("renderEvent", chunked[i]); //Manually render each chunk
            }
        },0); //delay in ms. Could be tweaked for optimal perfomance

    }
})();

FC options

$("#calendar").fullCalendar({
    /*...*/
    selectable: true,
    selectHelper: true,
    select: function( start, end, jsEvent, view ){
        if(window.confirm("Create this event?")){
            $("#calendar").fullCalendar( "removeEvents", "chunked-helper");
            $("#calendar").fullCalendar( "addEventSource",chunk({start:start,end:end},"event"));
        }else{
            $("#calendar").fullCalendar( "removeEvents", "chunked-helper");
        }
    },
    eventRender: function (event,element) {
        if(event.className[0] === "fc-helper"){ //if it's the drag event
            renderChunkedHelper(event);
            return false; //don't actually render the select helper
        }
    }
});
like image 114
DanielST Avatar answered Sep 20 '22 15:09

DanielST


I ran into the same requirement recently. After digging on the Internet, no perfect solution was found. The above solution resolved the rendering problem but has some other issues, e.g. dragging issue, event ID.

So I forked the original fullCalendar repo on github and extended it with horizontal selection support.

DEMO

Usage:

Please replace the js file and set options as below:

(expandThrough is added. false means horizontal selection is on)

...
selectable: true,
selectOverlap: false,
eventOverlap: false,
editable: true,
expandThrough: false,
...

Javascript dist file:

https://github.com/deepskyr/fullcalendar/blob/horizontal_range_selection/dist/fullcalendar.js

like image 38
deepsky Avatar answered Sep 19 '22 15:09

deepsky