views:

1292

answers:

4

I have built a PHP calendar system and have pretty much everything done but not sure how to deal with a UI issue involving how the events that stretched out over a couple of days. I want to be able to stretch an event that stretches over couple of days in a div that spans those days in the calendar. Basically I would like to know how to achieve what these guys have achieved with the event that stretches out from 21st to 22nd with the yellow div background.

I have been trying to see how I can do it with PHP but I feel like I might be trying the wrong thing. Perhaps this is done with javascript?

+2  A: 

Really, to explain how to do this would take quite a while. I can give you some general pointers, however...

Basically, in the example you provided, the authors of that calendar used absolutely-positioned divs that layed over the calendar. If you open up Firebug in Firefox and 'inspect element' one of the spans, and then watch the element as you re-size the browser, you'll notice that they turn yellow. This is because JavaScript is actively re-sizing the elements when items are added or when the page is re-sized. I tried to do something similar to this for a while and eventually gave up due to it's complexity and unnecessary cumbersomeness.

What I eventually did was go against my strong anti-table mentality and used the colspan attribute of <td> elements in the table itself. Each line of events is a <tr> and each event is a <td>. Since <td>s can span multiple "columns" using the colspan attribute.

So, to break it down...

The calendar is a <div>. Each week is another 100%-width <div> that contains two tables:

  1. The first table just contains the cell borders, to give the calendar look.
  2. The second contains the the day numbers, events, etc...

In the second table, the first row has 7 columns (1 for each day of the week). All the tertiary rows only have the number of rows necessary to show their events. So, a week that only has 1 event, on, say, Thursday which spans 2 days (from Thurs. to Fri.) would have 6 columns:

That row would be something like:

<tr>
    <td class="no-event"></td> <!-- Sunday -->
    <td class="no-event"></td> <!-- Monday -->
    <td class="no-event"></td> <!-- Tuesday -->
    <td class="no-event"></td> <!-- Wednesday -->
    <td class="no-event" colspan="2">  <!-- Thursday through Friday -->
        <div class="some-styling-class">Vacation to Orlando!</div>
    </td>
    <td class="no-event"></td> <!-- Saturday -->
</tr>

Notice how there are only 6 columns... (since the event with colspan="2" takes up 2 columns worth).

Each table is positioned fixedly to the parent 'week' div... the first one has a lower z-index so that the second table (events, etc...) will show up on top and span over the calendar cell borders.

This is actually what Google uses to construct their Google Calendars. It's actually quite elegant, easy to work with, and there's little-to-no crazy javascript to write. The most challenging thing is to wrap an event from, say, Thursday on one week to, say, Wednesday on another week (since you have to make n number of colspans <td>'s depending on the amount of weeks spanned in the visible calendar space).

So, my suggestion would actually be to investigate Google's G-Cal table structure and see what you can extrapolate from that. The easy way is to just copy the entire HTML from it using Firebug and paste it into an editor and then just toy around until you understand how it works.

I hope what I've shown helps. Good luck dude.

KyleFarris
Just a note: The fact of the matter here is that calendars *are* tabular data so a table structure actually makes syntactic and semantic sense. No need to feel guilty about using them here.
KyleFarris
This really pointed me in the right direction. I got it done.
play
Basically I followed your advice and studied Google calendar and using PHP tried to mimic the layout. I didn't use two tables but one, just manipulated the rendering of the tr and, mostly, td elements using PHP.
play
Sweet man! Glad I could help. This one drove me wild for a week or so when I had to do it for a corporate intranet portal. :-)
KyleFarris
A: 

The way Google Calendar solves this problem is, believe it or not, through tables. It's a bit more sophisticated (they have one table for the calendar grid, and then superposed on top is another table for the events inside), but the basic approach will have you use multiple rows for each calendar box, and put one event per row, per column. Then when you want to stretch the event over multiple days, you simply use colspan on the table cell for that specific event. Something like this:

===============================
||   Monday   ||   Tuesday   ||
===============================
||   Evt 1    ||    Evt 2    ||    ...
-------------------------------
||   Evt 3 (colspan=2)       ||
-------------------------------
||            ||             ||
-------------------------------    ...
||            ||             ||
===============================
||   Monday   ||   Tuesday   ||
===============================

              ...

Where the double lines represent borders that you actually render, and the single lines represent invisible borders between rows. In this example, you'd have 4 rows per calendar grid (so you can have a maximum of 4 events in a day).

You can achieve all this from PHP through careful rendering of the HTML and use of CSS.

Something else I would recommend is like Michael said, study Google Calendar, but a much better way than looking at the code would be to get Firefox (you hopefully have it already) and install the extension Firebug (that you also hopefully already have). Then go to the Firebug menu and choose "Inspect element" and click on one of the events on the calendar, and study the structure from there on.

Tekahera
A: 

The problem with using a single div spanning multiple 'cells', is that you'll be confronted with line breaks. Say, an event lasts from thursday until tuesday, but each week (starting at monday) will get its own row.

An alternative solution would be to use multiple divs, and setting a seperate class for the first and last days of an event. Something like...

<div class="event01 first">(text)</div>
<div class="event01"></div> <!-- repeat -->
<div class="event01 last"></div>

Ofcourse, the downside to this would be that the description will be limited to the first div. Hence, a combination of two would probably work best; one div spanning from the start to the end of the week, and a second (and possibly third one, etc) until the end date of the event.

Or, in the case of tables, you could ofcourse combine Tekahera's answer:

<td class="event01 first last">1-day event</td>

<td class="event01 first">Multi-day event</td>
<td class="event01"></td>
<td class="event01 last"></td>

In both examples, the "event01" class will set the background and top/bottom borders, while the "first" and "last" classes would set the left and right border, respectively. (By default, these will be 0).

Duroth
A: 

Just curious, Did you try any of the Ajax Events calendar packages?

www.web2cal.com

They have inbuilt ability to render multi-day events. You really don't have to do it all over again

Hope it helps.

beeZee