Showing posts with label HTML. Show all posts
Showing posts with label HTML. Show all posts

Friday, November 28, 2008

Dojo Domino Applications : Performance Tips

Are you curious about how to get better performance from your dojo domino apps, here are the results of me taking a little peek.

In my last dojo app, I only used a few controls and as such performance was 'good enough'. However, it was niggling me that I should look into the dojo custom build system. I'm currently building a new audit and I need to use additional controls. It was enough of a reason for me to take a peek.

The two things that I wanted to find out were;
  • How easy is the dojo custom build system ?
  • How much difference will this make to the performance ?
I also wanted to explore some of the server side settings that would help overall performance and document the whole lot in one place.

The Dojo Build System - Creating your own custom build.

As Tim has already blogged about, using Dojo in its vanilla state means that you will have a whole bunch of seperate HTTP requests - which affects performance. In addition, the files haven't been optimized for downloading quickly. The dojo build system optimise the files by interning, removing whitespace, removing some comments, shortens variable names and rationalising the dojo layers.

I was quite surprised just how easy the build system was to set up and use. Here is what to do.

1. Download the source code files - I used the dojo-release-1.2.2-src.zip

2. You then need to create a profile. This tells the build system what bits of dojo you use. Its pretty much the dojo.requires entries. This is what my scius-profile.js looks like and you need to put this in the util\buildscripts directory.

dependencies = {
layers: [
{
name: "scius-dojo.js",

dependencies: [

"dojo.parser",

"dijit.Dialog",

"dijit.form.Button",

"dijit.form.DateTextBox",

"dijit.form.NumberTextBox",
"dijit.form.CheckBox",
"dijit.ProgressBar",

"dijit.layout.ContentPane",

"dijit.layout.StackContainer"

]
},
],


prefixes: [ [ "dijit", "../dijit" ], [ "dojox", "../dojox" ] ] }


3. You then need to run the build script, you can do this from the command line - or from a batch file in the buildscript directory. My scius-build.bat looks like this

build.bat
profile=scius

action=release

profileFile=scius-profile.js

releaseName=scius-dojo-122

optimize=shrinksafe

layerOptimize=shrinksafe

copyTests=false

localeList=en,en-us,en-au


I've chosen to use the dojo version in my release, so that I can keep track of which dojo version it contains (you can also include your own version attributes). I've also decided to use a custom list of locales rather than the default, the audit is only available to Australians, so I wanted to cover most language settings that might be used.

After about 85 seconds, the build system is finished and you then have your own custom build waiting for you in the release directory.

How to use the custom build in your page ?

Now that you have your own compacted build you'll need to use it in your web app. In your pages that use dojo, you will need to update the dojo references to the new build and also include a reference to your custom build js.

I update the head tags to include /dojo/scius-dojo.js as well as the reference to the /dojo/dojo.js. My new script links look like this;

<script type="text/javascript" src="https://website/scius-dojo-122/dojo/dojo.js" djconfig="isDebug: false, parseOnLoad: true"></script>
<script type="text/javascript" src="https://website/scius-dojo-122/dojo/scius-dojo.js"></script>


When the pages loaded, the number of http requests is reduced from 80 to 59 requests and even though the number of Kb increased, this changed the initial load time from 12.98 seconds to 4.21 seconds and the cached time from 6.98 to 2.185.

Where should I store the dojo files ?

You may have noticed that the path to the dojo files did not include a database. That's right, I've placed the files directly under the servers data directory. On my linux server that is /local/notesdata/domino/html/scius-dojo-122. Putting commonly used web files under the html directory is a well known performance technique. However, sometimes it's not always possible or desirable. For example, I'm quite happy to put my compacted versions of the standard dojo implementation there as I don't have a lot of applications or dojo variations to manage. I also have easy access. If you want out-and-out performance, that's the way to go.

Can you reduce the number of requests further ?

Maybe not for the original request but for further requests, yes you can. You need to set the expires header. If you follow the teachings of Yahoo, YSlow will give you a report on the files that don't have the expires headers set. Chris Linfoot and Chris Brandlehner have both blogged about setting the expires header for domino applications in more detail.

