PDA

View Full Version : [3.0] Themable Checkbox replacement with 3 working modes



prometheus
25 Jun 2009, 3:09 PM
This is a brand new replacement of original Ext.form.Checkbox with many more improvements. First I say thanks to Condor for his replacement - I`m just saw that code and I hope I`m being permitted to implement his features too so I`m do that. Most of the features are independent from many other implementation.

My Checkbox worked in three mode:

compat: this emulates how the original Checkbox works
switch: Always sent a value to server, defaults to '0' or '1' if unchecked/checked.
cycled: Always sent a value to server, it has 7 states by default, clicks skiping to next state.

You can change any state value and CSS classnames default to your best fit, expected the compat mode settings (but classnames are changable for that). You can really theme all states by redefining these settings. In compat mode you can specify that if you want or not to use theme. By ideas and with some codes from Condors implementation you able to use the power of ExtJS`s validation system.

Here is the JS code:
Ext.namespace('Ext.sm.Form');

Ext.sm.Form.BasicCheckbox = Ext.extend(Ext.form.Field, {
/**
* @cfg {String} focusClass The CSS class to use when the checkbox receives
* focus (defaults to undefined).
*/
focusClass : undefined,
/**
* @cfg {String} fieldClass The default CSS class for the checkbox (defaults
* to "x-form-field").
*/
fieldClass: "x-form-field",
/**
* @cfg {Boolean} checked True if the the checkbox should render already
* checked (defaults to false). When checked is false, first value will
* associated to {@link #inputValue} in all {@link #mode}.
*/
checked: false,
/**
* @cfg {String} mode Determinates that how the checkbox will be work. You
* can choose from three working mode:
* <ul>
* <li><b>compat</b>: This is how the normal checkbox works - ONLY if checked,
* {@link #inputValue} being send to the remote server.</li>
* <li><b>switch</b>: In this mode a checkbox must be have a value based on
* its state checked/unchecked.</li>
* <li><b>cycled</b>: This mode evolves <i>switch</i>-mode, values and looks
* cycled on evry clicks, a value must have.</li>
* Default is: compat
*/
mode: 'compat',
/**
* @cfg {Boolean} themedCompat True if use themes in compat mode (defaults
* to false).
*/
themedCompat: false,
/**
* @cfg {String/Object} autoCreate A DomHelper element spec, or true for a
* default element spec (defaults to {tag: "input", type: "checkbox",
* autocomplete: "off"})
*/
defaultAutoCreate : { tag: "input", type: 'checkbox', autocomplete: "off"},
/**
* @cfg {String} boxLabel The text that appears beside the checkbox.
*/
boxLabel: undefined,
/**
* @cfg {String} inputValue The value that should go into the generated
* input element's value attribute.
*/
inputValue: undefined,
/**
* @cfg {String} markEl Defines that what element used to marking invalid.
*/
markEl: 'wrap',
/**
* @cfg {Boolean} mustCheck True if want to mark as invalid if checkbox
* unchecked (defaults to false). Only works in <i>compat</i>-{@link #mode}.
*/
mustCheck: false,
/**
* @cfg {String} mustCheckText Specifies what message will be appear if
* checkbox marked as invalid.
*/
mustCheckText: 'This field is required',
/**
* @cfg {Object} compatConfig This is a mode config describes what class
* to be use if <i>compat</i> checkbox enabled/disabled and checked/unchecked.
* <pre><code>compatConfig: {
enabled: {
'no': 'checkbox_off',
'on': 'checkbox_on'
},
disabled: {
'no': 'checkbox_off_dled',
'on': 'checkbox_on_dled'
},
width: 23,
height: 23
}</code></pre>
* The keys <i>on</i> and <i>no</i> are fixed and must not changed - their
* value pairs are changeable and must be valid CSS class names with a
* visible background image.
* <p><b>Important:</b> If you want to redefine a setting, you MUST redefine
* all settings in this section!</p>
* <p><b>DO NOT USE boolean true/false for keys or values!</b></p>
*/
compatConfig: {
enabled: {
'no': 'checkbox_off',
'on': 'checkbox_on'
},
disabled: {
'no': 'checkbox_off_dled',
'on': 'checkbox_on_dled'
},
width: 14,
height: 16
},
/**
* @cfg {Object} switchConfig This is a mode config describes what class
* to be use if <i>switch</i> checkbox enabled/disabled and checked/unchecked.
* <pre><code>switchConfig: {
enabled: {
'0': 'checkbox_off',
'1': 'checkbox_on'
},
disabled: {
'0': 'checkbox_off_dled',
'1': 'checkbox_on_dled'
},
width: 23,
height: 23
}</code></pre>
* The keys - defaults to <i>0</i> and <i>1</i> - and their value pairs are
* changeable. Keys used to set checkbox value when checkbox checked/unchecked,
* values are valid CSS class names with a visible background image.
* <p><b>Important:</b> If you want to redefine a setting, you MUST redefine
* all settings in this section!</p>
* <p><b>DO NOT USE boolean true/false for keys or values!</b></p>
*/
switchConfig: {
enabled: {
'0': 'checkbox_off',
'1': 'checkbox_on'
},
disabled: {
'0': 'checkbox_off_dled',
'1': 'checkbox_on_dled'
},
width: 14,
height: 16
},
/**
* @cfg {Object} cycledConfig This is a mode config describes what class
* to be use if <i>cycled</i> checkbox enabled/disabled in any state.
* <pre><code>cycledConfig: {
enabled: {
'0': 'flag_blue',
'1': 'flag_green',
'2': 'flag_orange',
'3': 'flag_pink',
'4': 'flag_purple',
'5': 'flag_red',
'6': 'flag_yellow'
},
disabled: {
'0': 'flag_grey',
'1': 'flag_grey',
'2': 'flag_grey',
'3': 'flag_grey',
'4': 'flag_grey',
'5': 'flag_grey',
'6': 'flag_grey'
},
width: 23,
height: 16
}</code></pre>
* The keys - defaults to <i>0</i> ... <i>6</i> - and their value pairs are
* changeable. Keys used to set checkbox value when checkbox is in a specific
* state of its cycle, values are valid CSS class names with a visible
* background image.
* <p><b>Important:</b> If you want to redefine a setting, you MUST redefine
* all settings in this section!</p>
* <p><b>DO NOT USE boolean true/false for keys or values!</b></p>
*/
cycledConfig: {
enabled: {
'0': 'flag_blue',
'1': 'flag_green',
'2': 'flag_orange',
'3': 'flag_pink',
'4': 'flag_purple',
'5': 'flag_red',
'6': 'flag_yellow'
},
disabled: {
'0': 'flag_grey',
'1': 'flag_grey',
'2': 'flag_grey',
'3': 'flag_grey',
'4': 'flag_grey',
'5': 'flag_grey',
'6': 'flag_grey'
},
width: 16,
height: 16
},
// private - stores the first value of this checkbox
originalValue: undefined,
// private - stores active value all the time
protectedValue: undefined,

// private
initComponent : function(){
Ext.sm.Form.BasicCheckbox.superclass.initComponent.call(this);
this.addEvents(
/**
* @event check
* Fires when the checkbox is checked or unchecked.
* @param {Ext.form.Checkbox} this This checkbox
* @param {Boolean} checked The new checked value
* @param {Mixed} value The new {@link #inputValue} value
*/
'check',
/**
* @event click
* Fires when clicking on the checkbox.
* @param {Ext.form.Checkbox} this This checkbox
* @param {Boolean} checked The new checked value
* @param {Mixed} value The new {@link #inputValue} value
*/
'click'
);
},

// private
onResize : function()
{
Ext.sm.Form.BasicCheckbox.superclass.onResize.apply(this, arguments);
if (!this.boxLabel)
{
this.el.alignTo(this.wrap, 'c-c');
}
},

// private
initEvents : function()
{
Ext.sm.Form.BasicCheckbox.superclass.initEvents.call(this);
if (this.mode != 'compat' || this.themedCompat)
{
this.mon(this.el, {
click: this.onClick,
change: this.onChange,
mouseenter: this.onMouseEnter,
mouseleave: this.onMouseLeave,
mousedown: this.onMouseDown,
mouseup: this.onMouseUp,
scope: this
});
}
else
{
this.mon(this.el, {
click: this.onClick,
change: this.onChange,
scope: this
});
}
},

// private
getResizeEl : function()
{
return this.wrap;
},

// private
getPositionEl: function()
{
return this.wrap;
},

// private
alignErrorIcon: function()
{
this.errorIcon.alignTo(this.wrap, 'tl-tr', [2, 0]);
},

/**
* Mark this field as invalid, using {@link #msgTarget} to determine how to
* display the error and applying {@link #invalidClass} to the field's
* element.
* @param {String} msg (optional) The validation message (defaults to
* {@link #invalidText})
*/
markInvalid: function(msg)
{
Ext.sm.Form.BasicCheckbox.superclass.markInvalid.call(this, msg);
},

/**
* Clear any invalid styles/messages for this field.
*/
clearInvalid: function()
{
Ext.sm.Form.BasicCheckbox.superclass.clearInvalid.call(this);
},

// private
validateValue: function(value)
{
var v = (this.rendered? this.el.dom.value : this.inputValue);
var d = ((this.rendered? this.el.dom.disabled : this.disabled)? 'disabled' : 'enabled');
if (this.mode == 'compat' && this.mustCheck && !value)
{
this.markInvalid(this.mustCheckText);
return false;
}
if (this.mode != 'compat')
if (v !== undefined && v !== null && this[this.mode+'Config'][d][v] === undefined)
{
this.markInvalid();
return false;
}
if (this.vtype)
{
var vt = Ext.form.VTypes;
if (!vt[this.vtype](value, this))
{
this.markInvalid(this.vtypeText || vt[this.vtype +'Text']);
return false;
}
}
if (typeof this.validator == "function")
{
var msg = this.validator(value);
if (msg !== true)
{
this.markInvalid(msg);
return false;
}
}
if (this.regex && !this.regex.test(value))
{
this.markInvalid(this.regexText);
return false;
}
return true;
},

// private
onRender : function(ct, position)
{
Ext.sm.Form.BasicCheckbox.superclass.onRender.call(this, ct, position);
var vw = this[this.mode+'Config'].width;
var vh = this[this.mode+'Config'].height;

this.protectedValue = this.inputValue;
if (this.protectedValue !== undefined)
{
this.el.dom.value = this.protectedValue;
}
else
{
this.setNextValue(); // initialize first value set
}

if (this.mode != 'compat' || this.themedCompat) this.el.setOpacity(0);
this.innerWrap = this.el.wrap({cls: "x-sm-form-check-innerwrap"});
this.innerWrap.setStyle({
'position': 'relative',
'display': 'inline'
});
this.wrap = this.innerWrap.wrap({cls: "x-form-check-wrap"});
this.vel = this.innerWrap.createChild({tag: 'div', cls: 'x-sm-form-check'}, this.el.dom);
if (this.mode != 'compat' || this.themedCompat)
{
this.vel.setSize(vw, vh);
this.el.setStyle({
'position': 'absolute'
});
this.el.setTop(Math.round((vh-16)/2));
this.el.setLeft(Math.round((vw-14)/2));
}

if (this.boxLabel)
{
this.wrap.createChild({tag: 'label', htmlFor: this.el.id, cls: 'x-form-cb-label', html: this.boxLabel});
}

if (this.mode == 'compat')
{
this.checked = (this.checked? true : (this.el.dom.checked? true : false));
this.setValue(this.checked);
}
else
{
this.el.dom.checked = true;
this.el.dom.defaultChecked = true;
this.setValue(this.protectedValue);
}
},

// private
manageActiveClass: function()
{
if (this.rendered && (this.mode != 'compat' || this.themedCompat))
{
var v = (this.mode == 'compat'? this.protectedValue : (this.rendered? this.el.dom.value : this.protectedValue));
var d = ((this.rendered? this.el.dom.disabled : this.disabled)? 'disabled' : 'enabled');
var c = this[this.mode+'Config'][d][v];
var fval;

for (var i in this[this.mode+'Config'][d])
{
fval = i;
break;
}

if (c === undefined)
{
c = this[this.mode+'Config'][d][fval];
}

if (this.previousClass !== undefined)
{
this.vel.removeClass(this.previousClass);
}
this.previousClass = c; // store previously set classname.
this.vel.addClass(c);
}
},

// private
setNextValue: function()
{
var v = (this.mode == 'compat'? this.protectedValue : (this.rendered? this.el.dom.value : this.protectedValue));
var d = ((this.rendered? this.el.dom.disabled : this.disabled)? 'disabled' : 'enabled');
var setNewValue = false;
var fval = null;

this.protectedValue = null;
for (var i in this[this.mode+'Config'][d])
{
if (fval === null) fval = i;
if (v === undefined) break; // undefined sets first value
if (setNewValue && this.protectedValue === null)
{
this.protectedValue = i;
}
if (i == v)
{
setNewValue = true;
}
}
if (this.protectedValue === null) this.protectedValue = fval;

if (this.mode != 'compat')
{
this.inputValue = this.protectedValue;
}
if (this.rendered && this.inputValue !== undefined)
{
this.el.dom.value = this.inputValue;
}
},

// private
onDestroy : function(){
if (this.wrap) this.wrap.remove();
Ext.sm.Form.BasicCheckbox.superclass.onDestroy.call(this);
},

// private
initValue : function()
{
// reference to original value for reset
this.originalValue = this.inputValue;
if (this.mode == 'compat')
{
this.originalValue = this.checked;
}
},

/**
* Returns the raw data value which may or may not be a valid, defined
* value. To return a normalized value see {@link #getValue}.
* @return {Mixed} value The field value
*/
getRawValue : function()
{
if (this.mode == 'compat')
{
if (this.rendered) return this.el.dom.checked;
else return this.checked;
}
var v = this.rendered ? this.el.getValue() : Ext.value(this.value, '');
return v;
},

/**
* In <i>compat</i>-{@link #mode} returns the checked state of the checkbox.
* In other modes returns the state`s value.
* @return {Boolean/Mixed} True if checked, else false, Mixed on non-compat
* modes.
*/
getValue : function()
{
var result = false;

if (this.mode == 'compat') if (this.rendered) result = this.el.dom.checked;
else result = this.protectedValue;

return result;
},

// private
onClick : function()
{
if (this.mode == 'compat')
{
if (this.el.dom.checked != this.checked)
{
this.setNextValue();
this.checked = this.el.dom.checked;
}
}
else
{
this.setNextValue();
this.el.dom.checked = true;
this.el.dom.defaultChecked = true;
}
this.manageActiveClass();
this.validate();
this.fireEvent('check', this, this.checked, this.inputValue);
this.fireEvent('click', this, this.checked, this.inputValue);
},

// private
onChange : function()
{
if (this.mode == 'compat')
{
if (this.el.dom.checked != this.checked)
{
this.setNextValue();
this.checked = this.el.dom.checked;
}
}
else
{
this.inputValue = this.el.dom.value;
this.protectedValue = this.inputValue;
this.el.dom.checked = true;
this.el.dom.defaultChecked = true;
}
this.manageActiveClass();
this.validate();
this.fireEvent('check', this, this.checked, this.inputValue);
this.fireEvent('change', this, this.checked, this.inputValue);
},

/**
* Sets the checked state of the checkbox.
* @param {Boolean/Mixed} value In <i>compat</i>-{@link #mode}, boolean
* true, 'true', '1', or 'on' to check the checkbox, any other value will
* uncheck it. In other modes, boolean values ignored, valid modevalues
* sets checkbox input value and changing state, invalid values sets to
* first valid value.
* @return {Ext.form.Field} this
*/
setValue : function(value)
{
if (this.mode == 'compat')
{
this.checked = (value === true || value === 'true' || value == '1' || String(value).toLowerCase() == 'on');
if (this.rendered)
{
this.el.dom.checked = this.checked;
this.el.dom.defaultChecked = this.checked;
}
this.protectedValue = (this.checked? 'on' : 'no');
}
else
{
var d = ((this.rendered? this.el.dom.disabled : this.disabled)? 'disabled' : 'enabled');
this.checked = true;
if (this[this.mode+'Config'][d][value] !== undefined)
{
this.protectedValue = value;
}
else
{
for (var i in this[this.mode+'Config'][d])
{
this.protectedValue = i;
break;
}
}
this.inputValue = this.protectedValue;
if (this.rendered && this.inputValue !== undefined)
{
this.el.dom.value = this.inputValue;
}
}
this.manageActiveClass();
this.validate();
this.fireEvent("check", this, this.checked);
return this;
},

disable: function()
{
Ext.sm.Form.BasicCheckbox.superclass.disable.call(this);
this.manageActiveClass();
},

enable: function()
{
Ext.sm.Form.BasicCheckbox.superclass.enable.call(this);
this.manageActiveClass();
},

onMouseEnter: function()
{
this.wrap.addClass('x-sm-form-check-over');
},

onMouseLeave: function()
{
this.wrap.removeClass('x-sm-form-check-over');
},

onMouseDown: function()
{
this.wrap.addClass('x-sm-form-check-down');
},

onMouseUp: function()
{
this.wrap.removeClass('x-sm-form-check-down');
},

onFocus: function()
{
Ext.sm.Form.BasicCheckbox.superclass.onFocus.call(this);
this.wrap.addClass('x-sm-form-check-focus');
},

onBlur: function()
{
Ext.sm.Form.BasicCheckbox.superclass.onBlur.call(this);
this.wrap.removeClass('x-sm-form-check-focus');
}
});

