Crafting the SAPO Campus platform, a thousand pixels at a time.
Latest posts

High Performance Javascript - dealing with JSON

No Widget is an Island

Designing Email - Part II

Designing Email - Part I

The amazing "widget" object

The Facebook Witch Project

SAPO Campus keynote from OSL Unesco demonstration session

SAPO Campus session at the UNESCO OSL Seminar

SAPO Campus - Eden Seventh Open Classroom Conference

SAPO Campus leaflet for the UA freshmen


Janeiro 2011

Novembro 2010

Fevereiro 2010

Dezembro 2009

Novembro 2009

Outubro 2009

Setembro 2009

Julho 2009

Maio 2009

Abril 2009

Março 2009

Fevereiro 2009

Dezembro 2008

Novembro 2008

Outubro 2008

Setembro 2008

Quinta-feira, 6 de Janeiro de 2011
High Performance Javascript - dealing with JSON

We love JSON. It's a highly interchangeable, lightweight data format. JSON is particularly better suited at passing data around than say XML or HTML because of its low ratio of  structure to data. Besides the fact that it's so light over the wire, there are a huge number of libraries for encoding and decoding JSON on the server-side. On the client-side of things, JSON is trivial to parse, allowing you to spend less time parsing data and more time actually doing something with it.

With all of these advantages under its belt, JSON was a natural choice when we at SAPO Campus wondered how we'd pass data around between servers and Javascript-powered applications. When using JSON, two of the most common operations revolve around either parsing strings into valid Javascript Literal Objects or converting the latter into strings. At the first stages of development of the My UA platform, I found a small Javascript library called JSONUtils that handled these two tasks. You might be asking: but don't browsers do JSON parsing and stringifying natively? At the time, only a few did, so we ended up not caring about it and just using JSONUtils every time.

Going native

Yesterday, while auditing some of My UA's code for performance, the thought of native JSON handling popped up in my head. Native implementations are always better than using another script, and these two operations are so commonplace that even a gain of just a few milliseconds could have a major impact on performance. After making the change to use native JSON when available, I started wondering about the real impact on performance the switch to the native implementation had. So I wrote a little test case.

The test

I coded up a simple page that parsed a sample JSON string and stringified a similar JS literal object for, oh say, 20000 iterations, then measured the time it took for the 20000 parsing and stringifying operations to run. I did this for both operations using JSONUtils and native JSON. The results are below:

The results

JSON test case - Parsing

 JSON test case - Stringifying

A few notes on the experiment:

A few thoughts

Native JSON is almost always much, much faster than the JSONUtils implementation. Google Chrome presents the strangest results, with native parsing actually being slower than its JSONUtils counterpart. Native parsing in Google Chrome is actually the slowest of all browsers tested. This is probably a bug in the otherwise excellent V8 engine, but it's still an annoying and potentially crippling oversight.

As expected, Internet Explorer provided the biggest gain in performance. Even if gains in other browsers are substantial (Firefox was a bit of a surprise, I admit) the dramatic improvement in IE justifies the change and this whole experiment.

Files used

Here are the files used in the test case.

tags: , , , ,

Published by bruno-abrantes às 16:01

Terça-feira, 16 de Novembro de 2010
No Widget is an Island
No widget is an island
View more presentations from Bruno Abrantes.


My talk at SAPO Codebits 2010. The presentation describes the concept (and a little bit of the implementation) of a Widget Cross-Communication system. Much of this is already available at the PLE.

tags: , ,

Published by bruno-abrantes às 11:38

Sexta-feira, 5 de Fevereiro de 2010
Designing Email - Part II
So yesterday I wrote a little about the conceptual and practical challenges of adding emailing capabilities to the SAPO Campus platform. I was adding some final touches to the design proposal for the new feature, and it's pretty much done by now, so I thought I'd finally put it out there, and discuss some finer points of the design.