So exactly how do you do that ? It's a server config thing. You can specify rules for a website where domino will set the expires date. I set mine to cache any of my database theme files, all the scius dojo files and one rogue js file in the design. Just remember, don't set this as a global setting - it's a bad idea.



So now, subsequent page loads are very snappy. Down from 2.1 to under 1 second. You can see for the subsequent load only the html is needed. Everything else has been cached. 515kb to 39k and 59 requests down to 1 request.

Of course, YSlow is still give me rating of F. I still need to move CSS at the top, GZip my files, use a CDN and reduce the initial number of HTTP requests. However, now that the page loads have been reduced, I'm not going to sweat it.

;-)

Of course, the last bit is reducing the time taken to download the HTML. If your application generates this dynamically through agents, views or forms, and it's this part that takes a long time, then you might need to consider performance improvements in the Notes application too.

Summary.

Was the custom build system easy to use ?

Yes. It didn't take too long to figure out my profile. Running a batch file and copying a directory doesn't take much effort either. Heck, you could probably automate that whole thing with ANT, including copying the custom build to your server by FTP - if you really wanted to.

How much difference did this make to performance ?

Using a custom build reduced both the initial and cached load time by half, setting the expires date reduced the cached loaded page by half again.

It terms of effort versus gain, it's well worth using the dojo custom build, maybe not for development. Maybe as a last step before promoting your application into your test and production environments.

Additional Notes about the Set up:

The environment I used was my development 8.0 server, running in a bridged VM with 512mb ram. The browser is on the host machine. I've noted in the past that this is slower than the response time I get on my production servers. However, it's a good control environment.

Wednesday, August 06, 2008

SnTT : The Dojo Example NSF - available now.

The NSF containing the recipe from my four Dojo posts, is available for download and reuse - plus there is an added bonus too! If you want to see the code for;

Dojo Dialogs for Validation and Help.
Dojo Stack Container for Wizards.
Dojo : Its not just Eye Candy.
Dojo without JavaScript Enabled.

The added bonus ?

I've included all of the image resources, example framesets, outlines, forms from the post
Lotus Notes and Web UI Examples. That's right, if you have a lotus notes application that is looking a little 'long in the tooth' then you can use the application resources to create a little more up-to-date look.

How to get started ?

1 - download the zipped nsf from here.
2 - sign the agent on you server.
3 - open the register form using http://[yourserver]/[file&directory]/register?open

A little more about the examples.

The NSF is to demonstrate the Dojo samples from the articles, I tried to keep the number of places where the code is located to a minimum. So you'll only need to look in the register form and the two agents. In practice you could take the JS Header contents and place them in a separate file.

The database is version ND8 (8.0.1), but should work the same for ND7 - I haven't tried that.
The dojo version is 1.0.2, which was the latest when I started using Dojo - again, should work with later versions but I haven't tried.

What if I need more help with the example ?

You have two options,

1) - Free. I'll do my best to answer - but that will be limited to my availability and workload.
2) - Hire me. If you need more involved assistance or have a deadline.




Friday, August 01, 2008

Dojo without JavaScript Enabled

So what can you do if the users browser does not have JavaScript enabled ?

Even in todays day and age, there are still a small minority of Joe Average users that either don't have JavaScript enabled through bad set-up or overzealous security settings. Even for an intranet you might like to be able to help out the poor employee that 'some how' has managed to turn off JavaScript and give them a message that all is not well with the page that they are using.

If you are using JavaScript or an Ajax toolkit for use in building forms that collect data, and rely on scripting to perform validation, then having JS disabled can be a problem.

Like most things there are various schools of thought and regardless of whether you choose progressive enhancement or graceful degradation, you should at least have an alternative to solely relying on JS being available.

I decided that a simple graceful degradation was the most appropriate option for me. That is, if JS is disabled then show an error message and disabled the Ajax form. The solution is so simple that I wasn't sure if it would be worth a post - but hey what the heck!

