Showing posts with label Interface development. Show all posts
Showing posts with label Interface development. Show all posts

16 February 2009

Changing style regarding changing style

I was having a conversation with the esteemed Mr Alexander today about changing CSS styles based on whether JavaScript is enabled in the users browser.

This problem had consumed some of my thoughts in the past and eventually I chose to use the technique I termed progressive degradation, something I have blogged about in a previous post.

Progressive degradation involves writing your CSS with the assumption that JavaScript is enabled. You then include an additional style sheet in this way:

<noscript>

    <link rel="stylesheet" href="noscript.css" type="text/css" media="screen" />

</noscript>



This has generally worked well for me with the one caveat that this is invalid HTML. This has concerned me a little. The argument which both myself and Mr Alexander have used is that this is easily the simplest way to adjust styles depending on whether JavaScript is enabled or not.

I prefer to write my CSS with the assumption that the best possible experience is available and then include CSS to enhance the experience for those users with a less capable user agent as required.

Mr Alexander proposed another potentially neat solution:

<link rel="stylesheet" href="noscript.css" type="text/css" media="screen" id="noScriptCSS" />

<script type="text/javascript">

    var noScriptCSS = document.getElementById("noScriptCSS");

    noScriptCSS.parentNode.removeChild(noScriptCSS);

</script>



In this example, the noscript CSS file is always in the document and it is then removed using JavaScript immediately. I haven't tested this, but my first thought was that I would need to investigate if there would be a flicker on the screen as the page is reflowed, affecting the rendering performance of the page. My second thought is that this technique involves an additional HTTP request for all users not only those who need it.

There is another well known technique which involves writing your CSS assuming that JavaScript is not available and then including a script enabled CSS file using JavaScript as the page is being rendered. I am not a fan of this technique as I prefer not to write my CSS in this way.

There are a variety of other techniques as well such as changing a class on the BODY tag using JavaScript and cascading your selectors from that. If using this technique I would always have a noscript class on the BODY and then remove that (again, it fits better with the way I like to write my CSS).

This issue often raises its head and frankly I am now not fully satisfied with any of these techniques. So what do you think? What is the best way of handling this issue?

30 October 2008

The Quiet

Its been pretty quiet on this blog for the last 6 weeks or so. I have been very busy working on an interesting, fairly complex and fairly large JavaScript application during the day and then recovering from it at night! I also had the pleasure of a lovely week away in this period of quiet.

I have also recently got my hands on a rather sexy new phone - an HTC Touch Diamond - and have spent a lot of time playing with that. Its a Windows Mobile PocketPC and its been an interesting experience, particularly Opera 9.5 Mobile which is the default browser.

Browsing on a handheld device has been a new experience for me. My phone comes with Pocket IE installed as well, but that is rather archaic. I have done all I can to avoid using it.

Opera Mobile however is a fantastic browser. Its fairly fast, pretty standards compliant and renders most pages rather well. It has also given me a useful insight into a different type of user agent for browsing the web. Its quite a different experience and its easy to see which sites are well designed and which are not.

I have taken away a couple of important lessons from my experience. Firstly, clear interface design is very important on this type of device. The browser can zoom into pages but when a page loads, it is zoomed out and most text cannot be read clearly at all. However, a site with good design is very usable as I can zoom in on just the right area. Clearly defined navigation really helps with browsing on a mobile device.

The second lesson I have learnt is that the easiest sites to use employ a liquid or semi-liquid layout. My phone has a resolution of 480x640 and if a site can flow its content to fit into either of those widths, that helps greatly. If I were designing a website today, I would definitely ensure it works in a browser width of 640 pixels!

The final lesson I have taken with me thus far is that the size of elements on screen really matters. I use my finger to navigate a website and having links tightly packed together with a small font size makes life very difficult. Having small form fields or form fields with a small font size and another link right next to or just underneath the form field can make it difficult to select the element I want to interact with. Finally, having heavily styled buttons, especially image buttons makes submitting a form harder than it needs to be, particularly if pressing enter on the keyboard does not work.

For me, the most noteworthy new aspect of interface development that I will carry with me is the importance of keyboard interaction with a form - never ever stop a form being submitted with the enter key!

There is much more to say about this phone and browsing the web using Opera, but at least for now, the quiet is no more!

21 August 2008

The future of JavaScript

