PDA

View Full Version : Ext.ux.form.TriCheckbox



scottpederick
8 May 2008, 4:37 PM
Hi,

Thought this may be of use to someone - it's a three-state checkbox field. It can be set to inherited (inherits either on or off) or set to on or off. The checkbox states are indicated by images.

The setInheritedValue() method sets whether the control is inheriting on or off.
Applying setValue(null) means the control will use the inherited state.
Returns blank, zero or one on submit to indicate 'inherited', 'off' or 'on'.

I've attached the images I use as well as the css and js. Could do with some lovin' but it works well for what I needed. Any/all feedback welcome, if it needs more explanation just post it here.

Cheers,

Scott




/**
* Ext.ux.form.TriCheckbox - Tri-state checkbox
*
* @license Ext.ux.form.TriCheckbox is licensed under the terms of
* the Open Source LGPL 3.0 license. Commercial use is permitted to the extent
* that the code/component(s) do NOT become part of another Open Source or Commercially
* licensed development library or toolkit without explicit permission.
*
* License details: http://www.gnu.org/licenses/lgpl.html
*/

/**
*
* Default css:
* .tricheckbox-wrap {
* line-height: 18px;
* padding-top:2px;
* }
* .tricheckbox-wrap a {
* display:block;
* width:16px;
* height:16px;
* float:left;
* }
* .x-toolbar .tricheckbox-wrap {
* padding: 0 0 2px 0;
* }
* .tricheckbox-on {
* background:transparent url(./ext/resources/images/default/menu/checked.gif) no-repeat 0 0;
* }
* .tricheckbox-off {
* background:transparent url(./ext/resources/images/default/menu/unchecked.gif) no-repeat 0 0;
* }
* .tricheckbox-inherit-on {
* background:transparent url(./ext/resources/images/default/menu/checked.gif) no-repeat 0 0;
* }
* .tricheckbox-inherit-off {
* background:transparent url(./ext/resources/images/default/menu/unchecked.gif) no-repeat 0 0;
* }
* .tricheckbox-disabled {
* opacity: 0.5;
* -moz-opacity: 0.5;
* filter: alpha(opacity=50);
* cursor:default;
* }
*
* @class Ext.ux.TriCheckbox
* @extends Ext.form.Checkbox
*/
Ext.ns('Ext.ux.form');
Ext.ux.form.TriCheckbox = Ext.extend(Ext.form.Checkbox, {
offCls:'tricheckbox-off'
,onCls:'tricheckbox-on'
,inheritOnCls:'tricheckbox-inherit-on'
,inheritOffCls:'tricheckbox-inherit-off'

,disabledClass:'tricheckbox-disabled'
,submitOffValue:'false'
,submitOnValue:'true'
,submitInheritedValue:''
,inheritedValue: false //Iherited checkbox state is checked or not
,chk: null //Default to inherited
,allowInherited: true //Toggles the inherited/standard behaviour

,onRender:function(ct) {
// call parent
Ext.ux.form.TriCheckbox.superclass.onRender.apply(this, arguments);

//Set the initial value
if(Ext.isEmpty(this.chk)) {
this.chk = (this.allowInherited ? null : false);
}

// save tabIndex remove & re-create this.el
var tabIndex = this.el.dom.tabIndex;
var id = this.el.dom.id;
this.el.remove();
this.el = ct.createChild({tag:'input', type:'hidden', name:this.name, id:id});

// update value of hidden field
this.updateHidden();

// adjust wrap class and create link with bg image to click on
this.wrap.replaceClass('x-form-check-wrap', 'tricheckbox-wrap');
this.cbEl = this.wrap.createChild({
tag:'a',
href:'#',
cls: ((this.chk == null && this.allowInherited)
? (this.inheritedValue ? this.inheritOnCls : this.inheritOffCls)
: (this.chk ? this.onCls : this.offCls)
)
});

// reposition boxLabel if any
var boxLabel = this.wrap.down('label');
if(boxLabel) {
this.wrap.appendChild(boxLabel);
}

// support tooltip
if(this.tooltip) {
this.cbEl.set({qtip:this.tooltip});
}

// install event handlers
this.wrap.on({click:{scope:this, fn:this.onClick, delegate:'a'}});
this.wrap.on({keyup:{scope:this, fn:this.onClick, delegate:'a'}});

// restore tabIndex
this.cbEl.dom.tabIndex = tabIndex;
} // eo function onRender

,onClick:function(e) {
if(this.disabled || this.readOnly) {
return;
}
if(!e.isNavKeyPress()) {
switch (this.chk) {
case null: this.setValue(false); break;
case false: this.setValue(true); break;
case true: (this.allowInherited ? this.setValue(null) : this.setValue(false)); break;
}
}
} // eo function onClick

,onDisable:function() {
this.cbEl.addClass(this.disabledClass);
this.el.dom.disabled = true;
} // eo function onDisable

,onEnable:function() {
this.cbEl.removeClass(this.disabledClass);
this.el.dom.disabled = false;
} // eo function onEnable

,setInheritedValue: function(val) {
if (val == null) { //Inherited
this.inheritedValue = (this.allowInherited ? null : false);
} else { //Match to a boolean
this.inheritedValue = !(!val);
}

//Redraw the checkbox
this.redraw();
}
,setValue:function(val) {

if (val == null) { //Inherited
this.chk = (this.allowInherited ? null : false);
} else if('string' == typeof val) { //Match to the submit value
this.chk = val === this.submitOnValue;
} else { //Match to a boolean
this.chk = !(!val);
}

//Redraw the checkbox
this.redraw();

//Notify that the state was changed
this.fireEvent('check', this, this.chk);

} // eo function setValue

,redraw: function() {

if(this.rendered && this.cbEl) {
this.updateHidden();
this.cbEl.removeClass([this.offCls, this.onCls, this.inheritOffCls, this.inheritOnCls]);
this.cbEl.addClass(
((this.chk == null && this.allowInherited)
? (this.inheritedValue ? this.inheritOnCls : this.inheritOffCls)
: (this.chk ? this.onCls : this.offCls)
)
);
}
}

,updateHidden:function() {
this.el.dom.value = (
(this.chk == null && this.allowInherited)
? this.submitInheritedValue
: (this.chk ? this.submitOnValue : this.submitOffValue)
);
} // eo function updateHidden

,getValue:function() {
return this.chk;
} // eo function getValue

}); // eo extend

