ChocolateChip-UI 3.0.3 Supports jQuery

As of version 3.0.3, ChocolateChip-UI now supports jQuery 2.0.3. We tried earlier versions of 2.x, but there where performance issues that prevented us from offering it as an option. jQuery 2.0.3 has proven to be a good option for mobile Web apps as far as size and speed. As such, going forward we will be supporting jQuery with the latest version of ChocolateChip-UI.

This means you can use other frameworks or plugins with jQuery dependencies and still take advantage of the great features in ChocolateChip-UI for creating cross-platform Web apps for iOS 7, Android Jelly Bean and Windows Phone 8.

For more information about jQuery support in ChocolateChip-UI, please visit ChocolateChip-UI.com and read the documentation for jQuery Support.

About these ads

iOS 5 Style Switch Control

Recreating the iOS 5 Switch Control with HTML5, CSS3 and a Bit of ECMAScript 5

The final result of this post will run in iOS 5, Safari 5.1, as well as the latest versions of Chrome, Firefox and Opera.

Previously I had created a version of the switch control in iOS. With the launch of iOS5 Apple complete updated the look of the switch control. They went with a rounded style, which they also did with most controls in their desktop operating system, Lion.

After playing around with the early betas of iOS 5, I came up with the following reproduction of the new switch control look using just HTML5, CSS3 and some JavaScript for the interactive part. Functionally the switch control is nothing more than a fancier way of presenting a checkbox. So, for our purposes we are going to use a checkbox. Except that we need a couple of tags to wrap the checkbox so we can make it look like the switch control. Fortunately the amount of wrapper is really minimal. If you examine the picture below, you will notice that the switch control really has only two parts: the oblong base and the circular thumb. In our case we need a third part: a checkbox input.

Switch Control

We’re going to make a minor tweak to this default look. You’ll notice that the version above is in English. Actually, only the English version has labels for “On” and “Off”, everyone else uses the international symbols instead. They look like this:

International version of Switch Control

If we ignore the “On/Off” parts and just look at the colored areas we can see that we’re only really dealing with a simple vertical gradient on the thumb and some inset box shadows on the switch control base. This makes our styling really easy. For the “On/Off” parts we don’t need extra markup. You’ll notice that they exist in relation to the switch control’s thumb. We can use CSS pseudo elements on the thumb to create them.

To recreate the iOS5 switch control all we need is the following markup:

	<div class="switch">
		<span class="thumb"></span>
		<input type="checkbox" />
	</div>

Without styling, this gives us a very normal checkbox:

Unstyled switch control

We know what the dimensions need to be by measuring the screenshots, so we can give the switch control base some styling:

	.switch {
		height: 28px;
		width: 77px;
		border: 1px solid #979797;
		border-radius: 20px;
		overflow: hidden;
	}

This will give us the following:

Switch control with rounded border

It looks kind of funny with the checkboxes. We don’t need to see them. We will be setting their checked state with JavaScript later on anyway. So for now we can hide them:

	.switch input[type=checkbox] {
		display: none;
	}

Now let’s add some color. How to re-create that gray shadow area? We’ll use a series of inset box shadows. Like gradients, you can define multiple box shadows on an element. These stack up like layers, the last one being the bottom-most and the first being the top-most. We need to create a sizable gray choke inside the switch base, so we’ll use a box shadow with four values instead of three to create that effect:

	box-shadow: inset 0 12px 3px 2px rgba(232, 232, 232, 0.5);

To this we’ll add a second inset box shadow to create a darker shadow along the top inside of the switch control:

	box-shadow: inset 0 1px 3px #BABABA, inset 0 12px 3px 2px rgba(232, 232, 232, 0.5);

Switch control with gray box shadow

Here’s the complete CSS definition for the switch control:

	.switch {
		height: 28px;
		width: 77px;
		border: 1px solid #979797;
		border-radius: 20px;
		margin-top: -5px;
		box-shadow: inset 0 1px 3px #BABABA, inset 0 12px 3px 2px rgba(232, 232, 232, 0.5);
		cursor: pointer;
		overflow: hidden;
	}

Now for a tricky part. This gray inset box shadow is for the off state. How do we implement the bluish on state? Well, first of all we need to decide how to represent the states in markup. We’ll do this by added a class of “on” to the switch control base. That means that the base will have a class of “switch on” for when it’s flipped on and just “switch” when it’s off. We can use a pseudo element on the switch base to create the blue state and position it in view or out of view based on the presence of the “on” class. Of course we’re going to need a little JavaScript to set and remove the “on” class when the user clicks. So, here’s the CSS for the on state. We create an empty text node and give it the height we need to match the base. We don’t give it a width just yet since that will get set when the switch has the “on” class. We give it a bluish background color and inset box shadow. The absolute positioning is so that when it’s show, it doesn’t push the thumb out of the switch but instead sits independently inside the switch.

	.switch::before {
		content: "";
		display: block;
		height: 28px;
		width: 0px;
		position: absolute;
		border-radius: 20px;
		box-shadow: inset 0 1px 2px #0063B7, inset 0 12px 3px 2px rgba(0, 127, 234, 0.5);
		background-color: #64B1F2;
	}

To show the “on” state we just need to give the blue pseudo element the same width as the base:

	.switch.on::before {
		width: 77px;
	}

If we add the “on” class to one of our switches, we can see how the on state looks:

	<div class="switch on">
		<span class="thumb"></span>
		
	</div>

Switch control with 'on' state