For those who have not heard, ECMAScript 4 is no more. That also means that JavaScript 2 is currently at best paused. Some will mourn this as a great loss. I am not one of those.

JavaScript 2 had some very interesting ideas in it, but I am far from convinced that it was the future. I firmly believe that JavaScript 1.x has a long long way to run yet.

It is not often that I will link to an article on Slashdot, but this one piqued my interest.

The future of JavaScript is very much tied up in the present and future of browsers. Much of what I have to say here is also true about future versions of CSS.

The problems we as web professionals face today is not due to a shortcoming of JavaScript or CSS or HTML. They are due to shortcomings of the browsers. Until browsers support the standards, there may as well not be standards.

So we have options. We can introduce new ideas and new technologies which will only be supported by a sub-set of users for a fairly long period and will then fall into a category of technologies we are reticent to use due to the need to support older browsers.

Or, we can wait for the browsers to catch up with the standards so that we can exploit them to the full, with guaranteed compatibility.

Well, I dont fancy waiting something like 4 or 5 or even 6 years for browsers to catch up with the standards, I want to do cool, new and interesting things now. So, we are left with the former of the 2 options I present above.

Of course, the thing which allows us to push forward and use the new technologies of CSS and JavaScript which are being introduced and still provide a good level of cross browser support is JavaScript! Look at how the innovative use of JavaScript, largely by library authors, has driven the W3C and browser vendors to introduce new native features to the browsers. This is only of benefit to us.

I firmly believe that changing the core nature of JavaScript now would undermine a lot of the good work of the last few years and it would also be to deny the true power of JavaScript as it stands today. Yes, there is a barrier to people wanting to learn JavaScript - it can be complex, it is difficult to master - but this also is a good thing. Ultimately the standard of JavaScript development will improve and we don't need a new version of the language to make this happen.

JavaScript is an amazingly flexible language and finding new ways of bending it to our will is going to define the next set of standards, the next set of tools that we want to see, and it is the next set of standards that are far more likely to be adhered to than the current generation.

We must not stifle innovation, we must encourage it. Keeping a massive level of embedded knowledge whilst JavaScript is still at its infancy of true professionalism is the right way forward. Maintaining the core of the language as it stands moving forward must be a good thing. Yes, lets play with other languages in the browser, lets even use and support them, but where JavaScript is concerned, my message is clear - don't go changing!

24 June 2008

Firefox 3

Well, it has been a good few days now that I have been running the release version of Firefox 3 and I thought I would share some of my experiences - both positive and negative.

First off, I like the interface updates, the "awesome bar" and the speed improvements. I have been very impressed with its stability as well.

However, I have found difficulty using a number of plugins and in particular Firebug. This is simply unacceptable. I have tried using a number of different versions of Firebug but to no avail - all were slow and often crashed Firefox.

Whilst this has proven to be just about acceptable for working at home on things such as JSquared, at work it has proven utterly useless and I have downgraded to Firefox 2 and Firebug 1.05. The improvement in performance of Firebug was immense.

How are you finding Firefox 3 and Firebug? Have you found a combination that works for you?

9 June 2008

My JavaScript patterns

Since posting about my JavaScript "rules", I have had a number of requests to expand on the patterns I use for developing my JavaScript objects.

I use two main patterns, a singleton pattern and a constructor pattern. A singleton is an object which will have only one instance within an application. A constructor is a function which when invoked with the new keyword will create an object based on its definition. These objects are known as instances.

Constructor Pattern
A constructor pattern is something which JavaScript has native support for. Douglas Crockford has previously talked about this pattern at length.

function EventHandler() {

    //constructor

 

    //private members

    var registeredEvents = [];

 

    //public methods

    this.registerHandler = function(func) {

        if (typeof func === "function") {

            registeredEvents.push(func);

        }

    }

    this.fire = function() {

        for (var i = registeredEvents.length-1; i >= 0; i--) {

            registeredEvents[i]();

        }

    }

}



A constructor is simply a function which defines various members and contains its own variables and indeed other functions. You can also define constructor logic with a series of statements which do not declare methods or private variables or functions.

Its a fairly simple pattern and it is just as easy to use. To declare a new instance of this constructor, the code is simply this:

var myEventHandler = new eventHandler();



