Archive | Uncategorized RSS feed for this section

CSS Text-Shadow in Safari, Opera, Firefox and more

29 Sep

The CSS 2 property text-shadow is supported in Safari since version 3 (also available for Windows), Opera since 9.5, Firefox since 3.1, Google Chrome since version 2, Konqueror and iCab. In fact, text-shadow is supported by all browsers that are based on WebKit, the rendering engine behind Safari and Chrome. Internet Explorer 8 does not support such text shadows (except for some DirectX image transform filters).

Animated multiple Shadows (requires JavaScript)

Start/stop animations.

element.style.textShadow = "…";

Text shadows were defined in 1997 and became applicable in 2009

element.style.textShadow = "…";

Text shadows were defined in 1997 and became applicable in 2009

Multiple Shadows

Safari 3 supported one shadow only. Only the first shadow was displayed. Safari 4 supports multiple shadows. Opera 9.5 supported at most six shadows. Later, this limitation was dropped. Please note that Opera painted the shadows in the wrong order. This was fixed in Opera 10.5.

text-shadow: -1px -1px #666, 1px 1px #FFF;Text shadows were defined in 1997 and became applicable in 2009

text-shadow: 1px 1px 3px #666, -1px -1px 3px #FFF, 1px 1px #666, -1px -1px #FFF;Text shadows were defined in 1997 and became applicable in 2009

text-shadow: 0 -1px #000, 1px 0 #000, 0 1px #000, -1px 0 #000;Text shadows were defined in 1997 and became applicable in 2009

text-shadow: 1px 0 #F33, -1px 0 #33F;Text shadows were defined in 1997 and became applicable in 2009

text-shadow: 2px 0 4px #600, -2px 0 4px #006;Text shadows were defined in 1997 and became applicable in 2009

text-shadow: 0 6px 4px #33F, -3px -5px 4px #F00, 3px -5px 4px #0F0;Text shadows were defined in 1997 and became applicable in 2009

text-shadow: 0 0 24px #C00, 0 0 4px #C00, 1px 1px 2px #333;Text shadows were defined in 1997 and became applicable in 2009

Classical Shadows

text-shadow: 1px 1px 2px #999;Text shadows were defined in 1997 and became applicable in 2009

text-shadow: 2px 2px 3px #999;Text shadows were defined in 1997 and became applicable in 2009

text-shadow: 0 0 8px #000;Text shadows were defined in 1997 and became applicable in 2009

Glowing Borders

text-shadow: 0 0 11px #0F0;Text shadows were defined in 1997 and became applicable in 2009

text-shadow: 0 0 5px #FF0;Text shadows were defined in 1997 and became applicable in 2009

text-shadow: 0 0 3px #F90;Text shadows were defined in 1997 and became applicable in 2009

Unusual Effects

text-shadow: 0 7px 11px #390;Text shadows were defined in 1997 and became applicable in 2009

text-shadow: 0px -15px 0 #F00;Text shadows were defined in 1997 and became applicable in 2009

text-shadow: 0 0 11px #FF6;Text shadows were defined in 1997 and became applicable in 2009

text-shadow: 0 0 8px #000;Text shadows were defined in 1997 and became applicable in 2009

Create a Grid Based Web Design in HTML5 & CSS3

29 Sep

Follow this step by step walkthrough of the making of a sleek website design for an eyewear brand in HTML5 and CSS3. We’ll build the HTML structure with the latest elements then style up the appearance of the site with CSS3 affects to match the original Photoshop concept with minimal use of background images.

 

The design concept

Optik website design concept

The design we’ll be coding up is for a fictional eyewear brand named OPTIK. If you’re interested in seeing how the design concept was created in Photoshop, head over to Blog.SpoonGraphics so see part one of the tutorial. Essentially the page is based on an underlying grid and features a few key focal elements to direct the user towards the various ranges of eyewear.

View the Photoshop design tutorial

Exporting the images

I know I mentioned we’d build the website with minimal background images, but there’s still a few graphics that need pulling out of the Photoshop concept that just can’t be recreated in HTML or CSS (…yet!). The first of those graphics is the patterned background. Copy and export a selection so that the pattern will repeat seamlessly when tiled.

We’ll create the gradients used on the feature area with CSS3, but we’ll need to export the actual photograph. Draw a tight selection around the character and save for web as a JPEG.

In the original concept we saved two versions of the range graphics. Copy both into a new document to create mini sprite images then export as JPEGs.

This design was created according to columns and a baseline grid. Export a copy of the grid image from Photoshop. We’ll add this as a temporary background image so we can easily line up the elements with CSS to replicate the grid based layout.

The HTML structure

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>OPTIK</title>

<link href="style.css" rel="stylesheet" />

</head>

<body>

</body>
</html>

The HTML file begins with a typical document structure of Doctype, page title, link to CSS stylesheet and the opening & closing body tags. The simple HTML5 Doctype really looks great when compared to the long versions of HTML4 and XHTML.

<div id="container">
	<header>
		<h1><a href="#"><img src="images/optik-logo.png" alt="Return to the homepage" /></a></h1>
		
		<nav>
			<ul>
				<li><a href="#">Sun</a></li>
				<li><a href="#">Sport</a></li>
				<li><a href="#">Tech</a></li>
				<li><a href="#">Special</a></li>
			</ul>
		</nav>
	</header>	

A typical container div is added to ‘contain’ the elements to help centre everything up, then we can get stuck in to some fancy HTML5 tags/elements with<header>. As the name suggests, <header> is used to outline an introduction or group of navigation elements and is used in place of the traditional<div id="header"> code we usually use.
<nav> is another new element we can make use of, which identifies a section of navigation. Inside this element a normal unordered list lays out the four navigation links.

	<section id="feature">
		<a href="#"><img src="images/feature-image.jpg" alt="Man wearing Hydrotek sunglasses" /></a>
		<div id="feature-info">
			<a href="#"><h2>Hydrotek</h2></a>
			<p>HYDRO-TEK sports eyewear from OPTIK optimizes the flow of perspiration for an increased aerodynamic advantage over your competition.</p>
			<p><a href="#">Find out more</a></p>
		</div>
	</section>

Where we would previously use divs to create major structural areas of a webpage, in HTML5 we can use the <section> tag. <section> is used along with an ID to identify a clear ‘section’ of the document, such as the feature area at the top of the page. The photo of the guy wearing sunglasses could be added as a background image, but I expect users to naturally try to click it, so adding it as an <img> inside an anchor will allow us to link it up to its relative content.
<h2> and <p> elements semtantically lay out the few lines of content, with a class of ‘btn’ allowing us to style up that particular link as a button graphic later. All these elements will need floating next to the image, so a simple div helps group them all together.

	<section id="content">
		<div>
			<a href="#" id="sun">Sun range of OPTIK eyewear</a>
			
			<p>Enjoy the summer sun in style with OPTIK's range of casual eyewear. Choose from an array of fashionable frames and styles.</p>
			
			<p><a href="#">View the SUN range</a></p>
		</div>
		
		<div>
			<a href="#" id="sport">Sport range of OPTIK eyewear</a>
			
			<p>Protect and enhance your vision with the SPORT range of eyewear from OPTIK to give yourself the edge over your competition.</p>
			
			<p><a href="#">View the SPORT range</a></p>
		</div>
		
		<div>
			<a href="#" id="tech">Technicaly information about OPTIK eyewear</a>
			
			<p>Find out more about the science behind the materials, geometry and coatings that make OPTIK lenses so technologically advanced.</p>
			
			<p><a href="#">View the TECH info</a></p>
		</div>
		
		<div>
			<a href="#" id="special">Special range of OPTIK eyewear</a>
			
			<p>OPTIK also design eyewear for specific industries where eye protection is crucial. Make sure your team has the best optical safety.</p>
			
			<p><a href="#">View the SPECIAL range</a></p>
		</div>
	</section>	

Another <section> tag outlines the main content area, followed by four separate divs with a class of ‘bucket’ to lay out the four boxes seen on the design concept. Inside each of these boxes the images will need adding with CSS to allow the sprite hover effects to work, so they are created in HTML as simple anchors with a descriptive anchor text introducing the section.

</div>

