iPhone Checkboxes Using MooTools
One of the sweet user interface enhancements provided by Apple's iPhone is their checkbox-slider functionality. Thomas Reynolds recently released a jQuery plugin that allows you to make your checkboxes look like iPhone sliders. Here's how to implement that functionality using the beloved MooTools JavaScript framework.
The XHTML
<h2>Off by default</h2> <p><input type="checkbox" /></p> <h2>On by default</h2> <p><input type="checkbox" checked="checked" /></p>
This is how the XHTML code is initially embedded within the page. MooTools will change this drastically.
The CSS
.iPhoneCheckContainer{ position:relative; width:85px; height:27px; cursor:pointer; overflow:hidden; } .iPhoneCheckContainer input{ position:absolute; top:5px; left:30px; } .iPhoneCheckHandle{ display:block; height:27px; width:39px; cursor:pointer; position:absolute; top:0; left:0; } .iPhoneCheckHandle .iPhoneCheckHandleBG{ position:absolute; width:5px; height:100%; top:0; left:0; z-index:1; } .iPhoneCheckHandle .iPhoneCheckHandleSlider{ position:absolute; top:0; left:0; height:27px; width:39px; background:url(iphone-slider.png) no-repeat; z-index:2; } label.iPhoneCheckLabelOn,label.iPhoneCheckLabelOff{ font-size:17px; line-height:17px; font-weight:bold; font-family:Helvetica Neue,Arial,Helvetica,sans-serif; text-transform:uppercase; cursor:pointer; display:block; height:22px; position:absolute; width:52px; top:0; } label.iPhoneCheckLabelOn{ color:#fff; background:url(iphone-on.png) no-repeat; text-shadow:0px 0px 2px rgba(0,0,0,0.6); left:0; padding:5px 0 0 8px; } label.iPhoneCheckLabelOff{ color:#8B8B8B; background:url(iphone-off.png) no-repeat right 0; text-shadow:0px 0px 2px rgba(255,255,255,0.6); text-align:right; right:0; padding:5px 8px 0 0; }
The CSS is pretty simple but notice we have to define classes for each state.
The MooTools JavaScript
window.addEvent('domready',function(){ (function($) { this.IPhoneCheckboxes = new Class({ //implements Implements: [Options], //options options: { checkedLabel: 'ON', uncheckedLabel: 'OFF', background: '#fff', containerClass: 'iPhoneCheckContainer', labelOnClass: 'iPhoneCheckLabelOn', labelOffClass: 'iPhoneCheckLabelOff', handleClass: 'iPhoneCheckHandle', handleBGClass: 'iPhoneCheckHandleBG', handleSliderClass: 'iPhoneCheckHandleSlider', elements: 'input[type=checkbox]' }, //initialization initialize: function(options) { //set options this.setOptions(options); //elements this.elements = $$(this.options.elements); //observe checkboxes this.elements.each(function(el) { this.observe(el); },this); }, //a method that does whatever you want observe: function(el) { //turn off opacity el.set('opacity',0); //create wrapper div var wrap = new Element('div',{ 'class': this.options.containerClass }).inject(el.getParent()); //inject this checkbox into it el.inject(wrap); //now create subsquent divs and labels var handle = new Element('div',{'class':this.options.handleClass}).inject(wrap); var handlebg = new Element('div',{'class':this.options.handleBGClass,'style':this.options.background}).inject(handle); var handleSlider = new Element('div',{'class':this.options.handleSliderClass}).inject(handle); var offLabel = new Element('label',{'class':this.options.labelOffClass,text:this.options.uncheckedLabel}).inject(wrap); var onLabel = new Element('label',{'class':this.options.labelOnClass,text:this.options.checkedLabel}).inject(wrap); var rightSide = wrap.getSize().x - 39; //fx instances el.offFx = new Fx.Tween(offLabel,{'property':'opacity','duration':200}); el.onFx = new Fx.Tween(onLabel,{'property':'opacity','duration':200}); //mouseup / event listening wrap.addEvent('mouseup',function() { var is_onstate = !el.checked; //originally 0 var new_left = (is_onstate ? rightSide : 0); var bg_left = (is_onstate ? 34 : 0); handlebg.hide(); new Fx.Tween(handle,{ duration: 100, 'property': 'left', onComplete: function() { handlebg.setStyle('left',bg_left).show(); } }).start(new_left); //label animations if(is_onstate) { el.offFx.start(0); el.onFx.start(1); } else { el.offFx.start(1); el.onFx.start(0); } //set checked el.set('checked',is_onstate); }); //initial load if(el.checked){ offLabel.set('opacity',0); onLabel.set('opacity',1); handle.setStyle('left',rightSide); handlebg.setStyle('left',34); } else { onLabel.set('opacity',0); handlebg.setStyle('left',0); } } }); })(document.id); /* usage */ var chx = new IPhoneCheckboxes(); });
The class allows for customization of which events get iPhone-ized, the label text statements, and what each CSS class is called. Besides those given options, you have nothing else to do unless you plan on hacking the class completely.
Sweet, no? Funny how we emulate functionality from an inferior technology (mobile browser). I would consider this functionality "proof of concept," as increasing the font-size may cause issues in some browsers. Cool effect though -- consider it for your websites!
Make the text unselectable or it gets selected after a couple of clicks :P
Like it – but in my opinion it should also work with dragging the knob.
For doing what Darkimmortal said someone can add the following events:
Nice eye candy, but it would be harder for simple PC users to get, if it needed them to scroll that div by themselves.
//damn, for this example you should change the click to the mouseup function in the class xD
wow this is really cool…good work David
the spacing of the handle is a little messed up in IE7 and IE6…other than that it’s pretty cool…
It’s nice, but I agree, it would be even better if it could be dragged. That’s the first thing I tried to do
after reading the code I see that you create a new Fx instance on every mouse up. You should create a single object like you did with the other Fx, you can even set the ‘link’ option to cancel. You can can make bg_left a class variable so it’s accessible in the onComplete function
@olivier: Good point — I’ll update that.
If i had to choose word for this i would go with cute or sweet… hahaha… Good work by the way, i like it very much
Check out http://reaktivo.com/mt/mooswitch I made a year ago…
REALLY NICE!!!!!!!! Thx David!!
@Marcel
That is really cool. I like the options you have available
This is awesome! Great work David! Can’t wait to see what you come up with next!
is this thing on? it ‘ate’ my comment!
right. anyway – it’s a handy little class and all that, just a small change as I needed it to call a function on the change of state, hopefully posting it this time won’t have it disappear…
end of the
wrap.addEvent('mouseup',function() {
anon function:usage exmaple to enable / disable products from a list via ajax:
well twice already I cannot post the suggested change so I am putting it into a .txt file.
the idea is, as great as the class is, i needed it to be able to call a function with the checkbox state on each change, as well as pass on the original element to that function (in order to be able to update a DB via ajax)
resulting code looks like this: http://fragged.org/dev/iphoneCheckboxChange.txt (a quick change rather than implementing Events).
cheers
oh heh, and now they are here. can you delete the dupes please. http://fragged.org/dev/iphoneCheckboxChange.txt now contains an updated version which also addresses some issues with non-movers on click when there are MANY checkboxes on screen (30+)
so,this is very cool. I love it.
but I find a small problem: for the styles of of outer divs of the example, such as id=”content” or class=”content” or id=”wrap” and so on, if i add a margin property at them, the event will be invalid, it will not change status when you click at the button. you can test by adding “margin:10px” to #content or other div, it doesn’t work.
I wanna know why it comes with this. is it a little bug? or a margin property can’t be use here?
thnx for all your good scripts!
this one I have a problem installing, it hangs when loaded. I tried a demo page seperated from any other content and it still hangs when it comes to #fff. Tried you mootools version and it still stops..
Can you help me out? my javascript knowledge ain’t that good with debugging… only simple scripts I am able to implement and I am working from examples..
i got following error when using iPhone-CheckBox…..”handlebg.hide is not a function” :(
i got this error when i click on [on or off] button
you need to change the event from mousedown to click for this to work on Safari…
That have a conflict in off to on On Safari Web Browser ???
Fixed the demo. Sorry everyone!
Demo page doesn’t work.
Demo doesn’t work under safari, the switch flips sides only once…
Flipping only once on Firefox and you still haven’t made the text unselectable :P
Patched up the switching issues and updated my post’s code.
I found few years ago an example like this one.. only with on and off buttons from a old television..was pretty funny!
Here demo doesn’t work either.. it worked before, only when installing I had the same problem as Dipen.
oops sorry demo works now..
Actually, it still behaves funny under IE7.. looks like a layer priority issue because the widget seems to be working as designed…
please change the CSS to the following to fix z-index issue on IE7
Loved it These are checkboxes and i was wondering can these be achieved on list items?
Thanks
Hi David,
Here’s challenge for you. Can this script be made to work with a group of radio buttons so that when one is clicked, it slides to on, and the others automatically slide to off?
Best,
Matt
Notice on the demo video, they use the iPhone sliders? I don’t think they are yours, but still kinda neat!
http://preyproject.com/
it looks great but it dosen’t work with the latest version of mootools.
i’m having issues with handlebg.hide is not a function
And it also doesnt work since a few days in the latest IE 9 !? having big troubles with that… the first checkbox is hide and all others are in normal html style. Could someone help me? i have to deactivate it now because of the missing first checkbox :-(
iam sorry! not the first one is hide, the activated ones not visible.
Update from Mootools 1.2 to mootools-core-1.4.1-full-compat worked for me!
Someone can post the update code for mootools 1.4?