The idea is to hide all the forms and buttons using css, then if JS is disabled use the <noscript> tag to display a suitable message. If JS is available, then use the Dojo goodness to replace the style of the form objects.

In Domino, I added a subform to contain the contents between the noscript tag.

<noscript><img src="design/bb70/$file/error.jpg"/>
<h1>Error : JavaScript is not enabled</h1>
<p ><strong>Message:</strong>Your browser does not have JavaScript enabled and is required for this website to function correctly.</p>
<p ><strong>Action:</strong>You can do one of the following;</p>
<ul>
<li>Enable JavaScript for this website in your browser</li>
<li>Contact your IT support department or supplier to get JavaScript enabled in your browser</li>
</ul>
<p >You will need to refresh this page once JavaScript is enabled.</p>
</noscript>


In the sylesheet add in a new class.

.noscript {
display:none;
}


In the HTML node that contains the form, update (or add) the class to be "noscript", which hides the form so that it can't be submitted. Do the same for other nodes that rely on JS.

In the onload() event of the form, add the code to change the hidden forms, to be visible using the dojo.removeClass and dojo.addClass.

dojo.removeClass("caseForm","noscript");
dojo.addClass("caseForm","case-form");
dojo.removeClass("dojopopups","noscript");


You can take the noscript idea further and provide an alternative non JS form to submit, rather than an error message. You could also use server side validation as the definitive way ensure the forms submitted have been completed correctly.

Even if you don't expect JS to be disabled, implementing a system like the one described is simple and quick enough, that its not much extra effort and might just save you a headache or two.

Monday, May 19, 2008

SnTT : Dojo. It's not just eye candy

If you thought that Dojo was all about fancy widgets and eye candy for you web apps, then you might have missed another advantage of using Dojo. In fact, it's not just Dojo. Most of the popular toolkits provide the features to make OO in JavaScript easier. I'm using Dojo, so my third post on Dojo is all about how I used OO in Dojo.

The challenge.

Let me explain the challenge. I needed to build  a few HTML forms (without resorting to the whole lotus workplace forms solution). The forms, while fairly short (the longest being 30 multiple choice questions), were complicated by the fact that a large majority needed to include the 'Other - please specify' additional to the simple radio and checkbox fields. In addition the users could also choose different paths through questions. As a user answers the questions the subsequent questions that they need to answer change.

I wanted to have the simplest user experience possible and in my opinion that means, if you can't fill in a field then it should be hidden away. In short, I wanted the field that captures the 'other' detail to be hidden until the 'other' choice is selected. Likewise, fields that are not available based on previously selected choices are also hidden. 

To make it even simpler for the user I wanted to maintain the hidden fields choices. If the user changed their mind a few times, they would not need to repeat answering questions. I would also need to remove all the hidden values before the form was submitted so that the data sent to the server represented exactly what was on screen.

It sounds like a lot of work, for something so simple as filling in a few multiple choice fields - but I don't think of it has extra programming. Think of it as an investment in reducing the number of support calls.

So why Dojo ?

Sure, you could do all of this in plain old JS. Functions for this and functions for that, but wouldn't it be nice to be able to just write some simple JavaScript. Something like...

if(fielda.mandatorySelected()==false) {
// then record or show errors
}

or 

fielda.visible(true);
fieldb.visible(false);

and maybe...

fielda.display();
fieldb.display();


Dojo.Declare.

Dojo gives you a great framework for OO using Dojo.declare for building JS classes. Its simple to implement, simple to reuse and easy to read. If you are reusing it then you're writing less lines of code. Which means less that the browser needs to download which in turn makes the pages load faster. 

How did I use Dojo Declare ?

In the Notes form, the HTML looks like the screen shot below. A div for the radio or checkbox field with a unique id 'q8' and a div for the other field with a unique id of 'q8-other'.  All pretty standard stuff.



I started by calling my class scius.AuditField. I won't reproduce all the functions as I've attached the JS file here.

dojo.declare("scius.AuditField", null, 
{ ... } );