<footer>
	<p id="copyright">&copy; Copyright OPTIK 2011</p>
	<ul>
		<li><a href="#">About</a></li>
		<li><a href="#">Retailers</a></li>
		<li><a href="#">Corporate</a></li>
		<li><a href="#">Warranty</a></li>
		<li><a href="#">News</a></li>
		<li><a href="#">Contact</a></li>
	</ul>
	
	<p id="back-top"><a href="#">Back to top</a></p>
	
</footer>


</body>
</html>

The footer appears below the main content panel in the concept so the container div is closed before the <footer> tag opens. Just like <header>,<footer> is a new structural tag that replaces the old method of <div id="footer">.
The <ul> in the footer isn’t enclosed in a <nav> element because of guidelines in the HTML5 spec:

It is common for footers to have a short list of links to various pages of a site, such as the terms of service, the home page, and a copyright page. The footer element alone is sufficient for such cases.

The complete HTML

View the complete HTML

The CSS styling

body, div, h1, h2, h3, h4, h5, h6, p, ul, ol, li, dl, dt, dd, img, form, fieldset, input, textarea, blockquote {
	margin: 0; padding: 0; border: 0;
}

body {
	font: 14px Helvetica, Sans-Serif; line-height: 24px; color: #a6a6a6;
	background: #000 url(images/bg-pattern.png);
}

#container {
	width: 960px; margin: 0 auto 24px auto; background: #000; /*background: url(images/grid.png) center top no-repeat;*/
	box-shadow: 0px 5px 45px #343434;
	-moz-box-shadow: 0px 5px 45px #343434;
	-webkit-box-shadow: 0px 5px 45px #343434;
}

a {
	color: #abe2ff; text-decoration: none;
}
	a:hover {
		color: #5db5e3;
	}

Onto the CSS! First we clean things up with a simple reset and declarations to the body to set the global styling. Then the container div is centered up and given the outer glow styling from the Photoshop concept with CSS3 box-shadow. Remember that grid used in Photoshop? We can add that as a temporary background image to allow us to align all the page elements exactly into place.

header h1 {
	margin: 54px 0 0 21px; float: left;
}

header nav {
	float: left;
	margin: 79px 0 17px 0;
}
	header nav ul li {
		float: left; list-style: none;
		width: 58px; margin: 0 0 0 98px;
	}
		header nav ul li a {
			text-transform: uppercase;	
		}

Next up the header items are moved into place according to the grid with simple margins. This is where the Firebug plugin for Firefox comes in handy so you can edit the figures live in order to achieve pixel perfection.

#feature {
	clear: both; height: 431px; overflow: hidden; margin: 0 0 48px 0;
	background: #000;
	background: -moz-linear-gradient(top, #000 0%, #191919 5%, #000 5%, #000 94%, #191919 94%, #000 100%);
	background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#000), color-stop(5%,#191919), color-stop(5%,#000), color-stop(94%,#000), color-stop(94%,#191919), color-stop(100%,#000));
	background: -webkit-linear-gradient(top, #000 0%,#191919 5%,#000 5%,#000 94%,#191919 94%,#000 100%);
	/*opacity: 0.5;*/
}
	#feature h2 {
		width: 216px; height: 30px; margin: 0 0 31px 0;
		background: url(images/hydrotek.png); text-indent: -9999px;
	}
	#feature img {
		float: right; margin: 22px 0 0 0;
	}
	#feature-info {
		float: left; width: 370px; margin: 89px 0 0 100px;
	}
		#feature-info p {
			margin: 0 0 34px 0; font-size: 16px;
		}
		#feature-info p.btn a {
			display: block; width: 170px; height: 35px;
			background: #497389;
			background: -moz-linear-gradient(top, #497389 0%, #151e36 100%);
			background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#497389), color-stop(100%,#151e36), color-stop(100%,#000));
			background: -webkit-linear-gradient(top, #497389 0%,#151e36 100%);
			border: 1px solid #313e52;
			border-radius: 10px;
			-moz-border-radius: 10px;
			-webkit-border-radius: 10px;
			text-transform: uppercase; text-align: center; padding: 12px 0 0 0;
		}

We can really start going to town with CSS3 styling on the feature section. In the concept there’s a gradient glow above and below the feature area. We could replicate this in CSS3 with box-shadow or CSS gradients. Here I’ve gone for the gradient approach with the help of the handy CSS Gradient Generator tool, which makes it easy to match the format from Photoshop.
The <h2> uses a non-web font so a simple CSS image replacement technique switches the default H2 text for an image. The text content and image is moved into place, then the “btn” class is given some styling to convert it into a button style graphic. display:block; converts it into a block element so a width and height can be added, then another CSS gradient is generated to flow from dark to light blue. border-radius then rounds off the corners and the text is set to uppercase and bumped into position vertically using a touch of padding.
Tip: Use opacity: 0.5; as a temporary declaration on the feature section so you can see the underlying grid lines.

#content {
	overflow: hidden; clear: both;
}
	#content .bucket {
		width: 212px; float: left; margin: 0 0 48px 20px;
		border: 1px solid #262626;
		background: #000;
		background: -moz-linear-gradient(top, #000 0%, #000 39%, #191919 39%, #000 100%);
		background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#000), color-stop(39%,#000), color-stop(39%,#191919), color-stop(100%,#000));
		background: -webkit-linear-gradient(top, #000 0%,#000 39%,#191919 39%,#000 100%);
	}
		#content .bucket:first-child {
			margin: 0 0 0 22px;
		}
	
	#content #sun, #content #sport, #content #tech, #content #special {
		display: block; width: 212px; height: 143px;
		margin: 0 0 32px 0; text-indent: -9999px;
	}
		#content #sun { background: url(images/sun.jpg); }
		#content #sport { background: url(images/sport.jpg); }
		#content #tech { background: url(images/tech.jpg); }
		#content #special { background: url(images/special.jpg); }
	
		#content #sun:hover, #content #sport:hover, #content #tech:hover, #content #special:hover {
			background-position: 0 -143px;
		}
		
		#content .bucket p {
			margin: 0 0 24px 0; padding: 0 13px 0 13px;
		}

The four buckets in the content area can then be styled up with a specific width and margin and floated side by side. A simple border and another background gradient help replicate the shadow underneath the header images in the concept. To match the layout to the grid the first bucket’s margin is adjusted using thefirst-child selector.
All the header images can be grouped together for some general CSS such as the width, height and margin. text-indent: -9999px; shifts the default text off screen, then the specific background image for each link is added. These images has a hover state included in the basic sprite, so all anchors are set to move the background position on hover.

footer {
	width: 960px; margin: 0 auto; height: 80px;
	font-size: 12px;
}
	footer #copyright {
		float: left; margin: 0 0 0 22px;
	}
	
	footer ul {
		float: left; margin: 0 0 0 134px; list-style: none; overflow: hidden;
		
	}
		footer li {
			float: left; margin: 0 10px 0 10px;
		}
	
	footer #back-top {
		float: right; margin: 0 22px 0 0;
	}
		footer #back-top a {
			background: url(images/optik-logo-sm.png) left no-repeat; padding: 5px 0 5px 40px;
		}

Finally the footer area can be styled to finish off the page. Because it’s outside the container div it first needs moving into position with the 960px width andmargin: 0 auto; declarations. Then each of the three elements can be floated side by side and moved into place with margins.

The complete CSS

View the complete CSS

Patching up IE

Needless to say, Internet Explorer doesn’t support these fancy new HTML5 and CSS3 goodies. Our CSS will simply degrade back to non CSS3 styling, so there will be no gradients or round corners. The HTML5 tags on the other hand won’t be recognised at all, which will bork the layout altogether. Luckily there’s a snippet of code you can add to the head of your page to render the tags as normal elements:

<!--[if IE]>
<script>
  document.createElement('header');
  document.createElement('footer');
  document.createElement('section');
  document.createElement('nav');
</script>
<![endif]-->

Then you can simply create a conditional stylesheet to fix up the mess IE makes of your standard CSS. With this tutorial being a HTML5/CSS3 demonstration, I’ll leave those exciting fixes for another time…

The final website design

View the demo

Our final coded website matches the original Photoshop concept identically with the help of a few CSS3 features and looks cool under the hood with the new HTML5 tags. Check out the demo in the latest Firefox, Safari or Chrome browsers.

Happy 10th Birthday Firefox!

29 Sep

