Spot the web RSS 2.0
# Wednesday, March 05, 2008

When structuring your markup there are many paths you can choose to reach the same goal. Most of the times it's a matter of preferences which element you wish to apply on a specific spot. I have my own personal preferences. One of them is preferring BUTTON over INPUT type="submit" elements. Why? Well W3C says it "Buttons created with the BUTTON element function just like buttons created with the INPUT element, but they offer richer rendering possibilities".

It's the rendering that I am after. You can easily apply image replacement techniques to buttons and make your form look good. Most interesting feature is that BUTTON element may have content. I will use that possibility in this tutorial.

So, the goal is to create and style button that can handle variable length so there is no need for later interventions. We'll treat button element as a container and add some markup.

Take a look at the demo | Download zip file

HTML

Here it is:

<button><span><em>Button text</em></span></button>

This is a valid code, and it gives us a lot to work with.

Please note, I am using two child elements instead of only one because I couldn't get rid of some paddings that button preserved. If anyone succeeds in styling with one child element only, please let me know :)

Concept

This concept is probably familiar to you from various navigation tab styling techniques. We have one long background image:

image

This one is 550px wide. I believe that is more than sufficient for buttons :)
So, we apply this image as a background image of a top element (in this case SPAN), place it to top left and add some left padding. Nested element (in this case EM) have the same background image but placed to top right and with right padding. As the content text grows so will the button.

image

Height of the button is fixed in my example but you can use similar technique and some more markup and place the same background image to all 4 corners.
To make sure that the text is vertically centered I use line-height property.

CSS

button{
	border:none;
	background:none;
	padding:0;
	margin:0;
	width:auto;
	overflow:visible;					
	text-align:center;	
	white-space:nowrap;	
	height:40px;
	line-height:38px;			
	}

Resetting button's default styling.

button span, button em{
	display:block;
	height:40px;
	line-height:38px;			
	margin:0;
	color:#954b05;
	}

Setting child elements. Note that value of height property is different than line-height. That's because I have 2px shadow at the bottom. Line-height vertically centers the text within the button graphic, shadow is excluded.

button span{
	padding-left:20px;
	background:url(bg_button.gif) no-repeat 0 0;
	}	
button em{
	font-style:normal;
	padding-right:20px;
	background:url(bg_button.gif) no-repeat 100% 0;
	}

Setting backgrounds and paddings for both child elements.

As I mentioned earlier, it would be more elegant if I could use BUTTON and SPAN only, but I couldn' t get rid of BUTTON paddings.

Wednesday, March 05, 2008 10:14:42 AM (Jerusalem Standard Time, UTC+02:00)  #    Comments [0] - Trackback
CSS | Design | Web Design
# Tuesday, March 04, 2008
  1. If your site's content can be turned into a widget somehow, such as with an RSS feed or just a mini version of your site (ex. the puzzles widget on this site) - do so - and then submit your widget to all the major widget-oriented websites such as iGoogle, Netvibes, Pageflakes, Facebook, Live, Widgetbox and Widgipedia - it will help drive a LOT of traffic to your site - think of it as a great form of content syndication.
  2. Do NOT: have a public link exchange on your site, sign your site up on link farms or on SEO directories - this will lower your rankings on Google a lot - take it from experience.
  3. Though CSS can replicate the styling brought from these tags, search bots love them - so they're worth using for SEO purposes: <h1> - <h5>, <strong>, <em>.
  4. Make sure your site supports the big four: Internet Explorer 6+, Firefox 1.5+, Opera, and Safari.
  5. Make sure your site fits down to a 1024 x 768 monitor resolution.
  6. Use the color wheel when creating layout themes. Try to keep your site layout down to three distinct colors.
  7. Create a website shell (a.k.a. template), so that if you decide to make another website down the road, it will be a lot quicker to make because you'll already have a framework set up.
  8. Create a to-do list for your site so you don't forget anything as it grows bigger - I like to jot sudden ideas I get down on it too.
  9. A successful website provides a service to its users - such as teaching (Wikipedia) and/or social networking (Facebook).
  10. Whenever possible, use onmousedown instead of onclick - it's ~100ms faster.
  11. Use file compression for your javascript and web page files so that your pages load faster - also if you can, put the script include tags at the bottom of your page - this will give the illusion that your site loads faster because browsers usually comb through an entire js file before continuing on with loading the rest of your page.
  12. If you have a rails site, I suggest checking out Mongrel and Monit for Mongrel (or God) if you are currently using Apache with FastCGI. You may notice your app is a lot faster with Mongrel clustering than on FastCGI.
  13. This one is more of a for-your-health point, but our eyes naturally look slightly downwards - so if your computer screen is straight in front of you at eye level or higher, trying moving it down to neck or chest level - you may notice that your eyes feel more relaxed -- (I learned this last point from an eye doctor and feel that it helps me.)
Tuesday, March 04, 2008 11:30:24 AM (Jerusalem Standard Time, UTC+02:00)  #    Comments [0] - Trackback
Programming | Web Design
# Monday, March 03, 2008

Object oriented programming has been around for quite some time and was made popular by C++ back in the day. Nowadays, even web scripting languages support the paradigm. JavaScript does not have true OO but allows you to use the design pattern in your code. Today, we will dive into using object oriented programming with the popular JavaScript framework Prototype.

Prototype makes it easy to declare your own objects by using the "Class.create()" method:

  1. var sampleObject = Class.create();  