then I added in some member variables and the constructor. The constructor allows me to initially specify the visibility, and if this field has the 'other' field.

_id:null,
_other:"other",
_hasOther : null,
_isVisible : null,
_otherIdSuffix : "-other",
_otherFieldSuffix  : "other",
constructor : function(id, isvisible, hasOther) {
this._id = id;
this._hasOther = hasOther;
this._isVisible = isvisible;
},

some setters and getters (or properties), which I can use to determine the visibility or set the visibility.

visible : function(isVisible) {
this._isVisible = isVisible;
},
isVisible : function() {
return this._isVisible;
},

The hiding and showing using CSS classes through hide() and show() which is called by the display() function. The display function also checks to see if it needs to display the 'other' field (see the source code attached).

hide : function(fieldid) {
dojo.removeClass(fieldid,'form-fields');
dojo.addClass(fieldid,'form-fields-hidden');
},
show : function(fieldid) {
dojo.removeClass(fieldid,'form-fields-hidden');
dojo.addClass(fieldid,'form-fields');
},


Next is the checking of mandatory fields function. Note I reused an existing function to determine the actual value of the radio button via the 'isRadioChecked(rbo)' line. I guess it should really be part of the class or a utility class of its own.....maybe one day it will !

mandatorySelected : function() {
var rbo= document.forms[0][this._id];
if(isRadioChecked(rbo)) {
if (this._hasOther && this.hasValue("other")) {
var oth = document.forms[0][this._id+this._otherFieldSuffix];
if (oth.value=="") {
return false;
} else {
return true;
}
} else {
return true;
}
} else {
return false;
}
},

So how did I use this class in the Form ?

As I had around 30 questions, I decided to store the questions in an array and initialize them in the Notes forms JSHeader object. Creation is fairly simple. 

The format is scius.AuditField(domid, visible, hasOther).

var qlist = new Array();
...
qlist[8] = new scius.AuditField("q8",false, false);
qlist[9] = new scius.AuditField("q9",false, true);
....

I have a checkConditionalQuestion() function that gets called from the onClick() of each field, which checks the visibility of dependent fields.


function checkConditionalQuestion(cond_question) {
...
} else if (cond_question=="7") {
if (qlist[7].hasValue("yes")) {
qlist[8].visible(true);
qlist[9].visible(false);
}else if (qlist[7].hasValue("no")) {
qlist[9].visible(true);
qlist[8].visible(false);
}
qlist[7].display();
qlist[8].display();
qlist[9].display();
} else if (cond_question=="9") {
qlist[9].display();
}

...
}

You've already seen the checking of mandatory field values and of course there is the emptying of the invisible fields. Called after validation and before the submit.

function emptyInvisible() {
for (var i = 1; i <= 30; i++) {
if (qlist[i].isVisible()==false) {
qlist[i].empty();
}
}
}

Summary.

Using the Dojo.declare to create classes is more readable than the JS prototype way. The format is closer to the way you would create Object in LotusScript and Java and so is familiar and easier to read. I only scratched the surface of what's possible and I can see areas for improvement. If you are interested, here it is in action.  

Next.

I think that a database containing the three articles as a download would be a useful starting place if you need to implement similar forms. I've already started pulling out the various components into a standalone application and I'd like to tidy up a few areas before releasing it. As soon as its ready I'll post it.  I can't say when - it all depends on the workload over the next few months. 

Wednesday, May 07, 2008

YSlow - in moderation.

An interesting post popped up on my Ajaxian feed, which linked to a post in developerworks. The post is about using Yahoos YSlow tool. YSlow analyzes a website and gives you a performance score complete with suggestions.

The posts are worth a read if you are interested in how to make your websites and web applications quicker. 

I decided to run YSlow against a web application that is in the final testing phase - just out of curiosity. I'd already checked the performance with firebug and was pretty happy with the speed, especially seeing as it used a few of the dojo libraries and was much faster that the clients website. 

I was disappointed when YSlow reported a middle of the range score. 

