Portal/Portlet work continues
So I thought I’d update everyone on my progress so far with the Portal/Portlet component I’ve been working on, as well as some of the issues I’ve run into.
Normally I would have posted this to my Tapestry 101 blog but I’m going to try and consolidate my blogs together and I’m extremely tired of JRoller’s broken Textile formatting, such a pain in the ass (I have fallen in love with Markdown and code markup, it rocks!). I’ll be crossposting this, but soon I will stop updating the JRoller blog.
I now have a basic implementation of the Portal component complete and it consists of the following classes:
- Portal.java - Stores a TreeSet of columns
- Portal.html - Adds in the portlet controls div and some custom CSS stuff (which I’ll talk about shortly)
- PortalColumn - Stores a TreeSet of Portlets plus some configuration for viewing (width and background color)
- Portlet - Stores the Portlet title, content and it’s location
- portal/scripts/
- Portal.script - includes all the JavaScript files and does some dynamic stuff (coming up shortly)
- prototype/scriptaculous scripts
- portal_hooks.js - the hooks for the portal actions (close, move, etc.)
- portal.js - the actual JavaScript for the portal functionality that can be called by the portal_hooks.js file
- portal/css - portal.css
- portal/images - all the images for the portal controls and rendering (rounded corners)
Ok, so that’s the basics here are some of the specifics.
Portal.script
<input-symbol key="columns" required="yes" />
<initialization>
function init() {
portal = new Xilinus.Portal("#portal div", {onOverWidget: onOverWidget, onOutWidget: onOutWidget, onChange: onChange, onUpdate: onUpdate, removeEffect: Effect.SwitchOff});
<foreach key="column" expression="columns">
<foreach key="portlet" expression="column.portlets">
portal.add(new Xilinus.Widget().setTitle('${portlet.title}').setContent('${portlet.content}'), ${column.index});
</foreach>
</foreach>
// Add controls buttons
portal.addWidgetControls("control_buttons");
}
Event.observe(window, "load", init);
</initialization>
What I’m doing here is creating a new Portal (from Xilinus) and then I’m looping through each column and then each portlet inside of the column to add it’s content.
I dive into the hackish parts after the break.
Portal.html
This part contains some of the CSS hackish-ness I was hoping to avoid.
<span jwcid="@Script" script="Portal.script" columns="ognl:columns"/>
<div id="portal">
<div jwcid="@For" value="ognl:column" source="ognl:columns">
<div jwcid="@Any" id="ognl:'widget_col_' + column.index" />
</div>
</div>
This first part just adds in the Portal.script and then declares the html div element we want to use (this element is used throughout the CSS and JavaScript files. The next piece loops over the TreeSet of columns and outputs one specially-named div for each column.
This just creates the HTML for the portlet controls (don’t know how customizable I’m going to make this yet).
Now comes the hack.
<style type="text/css">
<span jwcid="@For" value="ognl:column" source="ognl:columns" renderTag="false">
#widget_col_<span jwcid="@Insert" value="ognl:column.index"/> {
float:left;
width: <span jwcid="@Insert" value="ognl:column.width"/>;
background:<span jwcid="@Insert" value="ognl:column.backgroundColor"/>;
}
</span>
#edit_button {
background: url(<span jwcid="@Insert" value="ognl:editButton.buildURL()"/>);
}
#delete_button {
background: url(<span jwcid="@Insert" value="ognl:removeButton.buildURL()"/>);
}
</style>
Here you see I had to do some inline styles so that I could add in some new attributes for the columns, as well as images for the control buttons. I posted a query to the mailing list about 2 weeks ago, asking if there was anything like RCSS (Ruby CSS) where you could actually use Ruby to generate CSS stylesheets - which is exactly what I need here.
After talking with Howard there did not appear to be any good way of going about doing this. One solution discussed was to let the user drop in a replacement stylesheet, but to me this seems silly, they don’t need to recreate the whole style sheet.
Another solution was to create a Tapestry page that acted like a CSS file. This still holds some promise, but is technically going to be a bear to implement due to the fact that we have to change the mime-type. The kicker in all of this though is that this isn’t going to be easier in Tapestry 5, at least not right away.
The other issue that I have with implementing this is what a pain it is to work with JavaScript in this environment and now I completely understand why it wasn’t really worked with before. Customizing the JavaScript that I need to output is a truly a pain, using XML to do my looping for me feels…wrong. If there are two areas I would like to contribute to these are it - making JavaScript and CSS more first-class citizens. Outputting HTML isn’t everything you do in a Web application.
What’s left?
Not quite done with this yet. I still have the following items to clear up:
- Need to make the
Portal,Portlet, andPortalColumnclasses persistable - Once that’s done I need to modify the JavaScript hooks so that some kind of Ajax call happens whenever a user moves a portlet, adds or removes a portlet so that their selected portlets are saved in the database
- Need a new Page so that a user can see all possible portlets to add to their custom page
- For this page was kind of thinking of doing a slick sliding door effect, dunno yet
- Add in some further customizations
- Replace default button images with ones that are easier to read/understand and fit with our internal scheme a bit better (these are customizable)
I’m trying to get this code Open-Sourced, so it may take a little bit to get this code available but it shouldn’t be too much of a problem (and we have some other cool little items we’re going to release as well - just need to clean them up).
Not happy with Linux 7
So at work I’ve been using Ubuntu on my desktop as my primary computer. I have primarily been a Windows user at work (because I have been forced to) and an OS X user at home because I prefer it. At first I kinda liked it, at least a little better than Windows. Then I began to hate it for the following reasons:
- It works just like Windows (and looks almost like Windows)
- Except when it doesn’t - then it sucks because it doesn’t work in a predictable manner
Here are some key problems I’ve had with Ubuntu:
- It can never quite remember my monitor settings properly - every time I remove a monitor or want to switch a display it loses everything or goes extremely flakey
- We play Unreal here afterhours and the audio just “disappears” - if I futz with the monitor settings then I lose Audio, hunh? Reboot required to get audio back
- No common UI - dialog boxes behave differently, things just feel “off” depending on which program I’m using
- Katapult is a poor replacement for LaunchBar or QuickSilver (which started crashing repeatedly on me on the last update so switched to LaunchBar)
- Installing an application takes command-line work - blech
The are a few good things, but not enough for me to love it:
- Wow, a real terminal - but I have this in OS X
- Updates are painless - again I already have this on OS X
- It’s stable - again I already have this on OS X
- That’s about it - otherwise, eh
This isn’t to say I don’t use Linux, I use it for my server, but I can’t see using it as a desktop replacement, not by a long shot. In order to win me over they have to really be thinking out of the box and not just duplicating what Windows or OS X has done - which they really haven’t yet (yes I know about things like Compiz Fusion - but that isn’t the whole user experience that’s just one small part - yes I said small).
So, I’m using a G4 machine right now to VNC into my work machine for specific apps I can’t install (or don’t want to) and will be upgrading the laptop to either a MacBook or MacBook Pro in the next few months. Then I’ll be really happy.
Looking for a good CMS 11
I’ve been working on a project for a family member and need a good Content Management System for them to use. Here are my requirements:
- Easy to understand interface
- Generates URLs that are human readable - no blah.php?page_id=123 crap
- Easily supports internationalization as the site itself will need to be translated into multiple languages
- Preferrably Java (but open to Rails, and not really interested in PHP)
- Doesn’t take a rocket scientist to create and edit site templates
What I’ve looked at so far has been:
- Radiant CMS - too simple, with code embedded and no Rich Text editor that they won’t understand
- Magnolia - Waaaay too complex, nice for an enterprise solution but not for what they need it for
Just downloaded Liferay and will be taking a look at that, Daisy and JBoss Portal. Another suggestion made to me was to possibly use Contribute, which I think I’ll have them download and try out to see if it works for them (but then I’ll have to do the whole locale thing through Apache).
I’ve looked at the CMSes listed here.
- Jahia - ok, after relooking at it I may download it and try it out
- Magnolia - too complex for my needs
- InfoGlue - looks complex just like Magnolia
- Apache Lenya - had a very bad experience with this in the past and the interface looks just as awkward to use as it did before - pass
- Daisy - looks interesting
- MMBase - no online demo and I wasn’t wild about the screenshots I did see, passing for now
What I’ve found so far with alot of these (just through using their online demo) is that the interfaces are very complex. I don’t know if this is supposed to go along with their “Enterprise” tag or not, and of course a fair number of them tout their JSR-170, 168 compliance. Ok, JSR-168 might be important to know, but do I really care if they are a fully compliant Java Content Repository? Nah, not really, I just want it to work and have a usable interface. Some may care about that but to me it isn’t a selling point. I respect the CMSes who put up an online demo, it gives me a chance to play with it first to see if it’s even close to something I want, those that don’t I look for screenshots, and most likely move on anyways.
Interesting trick to finding Java caller 17
Have you ever wondered how to find the Class that has just called your class? Well, now you can (or rather you always could) by using this little trick that I got from my friend and former co-worker Leo.
Class.forName(new Throwable().getStackTrace()[2].getClassName()));
This will retrieve the caller name from the stacktrace and then you can get the actual class using Class.forName(). He uses this in an interesting way for logging.
private static final Log getLog() {
try {
return LogFactory.getLog(Class.forName(new Throwable().getStackTrace()[2].getClassName()));
}
catch (Exception e) {
return LogFactory.getLog(FormattedLogger.class);
}
}
Which he then imports as static methods so that he can just do:
info("Some intereting INFO logging going on here");
Pretty slick and an interesting use of the Java libraries.
Thinking about picking the Groovy DSL book up again 6
But before I do I thought I’d ask everyone out there (who are interested in such a book), what would you like to see in it?
One possibility I’ve been tossing around is to turn it into a techniques or cookbook-style book. I’ve been reading through “Designing Interfaces” by Jennifer Tidwell. In this book she organizes the interface solutions into different sections and goes through each one with an example and what it solves and when to use it. I really like this idea (but others might not). Originally my book was a “How do I get started designing DSLs?” and “What in the world are they and why should I care?”.
Another thing I’ve been thinking about is ditching the Java part and making it Groovy only. This appeals to me because I feel that Groovy is much cleaner to implement an Internal DSL than Java is. Can you do DSLs in Java? Of course you can, but I’m not sure that I can give it the best treatment because it isn’t what I’m passionate about.
So, sound off in the comments, let me know what topics you’d like to see covered, what challenges have you faced in writing a DSL (or API/Framework) that you would have liked someone to trailblaze for you to show the dead-ends first?
Gary Gygax (1938-2008) 1
I was saddened to hear the news today that Gary Gygax passed away yesterday. For those of you not familiar with the name he is the co-creator of Dungeons and Dragons (now owned by Wizards of the Coast).
I spent much of my youth playing D&D and later AD&D as well as many other role-playing games. These games helped me become more socially interactive with people who became close friends. They also led me into programming and writing - where I wanted to recreate some of the cool images in my head in some way. If it hadn’t been for D&D (and Wargames West the local gaming shop in Albuquerque, NM) I don’t know where I would be right now.
Thanks Gary for all the fun I had as a kid (and as an adult!), I never met you but you changed my life.