Ext.form.Checkbox = Ext.sm.Form.BasicCheckbox;
Ext.reg('checkbox', Ext.form.Checkbox);

Ext.sm.Form.Checkbox = Ext.extend(Ext.sm.Form.BasicCheckbox, {
mode: 'switch'
});
Ext.reg('switch_checkbox', Ext.sm.Form.Checkbox);

Ext.sm.Form.CycleCheckbox = Ext.extend(Ext.sm.Form.BasicCheckbox, {
mode: 'cycled'
});
Ext.reg('cycle_checkbox', Ext.sm.Form.CycleCheckbox);

// This is where I say, credit to Condor for implement his replacement!

Ext.override(Ext.form.Field, {
markEl: 'el',
markInvalid: function(msg){
if(!this.rendered || this.preventMark){
return;
}
msg = msg || this.invalidText;
var mt = this.getMessageHandler();
if(mt){
mt.mark(this, msg);
}else if(this.msgTarget){
this[this.markEl].addClass(this.invalidClass);
var t = Ext.getDom(this.msgTarget);
if(t){
t.innerHTML = msg;
t.style.display = this.msgDisplay;
}
}
this.fireEvent('invalid', this, msg);
},
clearInvalid : function(){
if(!this.rendered || this.preventMark){
return;
}
var mt = this.getMessageHandler();
if(mt){
mt.clear(this);
}else if(this.msgTarget){
this[this.markEl].removeClass(this.invalidClass);
var t = Ext.getDom(this.msgTarget);
if(t){
t.innerHTML = '';
t.style.display = 'none';
}
}
this.fireEvent('valid', this);
}
});
Ext.apply(Ext.form.MessageTargets, {
'qtip': {
mark: function(field, msg){
var markEl = field[(field.markEl? field.markEl : 'el')];
markEl.addClass(field.invalidClass);
markEl.dom.qtip = msg;
markEl.dom.qclass = 'x-form-invalid-tip';
if(Ext.QuickTips){
Ext.QuickTips.enable();
}
},
clear: function(field){
var markEl = field[(field.markEl? field.markEl : 'el')];
markEl.removeClass(field.invalidClass);
markEl.dom.qtip = '';
}
},
'title': {
mark: function(field, msg){
var markEl = field[(field.markEl? field.markEl : 'el')];
markEl.addClass(field.invalidClass);
markEl.dom.title = msg;
},
clear: function(field){
field[field.markEl].dom.title = '';
}
},
'under': {
mark: function(field, msg){
var markEl = field[(field.markEl? field.markEl : 'el')], errorEl = field.errorEl;
markEl.addClass(field.invalidClass);
if(!errorEl){
var elp = field.getErrorCt();
if(!elp){
markEl.dom.title = msg;
return;
}
errorEl = field.errorEl = elp.createChild({cls:'x-form-invalid-msg'});
errorEl.setWidth(elp.getWidth(true) - 20);
}
errorEl.update(msg);
Ext.form.Field.msgFx[field.msgFx].show(errorEl, field);
},
clear: function(field){
var markEl = field[(field.markEl? field.markEl : 'el')], errorEl = field.errorEl;
markEl.removeClass(field.invalidClass);
if(errorEl){
Ext.form.Field.msgFx[field.msgFx].hide(errorEl, field);
}else{
markEl.dom.title = '';
}
}
},
'side': {
mark: function(field, msg){
var markEl = field[(field.markEl? field.markEl : 'el')], errorIcon = field.errorIcon;
markEl.addClass(field.invalidClass);
if(!errorIcon){
var elp = field.getErrorCt();
if(!elp){
markEl.dom.title = msg;
return;
}
errorIcon = field.errorIcon = elp.createChild({cls:'x-form-invalid-icon'});
}
field.alignErrorIcon();
errorIcon.dom.qtip = msg;
errorIcon.dom.qclass = 'x-form-invalid-tip';
errorIcon.show();
field.on('resize', field.alignErrorIcon, field);
},
clear: function(field){
var markEl = field[(field.markEl? field.markEl : 'el')], errorIcon = field.errorIcon;
markEl.removeClass(field.invalidClass);
if(errorIcon){
errorIcon.dom.qtip = '';
errorIcon.hide();
field.un('resize', field.alignErrorIcon, field);
}else{
markEl.dom.title = '';
}
}
}
});