On September 23, 2012 Mozilla Firefox celebrated its tenth birthday. Or, more specifically, the browser project which ultimately became Firefox was released on September 23, 2002.

Phoenix, as it was then known, was an experimental browser developed by Blake Ross, Dave Hyatt, Pierre Chanial and Joe Hewitt. The amusing version 1.0 (Pescadero) release page remains live today and you can even download the installation (extract and run — no user-friendly installers here).

Mozilla Phoenix

There have been a few obvious interface changes in the past decade, but features such as tabs, preferences and the JavaScript console remain recognizable.

The 2002 Browser Market

In 2002, Internet Explorer 6.0 reigned supreme with a 90%+ market share. Microsoft’s business tactics may have been questionable, but IE had little competition:

  • Opera was good and had a passionate following, but the commercial software was more expensive than the alternatives.
  • Netscape 4.x was an abomination. It’s few remaining users were ditching the old browser.
  • The Netscape 6+ and Mozilla 1+ suites used the same code base and were slow, buggy and bloated. Few people needed a multi-megabyte installation which contained a browser, email client, newsgroup reader, address book, chat client, web page editor, developer tools and Palm Pilot synchronization.

Despite the hassle IE6 caused in later years, the browser’s success was largely deserved.

Phoenix Rises From the Ashes

Phoenix evolved because the developers believed Netscape’s commercial requirements and Mozilla’s scope creep compromised the browser’s future. They wrapped the Gecko rendering engine in a lightweight shell, removed unnecessary features and introduced the concept of add-ons.

If you think Firefox releases appear rapidly today, Phoenix 0.2 was released within one week. Version 0.3 appeared on October 16 2002, 0.4 on October 31 and 0.5 on December 7. The browser had started to gain momentum in the developer community. Like many, I had it installed although still used IE6 as my default.

Following trademark issues with Phoenix Technologies, the browser was renamed “Firebird” and version 0.6 appeared on May 16, 2003 for Windows, Mac and Linux. Versions 0.6.1 and 0.7 appeared in July and October 2003 respectively. These editions changed everything:

  • the browser had overtaken IE6 in terms of standards support, stability, speed and functionality
  • a thriving set of add-ons also provided developers with tools that had been sorely lacking
  • while it was still a beta release, developers spread the word and non-technical users began to install the application
  • many people adopted it as their default browser
  • Mozilla scrapped their browser suite to concentrate on Firefox and the Thunderbird email client (originally named Minotaur).

Fox Eats Bird

The Firebird name didn’t last long, particularly as it clashed with the open source Firebird database server. Following delays in the trademarking process, the browser was re-branded “Firefox” on February 10, 2004. Reactions were mixed — partly because it shared its name with the dire 1982 Clint Eastwood movie — but it stuck and Firefox 1.0 was launched on November 9, 2004.

The Legacy Continues

Today, Firefox usage accounts for 23% of the browser market — down from its peak of 33% in November 2009. But, without Firefox, the web would not be the same. Would Google and Apple challenged Microsoft’s domination if it were not for Mozilla’s success? Would IE6 still have a stranglehold on the web? Even if you prefer another browser, that application may not have existed had Firefox failed.

Firefox usage is slowly dropping but it still provides two major benefits:

  1. It is the best development browser. The competition has caught up, but the quantity and quality of add-ons created by web developers for web developers remains unsurpassed.
  2. Mozilla is an independent, open-source organization. No one can buy Mozilla or shut it down. Firefox is the only browser not influenced by commercial requirements or shareholder demands.

Congratulations to Mozilla and the Firefox development team for reaching double-figures. I’m sure the browser will still be around in another ten years. Are you?

How to Create Facebook FBML Template

15 Feb

Everyone knows a social network called FaceBook. It’s the place where lots of people are constantly spending lots of time. It didn’t take a long time for brands and local businesses to join FaceBook too. So when the amount of non-human accounts started to grow, FaceBook guys have decided to add an ability to create separate pages for businesses and brands.

Today FaceBook pages can be equipped and customized with a lot of different widgets and applications. However the most important of all is the FBML box – it lets you create awesome landing pages, using HTML, CSS, FBML, FBJS, iframes and even Flash.

In this tutorial we will show you how to design a photographers FaceBook FBML page. Follow carefully what we say and you will get a nice layout like this:

 

1. Let’s start with creating a new document 520 * 800 pixels. That’s because FaceBook has recently announced that the page width will be shortened from 760 to 520 pixels.

2. To create a fancy bubbles background we have used this great tutorial.

3. Now take the Rounded RectangleTool (U) and create a rectangle, which will contain our logo. The radius that I’ve used is 15px.

To enhance the rectangle let’s set a Opacity to 70%

and add a tiny shadow to it:

4. Fill in the rectangle with the name of your company using the Type Tool (T). To make it look more like a logo we can play with the fonts a bit. “John” is written with a thin font FuturaBTLight of #f5634a color, while “Marley” is black (#000000) FuturaBTBold. I have also added a tiny slogan at the bottom. It’s a Visitor TT1 BRK font with 10px height.

5. Adding some effects to the texts as shown on screenshots:

Gradient:

Outer Glow:

6. There’s some free space to the right from our logo – a perfect place to insert some photographers attribute. The most obvious one is undoubtedly a camera :)

7. The title of our page is “Welcome to my FaceBook page” which is also made of two above fonts of different colors.

8. Fill the page with some text content and add a bit styling to it by making some phrases bold and some underlined. I’ve used Tahoma font in this part:

9. As far as we’re creating a photographer layout, we need to add a tiny photo gallery to a page. Insert some photos and resize them to 210 * 115 pixels. Order in a line with a 10px distance between them. The third picture will not fit to a page, so we’ll have to cut it with Marquee Tool (M).

10. Add a Stroke effect on the layer with pictures – this will create a nice border:

Adding effect:

Stroke settings:

11. We obviously need a scrollbar under the pictures, so take a RectangleTool (U) and draw it. Then add DropShadow, GradientOverlay and Stroke effects as per screenshots:

Stroke:

Drop Shadow:

Gradient Overlay:

12. Pick a Pencil Tool (B) and draw 3 white and 3 black lines in the center of the scroller.

13. To finish the scroll box we need a scroll holder. Pick a Rectangle tool and make a black rectangle of the same height as the scroll. The width should be adjusted in accordance to the photo thumbs. Set the Opacity of the layer to 10%. The scroll box is all set:

14. Using a Text Tool add 2 more boxes in the footer – “Latest News” and “Contacts”. At the very bottom add the copyrights:

15. You can also add the icons of your social profiles to the header. And don’t forget to ask people to become a “Fan” of your page. Add a “Like” button with a supporting text to engage them to join:

Finally our FaceBook page is ready:

Autoloading in PHP and the PSR-0 Standard

14 Feb

Let’s say you have the file Rectangle.php which contains the definition for a Rectangle class. Before you can create an instance of the object elsewhere in your code, you first need to pull in the Rectangle.php file, perhaps by writing something like this:

1 <?php
2 require "Rectangle.php";
3 $rect = new Rectangle(42, 25);

Normally we put each class’ definition in its own file for better organization, and so you need to require/include each of the class files you want to use. If there are only a few files then it isn’t too much of a problem, but oftentimes that’s not the case. It can be very cumbersome to load a large library including all of its dependencies like this.

In this article I’ll walk you through the “history of autoloading,” from the older to the current PSR-0 standard autoloader approach found in many PHP frameworks such as Lithium, Symfony, Zend, etc. Then I will introduce you to the ClassLoader component from the Symfony2 project for PHP 5.3 which follows the PSR-0 standard.

Warning: Most of the code samples in the beginning of this article demonstrate deprecated approaches. It would be unwise to use them in production. I recommend you use one of the PSR-0 standard autoloaders instead.

Autoloading in the “Olden Days”

PHP 5 introduced the magic function __autoload() which is automatically called when your code references a class or interface that hasn’t been loaded yet. This provides the runtime one last chance to load the definition before PHP fails with an error.

Here’s an example of an extremely basic __autoload() implementation:

1 <?php
2 function __autoload($className) {
3     $filename = $className . ".php";
4     if (is_readable($filename)) {
5         require $filename;
6     }
7 }

It’s a good idea to make sure a file exists before you try to include it, but sometimes the file may be there but will not have sufficient read permissions so it’s better to use is_readable() over file_exists() which will for test both conditions.