I then ran YSlow against a number of popular websites and web applications, all of which fared similar to mine. Finally, I decided to run YSlow against the local Yahoo website au.yahoo.com.

Guess what....



Yahoo gets an F. 

I felt much better after that.

After a bit of research, it seems as though you shouldn't take the score card too literally. There are plenty of popular websites out there that don't score highly according to YSlow.

Thursday, February 28, 2008

SnTT : Dojo Stack Container for Wizards

Here is a simple tutorial of how you can use the Dojo stack container (dijit.layout.StackContainer) to make a multi-page (dijit.layout.ContentPane) wizard. The sort of thing where you can progressively lead users through completing a form or reading content. The tutorial also shows how you can integrate your own website styling rather than having to use the three shipped themes with Dojo. You can get all the dojo goodness such as ease of use and use your own styles at the same time.

The tutorial is in flash/camtasia format and is my second attempt at camtasia recording, which include my slow typing and excessive mouse movements - but you'll get the idea.

So enjoy the Dojo Stack Container tutorial.

Wednesday, February 06, 2008

SnTT : Dojo Dialogs for validation and help

Greetings,

It looks like 2008 started of nicely judging by the post and comments on the blogsphere in January. While most of you were getting insane brain dumps of all things Lotus and quite possibly bleeding yellow, I was doing the same as Stuart. I was also getting started on a new project, toiling away in the southern hemisphere - where we have experienced one of the wettest summers in the 10 years that I been in Sydney

One of the interesting announcements was the support for Dojo in the Domino 8.5 server (although seeing it is used in quikr I was expecting it at some point). Dojo has been on my list of things to look at for a while. I know that others prefer different tool kits and I've had a look at some of them. I guess knowing that dojo will ship with Domino is some indication that it will be better supported and less gotchas. So if you have only time to learn one, then dojo is a safe bet for Domino developers.

I've wanted to use dojo but never had a reason to use Ajax. For the new project there was specific functionality that I wanted and dojo looked like it could provide it. My requirements were that firstly I wanted to have a validation dialog that shows the user, in one hit, all of the fields that failed validation and why. I also needed to check that a user name wasn't already a registered user in the NAB (Domino Directory). I also wanted this to be cross browser and I also quite liked the way that lightshow and quickr fade the background and have a modal type effect where the user can't access the rest of the page.

This post explains the recipe and how to implement this is your own applications using dojo 1.0.2. If you want to see this in action I've linked to a flash movie. (my first effort in using Camtasia - thanks Carl)

Step1. download Dojo and mix with Domino.