Singleton Pattern
My aim with a singleton is to have a highly readable object formation pattern which allows for private members and the exposure of a public interface. The syntax also must ensure that only one instance of the singleton can exist though of course there is nothing to stop the object being inherited from.

I also wanted the pattern to look similar to the constructor pattern above. This should make it easier to code and maintain.

For this example, I am using a simplified version of an object in JSquared. JSquared makes extensive use of this pattern as much of the library is built up from singleton objects. The object I am using here is the cookies object. For details on how to use this within an application of your own, look out for a post on the JSquared blog.

var cookies = new (function() {

    //private members

    var cookies = {};

 

    //constructor

    //get the current set of cookies

    var currentCookies = document.cookie.split(";");

    var cookie;

    //loop through current cookies and add their values to the cookies collection

    for (var i = currentCookies.length - 1; i >= 0; i--) {

        cookie = currentCookies[i].split("=");

        if (cookie.length >= 2) {

            cookies[cookie[0]] = cookie[1];

        }

    }

 

    //public methods

    this.set = function(name, value, expiration) {

        document.cookie = name + "=" + value + ";expires=" + expiration + ";path=/";

        cookies[name] = value;

    }

    this.get = function(name) {

        return cookies[name];

    }

    this.delete = function(name) {

        this.set(name, "", -1);

        delete cookies[name];

    }

});



You will I am sure notice how similar this singleton pattern is to the constructor pattern above. The major difference is that the singleton pattern created the constructor as an anonymous function and then invoked an instance of that anonymous function immediately.

Just like when creating a new instance of a constructor, an object defined as per the constructor function will automatically be returned from the invocation. So in the example above, the variable cookies will contain the singleton.

The syntax may look odd, but it has proven itself very resilient and extremely effective. It allows for private members and functions, the public methods have access to those private members. It contains constructor logic and of course parameters can be passed in to the constructor just like they could be in the constructor pattern shown above.

As I seem to often say, its as simple as that!

27 May 2008

My JavaScript "rules"

In my day to day life, I see a lot of JavaScript code. I see a lot of code written by others and a lot of code which I have written in the past. As I look back over my own code and my coding style over the last 2 years or so, it is easy to see how far I have come and how much better my code is now.

None of this is meant to suggest that it cannot be improved. Nor am I saying that it is even that good! But, I thought it might be useful to talk about some of the ideas I have employed. These are my JavaScript "rules". I try to apply them in everything that I do:

1. Be unobtrusive
This is an absolutely imperative and key rule. Unobtrusive JavaScript code is easier to read, easier to write and is encapsulated within a JavaScript layer in your application. Writing unobtrusive code means having no JavaScript in the markup of your documents. Make use of browser events (onLoad, DOMContentLoaded etc) to apply the JavaScript enhancements to your pages. Use ID's and if necessary classes to pick DOM nodes from the document to work with.

2. Name your spaces
Namespaces make for much friendlier JavaScript. If nothing else, a namespace will stop you polluting the global scope of the document. I always have one root namespace for an application and then other namespaces off that to define the functionally different regions of your application. Always group similar functionality. If for example you have a bunch of objects which are used for handling forms and form validation, group them all under a common namespace. Creating a namespace is as easy as creating an object. Here is an example of creating a root namespace and 2 sub-namespaces:

var Nortools = {};

Nortools.Login = {};

Nortools.Forms = {};



3. Cry over spilt milk
I always encapsulate functionality within relevant objects and namespaces. Dont let that functionality spill out of the object or the namespace. Use private members in objects to hide the secrets of an object and strengthen your code. This will prevent your application from being changed or interfered with in any way by other JavaScripts on the page. I use self executing functions to create completely closed and hidden objects, neatly encapsulating my code. It is even possible to have private members on the prototype of a constructor using this technique:

var myConstructor = function() {};

myConstructor.prototype = new (function() {

    var myPrivateMember = "some value";

    this.getPrivateMemeber = function() {

        return myPrivateMember;

    }

});


This code may look odd, but the prototype of myConstructor is now a self creating singleton object which cannot be forced to give up its secrets. I use this technique for creating all singleton objects - its encapsulated!

4. Separate
I always separate the various types of code in my applications strictly. If I am dealing with data, I create a data layer to manage all that logic with as few public methods as possible. If I have business rules, the same applies. All presentation logic should also be self contained and independent of the data and the business rules which translate that data into objects which can then be displayed.