The major drawback to the __autoload() function is that you can only provide one autoloader with it. PHP 5.1.2 introduced spl_autoload() which allows you to register multiple autoloader functions, and in the future the __autoload() function will be deprecated.

The introduction of spl_autoload_register() gave programmers the ability to create an autoload chain, a series of functions that can be called to try and load a class or interface. For example:

01 <?php
02 function autoloadModel($className) {
03     $filename = "models/" . $className . ".php";
04     if (is_readable($filename)) {
05         require $filename;
06     }
07 }
08
09 function autoloadController($className) {
10     $filename = "controllers/" . $className . ".php";
11     if (is_readable($filename)) {
12         require $filename;
13     }
14 }
15
16 spl_autoload_register("autoloadModel");
17 spl_autoload_register("autoloadController");

Generally the functions are called in the order they’re registered, but the order can also be affected by additional arguments passed to spl_autoload_register().

It’s important to remember that once a function has been registered with spl_autoload_register(), the __autoload() function will no longer be called. If you have an __autoload() function you want to run as part of your autoloader chain, then you’ll have to register it with spl_autoload_register().

Of course, the implementations of the autoloading functions I’ve shown this far have been rather simple. Real-world autoloaders are more complex.

Before real namespace support was introduced in PHP 5.3, developers devised their own approaches to prevent naming collisions. The PEAR Coding Standard used underscores to prefix class names with their directory path; the class Zend_Translate for example would be defined in the file Zend/Translate.php. The autoloader needed to replace the underscores with directory separators to locate the definition.

Also, different developers adopted different conventions when it came to naming their class files, for example the files might end in .php, .class.php, .inc, etc. Some libraries may be installed in different paths as well. The loader needed to look in various places for them, so now the loader begins to look like this:

01 <?php
02 function __autoload($className) {
03     $extensions = array(".php", ".class.php", ".inc");
04     $paths = explode(PATH_SEPARATOR, get_include_path());
05     $className = str_replace("_" , DIRECTORY_SEPARATOR, $className);
06     foreach ($paths as $path) {
07         $filename = $path . DIRECTORY_SEPARATOR . $className;
08         foreach ($extensions as $ext) {
09             if (is_readable($filename . $ext)) {
10                 require_once $filename . $ext;
11                 break;
12            }
13        }
14     }
15 }

Autoloading is a useful idea, but was an idea that desperately needed some standardization.

PSR-0 Standard

After PHP 5.3′s introduction of true namespace support, a group of people from the PHP community decided to create the PHP Standards Working Group in 2009 (later renamed to the Framework Interoperatability Group) and establish the PSR-0 standard which outlines various practices and constraints that must be followed for autoloader interoperability. Below are the requirements for PSR-0 compliance:

  • A fully-qualified namespace and class must have the following structure \<Vendor Name>\(<Namespace>)*\<Class Name>.
  • Each namespace must have a top-level namespace (“Vendor Name”).
  • Each namespace can have as many sub-namespaces as it wishes.
  • Each namespace separator is converted to a DIRECTORY_SEPARATOR when loading from the file system.
  • Each underscore in the class name is converted to a DIRECTORY_SEPARATOR. The underscore has no special meaning in the namespace.
  • The fully-qualified namespace and class is suffixed with .php when loading from the file system.
  • Alphabetic characters in vendor names, namespaces, and class names may be of any combination of lower case and upper case.

According to the PSR-0 standard, there should be a top level directory with the vendor’s name and then the package name, so the directory tree will look like this:

example component path

The classes would then be namespaced accordingly:

1 <?php
2 namespace Vendor\Package;
3 class Example
4 {
5 }

Thus, the class definition for \Doctrine\Common\Connections would be found at /path/to/project/lib/Doctrine/Common/Connections.php, and \Symfony\Core\Request at /path/to/project/lib/Symfony/Core/Request.php. The PSR-0 standard does not mandate what the base /path/to/project/lib portion of the path is, and conforming autoloaders offer different methods for its resolution. Some will allow you to register the directory, some will search PHP’s include_path, and some offer you both.

You can use any one of the PSR-0 compliant autoloaders from frameworks such as Symfony, Pear2, AuraPHP (which is for PHP 5.4+), etc. and adhere to the rules above with your own code to take advantage of autoloading without the uncertainties I discussed previously.

Using Symfony’s Autoloader

The Symfony2 project is a component-based framework for PHP 5.3 and greater which you can use as a component library or as a full-stack framework. You can download Symfony’s Autoloader, the ClassLoader component, via different means — pear.symfony.com, packagist, or from GitHub.

Here’s the directory structure of Symfony’s ClassLoader component:

Symfony ClassLoader Component

Using the component then looks like this:

1 <?php
2 require_once "/path/to/Symfony/Component/ClassLoader/UniversalClassLoader.php";
3 use Symfony\Component\ClassLoader\UniversalClassLoader;
4
5 $loader = new UniversalClassLoader();
6 $loader->registerNamespace("Symfony\Component" => "/path/to/symfony/components");
7 $loader->registerNamespace("Monolog" => "path/to/monolog/src/");
8 $loader->registerPrefix("Zend_", "path/to/zend/library");
9 $loader->register();

The registerNamespace() method is used to inform the autoloader where the given namespace’s base directory maps to on the file system and accepts a namespace as its first argument and path as its second value. You can also register multiple namespaces in a single call with the registerNamespaces() method.