Firstly, download the Dojo toolkit. I used 1.0.2. Then use the ridiculously easiest WebDAV method for uploading the toolkit into a database (really it's so easy that it almost hurts). Check out the instructions on the award winning bloggers website ( BTW, congratulations to Jake). Just make sure that 'design locking' is enabled.

Secondly, (and optionally) you can the run the Dojo test harness <dojo-root>\dijit\tests\runTests.html just to check that the installation is fine and dandy.


Step2. Libraries

Next we will need to include the appropriate dojo libraries for our use. You do this in the <HEAD> tag for your form.


</script>
<script type="text/javascript" src="http://dev.bonesbeyond70.com.au/development/bonesbeyond.nsf/dojo102/dojo/dojo.js" djConfig="isDebug: true, parseOnLoad: true"></script>
<style type="text/css">
@import "http://server/development/bonesbeyond.nsf/dojo102/dojo/resources/dojo.css";
@import "http://server/development/bonesbeyond.nsf/dojo102/dijit/themes/dijit.css";
@import "http://server/development/bonesbeyond.nsf/dojo102/dijit/themes/tundra/tundra.css";
</style>
<script language="JavaScript" type="text/javascript">
<
!--
dojo.require("dijit.Dialog");
dojo.require("dijit.form.Button");
dojo.require("dojo.parser");
dojo.require("dijit.ProgressBar");
var baseurl = "http://server/development/bonesbeyond.nsf/";
// --
>
</script>


Step 3 - Presentation and Dialog place holders

You'll also need to add the dojo styling to the Body tag as a class attribute on the Domino Form

"class=\"tundra\""

Add your fields into the form as you would for a web application. The validation will be done in JavaScript so you can leave out validation formulas.

Then we'll need two define the actual dialogs html, in this case I need two. One for a progress dialog so that if the web server, the directory query or connection is slow the user knows that something is happening. The second dialog will then display the results of the validation. We do this by defining two div areas that are hidden and displayed by dojo. Take note of the dojoType and id attributes.

<!--
dialog box for the progress
-->
<div dojoType="dijit.Dialog" id="dialog1" title="Validating your registration" loadingMessage="loading" >
<div id="progress">
<center>
<p>Please wait while we check your registration details.</p>
<div dojoType="dijit.ProgressBar" style="width:300px" jsId="jsProgress" id="downloadProgress">
</center>
</div>
</div>
</div>

<!--
dialog box for the error messages
-->
<div dojoType="dijit.Dialog" id="dialog2" title="Validating your registration" loadingMessage="loading" >
<div id="errors">
<img src="design/bb70/$file/error.jpg"/>
<div id="errorContainer" >
</div>
<button dojoType="dijit.form.Button" type="submit">OK</button>
</div>
</div>

Finally we then need a button to call a JavaScript function that handles the validation.

<input type="button" class="login-button" value="Register" onclick="validateForm()">


Step 4 - Validation

The validateForm() functions, starts by showing the progress dialog (dialog1) so that immediately the users knows that something is happening. You remember that I need to check if a user is registered (or not!). In the script this only happens if the username field contains a valid value. If the user name is empty I add the mandatory error message to the stack, skip checking the NAB and then continue to validate the rest of the form.


/*
* function to check mandatory fields, field properties and username availability
*/
function validateForm() {
var un=document.forms[0].username.value;
var errors = false;
var isavailable = true;
var user_msg = "";

showDialog();

if (un=="")
{
errors = true;
validateRestForm(errors, isavailable, user_msg);
} else {
if (isValidUserName(un)) {
dojo.xhrGet({
url: baseurl+'validateUser?OpenAgent&username='+un,
handleAs: "json",
load: function(responseObject, ioArgs) {
isavailable = responseObject.user[0].isavailable;
validateRestForm(errors, isavailable, user_msg);
}
});
} else {
errors = true;
user_msg = "
<b>Username</b> contains one of the following invalid characters<br/> space / \ + & % @ # * ( ) ! $ [ ] <br/>";
validateRestForm(errors, isavailable, user_msg);
}
}
}

Step 5 - dojo.xhrGet and JSON

You might have noticed the dojo.xhrGet. In order to determine if a user is registered or not I have an agent that queries the Domino Directory ($Users) view and returns a JSON object that indicates if the user exists already. Note I had to add a 2 second delay in the agent to make the progress show.

{ "user": [{"isavailable": "false" }] } or { "user": [{"isavailable": "true" }] }

The validateRestForm() then continues to validate the form and the last steps are to open the dialog. I won't bother you with all the validation, but enclosed is the last field validation and the main flow. If there are no errors then the hideDialogs() function is called. If there are errors then the refreshDialogs() hides the progress dialog and display the error dialog (dialog2).

racgp = document.forms[0].racgpnumber.value
if (racgp == "") {
errors = true;
msg = msg + "RACGP/ACCRM "+mdt;
}
else
{
if(isValidRacgp(racgp)==false)
{
errors = true
msg=msg+"RACGP/ACCRM number is invalid
";
}
}

if (errors) {
var ob = document.getElementById("errorContainer")
ob.innerHTML = msg
refreshDialog();
}
else
{
hideDialog();
document.forms[0].submit();
}

}

Below are the functions that Hide, Show and Refresh the dialogs

/*
* show the progress dialog for slow connections and busy servers
*/
function showDialog() {
var dlg = dijit.byId('dialog1');
dijit.byId("downloadProgress").update({indeterminate: true});
dlg.show();
}