5. I object
Use objects and use them extensively. I never store any value within global scope and with everything in a well organised object model, you always know where things are. Use the singleton pattern above (or the many others which are just as good) to create singleton objects - an object that only has one instance.

6. JSON
JSON is extremely useful and powerful. I always use JSON for storing and transferring data in my applications. I also make extensive use of object notation for providing options to my objects. Passing in a JSON object to a constructor can be much easier than handling optional parameters. This is one method for handling optional parameters:

var myConstructor = function(param1, param2, param3) {

    param1 = param1 || "defaultValue";

    param2 = param2 || "defaultValue";

    param3 = param3 || "defaultValue";

};

var myInstance = new myConstructor( "value", null, "value" );


With this method, on creating an instance, I have to know which parameter is which and what order they are in. Its also slightly clumsy looking.

My preferred method is:

var myConstructor = function(options) {

    var param1 = options.param1 || "defaultValue";

    var param2 = options.param2 || "defaultValue";

    var param3 = options.param3 || "defaultValue";

};

var myInstance = new myConstructor( {

    param2: "value",

    param3: "value"

} );


Much neater and I find it much easier to understand and read.

7. Be a detective
I always try to code defensively. I dont want errors to even be possible in my code. To this end, I always want to detect whether the operation I am about to perform is possible. Sometimes this means checking my own objects for a feature, sometimes a built in object. This is much more effective than user agent sniffing for browser features. Not only do I not have to know what each specific browser supports, but I also do not have to keep changing my code each time there is a new version of a browser. It makes my code future proof!

if (document.getElementById) { //check the browser supports getElementById

    var myElement = document.getElementById("myElement");

    if (myElement) { //check an element was found

        //perform some action

    }

}



8. Lets go native
Always use native functionality when its there. Its the fastest method. If you want to have a getElementsByClassName function in your application, check if the browser already has it built in and use that method if it is there. Replacing it will only make your application slower.

9. Delegation's what you need
Events are very important when building web applications. But adding event handlers to lots of nodes can be bad for performance and lead to management overheads. If for instance you have a list of items and clicking on an item in the list performs an action, consider adding the click event to the parent of the list items and using a delegation pattern to handle the event. For a more detailed explanation see this excellent article.

10. Get organised
I always try to organise my code well. It is vital during a build phase of a project to be well organised. I only ever put one object or constructor in a JavaScript file and I name the file accordingly. If the full path (taking into account namespaces etc) to my object is MyApplication.ApplicationSection.ObjectName, then I will name the file MyApplication.ApplicationSection.ObjectName.js. In a large application, my folder structure will represent the namespace hierarchy as well.

Choose a coding style for your application and stick to it. I have my own coding style with naming conventions etc, and I always stick to it. It makes the code more consistent and easier to read and understand.

Comment code wherever it is needed to help understand why the code does what it does. Dont comment code when the comments will not add to the understanding of the code.

11. Dont panic
Writing JavaScript is hard. Writing web applications is harder still. Dont panic. Help is at hand. Use a library.

12 December 2007

What is Interface Development

This is a very very good question. I often get asked what Interface Development really is (other than the obvious answer). Many people will know it as front end development. But its easier to answer the question in the form of a skill set.

I consider the core skills for a Web Interface Developer (or ID) to be:
HTML
CSS
JavaScript
User Agents
Accessibility

So what do these terms mean?

HTML
Fairly self-explanatory really. But an ID should know about HTML and XHTML in all its different forms. That is every widely supported doctype around.

CSS
Also self-explanatory. Everything up to CSS 2.1 is useful at this time.

JavaScript
Another one of those obvious ones. This is not to say that all IDs should be expert in JavaScript, but all IDs should have a good working knowledge

User Agents
This is less obvious. But I think an ID should know all about the most common browsers in use in the market today. How we define common is perhaps not a subject for this post, but once you have decided what is common, an ID should be able to write code to be compatible for all of them and should be able to understand their foibles and quirks

Accessibility
Well here is something that is a bit more contentious! IDs should ultimately be versed in best practice. Accessibility is a large subject and deserves many posts all of its own, but suffice to say that knowing what the WCAG say is not enough. Understanding best practice and why some approaches are good and others bad is far more useful.


So this is what an ID is. Its what we preach and what we practice and these are the topics that this blog will discuss. Enjoy.