Here is my pure CSS:

/**
* sYs-mini Checkbox control
*/
.x-sm-form-check-innerwrap
{
float: left;
}

.x-sm-form-check.checkbox_on
{
background-image: url(<P_WEB_PATH>media/images/admin/components/checkbox_on.png);
background-repeat: no-repeat;
}

.x-sm-form-check.checkbox_off
{
background-image: url(<P_WEB_PATH>media/images/admin/components/checkbox_off.png);
background-repeat: no-repeat;
}

.x-sm-form-check.checkbox_on_dled
{
background-image: url(<P_WEB_PATH>media/images/admin/components/checkbox_on_dled.png);
background-repeat: no-repeat;
}

.x-sm-form-check.checkbox_off_dled
{
background-image: url(<P_WEB_PATH>media/images/admin/components/checkbox_off_dled.png);
background-repeat: no-repeat;
}

.x-sm-form-check.flag_blue
{
background-image: url(<P_WEB_PATH>media/images/admin/components/flag_blue.png);
background-repeat: no-repeat;
}

.x-sm-form-check.flag_green
{
background-image: url(<P_WEB_PATH>media/images/admin/components/flag_green.png);
background-repeat: no-repeat;
}

.x-sm-form-check.flag_orange
{
background-image: url(<P_WEB_PATH>media/images/admin/components/flag_orange.png);
background-repeat: no-repeat;
}