As email clients go, this solution is pretty much standard, so no revolutions here. I went to some length discussing this on the last post so, if you haven't read it, go do it now. It's the least you can do. The best I can do then is try to make the whole experience not suck. Part of this is still up for grabs, since I don't know yet how fast and responsive the interface will be. For now, I've focused my efforts into making it as simple and clean-cut as possible: Email in general has evolved into one hell of a gargantuan system, with lots of features most people don't really give a crap about. So my main task involved getting rid of as much feature-creep as humanly possible. I thought about the features most people use on their day-to-day emailing and put those in the front row, and hid or altogether scrapped the more obscure ones.

So yeah, here it is.

The first iterations were all designed sans colour, using only shades of gray. It's tremendously helpful to do this before slapping your colour scheme on the design, to make sure there's enough contrast and that the hierarchy and element states are properly conveyed. The image shown here is what I consider to be the "final" interface iteration.

In full-blown Technicolor®

Same deal as before, but now in full colour. Although I say "full", the interface actually uses colour (the SAPO Campus trademark greenish) very sparingly. I think this does a good job of highlighting key elements in the application without confusing and cluttering up the user experience.

Basically, the application is composed by four key elements: the toolbar, the accounts pane, the message list pane, and the message viewer pane.

The toolbar

This area exposes the main actions available to the application, from left to right: Getting new mail, Composing new mail, Replying, Replying to All, Forwarding, Deleting and Marking as Spam and, finally, Searching through your mail.

