Hey guys. I had to build a form with lots of on and off switches and I liked the look of the iPhone's on / off switch so I extended the RadioGroup element to make an iPhoneSwitch.

Feel free to use it as you please. If you have any suggestions of how it can be improved let me know. I'm using CSS3 transitions for the animation of the switch.

Here is a picture of how it looks. Sorry, no live demo yet.

iPhoneSwitch.png

Here is the CSS.

Code:
 
.x-iphone-switch img{background: url(../images/iphone_switch.png) no-repeat 0 0;width:94px;height:27px;cursor:pointer; -webkit-transition: background-position .25s linear;-moz-transition: background-position .25s linear;-o-transition: background-position .25s linear;transition: background-position .25s linear;}
    .x-iphone-switch.off img{background-position: -53px 0;}
    .x-iphone-switch-label{margin-top:2px;}
Here is the iphone_switch.png and the container image.
iphone_switch.pngiphone_switch_container.gif

Here is the actual plugin. I've only tested this in ExtJS 3.3.1. Should be easily portable to other versions.

Code:
// create namespace for plugins
Ext.namespace('Ext.ux.plugins');
 
/**
 * Ext.ux.plugins.iPhoneSwitch plugin for Ext.form.Radio
 *
 * @author   Chalres Himmer
 * @stardate January 25, 2010
 *
 * @class Ext.ux.plugins.IphoneSwitch
 * @extends Ext.form.RadioGroup
 */

Ext.ux.plugins.iPhoneSwitch = Ext.extend(Ext.form.RadioGroup, {
    
    initComponent:function() {
        
        this.addEvents(
            'changed'
        );
        
        // private hard coded config
        var config = {
            items:[
                {boxLabel: 'On', name: this.name + '-on', inputValue: true, hidden: true},
                {boxLabel: 'Off', name: this.name + '-off', inputValue: false, hidden: true, checked: true}
             ]
        };

        Ext.apply(this, config);
                
        // call parent initComponent
        Ext.ux.plugins.iPhoneSwitch.superclass.initComponent.call(this);
 
    }, // end of function initComponent
    
    onRender: function(ct, position){
     
        Ext.ux.plugins.iPhoneSwitch.superclass.onRender.call(this, ct, position);
        
        var statusClass = (this.getValue().inputValue == 0) ? ' off':'on';
        
        this.switch = new Ext.Element(Ext.DomHelper.append(this.el, {
            tag: 'div',
            cls: 'x-iphone-switch' + statusClass,
            children:[{
                tag: 'img',
                src: 'static/images/iphone_switch_container.gif'
            }]
        }));
        
        // add class to label so we can target it using css
        this.switch.parent('div.x-form-element').prev('label').addClass('x-iphone-switch-label');
        
        // add listener
        this.switch.on('click', this.onClick, this, {delegate:'img'});
    },
    
    onClick: function(e, t){
        e.stopEvent();
        
        // change the value of the form
        this.setValue('toggle');

        // fire event
        this.fireEvent("afterchange", this, this.value);
    },    
    
    /**
     * @param {string} val
     *
     * We are overriding the default behavior of the setValue method
     * so we can use the form's bulk setValues method and just pass in
     * either true, false, on, off, or toggle.
     */
    setValue: function(val){

		// see if we are toggling the switch's state
		if(val === 'toggle'){
			val = (this.getValue().inputValue) ? false:true;
		}
		// if val is 'on', true, or 1 turn this on the switch
		else if([1,'true',true,'on'].indexOf(val) !== -1){
			val = true;
			console.log(this.switch);
		}
		// then we must be turning the switch off
		else if([0,'false',false,'off'].indexOf(val) !== -1){
			val = false;
			this.switch.removeClass('on').addClass('off');
		}
		// unrecongized value
		else{
			console.log('Unknown value for iPhoneSwitch: ' + val);
		}
		
		// set the internal radio button's value
		this.items.first().setValue(val);
				
		// animate image
		this.animateSwitch(val);
    },
    
    /**
     * @param {string} - Possible values are true or false
     *
     * This animates the switching of the switch use CSS3 animations
     */
    animateSwitch: function(status){
        
        if(status){
	        this.switch.removeClass('off').addClass('on');
	    }else{
			this.switch.removeClass('on').addClass('off');	
	    }
    }
});
 
// register xtype
Ext.reg('iphoneswitch', Ext.ux.plugins.iPhoneSwitch);

// end of file