.x-sm-form-check.flag_pink
{
background-image: url(<P_WEB_PATH>media/images/admin/components/flag_pink.png);
background-repeat: no-repeat;
}

.x-sm-form-check.flag_purple
{
background-image: url(<P_WEB_PATH>media/images/admin/components/flag_purple.png);
background-repeat: no-repeat;
}

.x-sm-form-check.flag_red
{
background-image: url(<P_WEB_PATH>media/images/admin/components/flag_red.png);
background-repeat: no-repeat;
}

.x-sm-form-check.flag_yellow
{
background-image: url(<P_WEB_PATH>media/images/admin/components/flag_yellow.png);
background-repeat: no-repeat;
}

.x-sm-form-check.flag_grey
{
background-image: url(<P_WEB_PATH>media/images/admin/components/flag_grey.png);
background-repeat: no-repeat;
}

Images attached to this post. Please do not forget that You must replace my image paths!

Here is a test case (or a little demo):

Ext.namespace('Test');

Test.AddWindow = Ext.extend(Ext.Window, {
width: 600,
height: 230,
title: 'Test title',

initComponent : function()
{
Test.AddWindow.superclass.initComponent.call(this);

this.content = new Ext.form.FormPanel({
xtype: 'form',
frame: true,
border: false,
autoHeight: true,
items: [{
xtype: 'fieldset',
title: 'Choose one',
autoHeight: true,
items: [{
xtype: 'checkbox',
ctCls: 'improvedCheckbox',
name: 'cb[exists1]',
mustCheck: true,
checked: true,
hideLabel: true,
boxLabel: 'Compatible mode (full - theme disabled)',
listeners: {
click: this.onCbClick
}
}, {
xtype: 'checkbox',
ctCls: 'improvedCheckbox',
name: 'cb[exists2]',
checked: true,
hideLabel: true,
boxLabel: 'Compatible mode (partial - theme enabled)',
themedCompat: true,
listeners: {
click: this.onCbClick
}
}, {
xtype: 'sm_checkbox',
ctCls: 'improvedCheckbox',
name: 'cb[value]',
inputValue: '0',
checked: false,
hideLabel: true,
boxLabel: 'Switch mode',
listeners: {
click: this.onCbClick
}
}, {
xtype: 'cycle_checkbox',
ctCls: 'improvedCheckbox',
name: 'cb[state]',
inputValue: '0',
checked: false,
hideLabel: true,
boxLabel: 'Cycled mode',
listeners: {
click: this.onCbClick
}
}]
}],
buttons: [{
text: 'Disable all',
handler: function()
{
var cbs = this.find('ctCls', 'improvedCheckbox');
Ext.each(cbs, function(i){i.disable();});
}.createDelegate(this)
}, {
text: 'Enable all',
handler: function()
{
var cbs = this.find('ctCls', 'improvedCheckbox');
Ext.each(cbs, function(i){i.enable();});
}.createDelegate(this)
}, {
text: 'Get values',
handler: function()
{
if(this.content.getForm().isValid()){
Ext.Msg.alert('Values', 'The following will be sent to the server: <br />'+
this.content.getForm().getValues(true).replace(/&/g,',<br/>'));
}
}.createDelegate(this)
}, {
text: 'Reset',
handler: function()
{
this.content.getForm().reset();
}.createDelegate(this)
}]
});

this.add(this.content);
},

onCbClick: function(s, c, v)
{
console.log('name: ' + s.name);
console.log('checked property: ' + c);
console.log('checked DOM value: ' + s.el.dom.checked);
console.log('value: ' + v);
console.log('DOM value: ' + s.el.dom.value);
console.log('--------------------------------------------------------');
}
});