// register xtype
Ext.reg('tricheckbox', Ext.ux.form.TriCheckbox);

wm003
14 May 2008, 5:57 AM
Nice code. Based on sakis XCheckbox i guess?. Only the design of the boxes should fit more to the standard Ext theme for my taste.

i changed css to use the default checkboxes from "resources/images/default/menu/" folder of ext distribution. (checked.gif and unchecked.gif) and a third gif with checked and darker background will look more perfect to me.

scottpederick
14 May 2008, 3:53 PM
Ah yes - I meant to give credit to XCheckbox (http://extjs.com/forum/showthread.php?t=25924) without which this wouldn't have been written. :) Many thanks to jsakalos for all his fine work. It's just a small mod on top.

The big, shiny checkboxes sit in line with some other pieces and thought I'd share them around. If you need to use the full inherited featureset, you'd have to create two 'inherited' (greyed) images - one checked and the other unchecked.

Zolcsi
1 Sep 2009, 3:41 AM
I had one small little problem with this component.
If I set the value before it was rendered, then the value just gets ignored.
Here is my fix:

Instead of this: (line 70)


this.chk = (this.allowInherited ? null : false);

I use this:


if(Ext.isEmpty(this.chk)) {
this.chk = (this.allowInherited ? null : false);
}

Hope this helps somebody.
And thanks for this component!

scottpederick
1 Sep 2009, 3:55 AM
Thanks for the fix :)

I've updated the first thread code and zip.