/*
* refresh the progress dialog with the error dialog
*/
function refreshDialog() {
var pg = dijit.byId('dialog1');
var dlg = dijit.byId('dialog2');
pg.hide();
dlg.show();
}

/*
* hide dialogs
*/
function hideDialog() {
var dlg = dijit.byId('dialog2');
var pg = dijit.byId('dialog1');
dlg.hide();
pg.hide();
}


Step 6 - You need HELP...(I've been told that before!)

The other requirement was that I had was to populate some context sensitive help. I used xhrGet and the dialogs to achieve this. The benefit of this approach is that users only pay the download penalty if the help is actually needed.

In terms of how this is implemented, the HTML dialogs are the same as the validations - with the exception of a help icon rather than an error icon and a different style. The help anchor link sends the unique helpid to a function that assembles it into a call.

<a href="#" onClick="getHelp('help+standard+drinks');return false">Standard Drink</a>

This time JSON is not required as the content is stored as HTML/Rich Text in the CMS (note the handleAs:text). The getHelp agent just queries the notes content document, gets the HTML and sends it to the dialog.

/*
* function to retrieve context sensitive help
* from the content, stored in the application
*/
function getHelp(helpid) {
showDialog();
dojo.xhrGet({
url: baseurl+'getHelp?OpenAgent&helpid='+helpid,
handleAs: "text",
load: function(response, ioArgs) {
var ob = document.getElementById("helpContainer")
ob.innerHTML = response
refreshDialog();
}
});
}


...and that's it.

When time permits, I'll en devour to produce a simple standalone database for download. I hope that entry will be of use to those of you that are hesitant to use dojo or ajax for your Domino web apps. I've shown that you don't need to use all of the dojo toolkit and widgits but that you can on a case-by-case basis use bits of the toolkits to enhance you web applications user experience. In fact I also used the JonDesign's Smooth Gallary 2.o (which is based on mootools) for the rotating images in the banner, so there is no reason why you can't mix and match toolkits when required.


Wednesday, November 07, 2007

SnTT: NotesSAX Parsing

Jake was asking about how to filter out malicous tags and code, I suggested using the NotesSAXParser after the HTML is converted to XHTML. I'm suprised that no one uses this as an approach, I mean fundementally XHTML is XML and the right tools for parsing this is the NotesSAXParser and NotesDOMParser. I figured that maybe there has not been a example of its use. So here is a sample class pulled right out of our home grown content management system - which uses NotesSAXParser - a little early for Show-and-Tell Thursdays...


Sunday, November 04, 2007

www.scius.com.au version 2.0

I've finished updating the company's website. The original design (below) was a bit incipid and dull, something that I managed to throw together in my spare time. We decided to spend a little more time and effort on the design and implementation for version 2.0 (on the bottom of the post).

The website runs on our home grown product - a web content management system written in Domino. This is primarily so that the non technical members of the team can update content easily without effecting the design and layout.

I wanted to target four of the most popular browsers, IE version 6 and 7, Firefox 2.0 and Safari 3. I've managed to achieve this, XHTML and CSS W3C validation by following some simple rules.


CSS

1. for height use both the HEIGHT and MIN-HEIGHT
2. for width use both WIDTH and MIN-WIDTH
3. for BORDERS, MARGIN always use the LEFT, RIGHT, TOP and BOTTOM qualifiers rather than the MARGIN:5px 10px 5px 10px even though its CSS 1 valid

4. use MARGIN-LEFT:AUTO rather than TEXT-ALIGN:LEFT/RIGHT/CENTER

XHTML Transitional

1. only have one occurance of id="identifier" for elements (if you need more than one then it's a class="" approach)
2. close all tags with either a forward slash of closing tag i.e. <img src="" alt="" /> or </img>
3 ensure that each IMG tag has an ALT attribute

4 keep all tags lowercase (even through I've used uppercase for clarity in this post...ok)
5 avoid nesting elements unless its in a div. i.e. don't nest a <h1> in a <p>

There you go, one css file and a simple design which displays the same for all of my target browsers and validates against XHTML and CSS.