Simple Events Calendar With Movable Type
August 19, 2004 |
32 Comments
Summary: A story relating my frustrations trying to use Movable Type to build a simple events calendar.
Sometimes something seemingly very simple can turn out to be quite a challenge. Often, when this is the case, the solution ends up being so simple you wonder why in the heck you had to put so much time and effort into it. Other times, you just can’t seem to get everything nailed down.
I had a little bit of both when building a simple events calendar with Movable Type.
It was supposed to be so easy…
The first part, a calendar that lists every event going forward and rolls off when the event has passed was pretty easy. The second part, a mini calendar for the homepage listing the next four events is a royal pain in the ass, enough so that I’ve given up.
But let’s start with what I did figure out.
The Easy Part
What I wanted to have was an events calendar that shows upcoming events and automatically expires them when the event has passed. This is pretty easily done in MT.
Simply output your entries like this:
<MTEntries category=”Events” sort_order=”ascend” days=”1”>
This displays all the entries from the current day forward. They roll off when they are supposed to and life is good. You can see this in action here. There should only be events listed from today on.
The Hard Part
So that was easy enough, but what do you do when you want to limit those events show to the last 4? You might link you can simply use the “lastn” attribute with MTEntries and thus limit the entries to the last 4. This doesn’t work, what it does is display the literal last 4, which causes a problem when you have entries extending months in advance. It’s effectively overriding the “sort_order” attribute.
You see, the MTEntries tag doesn’t allow you to combine the “lastn” attribute (which you need to set the entries to display the last four) with the “days” and “sort_order” attributes. At least not correctly. There are lots of plugins out there that might be able to assist with this. I tried many to no avail. Doesn’t mean they wouldn’t work, just that I couldn’t figure it out.
But I did get it almost to work using the EntryList plug in.
What I did was this: Create a list of your entries from this day forward and then use the EntryList plugin to apply the “sort_order” and “lastn” to trim it to the number of entries you want. The code for this shortened events listing looks like this:
<MTEntryList>
<MTEntries days=”1”></MTEntries>
<MTEntryListEntries lastn=”4” sort_order=”ascend”> <p><$MTEntryDate format=”%b %d”$>—<a href=”/events/default.asp#<$MTEntryID$>”><$MTEntryTitle strip_controlchars=”2”$></a></p></MTEntryListEntries>
</MTEntryList>
To see it in action check out Children’s Foundation and Guild Association home page.
That’s it. Simple, but took me hours to find and figure out, and it still has a big problem. It doesn’t handle the “days” attribute correctly! Now the events never roll off and you have to delete them manually, thus defeating the purpose.
How can something that seems so simple, be so amazingly difficult to figure out. I find it hard to believe that I’m the first person to try to use MT in this manner, but I can find nothing out there about it.
It’s not that big a deal, and pales in comparison to some of the workarounds and inflexibility I’ve found with other CMS systems (and lets be honest, MT wasn’t built to do this stuff) but man, it’s been frustrating.
Filed under: Web Development
Comments
1. Beerzie Yoink said:
Smartly done. Everything takes longer than you think. It’s like when I try to work on my car. I took nearly two hours to change the headlamp in my car last weekend when the guy at Kragen assured me it was a snap.
Posted on August 19, 2004 10:46 AM | #
2. Adam said:
How about running a cron job that goes every night, finds the expired entries, and sets them from published to draft (or deletes them if you don’t need them anymore)? I don’t know if you’re looking for that kind of solution, but something like Brad Choate’s SQL Plugin could make that pretty easy (I think!).
Posted on August 19, 2004 10:58 AM | #
3. Anil Dash said:
Hmm, it really is stretch MT to do something outside of its intended goals, but I know people have solved this problem before. Let me dig around and see what plugins/etc. were used to figure it out.
Posted on August 19, 2004 11:11 AM | #
4. Keith said:
Adam – Yeah, I briefly looked into that idea, and it *may* be something I look into again. Still, if the “days” and “lastn” attributes would just play nice, this would have been a piece of cake! A cron job and yet another plug-in seem like extreeme over-engineering to me. ;)
Posted on August 19, 2004 11:12 AM | #
5. Keith said:
Anil – Thanks! That’d be great. And come ‘on, you and I both know MT is always stretching to do something outside of its intended goals. You should see our Intranet. ;)
Posted on August 19, 2004 11:13 AM | #
6. kirkaracha said:
I had the same issues and ended up using this MySQL in a PHP include:
SELECT
mt_entry.entry_title,
mt_entry.entry_created_on,
mt_placement.placement_category_id
FROM mt_entry
LEFT JOIN mt_placement
ON mt_entry.entry_id = mt_placement.placement_entry_id
WHERE mt_placement.placement_category_id = ‘6’
AND mt_entry.entry_blog_id = ‘2’
AND mt_entry.entry_status = ‘2’
AND mt_entry.entry_created_on > CURDATE()
ORDER BY entry_created_on ASC
LIMIT 2
This gives me the next two upoming entries in the weblog and category I want.
Posted on August 19, 2004 11:19 AM | #
7. Dave P said:
MT Hacks, a suggestion for Cron jobs, good grief folks this is a simple SELECT Statment.
As in: “SELECT Title, Event_Date, Description FROM EVENTS WHERE Event_Date >= $DATE (or whatever) ORDER BY Event_Date”
I guess one of the difficutlies in working with a system such as MT (not that any other system would be any different) is that sometimes, realtivly easy tasks become difficult.
Keith have you thought about maybe moving this site onto something more powerful such as Drupal?
Or, is the need here (and for other larger sites) just for an easy to use content management system that isn’t tied to a “front end” at all.
Just thinking aloud… I’ll shut up now.
Posted on August 19, 2004 11:32 AM | #
8. Keith said:
kirkaracha – Hmm, yeah, sounds like that would work. Thing is we’re not using PHP. We’ve got ASP running on a linux machine (don’t ask…) and we’ve got very little support in that area (I don’t know ASP at all) so…One of the realities we’ve got to deal with.
And really, if there is a solution here it needs to be simple. Easier than just going in and deleting old events every once in awhile. I mean, sometimes offline solutions are best…that may be the case here.
Dave P – See what I mean? Should be easy. No we’re not looking for something else. MT suits our needs just fine here and anything else would be much more work than it’s worth. This was really easy to set up aside from this one…little…problem…
In about 3 hours I was able to add distributed authorship for 5 sections of our external site, RSS feeds for news, events and press releases and single source event publication. This little thing is a minor issue compared to all I was able to accomplish when you think about it.
Posted on August 19, 2004 11:37 AM | #
9. Robert said:
The SQL shouldn’t change between PHP and ASP, so you’ve got the ingredients for a solution there in kirkaracha’s comment.
I’m on the other side of the fence here, running ASP on Windows and not knowing any PHP or MT. What kind of ASP code snippet do you need to make this work?
Posted on August 19, 2004 11:59 AM | #
10. Dave P said:
ASP Code:
Dim pRS, SQL
SQL = “SELECT mt_entry.entry_title, mt_entry.entry_created_on, mt_placement.placement_category_id FROM mt_entry
LEFT JOIN mt_placement ON mt_entry.entry_id = mt_placement.placement_entry_id WHERE mt_placement.placement_category_id =6 AND mt_entry.entry_blog_id = 2 AND entry.entry_status = 2 AND mt_entry.entry_created_on >=’” & Date() & “’ ORDER BY entry_created_on ASC LIMIT 2”
Set pRS = Server.createobject(“ADODB.Recordset”)
pRS.open SQL, “CONNECTION_STRING HERE”
Do Until pRs.eof
response.write (pRS.fields(0) & trim(pRS.fields(2)))
pRS.movenext
loop
pRS.close
Set pRS = nothing
%>
Posted on August 19, 2004 12:20 PM | #
11. Dave P said:
BTW, Smarty pants was converting all the single quotes… but they should go where kirkaracha had them as well as around the date variable.
Posted on August 19, 2004 12:23 PM | #
12. Andrew said:
This article “Calendar of Events in MT” describes using the SomeDays plugin to do what you describe. SomeDays seems to have exactly the kind of date-limiting functions you wanted. Specifically, see Selecting A Range.
Posted on August 19, 2004 01:07 PM | #
13. Keith said:
kirkaracha and Dave – Thanks! I’ll look into that solution.
Andrew – Yeah, I looked into the SomeDays plugin and even read that article, but I couldn’t get it to work the way I wanted it to. It also seemed very complicated for my needs. But maybe I’ll look at that again, thanks!
Posted on August 19, 2004 01:11 PM | #
14. mashby said:
I too have run into the same issue with many sites. I’ve tried to do the same thing with my Nashville Palm Users Group web site, but have had no success in getting it to work. Since I don’t have as many events, I simply edit a template by hand.
However, if there is a fix out there, I’m all ears!
Posted on August 19, 2004 01:22 PM | #
15. Patrick Taylor said:
For event calendars using MT, I’ve used Kevin Shay’s DateTags plugin which provides NextNEntries and PrevNEntries derived from a BaseDate which I think is what you’re after.
It also has lots of neat stuff like IfDateAfter, IfDateAfterOrEqual, IfDateBefore, IfDateBeforeOrEqual, IfDateEqual, IfDateNotEqual, IfDateWithin, DeltaDays and NEntriesCount. Kevin is a genius, I’ve found that this plug-in has been perfect for event calendars.
Also worth looking at when making Event Calendars with MT is Lummox Jr’s Archive Year to create a calendar-based archive page for the full-year and Brad Choate’s Supplemental Calendar Tags which give you finer grained control over calendars (in particular <MTCalendarEx> lets you offset calendars into the future or the past.
Haven’t tested them in MT 3 though …
Posted on August 19, 2004 01:28 PM | #
16. Keith said:
Patrick – That sounds like a good solution to try. I’ll look into it. Thanks everyone for your help!
Posted on August 19, 2004 04:20 PM | #
17. Elaine Nelson said:
Keith, I think I remember Mike Kelley writing about using Movable Type for an events calendar (when he was still working at a hospital!)…you might want to give him a holler and see what he did.
Posted on August 19, 2004 05:49 PM | #
18. Steve said:
Knowing that I will eventually need to do something like this with one of my sites, I took a stab using the DateTags plugin. The following solves the problem of events rolling off on the proper date, but it doesn’t limit the list to the next 4 events.
<MTEntries sort_order=”ascend”>
<MTIfDateAfterOrEqual target=”[MTDate format=’%m%d%Y’]”>
<p><$MTEntryDate format=”%b %d”$>
—<a href=”/events/default.asp#<$MTEntryID$>”>
<$MTEntryTitle strip_controlchars=”2”$></a></p>
</MTIfDateAfterOrEqual>
</MTEntries>
To limit the list to 4 items, I messed around with the lastn argument for the EntryList tags, but to no avail. So we’re kind of back to square one, but I’ll keep plugging away.
Posted on August 19, 2004 08:01 PM | #
19. Keith said:
Steve – Look at my first bit of code. That is all you need (no plugins, hacks or whatnot) to force the dates to roll off. It’s forcing them to roll off and limiting them to the last 4 that is the problem. So yeah, back to square one.
But, hey, props for giving it a shot. If you figure it out, let me know and I’ll do the same.
Posted on August 19, 2004 09:26 PM | #
20. Steve said:
Keith, problem solved. No PHP, ASP, or SQL queries necessary. Just use the MTNextNEntries tag, part of the DateTags plugin:
<MTNextNEntries n=”4” target=”[MTDate format=’%m%d%Y’]”>
<MTEntries sort_order=”ascend”>
<p><$MTEntryDate format=”%b %d”$>
—<a href=”/events/default.asp#<$MTEntryID$>”>
<$MTEntryTitle strip_controlchars=”2”$></a></p>
</MTEntries>
</MTNextNEntries>
It works for me — let me know if it works for you.
Posted on August 20, 2004 06:26 AM | #
21. Keith said:
Steve – I will. I actually tried something close to that very solution, and it didn’t work for me, but I was at the end of my rope and might have given up too soon. Let me work on it some more and see if I can’t get that to work.
Thanks for sharing your solution with me!
Posted on August 20, 2004 10:58 AM | #
22. Christian Watson said:
As the instigator of this ‘little’ task and a fellow member of Keith’s web team at the hospital, I’d just like to say thanks to everyone for their comments and suggestions.
Although most of what you said passed over my head at a considerable height, it is heart-warming to see so much thought and effort being freely given to help us out. Thanks all!
Posted on August 20, 2004 12:14 PM | #
23. Woody said:
This is exactly what I need for a performance group’s website to show a list of upcoming shows.
I tried Steve’s solution with the DateTags plugin, but when I use the ‘sort_order’ argument in the ‘MTEntries’ tag, it seems to kill the enclosing ‘MTNextNEntries’ tag. So instead of the next n entries, I get everything, regardless of date. When I take ‘sort_order’ out it works.
Back to square one. (I am using Date::PCalc rather than Date::Calc, since my ISP doesn’t have Date::Calc installed. If that makes any difference.)
Posted on August 22, 2004 01:46 PM | #
24. mashby said:
Keith,
Did you make any further headway with this, or have we hit the wall on this one?
Posted on August 28, 2004 07:59 AM | #
25. Aaron said:
here’s how I did it: fix Movable type to handle firstn along with lastn! (note that the PHP dynamic engine already does the right thing with lastn and sort=”asc”, i.e. lastn==limit in the php code, so no need for firstn there, just for static templates). Now you don’t need to use DateTags or anything else. Anyone care to pass this along to MT developers?
The patch for MT: — lib/MT/Template/Context.pm~ Fri Sep 3 12:28:08 2004 +++ lib/MT/Template/Context.pm Tue Oct 12 09:57:19 2004 @@ -687,13 +687,15 @@ if ($entries) { @entries = @$entries; if (%$args) { - my $n = $args->{lastn}; + my $lastn = $args->{lastn}; + my $firstn = $args->{firstn}; ## If lastn is defined, we need to make sure that the list of ## entries is in descending order. - if ($n) { + if ($lastn) { @entries = sort { $b->created_on cmp $a->created_on } @entries; } + my $n = $lastn || $firstn; my $off = $args->{offset} || 0; my($i, $j) = (0, 0); my @tmp;
Posted on October 12, 2004 07:06 AM | #
26. JV said:
Greetings
http://www.staggernation.com/mtplugins/DateTagsReadMe.html#MTNextNEntries
This displays the next 8 entries from the day the the page was rebuilt.
Hope this is helpfull
JV
Posted on October 13, 2004 09:29 AM | #
27. John Zeratsky said:
It appears that the old events don’t roll off unless you rebuild. In fact, that’s the case with the example Keith provides. Any ideas about getting around this problem?
Posted on November 10, 2004 10:58 PM | #
28. Highforge said:
Thx for this info it helped. I just wanted to point out that there is a “bug” in that if you specify more than one category (using OR or AND) it breaks the day= function.
Posted on February 7, 2005 01:40 PM | #
29. arthur said:
Unfortunately, with MT 2x you’re not going to get the events to auto roll off unless you’re pulling them out with some kind of scripting language like php. Because MT is writing static html, unless you have a cron script to rebuild the site once a day, it’s not going to make old events roll off…
Posted on February 26, 2005 06:55 PM | #
30. Joelle said:
Keith, did Steve’s suggestion ever end up working for you?
Posted on May 31, 2005 03:38 PM | #
31. roderick said:
I know this is a year after your original problem, but I’ve run into the same problem for a project I’m working on, so I ended up using MTNextNEntries combined with a cron job.
BUT, I have found the plugin that would work for you: MTCatEntries. That plugin is used to exclude category posts and is used instead of MTEntries. Serendipitously, I found that it DOES honor “offset” AND “lastn” AND “days”. You could replace your MTEntries tag with MTCatEntries, not specify a category to exclude (or you could, I suppose) and then crack open a beer. Cheers!
The plugin and info about usage:
http://markpasc.org/weblog/2004/01/27/catentries_28
More info on using MTCatEntries:
http://www.fortysomething.ca/mt/etc/archives/004604.php
Posted on July 1, 2005 09:09 AM | #
32. Fabio S. said:
Likewise our friend Roderick I was fumbling around on how to (believe it or not) list just the first entry in a MT blog when I came across with your post and surprisingly it’s the best solution around for an application that’s already 4 years old.
But the current joke is: I was already using the EntryList plugin (listing of same author entries) and didn’t realize it could help me with this issue too. Thxs.
Posted on September 21, 2005 07:43 AM | #
Comments are now closed