Once you do that you can start writing your class specific methods and properties inside the "prototype" object:

  1. sampleObject.prototype = {   
  2. }  


To declare private properties you simply specify the name of the property followed by a colon and the value:

  1. sampleObject.prototype = {   
  2.     linkIDs: ['mainPageLink''cdmScreenLink''adminLink''helpLink'],   
  3.     statusMessage: '',   
  4.     currentLinkID: 'myLink'  
  5. }  


The important thing to remember is that each property needs to be separated from the next by a comma. As shown above, property values can be a array, a number, a string but cannot be empty value. While:

  1. currentLinkID: 'myLink',  


is valid while


is not.

Declaring your own functions is not any different. Before we look into functions however, there is one function that requires special attention: the "initialize" function:

  1. initialize: function() {   
  2. }  


The initialize function is what JavaScript calls automatically when you create an instance of your object. If you are familiar with OO, this function is the constructor of your object. Any setup and initial requirements for using your object should be done in here.

So to get back to regular functions, they are declared in the format functionName: function() {} as in:

  1. doSomething: function() {   
  2. }  


So far your object should like like this:

  1. var sampleObject = Class.create();   
  2. sampleObject.prototype = {   
  3.     linkIDs: ['mainPageLink''cdmScreenLink''adminLink''helpLink'],   
  4.     statusMessage: '',   
  5.     currentLinkID: 'myLink',   
  6.     initialize: function() {   
  7.     },   
  8.     doSomething: function() {   
  9.     }   
  10. }  


Big deal right, including that in your html page and/or a separate JavaScript file does not do anything for you. The next step in making it of any use is to actually create an instance of the object like so:

  1. var sampleObjectInstance = new sampleObject();  


Creating an instance of the object automatically calls all your code inside the "initialize" function. Here, a good practice is to wrap the creation of your object inside the windows load or dom:loaded (Prototype v1.6) event like:

  1. Event.observe(window, 'load'function() {   
  2.     var sampleObjectInstance = new sampleObject();   
  3. });  


Or

  1. document.observe("dom:loaded"function() {   
  2.     var sampleObjectInstance = new sampleObject();   
  3. });  


To expand on using properties inside your object, whenever you want to access a property such as "currentLinkID", you have to prefix it with "this" as in:

  1. this.statusMessage = 'Who Am I?';  


That is because inside your object's function, without "this", the code does not know about the property. The same applies to using function so you cannot simply called the "doSomething" function with:


but instead if you have to use:

  1. this.doSomething();  

 


This can get a little more complicated when it comes to using event listeners inside your code. Let me elaborate. To tie an event observer that will call the "doSomething" function when a users clicks the link with ID 'myLink', you would usually do:

  1. $(this.currentLinkID).observe('click'this.doSomething);  


While that will work, if you try to access any class properties (such as "statusMessage") inside the "doSomething" function, you will get "undefined" for their values. That is because, again as pointed out above, the function is not aware that it belongs to an object so it does not know that the object has properties. The remedy is simple, simply append .bind(this) to the function when it is tied to the event as in:

  1. $(this.currentLinkID).observe('click'this.doSomething.bind(this));  


A similar approach needs to be applied when using the prototype built-in Ajax object. If you want to tie your custom functions to the "onFailure", "onComplete" or "onSuccess" functions, you need to use the "bindAsEventListener" function:

  1. onSuccess: this.showContent.bindAsEventListener(this)  


"Bind" also needs to be used whenever you employ the "each" construct as described in Gotcha with Prototype.Bind and Arrays

Below is the full class:

  1. var sampleObject = Class.create();   
  2. sampleObject.prototype = {   
  3.     linkIDs: ['mainPageLink''cdmScreenLink''adminLink''helpLink'],   
  4.     statusMessage: '',   
  5.     currentLinkID: 'myLink',   
  6.     initialize: function() {   
  7.         this.statusMessage = 'Who Am I?';   
  8.   
  9.         $(this.currentLinkID).observe('click'this.doSomething.bind(this));   
  10.     },   
  11.     doSomething: function() {   
  12.         alert(this.statusMessage);   
  13.   
  14.         new Ajax.Request(   
  15.             $(this.currentLinkID).href,   
  16.             {   
  17.             method: 'get',   
  18.             onSuccess: this.processContent.bindAsEventListener(this),   
  19.             evalScripts: true  
  20.             }   
  21.         );   
  22.     },   
  23.     processContent: function(request) {   
  24.     }   
  25. }   
  26.   
  27. Event.observe(window, 'load'function() {   
  28.     var sampleObjectInstance = new sampleObject();   
  29. });  


To call the functions of the sampleObject from outside you would simply do:

  1. sampleObjectInstance.doSomething();  

While you can access it's properties with the syntax:

  1. alert(sampleObjectInstance.statusMessage);  


That concludes the basic guide to using object oriented programming with Prototype.

Monday, March 03, 2008 10:10:37 AM (Jerusalem Standard Time, UTC+02:00)  #    Comments [0] - Trackback
AJAX | Javascript | Programming
Navigation
Archive
<March 2008>
SunMonTueWedThuFriSat
2425262728291
2345678
9101112131415
16171819202122
23242526272829
303112345
About the author/Disclaimer

Disclaimer
The opinions expressed herein are my own personal opinions and do not represent my employer's view in any way.

© Copyright 2010
Guy Levin
Sign In
Statistics
Total Posts: 63
This Year: 0
This Month: 0
This Week: 0
Comments: 14
Themes
All Content © 2010, Guy Levin