There was a lot more I could've fit in here but I decided I'd keep it simple. Only the most useful actions are available in the toolbar and, furthermore, all the buttons are contextual, meaning that some of them stay inactive (visually less opaque) until a message is selected in the message list pane. You may notice the interface is lacking several common features such as filtering options and "Mark as..." buttons. The way I see it, filtering is kind of useless if you provide an awesome search function (and yeah, that's my idea here) and marking stuff as read/favorite/whatever probably makes a lot more sense if it's done in the same place where the message is displayed.

The accounts pane

Since the client we'll be using essentially uses an IMAP connection, the folder list for a given account will be automatically populated by the folders already on the server. It's also possible to add multiple accounts, and they'll be listed hierarchically and labeled by their actual email address. The folders display the number of unread messages, and the whole accounts pane is resizable (using the small dot on the border as a drag anchor). The only thing left to solve here is adding and removing folders: I'm not yet sure if this should be directly present in the main interface or if it should be tucked away in some kind of settings view.

The message list pane

Each row on this pane is a message. You can sort messages by clicking on the list headers, and you can visually tell apart messages that are unread, carry attachments or the ones which you marked as favourites. Marking a message as a favourite or as unread (once you've read it) is as easy as clicking on the appropriate row + column combination. This ensures that marking messages as favourites/unread is cognitively linked to to the message itself, and not distant from it as would occur if the UI had a specific "Mark as..." button(s). Once more, the entire pane is resizable using the small dot below as a drag anchor.

The message viewer pane

There's little to be said about the message viewer. The interface should take a step away here and just let you read your email comfortably enough. Most email clients use disclosure triangles and such to feed you a bunch of metadata about the message. I'm waging that most people don't really care about such data (and actually get confused when seeing it) so I chose to simply make it go away. Only the utmost important interface elements remain: Subject (in bold), From, To and Date Received. There's also this tiny icon on the top right corner of the pane that lets you view your message in all of its fullscreen glory.

Composing messages

Alongside reading messages, composing and sending are at the crux of the email experience, so this screen better be really well designed. Again, the goal was to keep message composing as pain-free as possible, providing simple interface controls and a well thought-out rich text editor. Once you click the "Compose" button on the toolbar, a dialog window pops up with the compose interface. This dialog window is draggable/resizable, it's not modal (meaning you can still interact with the UI below) and it's not exclusive (so you can type out two messages at once, or keep one message you've received earlier while composing a new one).

The left column on the compose window lets you keep track of your attachments and upload new ones. Since this is isn't a desktop app (and the HTML5 drag-and-drop spec is not quite there yet) you can't just drag attachments into the message body itself, which I think is the most awesome way ever of adding attachments to a message. Uploading attachments is done by AJAX magic and never forces a reload, so I believe it's a pretty much stress-free process.

This interface also provides a toolbar, and I've tried to keep the number of buttons down to a minimum. You can basically send your message (and this button is repeated at the bottom, just in case), check spelling and save it as a draft. These last two could've been avoided, since spell checking and periodic saving of your message should be done automatically without user input once every few seconds. However, most users are, I believe, extremely distrustful of "automagic" systems, and a big fat button that users can click feels all the more safe. If the application crashes or the user closes it by mistake, she'll then be pleasantly surprised that the email client was smart enough to save her work. Phew!

Glancing at the interface, you might notice some standard fields lacking, namely "BCC" (Blind-Carbon-Copy) and "Reply-to". These are without a doubt useful features, but ones that most people don't care about. I've chosen to tuck them away in a nice little dropdown field that expands when you click a button named "Add field".

Finally, actually writing text was made as simple as possible. There's a small tabbed navigation that allows you to switch between a rich-text editor (the one turned by default, since it's the most likely option for most people) and a plain-text editor. The rich-text editor is as uncluttered as possible, providing only the most crucial text-editing features: think Bold/Italic, linking to pages, aligning text, etc.


Without complicated things such as filters and fiddly controls to allow you to find the stuff you need, you naturally turn to the search facility. While nowadays the sort of "magical" search first introduced by Amazon is pretty much standard, there are still lots of applications who still don't quite "get" it. By this I mean the application forces the user to refine her search before actually searching: there's usually this list of checkboxes that can be turned on or off and your search will be limited those fields which were selected. This is just plain nonsense, and the geniuses at Amazon knew it. People don't want to make tough choices and worry about the kind of metadata they're searching for. That's what computers are for! Search should be as easy as:

  1. Type in query.

  2. Found it?

  3. No? Okay, look at some of the other results.

  4. Maybe try applying a filter or two?

  5. There you go, you found it!

This is the exact experience I had in mind while designing the search feature. It's dead-simple to use. You can search for whatever you want, and then filter the results later should you need to. The search is live and begins as soon as you type, so I bet you'll find that lost message in a matter of seconds.

Sweating the details

The devil is in the details, or so they say. Details can also make or break a design, so it's important that you spend a good amount of time working out the finer aspects of your application. Everyone else does the obvious stuff, so what gives your users that final push is the little things that make them smile when they notice them. I've already discussed the importance of periodically saving the user's work, but there's a few other things to consider when designing the email application.

First up is history management. Since the whole application is powered by Javascript and AJAX, users won't be able to rely normally on the back/forward buttons in their browser. Since other areas of the PLE already address this concern, it makes sense to develop a history stack for the email client as well. You'll be able to use your browser's built-in history buttons to go through your messages or to make your compose screen disappear or reappear.

The ability to undo your mistakes (ie. deleting a message) is something I normally strive to implement, but I'm not sure this will be as straightforward to do with Roundcube as if we were developing the whole application. It's something to keep in mind though.

We'll also try to make Roundcube play nice with our Notification Server so that, when using the PLE, the user doesn't need to keep checking the email page. The email icon (by the way, these are not the final icons in the screenshot above) will itself tell you how many new mails you have in your inbox, anywhere you are. In the future, advanced functionality could include message previewing using floating dialogs that are shown wherever you are in the PLE.

Finishing up

If you've read this far, then you deserve a cookie. No, really, this post kind of got out of hand. But hey, at least the mockups had a superhero theme going on! (Extra cookie if you noticed)

Published by bruno-abrantes às 00:56

Quinta-feira, 4 de Fevereiro de 2010
Designing Email - Part I
[caption id="attachment_362" align="alignnone" width="424" caption="The Interwebz LOLz at your lack of email facilities."]Zeus, sporting some lightning.[/caption]

So yeah, SAPO Campus is supposed to provide this wonderful set of happy magical fun tools to a University. It's a tough crowd, we're aware of it. On one hand you have Internet savvy students, skipping class for a few Farmville dollars, and on the other, teachers and support staff, most of them struggling to get this "social networking facemagazine thingamajig". Oh, and everyone in the middle. While we're convinced we already offer some very compelling tools that should please both ends of this crowd, there's this one thing that some (yours truly included) consider pretty damn central to the whole "unified" experience: an email client. While we've kept pretty much silent on the matter, this as always been on our list of awesome-must-haves (yes, i'm hyphenating it). Albeit pretty old, email is still pretty much central to the whole Internet experience, and the Gods, in all of their godliness, would surely scoff at a PLE which failed to provide at least a simple email client.

After much discussion and back-and-forth of ideas, I think we've finally nailed it, and, let me tell you, this is going to be wayyyyyy better than the iPad. Ok, not better, but still pretty damn close.

Round 1

Our first idea, and one that actually got quite a bit of traction, was to slap a mean and lean email client on a widget. It would use IMAP, and so would let you keep track of any account on whichever service you use (most provide an IMAP connection these days). This sounds neat, until you realize that a widget has precious few real-estate. Doing this in a widget meant we'd have to severely cut down on some features (dropping message composing and sending was tossed around), and simply would not do as the only email features in SAPO Campus.

Round 2

After ditching the widget format, we started to think about how we'd fit an email interface alongside our already existing interfaces. Right about at the same time, we started a major overhaul of our user profile system, and decided we'd integrate these new features in tandem with the already existing My Home widget-based PLE. Under this new system, a user's url (take mine, for example) would provide access to his/hers Profile, My Home and Portfolio platforms. Taking into account this new structure, it dawned on us that it made perfect sense to add an Email icon to the top navigation, and integrate the now illusory email client into the user's PLE.

Neatorama! But wait!

A huge statue of Bender, dressed up as a Pharaoh.

Designing and developing an email client is no walk in the park. In fact, here's how I think the experience would go down. Go ahead and read it, inhale the pain etched on those words, and then come back. Seriously, I'll wait.

Design-wise, it's just very hard to come up with an email client experience that doesn't suck. All of the clients I've gone through sucked. Some of them sucked a little less (wink wink Gmail & but, at the core, most of the whole email thing is boring and hard. Whenever I'm emailing, I actually wish I was having a taco somewhere in Mexico with some random girl named Consuela.

Development-wise, there's all these hoops to go through. Using IMAP takes away some of the pain, but it's still like giving birth to a small elephant. I'm not going to pretend I know what the actual problems would be, because just thinking about it makes me want to get another taco and ring up Consuela. Let's just agree it's a pain in the rear end of the human body.

Enter the Roundcube

After some Googling around, Roundcube started sounding like one of the best open-source webmail clients out there. Technology-wise, everything they use seems to be compatible with our setup. The interface is actually pretty decent, and it's clearly designed to look and feel like a desktop application, so it's pretty well in line with our existing platform.

Using an out-of-the-box system such as Roundcube allows us to skip much of the boring stuff and get a functional version out the door very soon, but it does pose a few obstacles:

So anyway, I started mocking up some interface designs, rocking it out to the Glee soundtrack. This was a few days ago, so they're ready (I think). Part II of this post (hopefully coming out tomorrow) will expose my new baby to the harsh spotlight that is the Web. Tough luck, kiddo.

Published by bruno-abrantes às 00:10

Quarta-feira, 16 de Dezembro de 2009
The amazing "widget" object

The UWA widget object

When developing widgets in conformity with the UWA spec, there is a seminal Javascript object which makes the UWA environment available, exposing essential methods that handle widget events, grab preference values and modify the widget's HTML. I'm talking about the widget object. This handy page lists every method readily available to use in the widget object.

What about my platform?

All these methods and callback functions, as useful as they are, are also very platform agnostic (hey, it's a good thing), thus failing to cover the particular interesting moments of a platform such as our very own PLE. I'm talking about basic stuff here, such as a widget knowing whether it was hidden, shown or closed.

Ok, that's all fine and dandy, but how about a solution? After fighting a somewhat uphill battle trying to access an iFrame's DOM (not the HTML per se, but rather its Global javascript objects) in a way that did not crash in certain browsers (ahem), I finally settled on this little line of (slightly ugly) code:

Armed with this code, I could now access random iFrames and have them execute arbitrary code (maniacal laughter ensues). So I decided it would be cool to let widgets implement some PLE specific functions, allowing developers finer control over how their widget reacts to specific platform events. The functions should be declared in your widget, inside the widget object. They're not required though, so if you have no need for a specific function (or all of them), it's cool, I guess. Not that I care. Hm. Anyway, here's the complete list:


This method is triggered when a user resizes columns in the platform. Since this causes the widget to resize as well, you might need to perform complicated Math equations or stuff. I don't know, just saying.


Unsurprisingly, this method is fired when the user hides the widget body using the little collapse button on the left of the widget chrome. This is useful if, for example, you need to stop a Flash movie in case the user hides the widget.


In 99% of cases, and if you're not CUI - Coding Under the Influence, you should use this method to undo anything the onHide() method did. It fires when the widget is uncollapsed and is thus once again visible to the user.


This method is triggered when a user deletes your widget (if your widget is awesome, this will never happen). Once again, use this to stop Flash movies or timed function executions.


The reverse of onClose(), this is triggered when the user undoes the delete action (yay, the user loves your widget again!).

Published by bruno-abrantes às 16:09

Sábado, 12 de Dezembro de 2009
The Facebook Witch Project

Sadly, this tale does not end with every one of the main characters being killed/kidnapped in the woods by a crazy hermit/ghost/monster. I say sadly because that movie ending is so awesome every other movies should be ashamed not to end the same way. Anyway, I digress.

A couple of days ago, our team decided it would be sweet to get some Facebook loving in our newly-launched PLE in the form of a widget. Upon discovering there's a great Facebook widget in the Netvibes Ecosystem, I giddily smiled and immediately thought we'd have a fully functional widget in under 15 minutes. Oh boy, was I wrong.

Telling our local widget to directly load the Netvibes widget remotely proved to simply not work. So I downloaded the code and ran it locally. Eventually, I found an if statement that seemed to be the culprit, and, upon stripping it from my code, the Facebook Connect badge finally appeared. And then all hell broke loose.

The Netvibes Facebook widget, very sensibly I might add, uses its own API key, which I later found out is actually tied to a specific domain ( in this case). Put simply, when accessed from our domain, Facebook Connect would go down in flames. Not about to give up, I registered a new Application at Facebook and got our own API key. Yay, now Connect worked! Well, not really. Since our widget runs in an iframe, I couldn't get Connect (which opens in it's own popup window) to tell the iframe that yes, it was ok to login the user.

After trying to fix the issue for what seemed to be hours I finally gave in to the frustration and officially broke up with Facebook. While she is indeed hot, she was way too high maintenance for a simple guy like me.

I was kind of heart broken (let's face it, it wasn't that long a relationship) when I met Facebook's younger, hotter sister. If you're beginning to feel lost in the girl metaphor, I'm talking about Facebook's iPhone Web App, which was the way folks with iPhones and iTouches accessed Facebook before the awesome native app came. In fact, this iPhone Web interface was so damn cool I figured I just had to have it.

In about five minutes I had a functional widget that displayed the iPhone Facebook page inside an iframe (which itself is inside an iframe... get it? I know, I know, it's ok). This was already pretty awesome, but still not anything near my usual awesomeness level, so I quickly tried to get to second base (there it is again, the metaphor!) with this new, hotter girl who didn't seem to mind me embedding her inside weird, deprecated HTML elements.

Second base means, of course (aren't you reading? Get with the program!), designing an auto-login system. With the widget the way it was, users had to login every single time they loaded the SAPO Campus PLE, which is no good in my book. So, i quickly hacked together some Javascript (plus some PHP magic provided by José which is far too complicated for me to make fun of) to automatically fill the login fields with information the user supplied in the widget options menu and click the button. Did I mention it did all of this automagically? Oh, baby, now we were getting frisky.

Then Internet Explorer crashed our party (I guess a sock on the door knob really isn't all that universal anymore). The iPhone interface would not load at all in any version of IE (gasp!). It's okay, IE, I understand. After all, this web app is specifically tailored to work in Webkit browsers (although Firefox doesn't seem to mind), so I really didn't expect you to just be cool and hang out with the rest of us. It turns out this beauty of a mobile web app has a cute cousin who, although slightly older and way less hotter, actually works in every browser alive today (and what does that say about you, Two lines of browser sniffing code later and voilá, a working Facebook widget! IE users are served the traditional Facebook mobile interface, while other browsers get the shinier iPhone interface. Most of Facebook's funcionality is available in both versions, though.

Oh yeah, here are a few images of the new widget in action:

You should also be able to date Facebook's hot little sister very soon. I just finished testing (cause these days you just have to get tested before diving into anything serious), and our server wizard is making sure the widget goes live without a hitch. Look for it under Categories->Social in our Add Content menu!
tags: ,

Published by bruno-abrantes às 00:41

Sexta-feira, 4 de Dezembro de 2009
SAPO Campus keynote from OSL Unesco demonstration session
Rethinking Open and Social Learning and institutional supported technologies: the case of SAPO Campus
View more presentations from Carlos Santos.

Published by bruno-abrantes às 19:16

Sexta-feira, 20 de Novembro de 2009
SAPO Campus session at the UNESCO OSL Seminar
The SAPO Campus project will be presented at the VI International Seminar on Open and Social Learning, promoted by the UNESCO Chair in e-Learning UOC.

Take a look at our proposal for the demonstration session and feel free to give us some feedback :)

Rethinking Open and Social Learning and institutional supported technologies: the case of SAPO Campus (Carlos Santos, Luís Pedro)

SAPO Campus is an integrated Web 2.0 services platform based on user-generated content production and aggregation for use in Higher Education.

Upon an independent and open set of social core services (photo and video sharing, blogs, wiki, social bookmarking) lies a set of aggregation services (rss reader, portfolio, assessment, presence manager) integrated in a widget-based platform, labelled as an institutionally supported Personal Learning Environment (PLE).

Although SAPO Campus is an institutionally supported service, it’s core concept lies in the promotion of open and social learning. Several hashtags may be used to define the promotion of these broader concepts in SAPO Campus, at an institutional and personal level:

#Institutional: All users from the community are equal and have the same privileges in the platform (dilution of hierarchy); Core services are open and free for all of the community, without prior requirements or technocracies; All user-generated content is (un)protected, by default, by a non-restrictive CC license; Wide-open consumption and participation of (and in) core services means that everyone everywhere can view and talk about content, tearing down the metaphorical walls that typically surround the institution space.

#Personal: Promotion of an active and autonomous construction of a personal and meaningful learning environment (technologically supported by the institution), keeping an open and optional gateway to the integration of curricula supported by Web 2.0 technologies; Opening the PLE environment, and thus introducing dynamic, community-wide sharing and recommendation features; Automatic and user-managed mechanisms which promote an accurate understanding/accountability of the progressive management of the user’s Digital Identity.

Within a PLE/PLN conceptual model, SAPO Campus tries to balance and compromise institutional concerns and responsibilities with an open, personal and social learning experience. The vision of what SAPO Campus should be has been continuously updated through an iterative and user-driven participatory design development process, based on the feedback of the community and in the involvement of graduate students in the development team.

Published by bruno-abrantes às 00:18

Terça-feira, 20 de Outubro de 2009
SAPO Campus - Eden Seventh Open Classroom Conference
This month we presented a demo session of SAPO Campus at the Eden Seventh Open Classroom Conference in Porto, Portugal. The "SAPO Campus: a social media platform and PLE for Higher Education" session was prepared with the contribution of Josie Fraser (thanks Josie!). You may find here the submitted text.
SAPO Campus - Conference Eden
View more documents from Carlos Santos.

The first part of the session was provided by Josie and was focused on a brief overview of the Personalisation and Personal Learning Environments (PLE) topics.

The SAPO Campus presentation has started with a brief overview of the main concepts and services of this platform. For the last part we've prepared a screencast of the platform to demonstrate what is currently available for the community and a lot more functionalities that are in the final stages of development.

Take a look at the screencast and let us know what you think!

Published by bruno-abrantes às 13:58

Terça-feira, 15 de Setembro de 2009
SAPO Campus leaflet for the UA freshmen

+2000 copies are being handed out to all the freshmen in the University of Aveiro. Did you get your copy? If not, swing by the SAPO Campus homepage anyway!

Published by bruno-abrantes às 16:15

About us
Janeiro 2011








todas as tags

subscrever feeds