They are everywhere: protopage, pageflakes, netvibes et al are free, easy to use -as long as you have a powerful browser- and moderatly eye-pleasing.
SO?
A couple months ago, I wondered how long it would take me to build my own
‘WebTop’ (You can play with it here). The
challenge would be to get it to a satisfactory state over a week-end.
Of course, I decided to use existing open-source code for the applications’
primary needs.
These needs being :
1. Users should be able to play with the application without being logged in
2. They need to know that if they do log in, the state of their webtop will
be memorized for their next session
3. Webtops are windows-based; webtops’ dimensions are virtually unlimited and
windows can be laid out anywhere in that immense space.
4. Also, windows may need to be iconified and when they are, displaying a
relevant icon would provide great visual clues.
I decided to use these four libraries:
- Sebastien Gruhier’s Prototype Window
- Mohamed Ahmed’s Users Login System
- Michal Migursky and Matt Knapp’s Json class
- InputParser.php, which I extracted from my very own nextBBS’ source tree
Oh, and the wonderfully simplistic red icons are the creation of P.J. Onori (thanks Sam!).
Of course, you could obviously use any piece of technology you like; I simply picked these four because they allowed me to hit the ground running.
HACKING AWAY
The one piece I heavily added to is Prototype Window.
For instance, I added a drop-down contextual menu to windows, activated when
clicking on the new ‘menu’ button, next to the ‘close’, ’expand’ and ‘iconify’
buttons.
These three menu items let the user:
1. Change the background color of the iconified version of the window
Let’s say…purple
Well…it is purple
2. Change the window’s overall theme
3. Reload the content of the window
To create these menus, I went with my usual method of creating HTML elements that I position and display on demand, instead of re-creating them every time.
![](/images/day.gif); Icon Color
![](/images/day.gif) Window Theme
![](/images/loop.gif) Reset
I had to further modify the code of Prototype Window because it did not offer
anything for iconified windows.
What I am doing is hide the actual window, create a square window that is a
representation of the hidden one and slap a relevant icon in the middle of it
-if I manage to retrieve one-.
About this icon : I simply query the server hosting the iconified
application for its default favicon and download it for caching purpose - see
below.
To implement these features, I only added a few hooks to window.js, leaving Sebastien’s code relatively untouched, and piling up my dirty code in cfr.js instead.
BEHAVIOURS
-
I had to add a hook to catch the fact that a user is leaving the current webpage, asking them whether they really wish to do this and canceling the event if they do not.
This was easily implemented using Javascript’s onbeforeunload(), which happens to work in all the browsers I tested.$obfulstr = “onbeforeunload=“return ‘For some reason, you are about to leave this page:nIt could be your decision or an application, such as Yahoo, trying to force its way out.nMAKE SURE THAT YOU SAVED YOUR DESKTOP!’;””;
-
The login window itself is simply Mohame’s login code embedded within an iframe, which in turn I turned into a CSS window.
function cfrNewLogin()
{
_loginwin = _doOpenWindow('Login', ROOTPATH+'login/', false, 340, 240);
}
AJAX
As you can imagine, Ajax is used fairly heavily. Here is how: all frontend
queries are channeled through a method in cfr.js, called _talkToMe()
This method uses Prototype’s Ajax implementation -but you could use any other
implenentation here- to contact the backend.
case 'minimize':
var iconcolor;
if(win && win.element.getAttribute('iconcolor'))
iconcolor = win.element.getAttribute('iconcolor');
else
iconcolor = '-';
var myAjax = new Ajax.Request(
'backend/index.php',
{
method: 'get',
parameters:
'action=minimize&id='+id+'&title='+prepare(message)+'&iconcolor='+prepare(iconcolor)+'&url='+prepare(url),
onComplete: getMinimizeReply
});
break;
The backend class BE, defined in index.php, extends BackEnd which itself
implements low-level communications using Json and/or XML.
The backend has knowledge of the code of the various widgets requested by the
frontend and has the ability to retrieve favicons from other websites. The
latter is done through the very straightforward use of fopen() and
file_get_contents().
// Build path to favicon.ico
preg_match("/^(http://)?([^/]+)/i", $url, $matches);
$prepath = $matches[1].$matches[2];
$path = $prepath.'/favicon.ico';
// Does this guy exist?
$bFound = false;
$f = @fopen($path, 'r');
if($f)
{
// /favicon.ico
@fclose($f);
$contents .= @file_get_contents($path);
axlog("FOUND CONTENTS=".strlen($contents));
if(strlen($contents)>0)
$bFound = true;
}
if(!$bFound)
{
// Get page contents
@fclose($f);
$contents .= @file_get_contents($url);
$c = preg_match("//i", $contents, $matches);
if($c > 0)
{
$s = &$matches[0];
$c = preg_match("/href=(.+?)(['">])/i", $s, $matches);
if($c > 0 )
{
$s = str_replace(array("'", """), array('', ''), $matches[1]);
// Build new URL
if(strpos($s, '://')===false)
{
if($s[0]=='/')
$path = $prepath . $s;
/** @todo 'else : relative path' */
axlog("Found relative favicon @ $path");
}
else
{
axlog("Found absolute favicon @ $path");
$path = $s;
}
}
else
$path = 'themes/window.gif';
}
else
$path = 'themes/window.gif';
}
DATABASE
Since we are using Mohamed’s login script, database connectivity comes for
free.
Note that his script uses one table: maaking_users
We need to add our own two tables:
maaking_session - each entry in this table will be a user window:
CREATE TABLE `maaking_session` (
`id` int(11) NOT NULL auto_increment,
`userid` int(11) NOT NULL default '0',
`url` text,
`useTop` tinyint(1) default NULL,
`useLeft` tinyint(1) default NULL,
`top` int(10) default NULL,
`bottom` int(10) default NULL,
`left` int(10) default NULL,
`right` int(10) default NULL,
`title` text,
`width` int(10) default NULL,
`height` int(10) default NULL,
`hidden` tinyint(1) default NULL,
`iconcolor` varchar(10) default NULL,
`contents` text,
`usertheme` varchar(16) default '',
PRIMARY KEY (`id`),
KEY `userid` (`userid`)
);
and maaking_favicons :
CREATE TABLE `maaking_favicons` (
`id` int(11) NOT NULL auto_increment,
`url` varchar(255) NOT NULL default '',
`icon` text,
PRIMARY KEY (`id`),
KEY `url` (`url`)
);
This is it for now. Download the zip package, play with it, let me know what you think or if you have any questions!
Comments powered by Talkyard.