That’s all we need for the switch control’s base. Now let’s tackle the thumb. We’ll make the span a block element with dimensions, set its positioning to relative so we can give it a higher z-index than the other elements in the switch control, specifically, the blue on state pseudo element. Next up: border, box shadow and gradient, very straightforward. And finally, because we want to have the thumb slide back and forth when the switch is clicked, we need to enable a CSS transition and give it a default translate value. Note: you will need to add an appropriate vendor prefix for the gradient, transition and transform.

	.switch > .thumb {
		display: block;
		width: 26px;
		height: 26px;
		position: relative;
		top: 0;
		z-index: 3;
		border: solid 1px #919191;
		border-radius: 28px;
		box-shadow: inset 0 2px 1px white, inset 0 -2px 1px white;
		background-color: #CECECE;
		background-image: linear-gradient(top, #CECECE, #FBFBFB);
		transition: all 0.125s ease-in-out;
		transform: translate3d(0,0,0);
	}

This gives us the following:

Switch control with thumb

As you can see, all thumbs are in the same place. We need to define a translate value for their “On” state:

	.switch.on > .thumb {
		-webkit-transform: translate3d(49px,0,0);
		-o-transform: translateX(49px);
		-moz-transform: translateX(49px);
	}

Which gives us:

Switch control thumb in 'on' state

Now the only thing left is to create the “on/off” indicators. We’ll start with the “on” one. It’s really quite simple. a vertical stripe with a border around it. We’ll create a pseudo element that has an empty text node, style it and position it beside the thumb. Here’s the CSS:

	.switch > .thumb::before {
		content: "";
		display: block;
		height: 14px;
		width: 2px;
		background-color: white;
		box-shadow: 0px -1px 1px #666;
		border: none;
		position: absolute;
		top: 6px;
		left: -24px;
	}

Switch control with 'on' state indicator

And for the “off” indicator, we create a pseudo element with an empty text node styles as a circle positioned to the right of the thumb:

	.switch > .thumb::after {
		content: "";
		display: block;
		height: 10px;
		width: 10px;
		border-radius: 10px;
		border: solid 2px #777;
		position: absolute;
		right: -32px;
		top: 6px;
	}

Switch control with 'off' state indicator

Now we have a fully styled switch control with minimal markup. We just need to add some interactivity. For that we’ll have to write some JavaScript. Since this is a self-contained example, I’m going to use the very latest version of ECMAScript 5. This gives me an easy way to get DOM elements and toggle classes on elements. If you want to reuse this you’ll need to switch those parts out for whatever methods your chosen JavaScript library provides.

So, first up I’m going to wrap everything up in an anonymous function:

	(function() {
	
	})();

Next I need a convenience method to get a collection of nodes and turn it into an array so I can iterate over it. I use call slice method of the Array object and pass in the results of querySelectorAll. That will convert the node collection into an array:

	(function() {
		var $$ = function(selector) {
			return Array.prototype.slice.call(document.querySelectorAll(selector));
		}
	})();

Now I want to define an event that executes when the DOM is fully loaded:

	(function() {
		var $$ = function(selector) {
			return Array.prototype.slice.call(document.querySelectorAll(selector));
		}
		document.addEventListener("DOMContentLoaded", function() {
		
		}, false);
	})();

After getting an array of all switch controls in the document, we iterate through them with the **forEach** method and bind a click event listener. The listener will execute a function that toggles the class “on”. ECMAScript 5 introduces a new token collection for classes called classList. This has several useful functions: add, remove, contains and toggle. To accomplish these methods with straight JavaScript you would need to use regular expressions. Instead I can just use **Element.classList.toggle(“on”)** to add and remove the class when the user clicks:

	(function() {
		var $$ = function(selector) {
			return Array.prototype.slice.call(document.querySelectorAll(selector));
		}
		document.addEventListener("DOMContentLoaded", function() {
			$$(".switch").forEach(function(switchControl) {
				switchControl.addEventListener("click", function toggleSwitch() {
					switchControl.classList.toggle("on");
				}, false);
			});
		}, false);
	})();

With the above JavaScript in our document, when the user clicks a switch control, the class “on” will be added to or removed from the switch, causing its thumb to slide to the left or right accordingly. This handily takes care of our visual requirements for the functionality of the switch control. However, we do need to manage the checked state of the checkbox. The first thing we’ll do is make sure any switch controls that had the class “on” during page load have their checkboxes set to chekced. Since the checkbox is the last element in the switch control div, we can reference it that way:

	(function() {
		var $$ = function(selector) {
			return Array.prototype.slice.call(document.querySelectorAll(selector));
		}
		document.addEventListener("DOMContentLoaded", function() {
			if (switchControl.classList.contains("on")) {
				switchControl.lastElementChild.checked = true;
			}		
			$$(".switch").forEach(function(switchControl) {
				switchControl.addEventListener("click", function toggleSwitch() {
					switchControl.classList.toggle("on");
				}, false);
			});
		}, false);
	})();

Next we need to update a switch controls checkbox when the switch control itself is clicked. We just need to again get a reference to the checkbox and set its clicked state to the opposite of what it was when the user clicked:

	(function() {
		var $$ = function(selector) {
			return Array.prototype.slice.call(document.querySelectorAll(selector));
		}
		document.addEventListener("DOMContentLoaded", function() {
			var checkbox;
			if (switchControl.classList.contains("on")) {
				switchControl.lastElementChild.checked = true;
			}		
			$$(".switch").forEach(function(switchControl) {
				switchControl.addEventListener("click", function toggleSwitch() {
					checkbox = switchControl.lastElementChild;
					checkbox.checked = !checkbox.checked;
					switchControl.classList.toggle("on");
				}, false);
			});
		}, false);
	})();

And that’s all you need to make the switch controls work. The final example has some extra JavaScript to output some text when the user flips a switch on to show them working. For Safari, Chrome and Opera, I use innerText to set the text value, but Firefox uses textContent. So the code has to deal with those differences.

You can try the working example. If you want the code, just save that page to your desktop. Everything is self-contained in the page.

ChocolateChip-UI for Zepto

I’ve ported ChocolateChip-UI to the JavaScript micro framework Zepto. Created by Thomas Fuchs of Scriptaculous fame, Zepto is a small JavaScript library for mobile devices that replicates the functions of jQuery. If you use jQuery but want to do mobile development and are disappointed with jQuery mobile’s size and performance, Zepto may be your solution. Zepto has a very small footprint and performs well on mobile devices. But Zepto provides only the equivalent of jQuery itself. If you need something to help you get your interface and widgets together, ChocolateChip-UI with Zepto provides a complete solution.

Although Zepto’s methods are the same as jQuery’s, it is not a clone of jQuery. The way it works internally is quite different. Yet it literally only took me a few hours to port the jQuery version of ChocolateChip-UI to Zepto. One major difference is that Zepto’s data method stores strings on a node using HTML5’s data attribute, whereas jQuery’s data method uses a sophisticated caching system to store any kind of data. However, on mobile browsers, HTML5 offers local storage and client side database for data persistence so this isn’t that big of a limitation. It does require more work (coding) on your part to accomplish the same thing that jQuery’s data method provides.

Check out .

Performance and size-wise, ChocolateChip-UI with Zepto is equivalent to ChocolateChip-UI with ChocolateChip. So, it’s really just up to a matter of personal preferences. If you like the coding conventions that jQuery demands, then go with Zepto. If you’d prefer more freedom to use normal JavaScript and want to break out of the jQuery mold, go with ChocolateChip.

ChocolateChip-UI

Learn more about ChocolateChip-UI

ChocolateChip.js is now ChUI (pronounced “chewy”)

In the course of time I’ve created a lot of POCs (proof of concepts) on this blog. Some where fairly good, some where flaky one-offs. In the process I also created a small JavaScript library — ChocolateChip.js — that I used for actualizing most of these demos. Seeing how many people come to this humble blog in search of solutions to their development projects, I though about taking all the good ideas in these demos and putting them together as a one stop solution for mobile Web app development. I’m therefore today announcing ChocolateChip-UI. At present it’s a beta, but I intend to keep developing it to add more useful features over time. I

ChocolateChip-UI consists of ChocolateChip.js plus two other files: ChUI.js and ChUI.css. ChUI.js is a collection of JavaScript methods built on top of ChocolateChip.js. ChUI.js provides controls and widgets enlivened with behaviors needed for Web app development. ChUI.css is the magical CSS that makes simple markup look and act in a amazing way.

ChocolateChip-UI also introduces a new concept: WAML (Web App Markup Language). This is a specialized set of tags and attributes that get around the limits of HTML. HTML tags are really about creating documents, like books and other text publications. In contrast, WAML is a collection of tags and attributes that make sense for Web app development. ChUI.js and ChUI.css are built around the implementation of WAML as the key to how ChocolateChip-UI works.

WAML takes the paradigms of mobile application development and transfers those over to the development of mobile Web apps. There’s no need to smother and bury HTML tags with tons of classes trying to make markup meant for publishing documents work for creating applications. At the same time, WAML is really just a superset of HTML5 markup. You can therefore use any HTML5 tags and attributes along with WAML and ChocolateChip-UI to implement your solution.

ChocolateChip-UI is about making Web app development more straightforward. It provides common controls which have built in functionalities. Instead of having to figure out how to build these yourself, you can spend that time providing the data you want through ChocolateChip-UI’s controls easy to use controls.

The interfaces and controls which ChocolateChip-UI provides are all created using only markup and CSS. No images are required, no gifs or pngs. This means that everything you build with ChocolateChip-UI will be resolution independent. It will look good on a handheld mobile device and on a big HDMI screen. ChocolateChip-UI also provides a set of 52 SVG icons for use with buttons. Because these are vector based, they too are resolution independent. ChocolateChip-UI is therefore the first resolution independent mobile Web app framework.

ChocolateChip Has Its Own Blog

ChocolateChip, the little guy that does big things

So, ChocolateChip, the tiny JavaScript mobile Web framework that is only 8k when minified, now has its own blog: ChocolateChip-Mobile.net. I put this blog together to show how ChocolateChip works and how you can use it to accomplish your coding needs. I also talk about best coding practices with ChocolateChip.

ChocolateChip can be so small because it doesn’t have to support ancient browsers or compensate for cross-browser nightmares. Instead it takes advantage of modern browsers’ implementation of the features in ECMAScript 5 and DOM level 3. The idea was to keep ChocolateChip simple, avoiding object wrappers and object obfuscation, and making everything interchangeable with regular JavaScript. That means you can adjust ChocolateChip to your coding style, not the other way around. You can substitute any ChocolateChip for your own code at any time. As a matter of fact, if you don’t like the default $, $$ aliases that ChocolateChip uses, open up the files and change them to whatever you want. ChocolateChip is open source with a BSD license, so if you want to add some feature, feel free to. And if you feel like sharing your feature with the rest of us, feel free to contact me.

Have a great day and enjoy your ChocolateChip.

Making an iPhone Switch Control without Images

Works on desktop Safari, Chrome and Firefox, iPhone, iPod Touch and iPad.

On the iPhone and iPad, Apple uses a control called switch. It’s actually a different take on the checkbox. Like radio buttons, checkboxes do not lend themselves to touch interfaces, especially guys with fat fingers, cough! Instead of making us suffer with those dinky checkboxes, Apple uses a more visual cue to what the user is actually doing, switching something on or off. As a matter of fact, that’s exactly how the control is labeled: “on” or “off”. They’re really easy to use, just swipe your finger to throw the switch, done. In case you’re not sure what I’m talking about, here they are:

switch control

OK, so all the mobile Web frameworks have a switch control. And I hate them all. They either do an instant switch between the on and off state, using an image sprite, or they do this really lame thing where they animate the horizontal background position of the image on a checkbox with its default styles removed. None of those implementations feels the same as when you swipe the switch control in a native iOS app.

So what am I going to do? I tell you, I’m going to throw the friggin’ image out and build the whole control from scratch using just HTML, CSS3 and some JavaScript to make it work. Bada-bing! To start with, here’s the basic markup for a checkbox:

<div class="checkbox unchecked" id="sleepSwitch">
	<div class="on">ON</div>
	<div class="thumb"><span></span></div>
	<div class="off">OFF</div>
	<input type="checkbox" value="ZZZZZZZZ!" offvalue="But, I need more sleep!">
</div>

As we did when we created iPhone style radios buttons, we’re using real checkboxes in our iPhone switch controls. And like in the radio button example, we’ll set the checkbox input’s display value to “none”. We’ll use CSS3 properties to style the markup to look like a real iOS switch control and we’ll attach event listeners to set the input checkbox’s check state to true or false, depending on whether we want it to be selected or not.

To create this switch control we’ll need to style the frame named “checkbox” with rounded corners. Notice that the markup above contains three parts: the on state, the thumb and the off state. The rounded frame will only be wide enough to show one state plus the thumb. Using CSS3 transitions and transforms, a click or touch will cause the three elements to side back and forth within the rounded frame. For positioning the switch’s elements and sliding them back and forth we’re going to use CSS3 3d transforms on the x axis. Here is the CSS to make this happen:

/* Checkbox */
.checkbox {
	display: -webkit-box;
	-webkit-box-orient: horizontal;
	-webkit-box-pack:justify;
	-webkit-box-sizing: border-box;
	-webkit-tap-highlight-color: transparent;
	width: 94px;
	overflow: hidden;
	-webkit-border-radius: 6px;
	text-align: center;
	line-height: 28px;
	cursor: pointer;
	-webkit-user-select: none;
	position: absolute;
	right: 10px;
	top: 7px;
}
.checkbox > input[type="checkbox"] {
	display: none;
}
.checkbox .thumb {
	-webkit-border-radius: 7px;
	position: relative;
	z-index: 3;
	border: solid 1px #919191;
	-webkit-transition: all 0.125s  ease-in-out;
	-webkit-transform: translate3d(0px,0%,0%);
}
.checkbox .thumb span {
	display: block;
	-webkit-box-sizing: border-box;
	height: 25px;
	width: 38px;
	border-top: solid 1px #efefef;
	-webkit-border-radius: 6px;
	background-image: -webkit-gradient(linear, left top, left bottom, from(#cecece), to(#fbfbfb));
	border-top: solid 1px #efefef;
	position:relative;
}
.checkbox .on {
	color: #fff;
	background-image: 
		-webkit-gradient(linear, left top, left bottom, 
			from(#295ab2), 
			to(#76adfc));
	width: 54px;
	padding-right: 4px;
	border: solid 1px #093889;
	-webkit-border-top-left-radius: 6px;
	-webkit-border-bottom-left-radius: 6px;
	margin-right: -6px;
	height: 25px;
	-webkit-transition: all 0.125s  ease-in-out;
	position: relative;
	-webkit-transform: translate3d(0px,0%,0%);
}
.checkbox .off {
	color: #666;
	background-image: -webkit-gradient(linear, left top, left bottom, from(#b5b5b5), color-stop(0.50, #fff));
	width: 54px;
	padding-left: 4px;
	border: solid 1px #a1a1a1;
	-webkit-border-top-right-radius: 6px;
	-webkit-border-bottom-right-radius: 6px;
	margin-left: -6px;
	height: 25px;
	-webkit-transition: all 0.125s  ease-in-out;
	position: relative;
	-webkit-transform: translate3d(-54px,0%,0%);
}
.checkbox.unchecked .thumb {
	-webkit-transform: translate3d(-54px,0%,0%);
}
.checkbox.checked .thumb {
	-webkit-transform: translate3d(0px,0%,0%);
}
.checkbox.unchecked .on {
	-webkit-transform: translate3d(-60px,0%,0%);
}
.checkbox.checked .on {
	-webkit-transform: translate3d(0px,0%,0%);
}
.checkbox.unchecked .off {
	-webkit-transform: translate3d(-54px,0%,0%);
}
.checkbox.checked .off {
	-webkit-transform: translate3d(6px,0%,0%);
}
/* For Very Important changes, use the orange checkbox */
.checkboxBase.important .on {
	border: solid 1px #d87100;
	background-image: -webkit-gradient(linear, left top, left bottom, from(#e75f00), color-stop(.5, #ff9c12));
}
/* End Checkbox */

To make the switch more realistic, I’m transforming all three pieces of the switch at the same time. This gives the switch a more realistic feeling. Notice the comment in at the end of the above CSS about the important class. You can use this to indicate a switch that makes a very important change. This class changes the default switch’s blue color to bright orange. This is the color Apple uses to show that a switch’s action is very important.

Having the CSS defined for the look and animation brings us close to the finished control, but we need to write some JavaScript to make the switch interactive. The JavaScript needs to do two things: toggle the classes “checked” and “unchecked” on the switch, and toggle the checked value of the checkbox between true and false. I’m using the ChocolateChip JavaScript framework to do this. You can switch my code to whatever library you want. If you know basic JavaScript, it shouldn’t be hard. Here’s the JavaScript to make it happen:

Element.prototype.toggleSwitch = function() {
	if (this.hasClass("switch")) {
		if (this.last().checked === true) {
			this.last().checked = false;
			this.toggleClass("checked", "unchecked");
		} else {
			this.last().checked = true;
			this.toggleClass("checked", "unchecked");
		}
	} else {
		return false;
	}
};

The last() used in the code above is a ChocolateChip method to return the last child of the control, which happens to be the checkbox input. That way we can set its checked state to true or false.

Now that we have the code to setup up the switch control, we can make it work as follows:

$(".switch").forEach(function(checkbox) {
	checkbox.bind("click", function() {
		this.toggleSwitch();
	});
	
	checkbox.bind("touchstart", function(e) {
		e.preventDefault();
		this.toggleSwitch();
	});
}); 

That’s it to make the switch switchable. But to make it do something you’d need a bit more as well. In my example, I’m getting some values from the switch and outputting it to a response field like this:

$(".switch").forEach(function(checkbox) {
	checkbox.bind("click", function() {
		if (this.last().checked === true) {
			$("#switchResponse").fill(
				this.last().getAttribute("value"));
		} else {
			$("#switchResponse").fill(
				this.last().getAttribute("offvalue"));
		} 
	});
	
	checkbox.bind("touchstart", function(e) {
		if (this.last().checked === true) {
			$("#switchResponse").fill(
				this.last().getAttribute("value"));
		} else {
			$("#switchResponse").fill(
				this.last().getAttribute("offvalue"));
		}
	});
}); 

You can try this out online or download the source code.

User Controled Color Theme

Works on Desktop Safari, desktop Google Chrome, desktop Firefox 3.6-4, iPhone, iPod Touch, iPad.

So, in the last blog post I showed how to make RGB slides with HTML, CSS and some JavaScript. I thought about it and, while interesting, it doesn’t have a whole lot of practical application. Sure you could take that and hook up any other type of value to get whatever result you might need for your interface. Well that got me to thinking, so I threw together an implementation of the RGB sliders that allow a user to change the color scheme of a Web app. No need to spend time creating different color themes. Let the user do it.

OK, before you think I’m crazy, especially you folks from the design community, let me explain. I came up with a basic theme technique. I call it chromaeleon &mdash because the app’s chrome can change colors like a chamaeleon. The way this works is, instead of solid color gradients, you create gradients with transparent values of black and white. Behind this you have a background color which shows through the transparent gradients. This way, when the user drags the sliders, the background colors update and the look of the interface changes. Now in the real world you’d want to provide a way for the user to save their color choice. You could save the choice to localStorage. Then when the app loads, it checks to see it the user saved a color choice, if not, it goes to the default. Sorry, I didn’t do all of that. Just the part to update the background colors. Here’s what it will look like:

iPhone Chromaeleon Interface

The structure we’re going to use is pretty must standard as we’ve used elsewhere, a header, a section, some buttons.

<body>
	<header>
		<a href="http://css3wizardry.com" class="button back"><span class="pointer"></span><span>Back</span></a>
		<h1>Chromaeleon Theme</h1>
		<span class="button">Click Here</span>
	</header>
	<section>
		<h2>Use the sliders to adjust the colors of the theme.</h2>
		<div class="colorRow">
			<div id="redSlider" class="slider">
				<div class="thumb"></div>
			</div>
			<div id="redColor" class="colorOutput"></div>
			<span> Red</span>
		</div>
		<div class="colorRow">
			<div id="greenSlider" class="slider">
				<div class="thumb"></div>
			</div>
			<div id="greenColor" class="colorOutput"></div>
			<span> Green</span>
		</div>
		<div class="colorRow">
			<div id="blueSlider" class="slider">
				<div class="thumb"></div>
			</div>
			<div id="blueColor" class="colorOutput"></div>
			<span> Blue</span>
		</div>
		<div class="colorRow finalResult">
			<span>Final Color: </span>
			<div id="rgbColor" class="colorOutput"></div>
			<br />
			<span>RGB: </span><span id="rgbResult">0, 0, 0</span>
			<br />
			<span>HEX: </span><span id="hexResult">#000000</span>
		</div>
	</section>
</body>

So, for the header and the buttons, we need to change their default gradients, as I mentioned above, to have RGBA transparency values. This is my basic gradient:

background-image: 
	-moz-linear-gradient(top, 
		rgba(255,255,255,.5), 
		rgba(30,30,30,.65) 50%, 
		rgba(0,0,0,.7) 50%, 
		rgba(0,0,0,.8)); 
background-image: 
	-webkit-gradient(linear, left top, left bottom, 
		from(rgba(255,255,255,.5)), 
		color-stop(0.5,rgba(30,30,30,.65)), 
		color-stop(0.5, rgba(0,0,0,.7)), 
		to(rgba(0,0,0,.8)));

And for the hover state of the button, we use this gradient:

background-image: 
	-webkit-gradient(linear, left top, left bottom, 
		from(rgba(0,0,0,.1)), 
		color-stop(0.5,rgba(0,0,0,.5)), 
		color-stop(0.5, rgba(0,0,0,.6)), 
		to(rgba(255,255,255,.2)));
background-image: 
	-moz-linear-gradient(top,
		rgba(0,0,0,.1), 
		rgba(0,0,0,.5) 50%, 
		rgba(0,0,0,.6) 50%, 
		rgba(255,255,255,.2));

Now to change the color, all we need to do is introduce a new method to our existing code:

/**
*
* Method to update chrome colors according to the RGB value of the sliders.
*
*/
$.updateInterfaceColors = function() {
	$("header").css("background-color: rgb(" + $.rgbColor[0] + "," + $.rgbColor[1] + "," + $.rgbColor[2] + ")");
	$$(".button").forEach(function(button) {
		button.css("background-color: rgb(" + $.rgbColor[0] + "," + $.rgbColor[1] + "," + $.rgbColor[2] + ")");
	});
	$("section").css("background-color: rgb(" + $.rgbColor[0] + "," + $.rgbColor[1] + "," + $.rgbColor[2] + ")");
	$(".pointer").css("background-color: rgb(" + $.rgbColor[0] + "," + $.rgbColor[1] + "," + $.rgbColor[2] + ")");
};

To execute this method, we invoke it in the slide mouse event handlers for each slider, and for touch-based mobile devices we invoke it in the updateSliderTouch method:

/**
*
* This is for the red slider's mouse interaction, you'd do the same for the green and blue sliders' setup scripts as well.
*/
// Set up three sliders for Red, Green and Blue:
$.slider("#redSlider", { 
	onDrag : function() {
		$("#redSlider").setColorFromSlider("red");
		$.updateInterfaceColors();
	},
	// onDragEnd function necessary to remove hover state off of slider thumb when drag ends.
	onDragEnd : function() {},
	top : -6
});
/**
*
* This is for touch-enabled devices. You invoke the $.updateInterfaceColors() method just once inside the updateSliderTouch method's definition, at the very end.
*/
Element.prototype.updateSliderTouch = function( color ) {
	this.style.left =  curX + 'px'; 
	if (color === "red") {
		$("#" + color + "Color").css("background-color: rgb(" + curX +",0,0)");
		$.rgbColor[0] = curX;
	}
	if (color === "green") {
		$("#" + color + "Color").css("background-color: rgb(0," + curX +",0)");
		$.rgbColor[1] = curX;
	}
	if (color === "blue") {
		$("#" + color + "Color").css("background-color: rgb(0,0," + curX +")");
		$.rgbColor[2] = curX;
	}
	$("#" + color + "Slider").css("-webkit-background-size:" + (curX + 1) + "px 9px, 100% 9px");
	$("#" + color + "Slider").css("background-size:" + (curX + 1) + "px 9px, 100% 9px");
	$("#rgbColor").css("background-color: rgb(" + $.rgbColor[0] + "," + $.rgbColor[1] + "," + $.rgbColor[2] + ")");
	$("#rgbResult").fill($.rgbColor[0] + ", " + $.rgbColor[1] + ", " + $.rgbColor[2]);
	$("#hexResult").fill("#" + $.rgb2hex($.rgbColor[0]) + $.rgb2hex($.rgbColor[1]) + $.rgb2hex($.rgbColor[2]));
	$.updateInterfaceColors();
};

This works great on desktop Safari, Chrome and even Firefox (Yay!), and fine on the iPad. For iPod Touch or iPhone you need to load it in portrait mode. it’s a bit cramped due to the size of the sliders. I needed them to be at least 255px long for the RGB values, and then borders, box shadows and the extra space for the thumbs made them barely fit in the iPhone’s and iPod Touch’s default width. Try hitting the plus icon at the bottom of the browser and save it to you device’s desktop. Then run it from there, you’ll have more vertical space. You can try this out online or download the source code. Enjoy!

Range Slider with CSS and JavaScript

Works on desktop Safari, desktop Chrome, desktop Firefox 3.5 – 4, iPhone, iPod Touch, iPad.

In this post I’m going to show how to make a range slider using HTML, CSS and JavaScript that works with both a mouse and a finger. The mouse-enabled version required a small drag-and-drop JavaScript framework. Fortunately I had already put that together several years back. After spending some time playing around with touch events on mobile Webkit, I was able to come up with a way to implement horizontal dragging for the range slider.
range slider

I’m not going to go into details about my mouse-enable drag-and-drop framework. You can popup it open and read the copious comments in the example. However, I will explain how I implemented the touch-enabled drag for the slider.

The structure for a slider is fairly straightforward. You need a track and a thumb:

<div id="redSlider" class="slider">
	<div class="thumb"></div>
</div>

Since the structure is so simple, you might be wondering how we give it the look. The thumb gets border radius to make it round, along with a box shadow and a background-gradient, including a blue background gradient for hover. The slider track is styled with two background gradients, the bottom-most gradient is the default grey which swans the width of the slider. Layered on top of the same track is a second, bluish gradient. By using CSS3’s background sizing property, we will dynamically resize it as the slider’s thumb is dragged.

Of course, just dragging a slider thumb back in forth is not suck a big deal. I therefore created three sliders implemented as RGB pickers. By dragging each thumb, you add or subtract from a red, green or blue value. Down below you’ll see the final RGB and Hex values.
RGB Slider

Here are the basic styles for the slider:

.slider {
	display: inline-block;
	-webkit-box-sizing: border-box;
	-moz-box-sizing: padding-box;
	box-sizing: padding-box;
	-webkit-box-shadow: 2px 2px 4px #666;
	-moz-box-shadow: 2px 2px 4px #666;
	box-shadow: 2px 2px 4px #666;
	height: 9px;
	width: 277px; 
	padding: 1px;
	-webkit-border-radius: 4px;
	-moz-border-radius: 4px;
	border-radius: 4px;
	background-image: 
		-webkit-gradient(linear, left top ,left bottom,
		   from(#0a3a86),
		   color-stop(.5, #4c8de7),
		   color-stop(.95, #6babf5),
		   to(#0a3a86)),
		-webkit-gradient(linear, left top ,left bottom,
			from(#919191),
			color-stop(.5, #f0f0f0),
			color-stop(.5, #fff),
			color-stop(.95, #fff),
			to(#919191));
	background-image: 
		-moz-linear-gradient(top,
		   #0a3a86,
		   #4c8de7 50%,
		   #6babf5 95%,
		   #0a3a86),
		-moz-linear-gradient(top,
			#919191,
			#f0f0f0 50%,
			#fff 50%,
			#fff 95%,
			#919191);
	background-repeat: no-repeat, repeat-x;
}
.thumb {
	position:relative;
	-webkit-box-shadow: 2px 2px 3px #666;
	-moz-box-shadow: 2px 2px 3px #666;
	box-shadow: 2px 2px 3px #666;
	height:20px;
	width:20px;
	left: 0px; 
	top: -6px;
	-webkit-border-radius: 10px;
	-moz-border-radius: 10px;
	border-radius: 10px;
	background-image: 
	   -webkit-gradient(linear, left top, left bottom,
		   from(#aaa),
		   color-stop(.5, #ddd),
		   to(#ccc));
	background-image: 
	   -moz-linear-gradient(top,
		   #aaa,
		   #ddd 50%,
		   #ccc);
	cursor: move;
	-webkit-tap-highlight-color: transparent;
}
.thumb:hover, .thumb.hover {
	background-image: 
	   -webkit-gradient(linear, left top, left bottom,
		   from(#6297f2),
		   color-stop(.5, #0251ae),
		   to(#6297f2));
	background-image: 
	   -moz-linear-gradient(top,
		   #6297f2,
		   #0251ae 50%,
		   #6297f2);
}

Notice the slider’s background gradient style. The first background gradient will be the top-most. The last will be the bottom-most. But the top-most is going to be the blue part of the track that appears to the left of the thumb as it is dragged away from the left start of the range slider.

We also need some styles to set the initial states of the three thumbs. Notice that I’ve used background sizing to control the two background gradients. The first is for the blue top-most gradient, the second is for the full width grey gradient.

#redSlider .thumb {
	left: 121px;
}
#redSlider {
	-webkit-background-size: 123px 9px, 100% 9px;
	-moz-background-size: 123px 9px, 100% 9px;
	background-size: 123px 9px, 100% 9px;
}
#greenSlider .thumb {
	left: 156px;
}
#greenSlider {
	-webkit-background-size: 158px 9px, 100% 9px;
	-moz-background-size: 158px 9px, 100% 9px;
	background-size: 158px 9px, 100% 9px;
}
#blueSlider .thumb {
	left: 230px;
}
#blueSlider {
	-webkit-background-size: 232px 9px, 100% 9px;
	-moz-background-size: 232px 9px, 100% 9px;
	background-size: 232px 9px, 100% 9px;
}

So, I’ve defined two gradients with different background repeats: background-repeat: no-repeat, repeat-x; and background sizing with values such as: 123px 9px, 100% 9px. 9px is the height of the slider track. The bottom-most gradient has a width of 100%, and the top-most bluish one gets a width of 123px. By using these values, with very little markup, we can create visually and functionally complex structures.

/**
* Touch enabled support:
*/
/**
*
* Method to set the colors of color swatches and width of the slider progress track when the slider thumb is dragged.
*/
Element.prototype.setupSliderTouch = function( event ) {
	event.preventDefault();
	var el = event.target;
	var touch = event.touches[0];
	curX = touch.pageX - this.parentNode.offsetLeft;
	if (curX <= 0) { 
		curX = 0;
	}
	if (curX > 255) {
		curX = 255;
	}
};
Element.prototype.updateSliderTouch = function( color ) {
	this.style.left =  curX + 'px'; 
	if (color === "red") {
		$("#" + color + "Color").css("background-color: rgb(" + curX +",0,0)");
		$.rgbColor[0] = curX;
	}
	if (color === "green") {
		$("#" + color + "Color").css("background-color: rgb(0," + curX +",0)");
		$.rgbColor[1] = curX;
	}
	if (color === "blue") {
		$("#" + color + "Color").css("background-color: rgb(0,0," + curX +")");
		$.rgbColor[2] = curX;
	}
	
	$("#" + color + "Slider").css("-webkit-background-size:" + (curX + 1) + "px 9px, 100% 9px");
	$("#" + color + "Slider").css("background-size:" + (curX + 1) + "px 9px, 100% 9px");
	
	$("#rgbColor").css("background-color: rgb(" + $.rgbColor[0] + "," + $.rgbColor[1] + "," + $.rgbColor[2] + ")");
	$("#rgbResult").fill($.rgbColor[0] + ", " + $.rgbColor[1] + ", " + $.rgbColor[2]);
	$("#hexResult").fill("#" + $.rgb2hex($.rgbColor[0]) + $.rgb2hex($.rgbColor[1]) + $.rgb2hex($.rgbColor[2]));
};

$("#redSlider > .thumb").bind('touchmove', function(event) {
	this.setupSliderTouch(event);
	this.updateSliderTouch("red");
});
$("#greenSlider > .thumb").bind('touchmove', function(event) {
	this.setupSliderTouch(event);
	this.updateSliderTouch("green");
});
$("#blueSlider > .thumb").bind('touchmove', function(event) {
	this.setupSliderTouch(event);
	this.updateSliderTouch("blue");
});

Basically, I attach a touchmove event to the slider thumbs. The event listener passes the event to the setupSliderTouch method. The first thing the setupSliderTouch method does is to prevent the default interaction from taking place, such as page scrolling. We want the user to be able to move the thumb without scrolling the page. From the event passed in to setupSliderTouch we get the touch event and calculate its x coordinate on the screen. To calculate the touch’s position in relation to the slider, we subtract the left offset of the slider from the pageX of the touch. This gives us the left-most edge of the slider’s thumb. We store this as curX. We check the value of curX. If it is less than zero, we set it back to zero. We do this because this value will be used to set the position of the thumb and one of the RGB values. We don’t want either the thumb being dragged off of the left edge of the slider, nor a value less than zero, since RGB values start at zero. We do the same thing when the curX value is greater than 255 for the same reasons.

The updateSliderTouch method uses the value of the slider’s thumb to calculate and update RGB and Hex values, giving the user visual feedback as the thumb is dragged. Then we use the value of curX to update the background size of the blues background gradient on the slider track:

$("#" + color + "Slider").css("-webkit-background-size:" + (curX + 1) + "px 9px, 100% 9px");
$("#" + color + "Slider").css("background-size:" + (curX + 1) + "px 9px, 100% 9px");

That’s all there is to it. You can try this out online using desktop Safari, Chrome, or Firefox for the mouse version, or on an iPhone, iPod Touch or iPad for the touch version. Or you can download the source code, which I recommend, so you can dig into the CSS and JavaScirpt.

Update: September 15, 2010
If you’re trying this out on an iPhone, I noticed that there seems to be a very slight delay before an initial touch is registered on the screen. This means that in order to slide the thumb, you need to press and hold for a very brief moment before sliding, otherwise no touch gets registered and nothing happens. This doesn’t seem to happen when performing the same action on the iPad. Touches seem more responsive.

iPhone Modal Popup with HTML5, CSS3 & JavaScript

Works on Desktop Safari, Desktop Google Chrome, iPhone, iPod Touch, iPad. Note that I’ve included some styling for Firefox, even though it has no presence to speak of in the mobile space. In particular, Firefox 4 beta still lacks support for CSS3 keyframe animation, although that will make it into a later update.

If you’ve used an iPhone, iPod Touch or iPad, then you’re familiar with the modal popup dialog boxes that the native system uses. Here’s a typical iPhone popup:
Native iPhone modal popup

Notice the white radial gradient behind the popup. I was able to replicate this, but when the user was on a long document and scrolled down to do something that would trigger a popup, I could find no way to center that radial gradient based on the vertical page scroll. I therefore went with a whitesh blur around the popup itself using a CSS3 box shadow. Here’s what my HTML5/CSS3 version looks like:

Originally I thought I would use just one popup per app, re-assigning values to the popup’s part each time the popup was invoked. However I ran into the problem of events from different and I failed to find an elegant way to resolve this. I therefore came up with a scheme where you initialize a popup at the view level, allowing each view to have a custom popup. The initializing script creates the popup and injects it as the last child of the view. The setup script creates the markup for the popup and populates it with values passed as an argument to the initializing script. The setup script also adds basic functionality to the buttons so that clicking either of them will close the popup. The setup script also creates a screen cover which traps events to prevent user interaction with what is behind the popup until it is closed.

The setup script accepts a single argument—an object literal containing key/values pairs to populate the popup. In order for the setup script to create a popup, you must at least pass a value for a valid view in your Web app. This would be like selector: "#Popup". If no other values are passed, the script will produce a basic popup that looks like this:
Basic popup

I used the ChocolateChip mobile JavaScript library to add the interactive functionality to the popup. Here’s the JavaScript that creates the markup and functionality for the popup:

/** 
* 
* A method to initialize a modal popup. By passing a valid selector for a view, this method creates a view based popup with the properties supplied by the options argument. It automatically binds events to both popup buttons to close the popup when the user clicks either. If a callback is passed as part of the opts argument, it gets bound to the "Continue" button automatically.
*
* @method
* 
* ### setupPopup
*
* syntax:
*
*  $.setupPopup({selector: "#News", title: "Subscribe", cancel: });
*
* arguments:
* 
*  - string: string A valid selector for the parent of the tab control. By default the an object literal.
*  - string: string An object literal which can have the following properties:
	title: a string defining the title in the popup.
	message: a string defining the popup message.
	cancelButton: a string defining an alternate name for the cancel button.
	continueButton: a string defining an alternate name for the confirm button.
	callback: a function to run when the user touches the confirm button.
	If no title is supplied, it defaults to "Alert!".
	If no cancelButton value is supplied, it defaults to "Cancel".
	If no continueButton value is supplied, it defaults to "Continue".
* example:
*
*  $.setupPopup({selector: "#buyerOptions"});
*  $.setupPopup({
		selector: "#Popup",
		title: 'Attention Viewers!', 
		message: 'This is a message from the sponsors. Please be seated while we are getting ready. Thank you for your patience.', 
		cancelButton: 'Skip', 
		continueButton: 'Stay for it', 
		callback: function() {
			$('#popupMessageTarget').fill('Thanks for staying with us a bit longer.');
			$('#popupMessageTarget').removeClass("animatePopupMessage");
			$('#popupMessageTarget').addClass("animatePopupMessage");
		}
	});
*
*/
$.setupPopup = function( opts ) {
	if (opts.selector) {
		var selector = opts.selector;
	} else {
		return false;
	}
	var title = "Alert!";
	if (opts.title) {
		var title = opts.title;
	}
	var message = "";
	if (opts.message) {
		var message = opts.message;
	}
	var cancelButton = "Cancel";
	if (opts.cancelButton) {
		cancelButton = opts.cancelButton;
	}
	var continueButton = "Continue";
	if (opts.continueButton) {
		continueButton = opts.continueButton;
	}
	var popup = '<div class="screenCover hidden"></div>';
	popup += '<section class="popup hidden"><div>';
	popup += '<header><h1>' + title + '</h1></header>';
	popup += '<p>' + message +'</p><footer>';
	popup += '<div class="button cancel">' + cancelButton + '</div>';
	popup += '<div class="button continue">' + continueButton + '</div></footer></div></section>';
	$(selector).insertAdjacentHTML("beforeEnd", popup);
	// Bind event to close popup when either button is clicked.
	$$(selector + " .button").forEach(function(button) {
		button.bind("click", function() {
			$(selector + " .screenCover").addClass("hidden");
			$(selector + " .popup").addClass("hidden");
		});
	});
	
	if (opts.callback) {
		var callbackSelector = selector + " .popup .continue";
		$(callbackSelector).bind("click", function() {
			opts.callback();
		});
	}
	
};

And here is an initialization of a popup:

$.setupPopup(
	{
		selector: "#Popup",
		title: 'Attention Viewers!', 
		message: 'This is a message from the sponsors. Please be seated while we are getting ready. Thank you for your patience.', 
		cancelButton: 'Skip', 
		continueButton: 'Stay for it', 
		callback: function() {
			$('#popupMessageTarget').fill('Thanks for staying with us a bit longer.');
                        // Remove this class in case the popup was opened previously.
			$('#popupMessageTarget').removeClass("animatePopupMessage");
                        // Then add the class to trigger an animation of the message being displayed.
			$('#popupMessageTarget').addClass("animatePopupMessage");
		}
	}
);

Now that a popup has been created and populated with the desired values, we need a way to show it. Before actually showing the popup, the $.showPopup method display a screen cover which captures user interaction and thereby prevents the interface behind the popup from being accessed until the popup is dispelled. The showPopup method accepts one argument, a selector indicating a uniquely identifiable node that contains the popup as a descendant.

$.showPopup = function( selector ) {
	var screenCover = $(selector + " .screenCover");
        // Make the screen cover extend the entire width of the document, even if it extends beyond the viewport.
	screenCover.css("height:" + (window.innerHeight + window.pageYOffset) + "px");
	var popup = $(selector + " .popup");
	$(selector + " .popup").style.top = ((window.innerHeight /2) + window.pageYOffset) - (popup.clientHeight /2) + "px";
	$(selector + " .popup").style.left = (window.innerWidth / 2) - (popup.clientWidth / 2) + "px";
	$(selector + " .screenCover").removeClass("hidden");
	$(selector + " .popup").removeClass("hidden");
};

With this method defined we can now show the popup as need. Here’s a script that attaches an event handler to a button with a class of “openPopup” for a popup somewhere among the descendant nodes of a node with an id of “Tabs”:

$("#Tabs .openPopup").bind("click", function() {
	$.showPopup("#Tabs");
});

OK, so we have the markup and functionality for the popup, but we don’t have the look. We’ll take care of that next. In order to create the unique look of the iPhone popup, I use several layers for encasing borders and composited transparent background gradients. Originally I had two gradients, the dark blue linear gradient and the whitish radial gradient, layered on top of each other as multiple backgrounds. But Google Chrome had a problem rendering the underlying linear gradient, ignoring its transparent alpha values and rending the colors as opaque. I was therefore forced to break them out into separate elements. The end result is the same. When the popup is created by the setup script, it is given a class of “hidden.” This defines its scale as 0% and its opacity as 0%. When we execute the showPopup method, it removes that “hidden” class. Because the popup has basic transitions properties defined on it, its scale and opacity transition from zero to full, making it appear to popup out of no where. The scripts also always make sure that the popup is centered in the viewport, regardless of where it was displayed when scrolling down a long document.

For their modal popups, Apple always indicates the default button, what would be equivalent to a submit or OK button, with slightly lighter colors so that it stands out from the other button, which is the equivalent of a cancel/close button. I have the buttons located in a footer and I use CSS3’s flexible box model styles to make the buttons position and size them selves according to available space.

/* Modal Popup Styles */
section.popup {
	width: 75%;
	max-width: 300px;
	border: solid 1px #72767b;
	-webkit-box-shadow: 0px 4px 6px #666, 0 0 50px rgba(255,255,255,1);
	-moz-box-shadow: 0px 0px 1px #72767b,  0px 4px 6px #666;
	box-shadow: 0px 0px 1px #72767b, 0px 4px 6px #666;
	-webkit-border-radius: 10px;
	-moz-border-radius: 10px;
	border-radius: 10px;
	padding: 0px;
	opacity: 1;
	-webkit-transform: scale(1);
	-webkit-transition: all 0.25s  ease-in-out;
	position: absolute;
	z-index: 1001;
	margin-left: auto;
	margin-right: auto;
	background-image: 
		-webkit-gradient(linear, left top, left bottom,
			from(rgba(0,15,70,0.5)),
			to(rgba(0,0,70,0.5)));
}
section.popup.hidden {
	opacity: 0;
	-webkit-transform: scale(0);
	top: 50%;
	left: 50%;
	margin: 0px auto;
}
section.popup > div {
	border: solid 2px #e6e7ed;
	-webkit-border-radius: 10px;
	-moz-border-radius: 10px;
	border-radius: 10px;
	padding: 10px;
	background-image: 
	   -webkit-gradient(radial, 50% -1180, 150, 50% -280, 1400,
		   color-stop(0, rgba(143,150,171, 1)),
		   color-stop(0.48, rgba(143,150,171, 1)),
		   color-stop(0.499, rgba(75,88,120, .9)),
		   color-stop(0.5, rgba(75,88,120,0)));
	color: #fff;
	text-shadow: 0px -1px 1px #000;
}
section.popup header {
	background: none;
	-webkit-border-top-left-radius: 10px;
	-webkit-border-top-right-radius: 10px;
	-moz-border-radius-topleft: 10px;
	-moz-border-radius-topright: 10px;
	border-top-left-radius: 10px;
	border-top-right-radius: 10px;
	border: none;
	color: #fff;
	text-shadow: 0px -2px 1px #000;
}
section.popup header > h1 {
	letter-spacing: 1px;
}
section.popup footer
{
	display: -webkit-box;
	-webkit-box-orient: horizontal;
	-webkit-box-pack:justify;
	-webkit-box-sizing: border-box;
	display: -moz-box;
	-moz-box-orient: horizontal;
	-moz-box-pack:justify;
	-moz-box-sizing: border-box;
}
section.popup footer > .button {
	-webkit-box-flex: 2;
	-moz-box-flex: 1;
	display: block;
	text-align: center;
	-webkit-box-shadow: none;
	-moz-box-shadow: none;
	box-shadow: none;
	margin: 10px 5px;
	height: 32px;
	font-size: 18px;
	line-height: 32px;
	-webkit-border-radius: 8px;
}
section.popup footer > .button.cancel {
	background-image: 
		-webkit-gradient(linear, left top, left bottom, 
			from(#828ba3), 
			color-stop(0.5, #4c5a7c), 
			color-stop(0.5, #27375f), 
			to(#2e3d64));
}
section.popup footer > .button.continue {
	background-image: 
		-webkit-gradient(linear, left top, left bottom, 
			from(#b0b6c4), 
			color-stop(0.5, #7a839b), 
			color-stop(0.5, #515d7c), 
			to(#636e8a));
}
section.popup footer > .button:hover, .popup footer > .button.hover {
	background-image: 
		-webkit-gradient(linear, left top, left bottom, 
			from(#70747f), 
			color-stop(0.5, #424857), 
			color-stop(0.5, #171e30), 
			to(#222839));
}
.screenCover {
	width: 100%;
	height: 100%;
	display: block;
	background-color: rgba(0,0,0,0.5);
	position: absolute;
	z-index: 1000;
	top: 0px;
	left: 0px;
}
.screenCover.hidden {
	display: none;
}

You can try this out online or download the source code to play around with it.

iPhone Style Radios Buttons with HTML, CSS & JavaScript


Works on desktop Safari, desktop Google Chrome, Android, iPhone, iPod Touch and iPad.

Have you ever surfed to a Web page on the iPhone or iPod Touch’s Safari browser and come across a form with standard radio buttons? It’s a pretty miserable experience trying to hit them with your finger. You have to zoom in to do so, maybe zoom in a lot. When Apple was designing the interface for the iPhone, they put a lot of thought into how to make conventional interface elements easier to use in a touch environment. If you think about it, what is a group of radio buttons but a list of items to select from. And only one item can be selected at a time. To cover this requirement Apple came up with the radio table control. A radio table is just a list of items, same as a radio button group. Only one list item can be chosen, and this is indicated by a checkmark on that particular list item which correlates to the single radio button being selected out of a group.

The radio button list looks like this:
Radio Button List

One of the things that I really can’t understand is why people think a mobile touch interface needs radio buttons like on the desktop browser. All the other mobile frameworks are providing ways to implement the standard tiny, round radio buttons. They don’t work for touch interfaces. Get over it. The radio list works better for touch. Embrace it and love it and it will love you. Wait, I didn’t really mean that, but you get the picture. I have a hard enough time hitting normal sized controls designed for the iPhone. Heck, sometimes I can’t even find my iPhone, but that’s another issue.

To make this more like the Web equivalent of radio buttons I added real radio buttons to my solution. Here’s the markup to implement them (note that you still need to great the grouping of the radio buttons by giving each radio button in the list the same name):

<ul id="activityChoices" class="radioList">	
	<li>
		<span>Go eat something</span> 
		<span class="check">&#x2713</span>
		<input type="radio" name="activity" value="Go eat something" />
	</li>
	<li>
		<span>Take a nap</span> 
		<span class="check">&#x2713</span>
		<input type="radio" name="activity" value="Take a nap" />
	</li>
	<li>
		<span>Get some work done</span> 
		<span class="check">&#x2713</span>
		<input type="radio" name="activity" value="Get some work done" />
	</li>
	<li>
		<span>Play a game</span> 
		<span class="check">&#x2713</span>
		<input type="radio" name="activity" value="Play a game" />
	</li>
</ul>

Notice that the last item in each list item is the radio input. Please leave this as such, since it makes it easy for us to target the actual radio button as the last child of the list items child nodes. If you have a need to add other things into the list, insert them elsewhere in the list items collection of child nodes.

We’ll use CSS to hide the radio buttons and when a user touches a list item, we’ll use JavaScript to set the checked state of that list item’s radio button to true. After that, what you do with the user interaction is up to you. In many cases that initial choice can immediately trigger a corresponding action, or you may wait until the user takes a decisive final action that triggers a submit or post of all the selected inputs. Notice the span with the class “check.” It contains a hex value of “&#x2713″ which is an HTML entity for a standard check mark. We’ll use CSS to position and hide or show it depending on the user’s interaction.

Here’s the CSS needed to make our list look like the iPhone one. Since the radio button group is based on the list control type, it shares some styles with standard lists:

.list, .radioList {
	-webkit-box-shadow: 2px 2px 4px #666;
	-webkit-border-radius: 12px;
	-moz-box-shadow: 2px 2px 4px #666;
	-moz-border-radius: 12px;
	box-shadow: 2px 2px 4px #666;
	border-radius: 12px;
}
.list li, .radioList li {
	cursor: pointer;
	padding: 8px;
	border-left:  1px solid #acacac;
	border-right: 1px solid #acacac;
	border-bottom: 1px solid #acacac;
	background-color: #fff;
	font-weight: bold;
	-webkit-tap-highlight-color: transparent;
}
.list li:hover, .radioList li:hover {
	background-image: 
		-webkit-gradient(linear, left top, left bottom, 
			from(#4286f5), 
			to(#194fdb));
	background-image: 
		-moz-linear-gradient(top, 
			#4286f5, 
			#194fdb);
	color: #fff;
}
.list li:hover:after, .radioList li:hover:after {
	color: #fff;
}
.list li:first-of-type, .radioList li:first-of-type {
	border-top: 1px solid #acacac;
	-webkit-border-top-right-radius: 10px;
	-webkit-border-top-left-radius: 10px;
	-moz-border-radius-topright: 10px;
	-moz-border-radius-topleft: 10px;
	border-top-right-radius: 10px;
	border-top-left-radius: 10px;
}
/** 
	Styles for single choice lists.
	These are the same in functionality as a 
	radio button group.
*/
.radioList li > .check {
	float: right;
	-webkit-transition: all 0.125s  ease-in-out;
	-moz-transition: all 0.125s  ease-in-out;
	transition: all 0.125s  ease-in-out;
	opacity: 0;
}
.radioList li.selected > .check {
	opacity: 1;
	color: #496691;
}
.radioList li > .check, .radioList li.selected:hover > .check {
	color: #fff;
}
.radioList li > input[type="radio"] {
	display: none;
}

The selector radioList li > .check defines the check mark. We set it’s initial opacity to 0 so that it is completely transparent. When the user selects a list item by clicking/touching, we add a “selected” class to the list item. The selector .radioList li.selected > .check then sets the check mark’s opacity to 100%.

To make all the behavior work, we need to write some JavaScript for a reusable control. We’ll use the light, mobile JavaScript framework ChococlateChip.

/** 
* 
* A method to initialize a list of radios buttons to present the user with a group of single choice options. It takes as the main argument, a unique selector identifying the view or section where the radio list resides.
*
* @method
* 
* ### RadioButtons
*
* syntax:
*
*  $.RadioButtons(selector);
*
* arguments:
* 
*  - string: string A valid selector for the parent of the tab control. By default the selector will target a class, id or tag of the radio list itself, so if you want to pass in a selector for a parent tag, such as an article, section or div tag, you'll need to make sure to put a trailing space on the end of the selector string.
*  - function: function A valid function as a callback. This is optional. The callback gets passed a reference to the clicked item, so you can access it in your callback function.
* 
* example:
*
*  $.RadioButtons("#buyerOptions");
*  $.RadioButtons("#buyerOptions", function(choice) {
	   // Output the value of the radio button that was selected.
	   // Since the actual radio button is the last item in a radio
	   // button list, we can use the last() method to get its value.
	   console.log(choice.last().value);
   };
*
*/
$.RadioButtons = function( viewSelector, callback ) {
	var items = viewSelector + ".radioList li";
	var radioButtons = $$(items);
	radioButtons.forEach(function(item) {
		item.bind("click", function() {
			radioButtons.forEach(function(check) {
				check.removeClass("selected");
			});
			this.addClass("selected");
			this.last().checked = true; 
			if (callback) {
				callback(item);
			}
		});
	});
};	

Because the radio input is the last child of the list’s node collection, we can set its checked value to true when the user clicks or touches a list item. We do this with the line: this.last().checked = true; We also manage toggling of the selected state of a list item by adding and removing a “selected” class. This hides or shows the check mark. We also have a conditional block to check for a callback. If one was passed as an argument, we invoke it. We pass in a reference to the list item that was clicked using the term “item.” This allows us to reference the clicked item in our callback. We can initialize a radio button list as follows:

// Radio button initialization:
$.RadioButtons("#activityChoices", function(item){
	$("#RadioButtons .response").fill(item.last().value);
});

In the above code we’re passing in a reference to the clicked list item in an anonymous function which fills a span with a class of “response” with the value of the list item’s radio button.

The radio button list has an id of “#activityChoices,” so I just pass that in. If “#activityChoices” were a parent node, I would have had to written the selector thus (notice the trailing space at the end before the closing parenthesis): $.RadioButtons(“#activityChoices “); This differentiation is necessary because the selector passed in gets concatenated with “.radioList li” to set up the radio button list’s functionality. There is no way for the control to know when you are targeting the list itself or a parent node. If the selector is the list itself, “.radioList li” gets appended to that, but if the selector is a parent node, you need to indicate that with a trailing space so that the “.radioList li” gets appended with the space separating. Otherwise the resulting complete selector will not identity the radio button list properly and nothing will get initialized. I hope this is clear. Yeah, I could have written the control to check to see if the selector was the list or a parent node, but that would have resulted in a performance hit as the code would have had to do quite a bit of evaluation to determine what the selector relation was.

Remember that the callback is optional. That means if you are construction a form with a submit process, then all you need to do for the radio button list is pass in a correct selector to initialize its behavior. You’ll then get the user’s choice during the submit process.

You can try out an example online or download the source code.

Follow

Get every new post delivered to your Inbox.

Join 45 other followers