Proposed Feature: 'Background Events' (with patch)

49 views
Skip to first unread message

Graeme Worthy

unread,
Oct 14, 2009, 4:50:59 PM10/14/09
to jquery week calendar
In my usage of this tool I have found a need for events that are not
editable, but also that do not cause 'overlap style sorting of events
that are placed atop them. I call these 'Background Events'

My use case for this is that I am constructing a scheduling
application, and so I have employees availabilities set as
'background' events, which allows for tasks and events to be set atop
those events.

These tasks and events on the top 'layer' bump and jostle each other
and show overlaps (which is a good visual indicator of conflict), but
do not cause overlap with the 'background layer'..

The changes to the code to meet my proposal are minimal.

639d638
< if (!$(this).hasClass
('weekcalendar_background')) {
663,665c662
< var options = this.options;
< var exclude = options.excludeFromOverlap;
< var $events = $weekDay.find(".cal-event:not(" + exclude
+ ")");
---
> var $events = $weekDay.find(".cal-event");
1269d1265
< excludeFromOverlap: ".weekcalendar_background",



When a user wishes to set an event as background, they do so in their
eventRender as part of the weekcalendar initialisation.

I did mine like so:

adding an 'event_type' to the json I pass the calendar

events : [
{"id":1,
"start": new Date(year, month, day, 9),
"end": new Date(year, month, day, 12, 30),
"event_type": "background"
}]

and then setting the eventRender to read that event_type, and set the
event type both as class (for styling) and turns on the
weekcalendar_background class, for the above script to parse.

eventRender : function(calEvent, $event) {
if(calEvent.event_type == "background"){
$event.addClass("weekcalendar_background");
calEvent.readOnly = true;
};
if(calEvent.event_type){
$event.addClass(calEvent.event_type);
calEvent.readOnly = true;
};

},

Could this feature be brought into the weekcalendar core. I could
contribute a working sample for the demos package.

Nathan Phelps

unread,
Oct 14, 2009, 4:53:20 PM10/14/09
to jquery-wee...@googlegroups.com
I have needs for a similar feature and would love to see this included in the core.

Thanks,

Nathan

Graeme Worthy

unread,
Oct 14, 2009, 5:08:18 PM10/14/09
to jquery-wee...@googlegroups.com
Please try out this code then Nathan, 
If your usage of it requires different things then perhaps we could abstract a more general case together.

Here is a more cut and paste friendly version of the changes.

I have cut from comment to comment to allow you to see some overlapping lines on each end, for ease in finding the end position.

// jquery.weekcalendar.js version 1.2.1 lines 617 +
        /*
         * If overlapping is allowed, check for overlapping events and format 
         * for greater readability
         */
        _adjustOverlappingEvents : function($weekDay) {
            var self = this;
            if(self.options.allowCalEventOverlap) {
                var groups = self._groupOverlappingEventElements($weekDay);
                
                $.each(groups, function(){
                    var groupAmount = this.length;
                    var curGroup = this;
                    // do we want events to be displayed as overlapping 
                    if (self.options.overlapEventsSeparate){
                        var newWidth = 100/groupAmount;
                        var newLeftAdd = newWidth;
                    } else {
                        // TODO what happens when the group has more than 10 elements
                        var newWidth = (100 - (groupAmount*10));
                        var newLeftAdd = (100 - newWidth) / (groupAmount-1);
                    }
                    $.each(this, function(i){
                      if (!$(this).hasClass('weekcalendar_background')) {
                        var newLeft = (i * newLeftAdd); 
                        // bring mouseovered event to the front 
                        if(!self.options.overlapEventsSeparate){
                            $(this).bind("mouseover.z-index",function(){
                                 var $elem = $(this);
                                 $.each(curGroup, function() {
               $(this).css({"z-index":  "1"});
           });
           $elem.css({"z-index": "3"});
                            });
                        }
                         $(this).css({width: newWidth+"%", left: newLeft+"%", right: 0});
                    });
                });
            }
        },
        
       
        /*
         * Find groups of overlapping events
         */
        _groupOverlappingEventElements : function($weekDay) {
            var self = this;
            var options = this.options;
            var exclude = options.excludeFromOverlap;
            var $events = $weekDay.find(".cal-event:not(" + exclude + ")");
            var sortedEvents = $events.sort(function(a, b){
                return $(a).data("calEvent").start.getTime() - $(b).data("calEvent").start.getTime();
            });
            
            var $lastEvent;
            var groups = [];
            var currentGroup = [];
            var $curEvent;
            var currentGroupStartTime = 0;
            var currentGroupEndTime = 0;
            var lastGroupEndTime = 0;
            $.each(sortedEvents, function(){
                
                $curEvent = $(this);
                currentGroupStartTime = $curEvent.data("calEvent").start.getTime();
                currentGroupEndTime = $curEvent.data("calEvent").end.getTime();
                $curEvent.css({width: "100%", left: "0%", right: "", "z-index": "1"});
                $curEvent.unbind("mouseover.z-index");
                // if current start time is lower than current endtime time than either this event is earlier than the group, or already within the group   
                if ($curEvent.data("calEvent").start.getTime() < lastGroupEndTime) {
                    return;
                }
                // loop through all current weekday events to check if they belong to the same group
                $.each(sortedEvents, function() {
                    // check for same element and possibility to even be in the same group  note: somehow ($curEvent == $(this) doens't work 
                    if ($curEvent.data("calEvent").id == $(this).data("calEvent").id || 
                        currentGroupStartTime > $(this).data("calEvent").start.getTime()+1 ||
                        currentGroupEndTime < $(this).data("calEvent").start.getTime()+1) {
                        return;
                    }
                    //set new endtime of the group
                    if ($(this).data("calEvent").end.getTime() > currentGroupEndTime) {
                        currentGroupEndTime = $(this).data("calEvent").end.getTime();
                    }
                    // ain't we adding the same element
                    if ($.inArray($(this), currentGroup) == -1) {
                        currentGroup.push($(this));
                    }
                    // ain't we adding the same element
                    if ($.inArray($curEvent, currentGroup) == -1) {
                        currentGroup.push($curEvent);
                    }
                });
                if(currentGroup.length) {
                    currentGroup.sort(function(a,b){
                        if ($(a).data("calEvent").start.getTime() > $(b).data("calEvent").start.getTime()) {
                            return 1;
                        } else if ($(a).data("calEvent").start.getTime() < $(b).data("calEvent").start.getTime()) {
                            return -1;
                        } else {
                            return ($(a).data("calEvent").end.getTime() - $(a).data("calEvent").start.getTime()) 
                                         - ($(b).data("calEvent").end.getTime() - $(b).data("calEvent").start.getTime());
                        }
                    });
                    groups.push(currentGroup);
                    currentGroup = [];
                    lastGroupEndTime = currentGroupEndTime;
                } 
            
            });
            
            return groups;
            
        },

        /*
         * Check if two groups containt the same events. It assumes the groups are sorted NOTE: might be obsolete
         */
--
--
Graeme Worthy
Workben.ch
778.885.7741

Graeme Worthy

unread,
Oct 15, 2009, 2:04:18 AM10/15/09
to jquery-wee...@googlegroups.com
I have made a pastie:

this contains a working edition of the above codes.

nodell

unread,
Dec 9, 2009, 1:31:05 PM12/9/09
to jquery week calendar
Hi Graeme,

I've tried to update the 1.2.2 code base with your changes but I can't
seem to get it to work. Have you possibly applied your changes to the
1.2.2 release? Also, can you provide a sample of your background css
class?

Thanks,

Neil

On Oct 15, 1:04 am, Graeme Worthy <graemewor...@gmail.com> wrote:
> I have made a pastie:http://pastie.org/655679
>
> this contains a working edition of the above codes.
>

nodell

unread,
Dec 10, 2009, 10:42:33 AM12/10/09
to jquery week calendar
Nevermind - I got it.

Neil

Graeme Worthy

unread,
Dec 10, 2009, 3:01:18 PM12/10/09
to jquery-wee...@googlegroups.com
Hey Neil,

I'm glad you got it, I actually hadn't moved to 1.2.2 myself!
Could you post your changes?

Heres the other stuff I was doing, to make background classes work nice.
And the css I use.

========================
This is not a patch to the core js, but arguments on the
$('#calendar').weekcalendar

eventRender : function(calEvent, $event) {
if(calEvent.end.getTime() < new Date().getTime()) {
$event.addClass("passed");
}
if(calEvent.event_type == "availability"){
$event.addClass("background");
calEvent.readOnly = true;
}
if(calEvent.event_type){
$event.addClass(calEvent.event_type);
calEvent.readOnly = true;
}
if(calEvent.event_type == "booked"){
$event.addClass("foreground")
$event.addClass("booking")
calEvent.readOnly = true;
};
if(calEvent.event_type == "undecided"){
$event.addClass("foreground")
$event.addClass("undecided")
calEvent.readOnly = false;
};
}

=======================
As for the css for those:

#calendar .cal-event.background {
background-color: #eee;
opacity: 1;
z-index: 1;
}
#calendar .cal-event.background div.time {
background-color: #eee;
}
#calendar .cal-event.background div.title{
color: #333;
}
#calendar .cal-event.foreground {
z-index: 10;
width: 90%;
margin-left: 5%;
}