var win = new Test.AddWindow();
win.show();

For testing use FF3 with FireBug, in other way you must make commented all console.log() calls!

I hope that this work being a must. :)

Regards,

galdaka
25 Jun 2009, 10:58 PM
Live example or screenshot?

Thanks in advance,

Greetings,

prometheus
26 Jun 2009, 1:32 AM
Live example or screenshot?

Nope, I`m still have problems with my bandwidth, ExtJS were not on my server therefore I must upload first which may a 1-3 hours long process :/

You can easily create a demo - if you have the required minimal practice as I assume you have that - like the FileUploadField demo in official examples.

I will create a demosite with my other components too as soon as my bandwidth resurrects.

mystix
26 Jun 2009, 1:38 AM
Nope, I`m still have problems with my bandwidth, ExtJS were not on my server therefore I must upload first which may a 1-3 hours long process :/


3 hours?! :s

why don't you try this instead:
http://extjs.com/blog/2008/11/18/ext-cdn-custom-builds-compression-and-fast-performance/

then rewrite your links to point there instead.

prometheus
26 Jun 2009, 3:39 AM
I`m just updated component`s source code because some bugfixing in validation and missed check event fire points. All of these are tested with RC1 in a complex app, FF3.

prometheus
26 Jun 2009, 3:52 AM
Thanks for tip. Well, I`ve 5k/s bandwidth :S and a powerfull deficit of time, both make many problems in supporting my sources correctly. Therefore I share my sources for those ppl who want to use but I have not enough time and bandwidth for creating a properly demosite and make other support except the bugfixes and updates with the required descriptions.

And I do not see the meaning of a screenshot, this is a checkbox only, not a "secret NASA satelite select control", all images what are used by default placed in the attached zip, all could be replaceable.

In the near future I will create a demosite as I promised, please be patient.

McCornic
21 Sep 2009, 1:40 AM
Hi,

Please find enclosed a full demo package.
Download and extract the content.
Then open in your navigator the index.html file.

Below a screenshot of the demo page: (You must be logged)

http://www.extjs.com/forum/attachment.php?attachmentid=16304&stc=1&d=1253525768

Prometheus, you have a little mistake in your test case:

xtype: 'sm_checkbox' => xtype: 'switch_checkbox'


Regards

rbraddy
20 Oct 2009, 10:36 AM
Prometheus,

I want to start by saying THANK YOU for this great checkbox implementation. I'm just using the "switch_checkbox" for now, but it's a lifesaver for those of us who need to be assured of a value being sent to the server.

I would like my switch_checkbox to the default theme (so it looks like a usual checkbox) - not sure what setting I need to use.

Thanks

Rick

rbraddy
20 Oct 2009, 10:58 AM
Just did some browser testing. Works great in Firefox and Chrome. As usual these days, Internet Explorer has some anomalies. There's some kind of initial display alignment issue, which is especially bad looking in a form column.

What's interesting is that if the mouse is position over the top of a checkbox in IE, it hops over to the left and redisplays in the proper location! (as shown in the image, I had moved the mouse over the first three checkboxes, which now appear where they should).

Very strange. I hope we can find a fix for this, as it's the only anomaly I've seen thus far with an otherwise perfect themable checkbox control replacement.

Here's the code:




},{
// right column
// defaults for fields
defaults:{anchor:'99%'}
,items:[{
xtype:'combo',
store:['1', '2', '3', '4', '5', '6', '7', '8', '9', '10'],
fieldLabel:'Relationship Strength',
mode:'local',
triggerAction:'all',
name:"answers[relationshipstrength]",
displayField:'name'
},{
xtype:'switch_checkbox',
fieldLabel:'List',
id:'cbmonetizelist',
boxLabel: 'Monetize existing list assets',
name:"answers[monetizelist]"
},{
xtype:'switch_checkbox',
id:'cbgrowlist',
boxLabel: 'Grow existing list size',
name:"answers[growlist]"
},{
xtype:'switch_checkbox',
id:'cbimproverelations',
boxLabel: 'Improve/repair relationships',
name:"answers[improverelationship]"
},{
xtype:'switch_checkbox',
id:'cbnewlist',
boxLabel: 'Establish a completely new list',
name:"answers[newlist]"
},{
id:'cbexistingcommunity',
fieldLabel:'Community',
xtype:'switch_checkbox',
boxLabel: 'Tap into existing, public communities',
name:"answers[existingcommunity]"
},{
xtype:'switch_checkbox',
id:'cbexpandcommunity',
boxLabel: 'Expand an existing, private community',
name:"answers[expandcommunity]"
},{
xtype:'switch_checkbox',
id:'cbcreatecommunity',
boxLabel: 'Create a new community',
name:"answers[createcommunity]"
}
]
}]




Rick

rbraddy
20 Oct 2009, 11:38 AM
I figured out a workaround that's working for me in IE8 (and Firefox and Chrome). I made a one-line addition to the Render method. Note that this has only been tested with "switch_checkbox" mode in my application, but it's a reasonable workaround that forces proper checkbox alignment in forms in IE 8.

The one line workaround is highlighted below in blue.

Best,

Rick



// private
onRender : function(ct, position)
{
Ext.sm.Form.BasicCheckbox.superclass.onRender.call(this, ct, position);
var vw = this[this.mode+'Config'].width;
var vh = this[this.mode+'Config'].height;

this.protectedValue = this.inputValue;
if (this.protectedValue !== undefined)
{
this.el.dom.value = this.protectedValue;
}
else
{
this.setNextValue(); // initialize first value set
}

if (this.mode != 'compat' || this.themedCompat) this.el.setOpacity(0);
this.innerWrap = this.el.wrap({cls: "x-sm-form-check-innerwrap"});
this.innerWrap.setStyle({
'position': 'relative',
'display': 'inline'
});
this.wrap = this.innerWrap.wrap({cls: "x-form-check-wrap"});
this.vel = this.innerWrap.createChild({tag: 'div', cls: 'x-sm-form-check'}, this.el.dom);
this.wrap.addClass('x-sm-form-check-over'); // 10/20/2009 rgb IE workaround
if (this.mode != 'compat' || this.themedCompat)
{
this.vel.setSize(vw, vh);
this.el.setStyle({
'position': 'absolute'
});
this.el.setTop(Math.round((vh-16)/2));
this.el.setLeft(Math.round((vw-14)/2));
}

if (this.boxLabel)
{
this.wrap.createChild({tag: 'label', htmlFor: this.el.id, cls: 'x-form-cb-label', html: this.boxLabel});
}

if (this.mode == 'compat')
{
this.checked = (this.checked? true : (this.el.dom.checked? true : false));
this.setValue(this.checked);
}
else
{
this.el.dom.checked = true;
this.el.dom.defaultChecked = true;
this.setValue(this.protectedValue);
}
},

prometheus
21 Oct 2009, 7:24 AM
Thanks for all who used and fixed up (especially: shared back) my component. If I have enough time, I`ll give all of my codes in my hand and create a correct demo site.