1 <?php
2 $loader->registerNamespaces(array(
3     "Symfony\Component" => "/path/to/symfony/components",
4     "Monolog' => "path/to/monolog/src"));

The registerPrefix() method is used to register pseudo-namespaces which was used by Pear, Zend, and other libraries and frameworks before real namespace support was implemented in PHP as we have already covered above. You can also register mulitple ones with the registerPrefixes() method and passing it as an associative array.

1 <?php
2 $loader->registerPrefixes(array(
3     "Zend_" => "/path/to/zend/library",
4     "Twig_" => "path/to/twig/library"));

If you are using the Alternative PHP Cache (APC), a free and open source opcode cache for PHP, then you can may want to consider using the ApcUniversalClassLoader class. The ApcUniversalClassLoader extends the UniversalClassLoader but uses apc_store() and apc_fetch() to store lookup information in APC’s cache. The standard UniversalClassLoader will of course work with APC, but the additional behavior offered by the ApcUniversalClassLoader class afford extra performance benefit.

1 <?php
2 require_once "path/to/Symfony/Component/ClassLoader/UniversalClassLoader.php";
3 require_once "path/to/Symfony/Component/ClassLoader/ApcUniversalClassLoader.php";
4 use Symfony\Component\ClassLoader\ApcUniversalClassLoader;
5 $loader = new ApcUniversalClassLoader("apc.prefix.");

The ApcUniversalClassLoader accepts a prefix with its constructor. For more information on APC, I suggest reading the APC documentation.

Summary

In this article we have discussed autoloading, from its early days to the current PSR-0 standard which has become widely adopted across many PHP frameworks. Recently, David Coallier tried to push the SplClassloader class into PHP 5.4 to offer native PSR-0 compliant autoloading functionality, but for various reasons it didn’t happen. Maybe in the future we will see it added.

Now the current hot discussion in the working group is focused on caching. If it’s something you’d like to be part of, feel free to join the discussion!

Creating Accessible JavaScript

12 Feb

Overview of Creating Accessible JavaScript

What is JavaScript?

a wheelchair ramp with the word 'javascript' written on itThis may best be answered by defining what JavaScript is NOT. First, it is not HTML. JavaScript does not use HTML tags or abide by any of the general rules of the HTML language. You can, however, use JavaScript with HTML on a webpage. Second, JavaScript is not Java. Although JavaScript is often called Java, the two are not the same. Java was developed by Sun Microsystems and is a stand-alone programming language. JavaScript, on the other hand, was developed by Netscape Corporation. Although similar to Java in syntax, JavaScript is not a stand-alone language; in order for JavaScript to work, it must be part of a web page that is being displayed in a browser that understands the JavaScript language. Sun’s Java programming language can be implemented in webpages as a built in program, whereas JavaScript scripts are reliant upon the client (visitor’s) computer in order for them to work.

Once again, JavaScript is not HTML or a version of HTML. It is a distinct, separate scripting language. HTML is read and processed by the web browser. When the browser reads JavaScript code within your HTML document, it processes the code, then displays any output within the web page. The computer reading the JavaScript must have a JavaScript interpreter, a program that interprets the script and runs it, and that interpreter must be enabled.

HTML, alone, creates very static pages. There is little user interaction and little by the way of dynamic content within a particular page. HTML cannot think; it does not have the capabilities to perform mathematics, store variables, or dynamically display content. JavaScript allows your web page to ‘think’. Although many server-side scripting programs (such as PHP, JPS, ASP, or ColdFusion) have the ability to perform such functions, JavaScript can perform these functions within the client web browser. Because JavaScript is a scripting language, it allows developers to implement little applications into their pages. These programs may do things as simple as changing a graphic when the mouse rolls over it to something as complex as performing advanced mathematical formulas on user input.

JavaScript Accessibility Issues

JavaScript allows developers to add increased interaction, information processing, and control in web-based content. However, JavaScript can also introduce accessibility issues. These issues include:

  • Navigation. Inability or difficulty navigating using a keyboard or assistive technology.
  • Hidden content. Presentation of content or functionality that is not accessible to assistive technologies.
  • User control. Lack of user control over automated content changes.
  • Confusion/Disorientation. Altering or disabling the normal functionality of the user agent (browser) or triggering events that the user may not be aware of.

A web page containing JavaScript will typically be fully accessible if the functionality of the script is device independent (does not require only a mouse or only a keyboard) and the information (content) is available to assistive technologies. Unfortunately, there is no easy fix that can be applied to solve all accessibility problems associated with JavaScript. The only way to ensure JavaScript accessibility is by evaluating each individual script and devising a unique solution to the accessibility problem it poses. Developers must be familiar with the issues surrounding JavaScript accessibility and apply techniques to do one or both of the following:

  1. Ensure the JavaScript is directly accessible
  2. Provide an accessible, non-JavaScript alternative

JavaScript that does not impact accessibility

Just because JavaScript is utilized on a page does not mean that the page is inaccessible. In many cases, JavaScript can be used to increase accessibility. Additional information, warnings, or instructions can be given to users through JavaScript prompts. For instance, under the Section 508 guidelines of United States law, a user must be notified when a timed response is required and given sufficient time to indicate more time is required. Such functionality would be difficult with HTML alone.
JavaScript is sometimes used to create visual interface elements that do not affect accessibility. JavaScript is commonly used for image rollovers, where one image is replaced with another when the mouse is placed above it; for example, when a navigation item changes to display a shadow, glow, or highlight when the user mouses over it.

Place your mouse over the following image to see a JavaScript example that does not impact accessibility.
Home

Problems

None. In this example, there is no important content or functionality introduced by the JavaScript. The swapping of images is purely cosmetic.

Solution

No additional accessibility techniques are required. Remember, the image itself must have alternative text (i.e., <img alt="home"...>). You can also accomplish image rollovers without using JavaScript – external link.

Such uses of JavaScript do not need additional accessibility features incorporated because important content is not displayed or functionality introduced by such scripting.
Making JavaScript accessible involves looking at the following issues. Each of these will be discussed in the next lessons.

  • When using event handlers, use only those that are device independent (e.g., do not require the use of the mouse only).
  • Content and functionality that is provided through scripting must be made accessible to assistive technologies.
  • Web pages that utilize scripting must be fully navigable using a keyboard.
  • JavaScript should not modify or override normal browser functionality in a way that may cause confusion.
  • When JavaScript cannot be made natively accessible, an accessible alternative must be provided.

Comparison of JavaScript Guidelines

Section 508 of the Rehabilitation Act (in the United States) and the W3C Web Content Accessibility Guidelines (WCAG) 1.0 both address the accessibility of scripting elements. They require that the functionality and content of scripts be accessible to assistive technologies such as screen readers. Additionally, users must be given control over time-based content changes. There are, however, differences between the two accessibility guidelines. WCAG requires that content and functionality be accessible with scripting disabled and that users should be alerted if JavaScript changes the appearance or functionality of the browser window, whereas Section 508 only requires that the scripting be made accessible or that an accessible alternative is provided.

Testing for JavaScript Reliance

As mentioned above, your web pages should be fully functional with JavaScript disabled. This is required under Priority 1 of the Web Content Accessibility Guidelines. Section 508 does not require the page to function if JavaScript is disabled, but does require that the scripts themselves be natively accessible. This tutorial will teach strategies for making your scipts natively accessible and assumes that if you, as a developer, want to achieve a higher level of accessibility or comply with the Web Content Accessibility Guidelines, that you will also test your pages to ensure that they work with JavaScript disabled.

Disabling JavaScript

Follow the directions to disable or enable JavaScript in your browser. You can also determine if JavaScript is disabled. Test a JavaScript enabled web page and see if the content and functionality are accessible. Be sure to re-enable JavaScript when you’re done.
Internet Explorer 6.X

  1. Open Internet Explorer.
  2. Select Tools > Internet Options.
  3. In Internet Options dialog box select the Security tab.
  4. Click Custom Level button at bottom. The Security Settings dialog box will pop up.
  5. Under the Scripting category, enable/disable Active Scripting, Allow paste options via script and Scripting of Java applets.
  6. Click OK twice to close out.
  7. Click Refresh.

Netscape 7.X

  1. Open Netscape.
  2. Select Edit > Preferences.
  3. Click the arrow next to Advanced.
  4. Click Scripts & Plugins.
  5. Check/uncheck Navigator beneath “Enable Javascript for”.
  6. Click OK.
  7. Click Reload.

Opera 7.X

  1. Open Opera.
  2. Select File > Quick Preferences.
  3. Check/uncheck Enable Javascript.
  4. Click Reload.

Overview

JavaScript can be processed using <script> elements and event handlers. The <script> element can contain JavaScript code directly:

<script type="text/javascript"> <!-- function doit(); --> </script>

or can open an external JavaScript (.js) file:

<script type="text/javascript" src="scripts.js">

The <script> element is processed when the page is loaded and requires no user intervention. The contents and functionality of the script processed within the <script> element must be directly accessible or an accessible alternative of the content and functionality must be provided.
Event handlers accompany existing HTML code and are triggered by a browser or user event – such as when the page loads, when the user clicks the mouse, or when the time is 8 p.m. Some event handlers are dependent upon use of a mouse or keyboard. These are called device dependent event handlers. Other event handlers are device independent and are triggered by both the mouse and keyboard or by other means. Using device dependent event handlers may cause the content to be inaccessible to someone that is not able to use the device that is required for that specific event handler.

onMouseOver and onMouseOut

The onMouseOver event handler is triggered when the mouse cursor is placed over an item. As its name implies, onMouseOver requires the use of a mouse, thus it is a device dependent event handler and may cause accessibility issues. onMouseOver, and its companion, onMouseOut, can be used, as long as any important content or functionality is also available without using the mouse.

Example 1

Place your mouse over the following image to see an example of onMouseOver. When the mouse is placed over the image of the word “Accessibility”, another image appears in its place which presents the definition of the word “Accessibility”.
Accessibility - The quality of being accessible, or of admitting approach; receptibility.

<a href="page.htm" onmouseover="document.images['myimage'].src='imageoff.gif';" onmouseout="document.images['myimage'].src='imageon.gif';"> <img src="media/imageoff.gif" width="289" height="79" id="myimage" alt="Accessibility - The quality of being accessible, or of admitting approach; receptibility." /> </a>
Important
All of the examples in this lesson are coded to be XHTML 1.0 Strict compliant. XHTML requires lower-case event handler names (e.g., onmouseover instead of onMouseOver).

Try navigating to the image using the keyboard. Notice that the additional information does not display. The alternative text for the image provides the content displayed using the onmouseover event handler. This allows users who know how to access this alternative text to get the content, but is not a truly universal solution.

Problems

In this example, additional content is being displayed using onMouseOver. This content can only be viewed if the user uses a mouse to hover over the image. It is not available to someone who is using the keyboard to navigate through the page. The onMouseOver event handler cannot be made directly accessible to keyboard users. Thus, an alternative must be provided.

Partial Solution

Place the additional content in the alternative text of the image itself. This would work for screen reader users – the screen reader would read the alternative text. But for sighted users whose browser does not display alternative text for images or who do not know to mouse over the image to see the alternative text, this is not a viable alternative. Still, the image must have equivalent alternative text.

Solutions

In addition to onMouseOver and onMouseOut, use onFocus and onBlur. These actions will be triggered when the keyboard is used to navigate to and from a link that surrounds the <img> element.
Accessibility - The quality of being accessible, or of admitting approach; receptibility.

<a href="page.htm" onmouseover="document.images['myimage'].src='imageon.gif';" onfocus="document.images['myimage'].src='imageon.gif';" onmouseout="document.images['myimage'].src='imageoff.gif';" onblur="document.images['myimage'].src = 'imageoff.gif';"> <img src="imageoff.gif" width="289" height="79" id="myimage" alt="Accessibility - The quality of being accessible, or of admitting approach; receptibility." /></a>

You must still provide the descriptive alternative text for non-visual users, but onFocus and onBlur will provide the visual image swap for users that are using a keyboard only.

Example 2

A common use of onMouseOver and onMouseOut is for fly-out or drop-down navigation systems. Place your mouse over the menu items below to view an example of drop-down menus. When the mouse is placed over the main menu items (onMouseOver), additional sub-menu items appear below. When the mouse is removed from the menu system (onMouseOut), then the sub-menus disappear.

Products

Services

Support

Problems

Additional content and functionality is being displayed using onMouseOver. In this example, JavaScript is controlling the display of Cascading Style Sheet elements within the page. The sub-menu items will only be visible if the mouse is placed over the main menu item. These items may not be available if JavaScript is disabled and may not be read by assistive technologies.

Solutions

When possible, use additional event handlers that allow keyboard navigation. When this is not possible, you must provide redundant navigation. This can be done one of two ways. First, provide links within the main content of the page to the pages displayed in the sub-menu navigation. This is often done as a list of categorized links at the bottom of the page. The downside of this approach is that the navigation is only accessible at the bottom of the page, which might be counter-intuitive to most users.
A second method of providing the redundant navigation is to add a standard href link from each main navigation items (e.g., Product, Services, etc.) to a separate web page that contains the sub-menu navigation items. If you select the Products, Services, or Support links above you will see an example of providing redundant navigation.

Example

<a href="productlinks.htm" onmouseover="SlideOutMenu();" onmouseout="SlideInMenu();">Products</a>

While this method does require the creation of an additional page and introduces an additional step, it also provides full access to the navigation elements in an intuitive way. This method also allows the sub-menu items to be accessible if JavaScript is disabled.

onFocus and onBlur

These event handlers are typically used with form elements, such as text fields, radio buttons, and submit buttons. onFocus is triggered when the cursor is placed on or within a specific form element. onBlur is triggered when the cursor leaves a form element.
Both of these event handlers are device independent, meaning that they can be performed with the mouse, keyboard, or other assistive technology. The actions that are performed as a result of these event handlers must be analyzed to determine if they cause accessibility problems. Typically, these events do not cause accessibility issues unless they are modifying the default behavior of the web browser or are interfering with keyboard navigation within the web page.

Example 1

Place your cursor within the following textbox to see an example of the onFocus event handler.
Enter your name :

<input id="fname" type="text" onfocus="alert('Enter your first name only');" />

Problems

None. Although the alert window may be distracting and unnecessary, it does not introduce any serious accessibility issues. The alert is triggered when the text box gains focus, either by using the keyboard or mouse. JavaScript alerts are read by most modern screen readers and can be used to increase the usability of forms by providing timely feedback, instructions, or cues. However, if JavaScript is disabled, then the alert will not be available at all.

Example 2

In this example, the onBlur event triggers JavaScript code that changes the functionality of the Web browser. Place your mouse into the following text box and enter a number between 1 and 10. Then press the Tab key or click the mouse outside of the text box to trigger the onBlur event which will validate the number you entered to ensure it is correct and present feedback regarding your answer. If it is incorrect, the text box will retain the cursor focus until you enter the correct number. In this example, you MUST enter the correct answer of ‘6’ to allow the browser to navigate to other portions of the page.
Guess a number between 1 and 10?
Enter Answer:

<input type="text" id="input1" size="5" onblur="checkAnswer();">

Problems

Although the onblur event is device independent, it is being used to execute JavaScript code that makes the page difficult to navigate. The textbox maintains focus until the correct answer is given. This change in browser default behavior may be confusing and restricting. Also, the feedback is displayed in a different part of the page. Because focus is maintained within the text box, a screen reader will not be able to access the feedback text or any other part of the page until the correct answer is entered.

Solution

Do not force the focus to remain within the text box. Allow the user to navigate throughout the page. Display the feedback on another page after the form has been submitted (works without JavaScript) or display the feedback with a JavaScript alert (requires JavaScript). Try entering a letter into the textbox above to see a JavaScript alert feedback message.

onClick and onDblClick

The onClick event handler is triggered when the mouse is pressed when over an HTML element. onClick is intended to be a mouse dependent event handler. However, if the onClick event handler is used with hypertext links or form controls, then most major browsers and assistive technologies trigger onClick if the Enter key is pressed when the link or control has focus. In these cases, onClick is a device independent event handler. Nevertheless, the Enter key will not trigger the onClick event if it is used with non-link and non-control elements, such as plain text or table cells.
The onDblClick event handler is associated with the double click of a mouse on a selected HTML element. There is no device independent or keyboard equivalent to onDblClick, which should be avoided.

Example 1

The following link triggers a JavaScript confirmation box which allows you to confirm whether you want to view the page or not.
View this onClick example

<a href="page.htm" onclick="return confirm('Are you sure you want to view this page?');">View this onClick example</a>

Problems

None. The confirmation box is read by all major screen readers. By using the return JavaScript parameter, the link action is cancelled if the user selects No in the confirmation dialog box. If JavaScript is disabled, the link will work normally.

Example 2

The following text is styled to appear like a link (blue and underlined), but is plain text that has an onClick event which opens another document in the browser window. Use the mouse to click the following text.

View another onClick example
<p style="color:blue; text-decoration:underline" onclick="location.href='page.htm'">View another onClick example</p>

Problems

Because the text is not a hypertext link or form control, it does not receive focus while navigating with the keyboard. Because it does not gain focus, the keyboard cannot be used to activate the onClick event.

Solution

Use the onClick event handler on a link or form control instead of an element that cannot be accessed using a keyboard.

Example 3

A very common use of JavaScript is to validate form information. The following form will use JavaScript to allow you to confirm the information you have entered.
Enter your name in the following box, then press the Submit button.
Name:

<form action="page.htm" onsubmit="validate(); return false;">
<p><label for="yourname">Name:</label><input type="text" id="yourname" />
<input type="button" value="Submit" onclick="validate();" /></p>
</form>

Problems

The confirmation and alert dialog boxes that are triggered by the onClick event are accessible to browsers and assistive technologies that have JavaScript enabled. Validating the form information with a server side script and then displaying feedback on another web page allows you to bypass any problems that may occur in the JavaScript code and allows the form to validate if JavaScript is disabled. If JavaScript is used to validate the form, make sure that all form elements and functionality can be completed using the keyboard. Because the onClick handler is used with a form element, it is activated using both the mouse and the keyboard.

Note
Because most browsers will submit the form when the Enter key is pressed, the onsubmit event handler has been added to the <form> tag to ensure that the form will validate if the user does not activate the Submit button, but presses the Enter key while focus is in the text box. Also notice the required form label for the text box.

Example 4

This example also validates the form information, but feedback is displayed in another place within the page.
How many items are in a dozen? Enter the amount into the box below, then press the Check button.
Enter Answer:

<form action="page.htm" onsubmit="checkAnswer2(); return false;">
<p id="answercorrect">Correct, there are 12 items in a dozen.</p>
<p id="answerwrong">Incorrect. There are 12 items in a dozen.</p>
<p><label for="answerbox">Enter Answer:</label>
<input type="text" id="answerbox" />
<input type="submit" onclick="checkAnswer2()" value="Check" />
</p>
</form>

Problems

The feedback is not presented in a manner that would be accessible to some assistive technologies. In this example, JavaScript is modifying the display style parameters for elements within the page to make them visible or invisible based upon the response. The screen reader user would not be aware that additional content has suddenly appeared within the page.

Solutions

  1. Validate the form information with a server side script, then display the feedback on another page.
  2. Provide the feedback in a way that is accessible, such as a JavaScript alert or another form element.

onChange and onSelect

The onChange event handler is triggered when a form element is selected and changed (for example, when a radio button is initially selected or when the text changes within a text box). The onSelect event handler is processed when text is selected within a text field or text area. Although these event handlers are device independent and can be activated using the mouse, keyboard, or other device, the actions that are performed as a result of these event handlers must be analyzed to determine if they cause accessibility problems.

onChange example

The following drop-down menu form element is used for navigation. By selecting an item from the list, JavaScript will automatically open the specified page within the browser.

Note
In some browsers you may have to hit the Enter key or click on the page after selecting a menu item to activate the onchange event handler. Click on the Back button in the browser to return to this page.

Go to:

<script type="text/javascript">
<!--
function goto_URL(object) {
window.location.href = object.options[object.selectedIndex].value; }
//-->
</script>

<form action="page.htm" onsubmit="return false;">
<p><label for="selectPage">Go to:</label>
<select name="selectName" onchange="goto_URL(this.form.selectName)">
<option value="">Select a page:</option>
<option value="page.htm">Page 1</option>
<option value="page.htm">Page 2</option>
<option value="page.htm">Page 3</option>
</select></p>
</form>

Problems

The JavaScript causes the browser to go to a new page using onChange or when the user selects an item from the select list. If the end user is using a keyboard, the onChange event handler is executed for every item within the list. It is impossible for the user to directly select the last item in the list, as each previous item within the list will trigger the page change. The only way the user can select the last menu item is by navigating to the page for the first item in the list, then pressing the Back button, navigating to the second item, then pressing the Back button, and so forth until the last menu item is accessed.

Solutions

Rather than using the onChange event handler, allow the user to select the item from a list then select a button or submit the form to activate the script. When server-side scripting is used to process the form information and redirect the browser accordingly, there is no need for JavaScript at all. The following code demonstrates one method of fixing the onChange problem.
Select a page using the drop-down menu then select the Go! button. Click on the Back button in the browser to return to this page.
Go to:

<form action="page.htm" onsubmit="return false;">
<p><label for="selectPage2">Go to:</label>
<select name="selectPage2" id="selectPage2">
<option value="">Select a page:</option>
<option value="page.htm">Page 1</option>
<option value="page.htm">Page 2</option>
<option value="page.htm">Page 3</option>
</select>
<input type="button" value="Go!" onclick="goto_URL(this.form.selectPage2);" />
</p>
</form>

Using Device Independent Event Handlers

As mentioned previously, several event handlers are device independent, including onFocus, onBlur, onSelect, onChange, and onClick (when onClick is used with link or form elements). When possible, use device independent event handlers. Other event handlers are device dependent, meaning that they rely wholly upon a certain type of input. For instance, onMouseOver, onMouseOut, and onDblClick rely upon the use of a mouse. There are also some event handlers that are dependent upon use of the keyboard (onKeyDown, onKeyUp, etc.). Multiple device dependent event handlers can be used together to allow both mouse and keyboard activation of JavaScript. For instance, both onMouseOver and onFocus (as well as onMouseOut and onBlur) can be used to provide both keyboard and mouse activation of a script. Using multiple device dependent event handlers together as a method of implementing device independence requires a great deal of testing across different browsers and assistive technologies to ensure that accessibility is not limited in any way.

Dynamic HTML and Accessibility

Dynamic HTML (DHTML) is typically a combination of Cascading Style Sheets (CSS) and JavaScript. DHTML allows developers to display, hide, or move information based upon input from the user or pre-programmed commands. Many of the examples in this section have used DHTML. Most drop-down or fly-out menu systems found on Web pages also use DHTML. Because most of these DHTML elements are modified based upon mouse input, they are typically inaccessible to users who do not use a mouse. When DHTML is used, two items must be evaluated to determine its impact on accessibility:

  1. Is the event used to trigger a change device independent? If the mouse is required, then it is not fully accessible.
  2. Is the DHTML content or functionality itself accessible? If assistive technologies cannot adequately access DHTML triggered content or functionality, then it is not fully accessible.

Using document.write

Dynamic, constantly changing information is being written to the page in this example using the document.write command in JavaScript. In most cases, content that is written to the page using JavaScript is accessible to assistive technologies. However, if the dynamic content is constantly changing or otherwise interferes with navigation or browser functionality, then it may cause accessibility problems.

document.write example

The current time is displayed in the text box below. It updates and changes every second.
The current time is:

Problems

In this case, because the content is constantly changing and refreshing, a screen reader would not be able to read it and it may cause some confusion.

Solutions

When using dynamic information, you must first ask yourself if it is necessary and vital to the function or content of the page. If so, there is often a way to provide the content without using inaccessible JavaScript. For instance, you could write the current time to the page when it loads using a server-side script. Though it will not be constantly updating, it may suffice. You may also have the user select a link or button to go to another page that displays the current time from server side processing. Another approach that uses a more accessible implementation of JavaScript would be to provide a link or button that allows the user to display the current time at their request.

<input type="button"
value="Display the current time"
onclick="alert('The current time is ' + timeValue);" />

Pop-up Windows

Pop-up windows provide a unique accessibility problem. First of all, most usability experts would argue against the use of pop-up windows except in the most extreme of cases. If you must use pop-up windows, know that they introduce several very unique accessibility issues. For a visual user, it may be difficult to notice and navigate to the new window. For someone who is using assistive technologies, the new window may be annoying and confusing because the default behavior for the link has been modified. JavaScript implementation may make the new window difficult or impossible to resize or scale for someone using a screen enlarger. For someone who is blind, there is typically no indication that they are presently navigating in a new window. When the screen reader user attempts to return to the previous page by selecting the back button, it may be confusing to find that this does not work.

Pop-up example

Select this link to open a new window

<a href="popup.htm"
onclick="window.open(this.href); return false;">Select this...</a>
Note
If you are using software to block pop-up windows, you may need disable the software or select the link in a way that bypasses the pop-up blocker (typically Ctrl + click or Ctrl + Enter with the link selected).

In the example code above, the link will continue to work normally (i.e., in the same browser window) if JavaScript is disabled.
When using JavaScript to open new windows, you can modify the size and position of the new window. You can also add or remove functionality of the window, such as the ability to resize, display scroll bars, show tool bars, etc. Be very careful when changing the default behavior of the browser window. If a user has low vision and must enlarge the content, a small window that cannot be enlarged and does not display scroll bars would be very inaccessible. Someone with a motor disability may rely upon large tool bars to accurately control the web browser, so removing or modifying them may introduce difficulties for this user.
As you can see, there are many difficulties in both usability and accessibility that arise through the use of pop-up windows. Care must be taken in making the decision to use them. If they are used, thorough user testing of your implementation is vital to ensure accessibility. Always alert the user to the fact that a pop-up window will be opened.

Redirecting and Refreshing Browser Windows

When the page the browser is viewing suddenly changes or refreshes, the person viewing that page may become disoriented or confused, especially if that person is using an assistive technology. This is commonly done with page redirects when page content has been moved or updated. Section 508 requires that users be given control over time sensitive content changes. Do not automatically change or refresh the browser window without first alerting the user that the change will occur and giving him/her the ability to disable or postpone the change.

Using Pure CSS as a JavaScript Alternative

As mentioned previously, Cascading Style Sheet (CSS) parameters are often modified using JavaScript to create dynamically changing DHTML pages. However, with the advent of CSS version 2, much of the dynamic functionality available with JavaScript is now contained within the specifications for CSS itself. This allows the construction of interactive and dynamic navigation and layout elements without the need for JavaScript events. You can create drop-down menus, interactive images, and other exciting features in Web sites without worrying about device dependent event handlers. However, the new CSS standards are not fully supported in modern browsers, namely Internet Explorer.
Also, screen readers do not have great CSS support, especially when presented with content that can be made visible or invisible using either the display:none or visibility:hidden styles. Many screen readers do not read content that is assigned these styles even though the content is still part of the underlying structure of the page. Until there is better CSS support in both web browsers and assistive technologies, using CSS alone to produce dynamic content should only employed with much testing in a variety of browsers and screen readers.

Introduction

Whenever JavaScript cannot be made directly accessible, an accessible alternative must be provided. Also, many user agents, such as web-enabled cell phones and PDA’s, do not yet utilize JavaScript. There are several ways you can provide accessible alternatives when the scripting cannot be made accessible or when the end user does not have JavaScript enabled.

Server-side Processing

In many cases, the functionality provided by JavaScript can be duplicated by server-side scripting. For example, JavaScript is often used to validate form elements before a form is posted. Instead of implementing such JavaScript programming and its accompanying accessibility techniques, you could use a server-side script to validate the form elements. JavaScript is often used to write dynamic information to a web page, such as the current date and/or time. Again, using a server script or server-side include negates the need for additional accessibility implementation.

Using the <noscript> Element

Making JavaScript natively accessible is very important. However, in some cases, the end user may not have JavaScript enabled or may be using technologies that do not support JavaScript (e.g., cell phone, PDA, etc.). In such cases, you can provide non-JavaScript alternatives to user’s who cannot or choose not to view JavaScript content.
When JavaScript is used within a Web page, the most straightforward way to provide an alternative for the JavaScript-generated content is to provide content within the <noscript> element. The <noscript> element can be used within your page to display content in browsers that do not support or have disabled JavaScript. However, if JavaScript IS enabled the <noscript> element is ignored.

Important
Providing an accessible alternative within the <noscript> element for an inaccessible script will not make the page accessible. The <noscript> content will only display if JavaScript is disabled. Most screen reader users have JavaScript enabled, and will thus encounter your inaccessible script and not the <noscript> content.

The <noscript> element provides alternative text for the JavaScript. If the content or functionality of the script needs an accessible alternative when JavaScript is disabled, then you need <noscript>. The <noscript> content should ideally contain the equivalent content or functionality that is provided by the script. However, this is often not possible. It is not sufficient to simply indicate, “Your browser does not support JavaScript.” This does nothing to make the content accessible. You may, for example, provide a link to an accessible HTML alternative or to a page that utilizes server-side scripting instead. Or, at very least, describe the type of content that would be displayed if JavaScript were enabled.
<noscript> should be used anytime alternative or non-javascript content or functionality is required.

<script type="text/javascript">
<!-- document.write("The current time is " + currenttime) -->
</script>
<noscript>
<!-- link to page that displays time from server-side script -->
<a href="time.htm">View the current time</a>
</noscript>

<noscript> example

In the following example, two form buttons are provided within the HTML code. If you have JavaScript enabled, the document.write command within the <script> element will display the first button. If this button is selected, it triggers a JavaScript function that may be used to validate and submit the form using additional JavaScript within the page. If JavaScript is not enabled, then the button contained within the <noscript> element is displayed, which could submit the form to a server-side processing script, which would provide the form validation and feedback.
Username:

<script type="text/javascript">
<!--
document.write('<input type="button" value="Submit" onclick="validateForm();" />');
-->
</script>
<noscript>
<p>
<input type="submit" value="Submit">
</p>
</noscript>

 

Overview

JavaScript allows developers to add increased interaction, information processing, and control in web-based content. JavaScript can also cause accessibility problems by limiting navigation using a keyboard or assistive technology, presenting content or functionality that is not accessible to assistive technologies, limiting user control over automated content changes, and modifying the normal functionality of the browser. When faced with JavaScript accessibility issues, you must do one of the following:

  • Ensure the JavaScript is directly accessible
  • Provide an accessible, non-JavaScript alternative

JavaScript is often used to make cosmetic or other content changes that do not affect accessibility. Content written to the page using JavaScript is accessible if:

  • Device independent event handlers are used.
  • JavaScript enabled content and functionality is accessible to assistive technologies.
  • Scripted pages and elements are navigable using a keyboard.
  • The normal browser functionality is not modified in a way that may cause confusion or inaccessibility.
  • An accessible alternative is provided when JavaScript cannot be made natively accessible.

JavaScript Event Handlers

There are two types of JavaScript event handlers – device dependent and device independent. When implementing event handlers, you must either use a device independent event handler or use multiple device dependent event handlers to accommodate all users. Below is a list of common event handlers and their associated accessibility issues.

onMouseOver and onMouseOut
Device dependent (require the use of a mouse)
Ensure important content or functionality is not introduced with these event handlers
Use in conjunction with the onFocus and onBlur event handlers to allow keyboard accessibility
Provide an accessible alternative if the content or functionality cannot be made natively accessible
onFocus and onBlur
Device independent (work with both keyboard and mouse)
Test to ensure that accessibility is not affected
onClick and onDblClick
Device dependent (require the use of a mouse)
onClick is activated by keyboard input when used with links and form elements
There are no device independent or keyboard accessible equivalents to these event handlers
Functionality and content provide by the onClick event handler must also be made accessible
onChange and onSelect
Device independent (work with both keyboard and mouse)
Functionality and content provide by the onChange and onSelect event handlers must also be made accessible
Drop-down menu navigation items that are triggered with onChange are not fully keyboard accessible

Dynamic HTML and Accessibility

Dynamic HTML (DHTML) is a combination of JavaScript and Cascading Style Sheets (CSS). By its very nature, DHTML can present dynamically changing content. DHTML is often triggered by user interactions, such as moving the mouse. When implementing DHTML, you must ensure that the DHTML is triggered in a device independent way and that the content and functionality provided by the DHTML is also accessible.
JavaScript can also be used to write dynamic content to the web page. In most cases, this content is accessible, unless the content is constantly changing or is in any other way interfering with accessibility of the page.

Pop-up Windows

The default behavior of the web browser and certain HTML elements can also be affected by JavaScript. Pop-up windows can be triggered by JavaScript or by JavaScript event handlers. If the user is not alerted to the fact that a pop-up window is opening, they may become confused or disoriented by the unnatural behavior of the Web browser. Further modification of browser windows to remove scroll bars, status bars, menu bars, or tool bars may also cause accessibility problems. Use pop-up windows with care and if they are used, always alert the user to this fact. The user must also be alerted when JavaScript is used to automatically perform browser functions, such as redirecting, refreshing, or automatic scrolling. In all cases, user testing and testing with assistive technologies can provide valuable feedback regarding accessibility of specific JavaScript implementations.

JavaScript Alternatives

There are many ways to provide alternatives to JavaScript. Newer versions of CSS allow much of the behavior of JavaScript to be replicated using CSS alone. Drop-down menus, navigation bars, and interactive images can all be developed without relying on JavaScript. However, the implementation of CSS across browsers and assistive technologies is varied and problematic. When JavaScript itself cannot be made natively accessible, you must provide an accessible alternative. This can be done by replicating or replacing the JavaScript behavior with server-side processing. You can also provide <noscript> content which will be accessible when JavaScript is disabled or not available to the end user.

Standards and Guidelines

The following standards and guidelines apply to JavaScript:

Section 508 of the Rehabilitation Act §1194.22:

  • (l): When pages utilize scripting languages to display content, or to create interface elements, the information provided by the script shall be identified with functional text that can be read by assistive technology.
  • (n) When electronic forms are designed to be completed on-line, the form shall allow people using assistive technology to access the information, field elements, and functionality required for completion and submission of the form, including all directions and cues.
  • (p) When a timed response is required, the user shall be alerted and given sufficient time to indicate more time is required.

W3C Web Content Accessibility Guidelines (WCAG) 1.0:

  • 6.3 (Priority 1): Ensure that pages are usable when scripts, applets, or other programmatic objects are turned off or not supported. If this is not possible, provide equivalent information on an alternative accessible page.
  • 6.4 (Priority 2): For scripts and applets, ensure that event handlers are input device-independent.
  • 6.5 (Priority 2): Ensure that dynamic content is accessible or provide an alternative presentation or page.
  • 7.4 (Priority 2): Until user agents provide the ability to stop the refresh, do not create periodically auto-refreshing pages.
  • 7.5 (Priority 2): Until user agents provide the ability to stop auto-redirect, do not use markup to redirect pages automatically. Instead, configure the server to perform redirects.
  • 8.1 (Priority 2): Make programmatic elements such as scripts and applets directly accessible or compatible with assistive technologies.
  • 10.1 (Priority 2): Until user agents allow users to turn off spawned windows, do not cause pop-ups or other windows to appear and do not change the current window without informing the user.
%d bloggers like this: