home
home profile hosting info news fun stuff Technical Stuff support contact us
Linux/UNIX PROGRAMMING TIPS

Ask an Expert - Visit my Virtual Office at Kasamba

Other Linux Tips

Customizing Squirrel Mail Login Page
Implementing Squirrel Mail Autocomplete Plugin under Mozilla Firefox
Go back to the Linux Programming tips page.
Go back to the Technical page.
Go back to the main page.

Customizing Squirrel Mail Login Page

For those of you who are using SquirrelMail (link opens in a new window), you might have noticed that it looks a bit well, let's just say amateurish :-) That doesn't go to say it isn't a good package! (I personally love it and I think it does a pretty good job -- hence my additions to this software.) However, as every open-source package in its early stages, there is still a lot more to be done to get it to a stage where it works beautifully and looks just as good! If you have been using it for a while chances are you have already installed some of the plugins (link opens in a new window) and configured them to your needs. Some of these plugins as you know allows certain visual customizations to SquirrelMail to make it look more pleasant to the eye.
It is one of these plugins that captured my attention, as I figured out straight away it will allow me to customize the login page! And here's how:
First of all download the Login Notes plugin (link opens in a new window). This plugin allows you to add your HTML code at the top and bottom of the login page. (Some of you might see already where this is going I guess, but for the others, I will go into details about how to use this.) Follow the plugin installation instructions (provided in the tar gzipped file) and enable the plugin.
For obvious reasons, I will use throughout this article the paths that I have used to configure and install SquirrelMail on my machine, but the same notes should apply for any other configurations as long as you replace the paths with the ones you have used in your configuration.
I am using a Debian Linux distribution, so my SquirrelMail plugins are installed under /usr/share/squirrelmail/plugins/ and the Login Notes plugin gets installed therefore under /usr/share/squirrelmail/plugins/login_notes -- your configuration might be different but the only path we are really interested in is the plugin directory. (You might also want to take a note of the images directory if you want to use images to customize your SquirrelMail login page -- in my case, they rely under /usr/share/squirrelmail/images/, but you might use a different path.) In order to avoid using the complete paths throughout this article, I will be referring to /usr/share/squirrelmail/images as the images directory and to /usr/share/squirrelmail/plugins as the plugins directory. Also, the /usr/share/squirrelmail/plugins/login_notes becomes the Login Notes directory.
So, you've installed the plugin, and enabled it in your SquirrelMail configuration (use squirrelmail-configure on Debian systems). Next, if you visit your SquirrelMail login page, you will notice a simple "Welcome" note at the top of the login page and a Tux image at the bottom of the page. You might think straight-away that even so the login page still doesn't look that much more appealing. Don't panic -- these are just the default HTML tags that the plugin creator has put in! We're going to change these to make the login page look prettier.
If you go to the Login Notes directory, you will notice that there is a config.php file and a few other files, but we're only going to use this particular file to customize the login page. Simply open it in a text editor, and you will find the following 2 variables: topText and bottomText. You don't have to be a PHP programmer to spot these, as the file itself contains very few lines: one line that declares these 2 variables as global variables and then 2 more sections/lines which assign values to these variables. It is exactly the assignment sections we are going to change.
As you can imagine, the topText variable stores the HTML code that will be inserted in the login page before the login controls; while the bottomText variable stores the HTML code that will be inserted after the login controls. So, let's start with the top one:
Typically, at the top of the page you would want to put some branding for your server, in order to remind the user the server s/he is logging into. Also, ISPs would probably want to add some self-promotion banners or some sort of "offer of the day", which the user might click on in order to get access to more services for their hostings. Also, this is probably the place to put any banners that might instruct the user that the server will be unavailable for a certain period due to hardware upgrades and such. Remember that any images you refer in this HTML code have to be present in your images directory, otherwise the browser will show them as broken links/images! In my case for instance, I have chosen to show just a simple stylish keyboard with the server name embossed on top of that, so the code looks like this:

$topText = "<center><table border='0' width='100%'>"
. "<tr><td width='100%' align='center'><img src='/images/keyboard.jpg'></td></tr>"
. "</table></center>";

(remember that the dot in PHP is used for string concatenation.)Of course, you can have anything else that takes your fancy here.
Let's now look at the bottom HTML part. Remember that this HTML code is pretty much placed in the page right before we're closing the </body> tag. Which means that by the time these tags are written onto the page most of the DOM has been built and the page has been rendered. While this might not sound as much, if you think about it though, it's a really important detail: if the DOM has been built and the page rendered it means we can execute a piece of JavaScript to modify the DOM and apply/change styling!
You would wonder why not do this via CSS in the top of the page? Well for starters, the top of the page is written after we have opened the <body> tag, and W3C says that the styling should be applied in the <head> element; however, most of browsers are tolerant to this and we can still try to apply CSS in that segment of HTML. Unfortuantelly, it will get overriden by whatever template SquirrelMail uses! :-( (well, most of it anyway, you might be lucky to have a few elements or attributes which are not overriden, but it's not worth digging for this) However, using a piece of JavaScript, we can traverse the DOM and apply inline styling on the fly which will then override any styling defined in the SquirrelMail CSS!
For instance, if you want to apply a background color to your page and change the default font, all you need is a script like this one:

$bottomText = "<script type='text/javascript'>"
. "var bd = document.getElementsByTagName( 'body' )[0];"
. "bd.style.background = 'url(\"/images/splash_screen.jpg\")';"
. "bd.style.font = 'normal 12px Verdana';"
. "</script>";

(again bear in mind that any image referrenced here should be copied in your images directory; either that or change the path /images/ to reflect where you have placed the image file). Simply, all this function does is retrieves the first <body> element (there has to be one single such element in the DOM!) and applies on-the-fly styling in terms of background and default text. You will notice now that if you reload the page, the tables used to align the login controls will still have the (default) white background. This can be changed again in the same script like this:

$bottomText = "<script type='text/javascript'>"
. "var tbls = document.getElementsByTagName( 'table' );"
. "for( var i=0; i< tbls.length; i++ ) tbls[i].style.background = 'transparent';"
. "</script>";

Or if you want to customize the Login button, you can do something like this:

$bottomText = "<script type='text/javascript'>"
. "var btns=document.getElementsByTagName('input');"
. "for( var i = 0; i < btns.length; i++ ){"
. "if( btns[i].value == 'Login' ){"
. "btns[i].style.cssText = 'font:bold 12px Tahoma;color:white;border:1px solid white;background-color:navy;';"
. "}"
. "</script>";

I guess the bottom line is that really the possibilities are endless here and you can take customizing the login page to any level you want following these guidelines -- the basic idea was to apply styling on the fly to the whole document after it was loaded, and the combination of Login Notes and JavaScript does it brilliantly!

Implementing Squirrel Mail Autocomplete Plugin under Mozilla Firefox

For the heavy SquirrelMail users, you are without a doubt using your address book a lot! (Unless you have a really good memory and can remember by heart any email address in your address book! Personally I can't! :)
And if you do, you might have contemplated using the Autocomplete Plugin for SquirrelMail (link opens in a new window), which does autocompletion of email addresses based on nicknames or first name + surname (or both!). I must admit, I love this little plugin as it saves me a lot of time and it's quite easy to use. Unfortunatelly it only works with Internet Explorer! :-( Well, this is at the time I'm writing this (2/Dec/06) -- future versions of this plugin will probably include the fix that I've submitted for Firefox, however, if you don't want to wait until the next release of the plugin, here's how you can change it to work with Firefox or any other Mozilla browser.
For obvious reasons, I will use throughout this article the paths that I have used to configure and install SquirrelMail on my machine, but the same notes should apply for any other configurations as long as you replace the paths with the ones you have used in your configuration.
I am using a Debian Linux distribution, so my SquirrelMail plugins are installed under /usr/share/squirrelmail/plugins/ and the Autcomplete plugin gets installed therefore under /usr/share/squirrelmail/plugins/autcomplete -- your configuration might be different but the only path we are really interested in is the plugin directory. In order to avoid using the complete paths throughout this article, I will be referring to /usr/share/squirrelmail/plugins as the plugins directory. Also, the /usr/share/squirrelmail/plugins/autcomplete becomes the Autocomplete directory.
So, you've installed the plugin, and enabled it in your SquirrelMail configuration (use squirrelmail-configure on Debian systems). Next, log into the system using MSIE and make sure the autcomplete plugin works fine. (Try the same with a Firefox browser and you will notice a whole lot of errors in your JavaScript Console!)
This is because the JavaScript provided with the plugin makes usage of some special features present only in Internet Explorer (so it's not cross-browser). We're going to change this JavaScript in order to support both IE (no point in breaking the compatibility with IE just for the sake of supporting Firefox only!) and Firefox as well.
To do so, go to your Autocomplete directory and look inside the folder. The file we are really interested in is functions.php. If you edit this function using a text editor, you will notice a line containing the following comment:

// Spit out javascript

Following this line there is a biiig echo call which (as the comment describes it) spits the needed JavaScript to the browser. So our task is to change this echo call such that the JavaScript produced is cross-browser. For the impatient users, scroll down to the download section and download this file, replacing the existing version (make sure you make a backup of it first!); those of you who want to rather modify their local copy, here's how:
The first JavaScript function being output is called autocomplete_find (function autocomplete_find (str) {) -- we are not going to change this file, so scroll in the code right after the closing brace for this function. Next we're going to introduce 2 new functions: selectRange and typeAhead as follows:

/*
* TheLiv at liviutudor.com : This is our selection function
*/
function selectRange( src, start, len ) {
 if( src.createTextRange ) {
  var oRange = src.createTextRange();
  oRange.moveStart( "character", start );
  oRange.moveEnd( "character", len - src.value.length );
  oRange.select();
 } else if( src.setSelectionRange ) {
  src.setSelectionRange( start, len );
 }
}

/*
* TheLiv at liviutudor.com : And this is our magincal type ahead/suggestion function that does it!
*/
function typeAhead( src, suggestion ) {
 if( src.createTextRange || src.setSelectionRange ) {
  var iLen = src.value.length;
  src.value = suggestion;
  selectRange( src, iLen, suggestion.length );
 }
}

Next, change the autocomplete_core (function autocomplete_core (src) {) function, the autocomplete_work function (function autocomplete_work (event) {) and the autocomplete_scroll function (function autocomplete_scroll(event) {) as follows:

function autocomplete_core (src) {
 // kinda support multiple addresses
 var Str = src.value;
 var StartPos = 0;
 var newSP = Str.lastIndexOf(", ");
 if (newSP >= StartPos) {
  StartPos = newSP + 2;
 }

 // do not search for nothing
 if (Str.length - StartPos <= 0)
  return;

 // If we can find something in our lookup list
 newValue = autocomplete_find(Str.substr(StartPos, Str.length));
 if (newValue == "" || newValue == Str.substr(StartPos, Str.length))
 return;

 newValue = Str.substr(0, StartPos) + newValue;
 var pos = Str.length;
 typeAhead( src, newValue );
 document.acMatch = Str;
}
function autocomplete_work (event) {
 var src = event.srcElement ? event.srcElement : event.target;
 if (! src.createTextRange && !src.setSelectionRange)
  return;

 // Ignore cursor keys, shift, alt, etc
 // look only for A-Z, 0-9, etc.
 if (event.keyCode < 48 || (event.keyCode > 57 && event.keyCode < 65) ||
 (event.keyCode > 90 && event.keyCode < 96) || event.keyCode == 108 ||
 (event.keyCode > 111 && event.keyCode < 186) ||
 (event.keyCode > 192 && event.keyCode < 219) || event.keyCode > 222)
  return;

 // If there is no change in the field, ignore
 if (src.value == src._value)
  return;
 autocomplete_core(src);
}

function autocomplete_scroll(event) {
 var src = event.srcElement ? event.srcElement : event.target;
 if (isNaN(document.acOffset))
  document.acOffset = 0;
 if (event.keyCode == 38 || event.keyCode == 40) {
  if (document.acMatch != "") {
   if (event.keyCode == 40) {
    ++document.acOffset;
   } else if (document.acOffset > 0) {
    --document.acOffset;
   }
   src.value = document.acMatch;
   autocomplete_core(src);
  } else {
   document.acOffset = 0;
  }
  event.returnValue = false;
 } else {
  document.acOffset = 0;
  document.acMatch = "";
 }
}

Next we introduce 2 new functions (getNamedEl and assignHandlers):

/*
* TheLiv at liviutudor.com: Function used to find an element by name.
*/
function getNamedEl(name) {
 var el = document.getElementsByName(name);
 if( !el ) return;
 if( el.length <= 0 ) return;
 return el[0];
}

/*
* TheLiv at liviutudor.com: Function used to assign dynamically our handlers.
* Note that we only do this if we have found our send_to text control!
*/
function assignHandlers(send_to) {
 if( !send_to ) return;
 var isIE = (navigator.appVersion.indexOf("MSIE") >= 0) || (navigator.appVersion.indexOf("Internet Explorer") >= 0);
 if( isIE ) { // Internet Explorer :-(
  send_to.onkeydown = new Function( "autocomplete_scroll(event);" );
  send_to.onkeyup = new Function( "autocomplete_work(event);" );
 } else { // The almighty Firefox :-)
  send_to.onkeydown = new Function( "event", "autocomplete_scroll(event);" );
  send_to.onkeyup = new Function( "event", "autocomplete_work(event);" );
 }
}

And finally we set up our newly introduced JavaScript handlers for the To:, Cc: and Bcc: text boxes on the Compose page:

/*
* TheLiv at liviutudor.com: Cross-browser compatibility.
* OK, so we are now doing stuff the DOM way which should work on all browsers.
*/
assignHandlers( getNamedEl("send_to") );
assignHandlers( getNamedEl("send_to_cc") );
assignHandlers( getNamedEl("send_to_bcc") );

Note that this last line of code is now followed by the closing </script> tag. Also, the original file has a few other <script> tags after this code -- you will need to remove those lines as they are no longer needed.
Having made the above changes, empty your browser cache and log back into SquirrelMail using Firefox, then go to the Compose screen, and you will notice that the autcomplete facility now works under Firefox too -- hooray!

Download the complete functions.php file to replace your local version (make sure you make a backup copy first!)
Read our download disclaimer.

Go back to the Linux Programming tips page.
Go back to the Technical page.
Go back to the main page.

Home | Profile | Hosting | Info | News | Fun Stuff | Tech | Support | Contact Us | J2ME tips and news

© Copyright liviutudor.com.
Based on a template from TemplatesBox.com

Valid CSS! Valid XHTML 1.0 Transitional Get FireFox! Powered by Debian Linux Powered by Apache Web Server No Software Patents View My profile on LinkedIn

Liviu Tudor personal web page details hobbies also loads of technical tips and fun stuff for you to browse code to download free and applications Java J2ME mobile code free mobile Java J2ME applications to download and use on your mobile phone read technical Java J2ME articles details for Liviu Tudor Lipu Liv have a look at the technical tips provided for various technical categories fun stuff funny quotes ASCII art drawing ascii bitmaps fun knowledge base technical tips programming sysadmin windows Java java knowledge base