Thanks again!

McCornic
22 Oct 2009, 11:01 PM
Prometheus,

I want to start by saying THANK YOU for this great checkbox implementation. I'm just using the "switch_checkbox" for now, but it's a lifesaver for those of us who need to be assured of a value being sent to the server.

I would like my switch_checkbox to the default theme (so it looks like a usual checkbox) - not sure what setting I need to use.

Thanks

Rick

I had the same problem, so I had the following css after the css of this extension :



/***** Basic Checkbox ************************************************************************/

.x-sm-form-check.checkbox_off {
background-image:url(../js/extjs/resources/images/default/form/checkbox.gif);
background-repeat:no-repeat;
background-position:0 0;
height:13px !important;
width:13px !important;
}
.x-sm-form-check.checkbox_on {
background-image:url(../js/extjs/resources/images/default/form/checkbox.gif);
background-repeat:no-repeat;
background-position:0 -13px;
height:13px !important;
width:13px !important;
}
.x-sm-form-check.checkbox_on_dled
{
background-image: url(../js/extjs/resources/images/default/form/checkbox.gif);
background-repeat: no-repeat;
background-position:0 -26px;
height:13px !important;
width:13px !important;
}

.x-sm-form-check.checkbox_off_dled
{
background-image: url(../js/extjs/resources/images/default/form/checkbox.gif);
background-repeat: no-repeat;
background-position:0 0;
height:13px !important;
width:13px !important;
}
input.x-form-checkbox
{
left:0 !important;
top:0 !important;
}
.x-sm-form-check-innerwrap{
margin-top:5px;
}
/*************************************************************************************************/


Hope it can help you!

rbraddy
23 Oct 2009, 12:45 AM
Thanks! I just ended up modifying the checkbox image files to be black/white, so they match the style of the ExtJS controls.

Best,

Rick