While working on custom calendar, I can\'t figure out how to find time slots that overlaps any other time slot.
Time slots start from 0 to 720 (9am to 9pm with each
Here's code that will do what you want. As others have mentioned you'd probably be better served by storing date objects, but that's a different issue.
function getOverlaps(events) {
// sort events
events.sort(function (a, b) {
return a.start - b.start;
});
var results = [];
for (var i = 0, l = events.length; i < l; i++) {
var oEvent = events[i];
var nOverlaps = 0;
for (var j = 0; j < l; j++) {
var oCompareEvent = events[j];
if (oCompareEvent.start <= oEvent.end && oCompareEvent.end > oEvent.start || oCompareEvent.end <= oEvent.start && oCompareEvent.start > oEvent.end) {
nOverlaps++;
}
}
if (nOverlaps > 1) {
results.push({
id: oEvent.id,
eventCount: nOverlaps,
toString: function () {
return "[id:" + this.id + ", events:" + this.eventCount + "]"
}
});
}
}
return results;
}
To me it is easier to use timestamps for each start and end event, that way you can work with them directly or change them to date objects. To get the value, create a date object for each start and end, then:
var a.start = startDate.getTime();
var a.end = endDate.getTime();
For overlap:
if (a.start <= b.start && a.end > b.start ||
a.start < b.end && a.end >= b.end) {
// a overlaps b
}
You can leave them as date objects if you like, the above will work just as well.
Ok here's a working example:
Assuming a nominal date of 2012-05-15, then the events array looks like:
// Use iso8601 like datestring to make a local date object
function getDateObj(s) {
var bits = s.split(/[- :]/);
var date = new Date(bits[0], bits[1] - 1, bits[2]);
date.setHours(bits[3], bits[4], 0);
return date;
}
var events = [
{id: 1, start: getDateObj('2012-05-15 09:00'), end: getDateObj('2012-05-15 09:30')},
{id: 2, start: getDateObj('2012-05-15 09:30'), end: getDateObj('2012-05-15 11:30')},
{id: 3, start: getDateObj('2012-05-15 09:20'), end: getDateObj('2012-05-15 12:00')},
{id: 4, start: getDateObj('2012-05-15 12:20'), end: getDateObj('2012-05-15 12:30')},
{id: 5, start: getDateObj('2012-05-15 18:00'), end: getDateObj('2012-05-15 19:00')},
{id: 6, start: getDateObj('2012-05-15 18:20'), end: getDateObj('2012-05-15 19:20')}
];
function getOverlappingEvents(eventArray) {
var result = [];
var a, b;
// Sort the event array on start time
eventArray.sort(function(a, b) {
return a.start - b.start;
});
// Get overlapping events
for (var i=0, iLen=eventArray.length - 1; i<iLen; i++) {
a = eventArray[i];
b = eventArray[i + 1];
if ((a.start <= b.start && a.end > b.start) ||
(a.start < b.end && a.end >= b.end) ) {
result.push([a.id, b.id]);
}
}
return result;
}
// Run it
alert(getOverlappingEvents(events).join('\n')); // 1,3 2,3 5,6
from my jquery-week-calendar commit, this is how i do it:
_groupOverlappingEventElements: function($weekDay) {
var $events = $weekDay.find('.wc-cal-event:visible');
var complexEvents = jQuery.map($events, function (element, index) {
var $event = $(element);
var position = $event.position();
var height = $event.height();
var calEvent = $event.data('calEvent');
var complexEvent = {
'event': $event,
'calEvent': calEvent,
'top': position.top,
'bottom': position.top + height
};
return complexEvent;
}).sort(function (a, b) {
var result = a.top - b.top;
if (result) {
return result;
}
return a.bottom - b.bottom;
});
var groups = new Array();
var currentGroup;
var lastBottom = -1;
jQuery.each(complexEvents, function (index, element) {
var complexEvent = element;
var $event = complexEvent.event;
var top = complexEvent.top;
var bottom = complexEvent.bottom;
if (!currentGroup || lastBottom < top) {
currentGroup = new Array();
groups.push(currentGroup);
}
currentGroup.push($event);
lastBottom = Math.max(lastBottom, bottom);
});
return groups;
}
there's a bit of component-specific noise around, but you'll get the logic:
currentGroup
) is a new array inside the groups
-arraysoo ... your code might look sth alike this (btw, no need to work with the real date
-instances)
events.sort(function (a, b) {
var result = a.start - b.start;
if (result) {
return result;
}
return a.end - b.end;
});
var groups = new Array();
var currentGroup;
var lastEnd = -1;
jQuery.each(events, function (index, element) {
var event = element;
var start = event.start;
var end = event.end;
if (!currentGroup || lastEnd < start) {
currentGroup = new Array();
groups.push(currentGroup);
}
currentGroup.push(event);
lastEnd = Math.max(lastEnd, end);
});
return groups;
soo ... you are not willed to push some own energy into your problem ... well
var output = new Array();
jQuery.each(groups, function (index, element) {
var group = element;
if (group.length <= 1) {
return;
}
jQuery.each(group, function (index, element) {
var event = element;
var foo = {
'id': event.id,
'eventCount': group.length
};
output.push(foo);
});
});