=============================
I've modified the standard data format (just by adding fields to the
json I send) to include this 'event_type'

var example_json = [{

"title":"Booked",
"end":"2009-04-09T14:00:00-07:00",
"id":26,
"start":"2009-04-09T12:00:00-07:00",
"event_type":"booking"

}]
--
Graeme Worthy

nodell

unread,
Dec 10, 2009, 4:02:35 PM12/10/09
to jquery week calendar
Graeme,

Code is here: http://pastie.org/737881

In reality this version may not exactly match the 1.2.2 code base with
background changes. I started with your 1.2.1 pastie and updated it to
work with the 1.2.2 css - so there may be some things that Rob updated
in 1.2.2 that's missing from this version.

There may be a couple of other modifications in the version that I
pasted specific to my needs but I don't think that should adversely
affect any functionality.

And here's the CSS that I'm currently using:

.wc-background {
background-color:#534a4a;
filter:alpha(opacity=40);
-moz-opacity:0.4;
-khtml-opacity: 0.4;
opacity: 0.4;
position: absolute;
text-align: center;
overflow: hidden;
cursor:default;
color: #fff;
width: 100%;
display: none;
}

.wc-background .wc-time {
background-color:#343030;
border: 1px solid #270808;
color: #fff;
padding: 0;
font-weight: bold;
}

Neil

nodell

unread,
Dec 11, 2009, 11:26:01 AM12/11/09
to jquery week calendar
Graeme,

Previous code pastie had an error (trying to create a new event on top
of a background event placed it in the wrong position).

Updated code here: http://pastie.org/739114

Neil
Reply all
Reply to author
Forward
0 new messages