PDA

View Full Version : Ext.ux.form.field.ClearButton - Small clear button/icon over field



stephen.friedrich
7 May 2011, 3:06 PM
A plugin for text fields (as well as date fields, combo boxes and text areas) that shows a small "clear button" in the text field when the mouse is over the field.

Demo and download page (http://www.eekboom.de/ClearButton.html)

This is a small feature, but initially I had totally under-estimated the effort to implement it.
Well, I have probably over-engineered the solution a little what with the animation option to fade in/out the icon and other config options ;-)

Feedback welcome!

morfeusz
8 May 2011, 1:16 PM
very good, thanks

johnleroux
28 May 2011, 9:33 PM
Very very good plugins. Thanks!!!!

Remy
8 Jun 2011, 4:26 AM
Very nice and elegant.

ZeusTheTrueGod
12 Jun 2011, 3:53 AM
Cute, but pretty useless plugin imlementation from a usability point of view.

The 'X' button should be always visible else it is hard to use it.

gustavo21
12 Jun 2011, 2:47 PM
How could add a store reload when i clear a textfield? I wanna use it for filters, and when i clear a textfield the store is reload...

Thanks.

kveeiv
13 Jun 2011, 9:27 AM
The 'X' button should be always visible else it is hard to use it.
Please see the documentation the author has included. This option is available through the configuration options "hideClearButtonWhenEmpty" and "hideClearButtonWhenMouseOut". Setting both to false should give you the functionality you desire.


Feedback welcome!
This is great. It is nice to be able to throw this plugin on to any textfield based input and be able to have a consistent means of clearing the field's value.

A few small notes:
* Your CSS references a custom image for the clear button (in a relative parent path), but this image is not linked to from the download page. I would move the image in to the same folder (or a subfolder instead of a parent), and compress the 3 files in to an archive that can be easily downloaded.

* Some fields might be rendered already by the time this plugin is activated (like when existing input fields are being transformed to extjs fields), which causes this plugin not to register properly. This can be overcome with a simple fix to init(). Additionally, handleAfterRender does not need the parameter it has listed, since the textfield is referenced off of 'this'.



init: function(textField) {
this.textField = textField;
if (!textField.rendered) {
textField.on('afterrender', this.handleAfterRender, this);
} else {
this.handleAfterRender();
}
},


* In an effort to get this compatible with the next version of the BoxSelect (http://www.sencha.com/forum/showthread.php?134751-Ext.ux.form.field.BoxSelect-Intuitive-Multi-Select-ComboBox) component, I modified the calculation of the clear button positioning to be "right" based instead of "left". I believe that this change improves positioning for all fields for both always-on and hover-on cases, using the examples/form/combos.html and examples/form/field-types.html pages for testing. Textareas still suffer from text overlap, but overall they seem to behave better and more consistently between browsers.



/**
* Repositions the clear button element based on the textfield.inputEl element
* @private
*/
repositionClearButton: function() {
var clearButtonEl = this.clearButtonEl;
if (!clearButtonEl) {
return;
}
var clearButtonPosition = this.calculateClearButtonPosition(this.textField);
clearButtonEl.dom.style.right = clearButtonPosition.right + 'px';
clearButtonEl.dom.style.top = clearButtonPosition.top + 'px';
},

/**
* Calculates the position of the clear button based on the textfield.inputEl element
* @private
*/
calculateClearButtonPosition: function(textField) {
var positions = textField.inputEl.getBox(true, true);
var top = positions.y;
var right = positions.x;
if(this.fieldHasScrollBar()) {
right += Ext.getScrollBarWidth();
}
if(this.textField.triggerWrap) {
right += this.textField.getTriggerWidth();
}
return {
right: right,
top: top
};
},

This plugin is cleanly implemented in a way that made these changes easy to make, and works as expected across all textfield-based classes, well done!

stephen.friedrich
14 Jun 2011, 3:30 AM
Cute, but pretty useless plugin imlementation from a usability point of view.

The 'X' button should be always visible else it is hard to use it.
Have a close look at the docs. Your requirement is already exactly documented:
Ext.override(Ext.ux.form.ClearButton, {hideClearButtonWhenEmpty: false});
IMHO it depends on your specific use case. If you want to have the clear button at a lot of text fields, then I think its better to have it only on mouse over because else it would clutter the UI too much.

stephen.friedrich
14 Jun 2011, 3:35 AM
@kveeiv: Thanks a lot for your detailed remarks!
I totally forgot about the button, the point about fields already being rendered is very valid and the new positioning makes sense. I'll updated the plugin shortly.

Now I have to prepare a little for our ExtJS User Group meeting this evening...

stephen.friedrich
15 Jun 2011, 4:46 PM
I have uploaded a new version with changes as proposed by kveeiv.

Also fading in/out of the clear button now uses CSS3 transitions where supported - because when you moved the mouse quickly in/out of a field the ExtJS animation is jumpy.
(Oh, well ok, mostly just for the fun of it and to learn CSS3 ;-)

mmarti
17 Jun 2011, 12:17 AM
Very nice!!! Good work, thank you!!! :D

grgur
17 Jun 2011, 11:14 PM
+1

wki01
21 Jun 2011, 4:28 AM
a small bug:
It should not be active if the field is disabled or readonly.
You can fix it?
thanks

softwareguy
23 Jul 2011, 7:33 AM
Nice!

loiane
5 Aug 2011, 9:48 AM
Nice!

slemmon
14 Aug 2011, 11:13 PM
a small bug:
It should not be active if the field is disabled or readonly.
You can fix it?
thanks

Yeah, looks like in FF the disabled field is honored and not in IE 8 (didn't test others). And readOnly displays the X as well - at least in FF. Didn't test in IE.

That said, VERY COOL plugin. I had modified a triggerfield to show/hide the X trigger when there is a value in the field and that worked, but lacked the sexy value this plugin adds. You have any sway with the devs for an inclusion of this feature in 4.2? :D

Radius-Service
5 Sep 2011, 11:28 PM
Very good.

Please add a custom event handler to "clean up".

austin1030
30 Sep 2011, 1:14 PM
Is there a way not to delete data when the field is set as "readOnly"?

ldonofrio
24 Oct 2011, 6:03 AM
Thanks for this,

I'm having problems with combos with multiSelect: true, setValue('') causes that the combo value to be [''] that is not true, combo value must be [] (0 items selected).

I've to override click and ESC handlers and change se setValue stuff by reset().

Here is the code


addEscListener: function() {
if (!this.clearOnEscape) return;
this.textField.inputEl.on('keydown', function(e) {
if (e.getKey() == Ext.EventObject.ESC) {
if (this.textField.isExpanded) return;
Ext.Function.defer(this.textField.reset, 1, this.textField);
e.stopEvent();
}
}, this);
},
handleMouseClickOnClearButton: function(event, htmlElement, object) {
if (!this.isLeftButton(event)) return;
this.textField.reset();
this.textField.focus();
}


Regards,

Leonardo

PHaroZ
4 Nov 2011, 2:34 AM
nice plugin but i've same trouble with combobox.

Because reset is not the same as clear value, I do this :

init : function(textField) {
this.textField = textField;
this.textField.addEvents('clear');
if (!textField.rendered) {
textField.on('afterrender', this.handleAfterRender, this);
} else {
// probably an existing input element transformed to extjs field
this.handleAfterRender();
}
},
addEscListener: function() {
if (!this.clearOnEscape) return;
this.textField.inputEl.on('keydown', function(e) {
if (e.getKey() == Ext.EventObject.ESC) {
if (this.textField.isExpanded) return;
Ext.Function.defer(this.clearValue, 1, this);
e.stopEvent();
}
}, this);
},
handleMouseClickOnClearButton: function(event, htmlElement, object) {
if (!this.isLeftButton(event)) return;
this.clearValue();
this.textField.focus();
},
clearValue : function() {
if (Ext.isFunction(this.textField.clearValue)) {
this.textField.clearValue();
} else {
this.textField.setValue('');
}
this.textField.fireEvent('clear', this.textField);
}

talha06
26 Nov 2011, 7:23 AM
pretty nice plugin, thanks for sharing! =D>

smcguire36
19 Dec 2011, 9:06 AM
PHaroZ, nice fix to that problem! I just implemented this plugin and the first thing I discovered when I added it to my combo boxes was this problem. Your solution works great!

PHaroZ
11 Jan 2012, 9:41 AM
Don't work with Ext 4.1. To fix-it



repositionClearButton : function() {
var clearButtonEl = this.clearButtonEl;
if (!clearButtonEl) {
return;
}
var right = 0;
if (this.fieldHasScrollBar()) {
right += Ext.getScrollBarWidth();
}
if (this.textField.triggerWrap) {
right += this.textField.getTriggerWidth();
}
clearButtonEl.alignTo(this.textField.bodyEl, 'tr-tr', [-1 * (right + 3), 5]);
},
And remove "calculateClearButtonPosition" method.

wemerson.januario
4 Mar 2012, 3:00 PM
can not work with extjs 4.1.0 beta 3

error:

Ext.core.Element.data is not a function

aghextjs
30 Apr 2012, 7:31 AM
In addition to PHaroZ changes above for 4.1.0, I commented out the following in updateClearButtonVisibility:



// Adjust padding-right of the input tag to make room for the button
// IE (up to v9) just ignores this and Gecko handles padding incorrectly with textarea scrollbars
// if (!(this.isTextArea && Ext.isGecko) && !Ext.isIE) {
// // See https://bugzilla.mozilla.org/show_bug.cgi?id=157846
// var deltaPaddingRight = clearButtonEl.getWidth() - this.clearButtonEl.getMargin('l');
// var currentPaddingRight = this.textField.inputEl.getPadding('r');
// var factor = (newVisible ? +1 : -1);
// this.textField.inputEl.dom.style.paddingRight = (currentPaddingRight + factor * deltaPaddingRight) + 'px';
// }


Otherwise, when in Chrome in 18 or Firefox 11, if I moused over a field with no width set and managed by a hbox layout, the field would add extra padding to the right. For a combobox, it would look combo box, clearbutton, whitespace, triggerfield. But, removing above worked for me. I looked at in IE 8, Chrome 18 and Firefox 11. One disclaimer, I only have single line text fields, combo boxes or date fields using the clearbutton.

Thanks for this extension.

talha06
19 May 2012, 6:43 AM
Don't work with Ext 4.1. To fix-it



repositionClearButton : function() {
var clearButtonEl = this.clearButtonEl;
if (!clearButtonEl) {
return;
}
var right = 0;
if (this.fieldHasScrollBar()) {
right += Ext.getScrollBarWidth();
}
if (this.textField.triggerWrap) {
right += this.textField.getTriggerWidth();
}
clearButtonEl.alignTo(this.textField.bodyEl, 'tr-tr', [-1 * (right + 3), 5]);
},
And remove "calculateClearButtonPosition" method.

thanks a lot PHaroZ for this fix, now it's working very well with ExtJS 4.1 too. =D>

demon222
8 Aug 2012, 3:51 AM
fix if readOlny...




if (oldVisible != newVisible && this.textField.readOnly !== true) {


but if i dynamic change to readOnly: false

not refresh combobox button X

any help ?

R

another_i
30 Aug 2012, 12:25 AM
fix if readOlny...




if (oldVisible != newVisible && this.textField.readOnly !== true) {


but if i dynamic change to readOnly: false

not refresh combobox button X

any help ?

R

I have the same trouble.
For quick decision you can try this code:


{
xtype: "textfield",
//...
plugins: [{
ptype: "clearbutton",
pluginId: "clrbtn", //need for correct getPlugin function
//...
}]
}
//...

var p = field.getPlugin("clrbtn");
if(p!==undefined){
p.clearButtonEl.stopAnimation();
p.clearButtonEl.setVisible(false, p.animateClearButton); //or true for enable
}


But I think that I need two additional methods for this plugin:
- enable() (http://docs.sencha.com/ext-js/4-1/#!/api/Ext.AbstractPlugin-method-enable);
(http://docs.sencha.com/ext-js/4-1/#!/api/Ext.AbstractPlugin-method-disable)- disable() (http://docs.sencha.com/ext-js/4-1/#!/api/Ext.AbstractPlugin-method-disable).

Thanks.

demon222
4 Sep 2012, 6:57 AM
my solution ( this.repositionClearButton(); )



updateClearButtonVisibility: function() {
var oldVisible = this.isButtonCurrentlyVisible();
var newVisible = this.shouldButtonBeVisible();

var clearButtonEl = this.clearButtonEl;
if (oldVisible != newVisible && this.textField.readOnly !== true) {
if(this.animateClearButton && this.animateWithCss3) {
this.clearButtonEl.removeCls(this.clearButtonCls + (oldVisible ? '-on' : '-off'));
clearButtonEl.addCls(this.clearButtonCls + (newVisible ? '-on' : '-off'));
}
else {
clearButtonEl.stopAnimation();
clearButtonEl.setVisible(newVisible, this.animateClearButton);
}

// Set background-color of clearButton to same as field's background-color (for those browsers/cases
// where the padding-right (see below) does not work)
clearButtonEl.setStyle('background-color', this.textField.inputEl.getStyle('background-color'));

// Adjust padding-right of the input tag to make room for the button
// IE (up to v9) just ignores this and Gecko handles padding incorrectly with textarea scrollbars
if (!(this.isTextArea && Ext.isGecko) && !Ext.isIE) {
// See https://bugzilla.mozilla.org/show_bug.cgi?id=157846
var deltaPaddingRight = clearButtonEl.getWidth() - this.clearButtonEl.getMargin('l');
var currentPaddingRight = this.textField.inputEl.getPadding('r');
var factor = (newVisible ? +1 : -1);
this.textField.inputEl.dom.style.paddingRight = (currentPaddingRight + factor * deltaPaddingRight) + 'px';
}


}
this.repositionClearButton(); // <<<<<< this reposition creal button;-)
},

zhengeili
11 Sep 2012, 7:07 PM
thanks a lot .it's very nice.

demon222
18 Sep 2012, 2:47 AM
complete source :



(function() {
/**
* @class Ext.ux.form.field.ClearButton
*
* Plugin for text components that shows a "clear" button over the text field.
* When the button is clicked the text field is set empty.
* Icon image and positioning can be controlled using CSS.
* Works with Ext.form.field.Text, Ext.form.field.TextArea, Ext.form.field.ComboBox and Ext.form.field.Date.
*
* Plugin alias is 'clearbutton' (use "plugins: 'clearbutton'" in GridPanel config).
*
* @author <a href="mailto:stephen.friedrich@fortis-it.de">Stephen Friedrich</a>
* @author <a href="mailto:fabian.urban@fortis-it.de">Fabian Urban</a>
*
* @copyright (c) 2011 Fortis IT Services GmbH
* @license Ext.ux.form.field.ClearButton is released under the
* <a target="_blank" href="http://www.apache.org/licenses/LICENSE-2.0">Apache License, Version 2.0</a>.
*
*/
Ext.define('Ext.ux.form.field.ClearButton', {
alias: 'plugin.clearbutton',

/**
* @cfg {Boolean} Hide the clear button when the field is empty (default: true).
*/
hideClearButtonWhenEmpty: true,

/**
* @cfg {Boolean} Hide the clear button until the mouse is over the field (default: true).
*/
hideClearButtonWhenMouseOut: true,

/**
* @cfg {Boolean} When the clear buttons is hidden/shown, this will animate the button to its new state (using opacity) (default: true).
*/
animateClearButton: true,

/**
* @cfg {Boolean} Empty the text field when ESC is pressed while the text field is focused.
*/
clearOnEscape: true,

/**
* @cfg {String} CSS class used for the button div.
* Also used as a prefix for other classes (suffixes: '-mouse-over-input', '-mouse-over-button', '-mouse-down', '-on', '-off')
*/
clearButtonCls: 'ext-ux-clearbutton',

/**
* The text field (or text area, combo box, date field) that we are attached to
*/
textField: null,

/**
* Will be set to true if animateClearButton is true and the browser supports CSS 3 transitions
* @private
*/
animateWithCss3: false,

/////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Set up and tear down
//
/////////////////////////////////////////////////////////////////////////////////////////////////////

constructor: function(cfg) {
Ext.apply(this, cfg);

this.callParent(arguments);
},

/**
* Called by plug-in system to initialize the plugin for a specific text field (or text area, combo box, date field).
* Most all the setup is delayed until the component is rendered.
*/
init: function(textField) {

this.textField = textField;
if (!textField.rendered) {
textField.on('afterrender', this.handleAfterRender, this);
}
else {
// probably an existing input element transformed to extjs field
this.handleAfterRender();
}
},

/**
* After the field has been rendered sets up the plugin (create the Element for the clear button, attach listeners).
* @private
*/
handleAfterRender: function(textField) {
/*
* Disable on pagingtoolbar !
**/
if(typeof(textField.ownerCt) !== 'undefined' ) {
if(textField.ownerCt.xtype === 'pagingtoolbar') {
return;
}
}
this.isTextArea = (this.textField.inputEl.dom.type.toLowerCase() == 'textarea');

this.createClearButtonEl();
this.addListeners();

this.repositionClearButton();
this.updateClearButtonVisibility();

this.addEscListener();
},

/**
* Creates the Element and DOM for the clear button
*/
createClearButtonEl: function() {
var animateWithClass = this.animateClearButton && this.animateWithCss3;
this.clearButtonEl = this.textField.bodyEl.createChild({
tag: 'div',
cls: this.clearButtonCls
});
if(this.animateClearButton) {
this.animateWithCss3 = this.supportsCssTransition(this.clearButtonEl);
}
if(this.animateWithCss3) {
this.clearButtonEl.addCls(this.clearButtonCls + '-off');
}
else {
this.clearButtonEl.setStyle('visibility', 'hidden');
}
},

/**
* Returns true iff the browser supports CSS 3 transitions
* @param el an element that is checked for support of the "transition" CSS property (considering any
* vendor prefixes)
*/
supportsCssTransition: function(el) {
var styles = ['transitionProperty', 'WebkitTransitionProperty', 'MozTransitionProperty',
'OTransitionProperty', 'msTransitionProperty', 'KhtmlTransitionProperty'];

var style = el.dom.style;
for(var i = 0, length = styles.length; i < length; ++i) {
if(style[styles[i]] !== 'undefined') {
// Supported property will result in empty string
return true;
}
}
return false;
},

/**
* If config option "clearOnEscape" is true, then add a key listener that will clear this field
*/
addEscListener: function() {
if (!this.clearOnEscape) {
return;
}

// Using a KeyMap did not work: ESC is swallowed by combo box and date field before it reaches our own KeyMap
this.textField.inputEl.on('keydown',
function(e) {
if (e.getKey() == Ext.EventObject.ESC) {
if (this.textField.isExpanded) {
// Let combo box or date field first remove the popup
return;
}
// No idea why the defer is necessary, but otherwise the call to setValue('') is ignored
Ext.Function.defer(this.textField.setValue, 1, this.textField, ['']);
e.stopEvent();
}
},
this);
},

/**
* Adds listeners to the field, its input element and the clear button to handle resizing, mouse over/out events, click events etc.
*/
addListeners: function() {
// listeners on input element (DOM/El level)
var textField = this.textField;
var bodyEl = textField.bodyEl;
bodyEl.on('mouseover', this.handleMouseOverInputField, this);
bodyEl.on('mouseout', this.handleMouseOutOfInputField, this);

// listeners on text field (component level)
textField.on('destroy', this.handleDestroy, this);
textField.on('resize', this.repositionClearButton, this);
textField.on('change', function() {
this.repositionClearButton();
this.updateClearButtonVisibility();
}, this);

// listeners on clear button (DOM/El level)
var clearButtonEl = this.clearButtonEl;
clearButtonEl.on('mouseover', this.handleMouseOverClearButton, this);
clearButtonEl.on('mouseout', this.handleMouseOutOfClearButton, this);
clearButtonEl.on('mousedown', this.handleMouseDownOnClearButton, this);
clearButtonEl.on('mouseup', this.handleMouseUpOnClearButton, this);
clearButtonEl.on('click', this.handleMouseClickOnClearButton, this);
},

/**
* When the field is destroyed, we also need to destroy the clear button Element to prevent memory leaks.
*/
handleDestroy: function() {
this.clearButtonEl.destroy();
},

/////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Mouse event handlers
//
/////////////////////////////////////////////////////////////////////////////////////////////////////

/**
* Tada - the real action: If user left clicked on the clear button, then empty the field
*/
handleMouseClickOnClearButton: function(event, htmlElement, object) {
if (!this.isLeftButton(event)) {
return;
}
this.textField.setValue('');
this.textField.focus();
},

handleMouseOverInputField: function(event, htmlElement, object) {
this.clearButtonEl.addCls(this.clearButtonCls + '-mouse-over-input');
if (event.getRelatedTarget() == this.clearButtonEl.dom) {
// Moused moved to clear button and will generate another mouse event there.
// Handle it here to avoid duplicate updates (else animation will break)
this.clearButtonEl.removeCls(this.clearButtonCls + '-mouse-over-button');
this.clearButtonEl.removeCls(this.clearButtonCls + '-mouse-down');
}
this.updateClearButtonVisibility();
},

handleMouseOutOfInputField: function(event, htmlElement, object) {
this.clearButtonEl.removeCls(this.clearButtonCls + '-mouse-over-input');
if (event.getRelatedTarget() == this.clearButtonEl.dom) {
// Moused moved from clear button and will generate another mouse event there.
// Handle it here to avoid duplicate updates (else animation will break)
this.clearButtonEl.addCls(this.clearButtonCls + '-mouse-over-button');
}
this.updateClearButtonVisibility();
},

handleMouseOverClearButton: function(event, htmlElement, object) {
event.stopEvent();
if (this.textField.bodyEl.contains(event.getRelatedTarget())) {
// has been handled in handleMouseOutOfInputField() to prevent double update
return;
}
this.clearButtonEl.addCls(this.clearButtonCls + '-mouse-over-button');
this.updateClearButtonVisibility();
},

handleMouseOutOfClearButton: function(event, htmlElement, object) {
event.stopEvent();
if (this.textField.bodyEl.contains(event.getRelatedTarget())) {
// will be handled in handleMouseOverInputField() to prevent double update
return;
}
this.clearButtonEl.removeCls(this.clearButtonCls + '-mouse-over-button');
this.clearButtonEl.removeCls(this.clearButtonCls + '-mouse-down');
this.updateClearButtonVisibility();
},

handleMouseDownOnClearButton: function(event, htmlElement, object) {
if (!this.isLeftButton(event)) {
return;
}
this.clearButtonEl.addCls(this.clearButtonCls + '-mouse-down');
},

handleMouseUpOnClearButton: function(event, htmlElement, object) {
if (!this.isLeftButton(event)) {
return;
}
this.clearButtonEl.removeCls(this.clearButtonCls + '-mouse-down');
},

/////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Utility methods
//
/////////////////////////////////////////////////////////////////////////////////////////////////////

/**
* Repositions the clear button element based on the textfield.inputEl element
* @private
*/
repositionClearButton: function() {

var clearButtonEl = this.clearButtonEl;
if (!clearButtonEl) {
return;
}
var clearButtonPosition = this.calculateClearButtonPosition(this.textField);
clearButtonEl.dom.style.right = clearButtonPosition.right + 'px';
clearButtonEl.dom.style.top = clearButtonPosition.top + 'px';

},

/**
* Calculates the position of the clear button based on the textfield.inputEl element
* @private
*/
calculateClearButtonPosition: function(textField) {
var positions = textField.inputEl.getBox(true, true);
var top = positions.y;
var right = positions.x;
if (this.fieldHasScrollBar()) {
right += Ext.getScrollBarWidth();
}
if (this.textField.triggerWrap) {
right += this.textField.getTriggerWidth();
}
return {
right: right,
top: top
};
},

/**
* Checks if the field we are attached to currently has a scrollbar
*/
fieldHasScrollBar: function() {
if (!this.isTextArea) {
return false;
}

var inputEl = this.textField.inputEl;
var overflowY = inputEl.getStyle('overflow-y');
if (overflowY == 'hidden' || overflowY == 'visible') {
return false;
}
if (overflowY == 'scroll') {
return true;
}
//noinspection RedundantIfStatementJS
if (inputEl.dom.scrollHeight <= inputEl.dom.clientHeight) {
return false;
}
return true;
},


/**
* Small wrapper around clearButtonEl.isVisible() to handle setVisible animation that may still be in progress.
*/
isButtonCurrentlyVisible: function() {
if (this.animateClearButton && this.animateWithCss3) {
return this.clearButtonEl.hasCls(this.clearButtonCls + '-on');
}

// This should not be necessary (see Element.setVisible/isVisible), but else there is confusion about visibility
// when moving the mouse out and _quickly_ over then input again.
var cachedVisible = Ext.core.Element.data(this.clearButtonEl.dom, 'isVisible');
if (typeof(cachedVisible) == 'boolean') {
return cachedVisible;
}
return this.clearButtonEl.isVisible();
},

/**
* Checks config options and current mouse status to determine if the clear button should be visible.
*/
shouldButtonBeVisible: function() {
if (this.hideClearButtonWhenEmpty && Ext.isEmpty(this.textField.getValue())) {
return false;
}

var clearButtonEl = this.clearButtonEl;
//noinspection RedundantIfStatementJS
if (this.hideClearButtonWhenMouseOut
&& !clearButtonEl.hasCls(this.clearButtonCls + '-mouse-over-button')
&& !clearButtonEl.hasCls(this.clearButtonCls + '-mouse-over-input')) {
return false;
}

return true;
},

/**
* Called after any event that may influence the clear button visibility.
*/
updateClearButtonVisibility: function() {
var oldVisible = this.isButtonCurrentlyVisible();
var newVisible = this.shouldButtonBeVisible();

var clearButtonEl = this.clearButtonEl;
if (oldVisible != newVisible && this.textField.readOnly !== true) {
if(this.animateClearButton && this.animateWithCss3) {
this.clearButtonEl.removeCls(this.clearButtonCls + (oldVisible ? '-on' : '-off'));
clearButtonEl.addCls(this.clearButtonCls + (newVisible ? '-on' : '-off'));
}
else {
clearButtonEl.stopAnimation();
clearButtonEl.setVisible(newVisible, this.animateClearButton);
}

// Set background-color of clearButton to same as field's background-color (for those browsers/cases
// where the padding-right (see below) does not work)
clearButtonEl.setStyle('background-color', this.textField.inputEl.getStyle('background-color'));

// Adjust padding-right of the input tag to make room for the button
// IE (up to v9) just ignores this and Gecko handles padding incorrectly with textarea scrollbars
if (!(this.isTextArea && Ext.isGecko) && !Ext.isIE) {
// See https://bugzilla.mozilla.org/show_bug.cgi?id=157846
var deltaPaddingRight = clearButtonEl.getWidth() - this.clearButtonEl.getMargin('l');
var currentPaddingRight = this.textField.inputEl.getPadding('r');
var factor = (newVisible ? +1 : -1);
this.textField.inputEl.dom.style.paddingRight = (currentPaddingRight + factor * deltaPaddingRight) + 'px';
}


}
this.repositionClearButton();
},

isLeftButton: function(event) {
return event.button === 0;
}

});

})();

predator
19 Jan 2013, 6:05 AM
@Author, please consider adding following event handler:


textField.on('readonly', this.handleDestroy, this);


@Sencha, please consider firing event readonly on method setReadOnly() for various input controllers.

Thank you.

vyomkesh.tiwari
23 Jan 2013, 5:22 AM
I am not able to use your plugin in my code. Can you please give some editor link where i can see you running code , like Jsfiddle. I want to know where i am using your code wrongly. I am new to extjs please help.
Thanks,
Vyom

vyomkesh.tiwari
23 Jan 2013, 5:30 AM
I used the plugin in my code and it gave me error - Ext.define is not a function and Ext.ux.form is undefined


Can you help me with these errors.

apastakia
18 Apr 2013, 10:05 AM
i found a config property in the doc for Ext.form.field.Text which states the following

clearCls (http://docs.sencha.com/extjs/4.2.0/#!/api/Ext.form.Labelable-cfg-clearCls) : String
(http://docs.sencha.com/extjs/4.2.0/#!/api/String)The CSS class to be applied to the special clearing div rendered directly after the field contents wrapper to provide field clearing.

Defaults to: Ext.baseCSSPrefix + 'clear'

Available since: 4.0.7
this had me totally confused thinking im not configuring the textfield properly, but having read this post it seems i would have to use a plugin if i want to have a X button to provide field clearing.

so why does Ext.form.field.Text class have clearCls since 4.0.7 ?

Mark
19 Apr 2013, 8:45 AM
Does anybody run this great plugin with ExtJs 4.2.?
I think the structure of the fields has changed in this version and therefore the small cross does'nt show at the proper position.
Could anybody help?

apastakia
22 Apr 2013, 3:39 AM
ExtJS 4.2

Overridden the field.Base class to add clear icon functionality

Javascript

Ext.override(Ext.form.field.Base, {
showClear: false,

afterRender: function () {
if (this.showClear && !this.xtype.contains('checkbox') && !this.xtype.contains('radio')) {
if (Ext.isEmpty(this.inputCell))
this.__clearDiv = this.bodyEl.insertHtml('beforeEnd', '<div class="x-clear"></div>', true);
else
this.__clearDiv = this.inputCell.insertHtml('beforeEnd', '<div class="x-clear"></div>', true);

this.__clearDiv.setVisible(!Ext.isEmpty(this.getValue()));
this.__clearDiv.on('click', this.clearField, this);
}
},

onChange: function () {
this.callParent(arguments);
if (!Ext.isEmpty(this.__clearDiv)) this.__clearDiv.setVisible(!Ext.isEmpty(this.getValue()));
},

clearField: function () {
this.setValue(null);
this.clearInvalid();
this.focus();
}
});

Style

.x-form-item-body .x-clear {
position: absolute;
top: 4px;
right: 2px;
width: 16px;
height: 16px;
display: none;
cursor: pointer;
opacity: 0.2;
filter: alpha(opacity=20);
background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAG7AAABuwBHnU4NQAAABl0RVh0U29mdHdhcmUAd3d3Lmlua3NjYXBlLm9yZ5vuPBoAAAGASURBVDiNrZOxThthEIRn9ipegCgVHQVyEclxzi34rIODFwiVS3fELQ9AS9JRuuIJiHMnn1tky1iisCjSpQHZL+DKOyngpLNFkKww9c7+8+3+S0koKzoOdwO3UyeqlKoAIHJiwmRpfp3/HP0u17NoQJLRUXhG4QLAFl7XQsR5/mv0Qy9GSgJJNg/DGwDJP4zr6vXT0YkkGQBER+HZBmYASF48YCP5smvO+1LsPy5rm3kXwodnPszcrWX0KwA7BY6bPlngdlpmdlk7T29TBw4AzAHMHTjI09vUZe1Sii06vpoT1XI2M+9GSX0v7w0f6MsGfdnIe8OHKKnvmXl3BYT2mc3D8BHAxzXGOX3ZyLLxFADiuFaRBQMA22t1T7bB4F6ViZysxsLMif0sG0/juFaJ41oly8ZTJ/ZBzMqlIidmwkoDd2sVzLJgIAsGxUzcrbXymPzuv9dISWgm9W8ULjdhF9Hp94bf3+crS1I/HZ2I6ABYvGFciOgUZqB0jYU2Pee/yjnfEUKuaMMAAAAASUVORK5CYII=');
}

.x-form-item-body .x-clear:hover {
opacity: 0.5;
filter: alpha(opacity=50);
}

.x-form-item-body .x-form-trigger-input-cell .x-clear {
right: 24px;
}

Test

Ext.widget({
xtype: 'container',
layout: 'vbox',
defaults: { labelWidth: 120, showClear: true },
items: [
{ xtype: 'textfield', fieldLabel: 'Textfield', value: 'Test Me' },
{ xtype: 'textarea', fieldLabel: 'Textarea' },
{ xtype: 'combobox', fieldLabel: 'Combobox' },
{ xtype: 'numberfield', fieldLabel: 'Numberfield' },
{ xtype: 'datefield', fieldLabel: 'Datefield' },
{ xtype: 'checkbox', fieldLabel: 'Checkbox' }
],
renderTo: document.body
});

lorezyra
24 Apr 2013, 12:38 AM
You guys are awesome! Thanks for this clever widget!

lorezyra
24 Apr 2013, 1:48 AM
A plugin for text fields (as well as date fields, combo boxes and text areas) that shows a small "clear button" in the text field when the mouse is over the field.

Demo and download page (http://www.eekboom.de/ClearButton.html)

This is a small feature, but initially I had totally under-estimated the effort to implement it.
Well, I have probably over-engineered the solution a little what with the animation option to fade in/out the icon and other config options ;-)

Feedback welcome!




I prefer the embedded image instead of a GIF sprite.
[thanks to apastakia (http://www.sencha.com/forum/member.php?329821-apastakia) for the CSS]


Here's my CSS that works well for the EXTJS 4.1 version of this plugin...

.ext-ux-clearbutton {
width: 16px;
height: 16px;
/* background-image: url(clear-text-icon.gif); */ /* 12 x 12 "X" */
background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAG7AAABuwBHnU4NQAAABl0RVh0U29mdHdhcmUAd3d3Lmlua3NjYXBlLm9yZ5vuPBoAAAGASURBVDiNrZOxThthEIRn9ipegCgVHQVyEclxzi34rIODFwiVS3fELQ9AS9JRuuIJiHMnn1tky1iisCjSpQHZL+DKOyngpLNFkKww9c7+8+3+S0koKzoOdwO3UyeqlKoAIHJiwmRpfp3/HP0u17NoQJLRUXhG4QLAFl7XQsR5/mv0Qy9GSgJJNg/DGwDJP4zr6vXT0YkkGQBER+HZBmYASF48YCP5smvO+1LsPy5rm3kXwodnPszcrWX0KwA7BY6bPlngdlpmdlk7T29TBw4AzAHMHTjI09vUZe1Sii06vpoT1XI2M+9GSX0v7w0f6MsGfdnIe8OHKKnvmXl3BYT2mc3D8BHAxzXGOX3ZyLLxFADiuFaRBQMA22t1T7bB4F6ViZysxsLMif0sG0/juFaJ41oly8ZTJ/ZBzMqlIidmwkoDd2sVzLJgIAsGxUzcrbXymPzuv9dISWgm9W8ULjdhF9Hp94bf3+crS1I/HZ2I6ABYvGFciOgUZqB0jYU2Pee/yjnfEUKuaMMAAAAASUVORK5CYII=');
background-position: 0 0;
background-repeat: no-repeat;
-moz-user-focus: ignore; /* https://developer.mozilla.org/en/CSS/-moz-user-focus */
cursor: pointer;
position: absolute;
overflow: hidden; /* IE 6 :-( */
margin: 0px;
background-color: white;
}

.ext-ux-clearbutton-mouse-over-input {
/* background-position: 0 -12px; */
}

.ext-ux-clearbutton-mouse-over-button {
/* background-position: 0 -24px; */
}

.ext-ux-clearbutton-mouse-down {
/* background-position: 0 -36px; */
}

.ext-ux-clearbutton-on {
opacity: 1;
visibility: visible;
transition: opacity .35s linear;
-webkit-transition: opacity .35s linear;
-moz-transition: opacity .35s linear;
-o-transition: opacity .35s linear;
-ms-transition: opacity .35s linear;
-khtml-transition: opacity .35s linear;
}

.ext-ux-clearbutton-off {
opacity: 0;
visibility: hidden;
transition: opacity .35s linear, visibility .0s linear .35s;
-webkit-transition: opacity .35s linear, visibility .0s linear .35s;
-moz-transition: opacity .35s linear, visibility .0s linear .35s;
-o-transition: opacity .35s linear, visibility .0s linear .35s;
-ms-transition: opacity .35s linear, visibility .0s linear .35s;
-khtml-transition: opacity .35s linear, visibility .0s linear .35s;
}



This makes it nicer to use in Sencha Architect.

lorezyra
24 Apr 2013, 2:13 AM
@apastakia,


Your override works okay... But it fails to position the clear button correctly when the label is above the base field or when the parent container is wider than the actual field... Also, when you have components with similar itemId strings (e.g. "Password" and "Password0") it attaches the clearButton to the first match instead of the exact match.


I'll see if I can find a fix for these.. Otherwise this works well enough for ExtJS 4.1.3.

lorezyra
24 Apr 2013, 10:24 PM
I tested the basic override code and it operates the same in ExtJS 4.2 as it does in ExtJS 4.1...


So, this solution needs more work. On the otherhand, the plugin works very well for both versions.


I happen to prefer the override method, but it needs work.

Mark
24 Apr 2013, 11:58 PM
Does anybody run this great plugin with ExtJs 4.2.?
I think the structure of the fields has changed in this version and therefore the small cross does'nt show at the proper position.
Could anybody help?

I add some changes to the plugin to choose the proper css-class depending on which position the label set
/**
* Creates the Element and DOM for the clear button
*/
createClearButtonEl: function() {
var animateWithClass = this.animateClearButton && this.animateWithCss3;

if(this.textField.labelAlign == 'top'){
this.clearButtonEl = this.textField.bodyEl.createChild({
tag: 'div',
cls: this.clearButtonCls + '-labeltop'
});
}
else
{
this.clearButtonEl = this.textField.bodyEl.createChild({
tag: 'div',
cls: this.clearButtonCls
});
}
if(this.animateClearButton) {
this.animateWithCss3 = this.supportsCssTransition(this.clearButtonEl);
}
if(this.animateWithCss3) {
this.clearButtonEl.addCls(this.clearButtonCls + '-off');
}
else {
this.clearButtonEl.setStyle('visibility', 'hidden');
}
}

and add another class to the stylesheet ClearButton.css



.ext-ux-clearbutton-labeltop {
width: 12px;
height: 12px;
background-image: url(assets/clear-text-red-icon.gif);
background-position: 0 0;
background-repeat: no-repeat;
-moz-user-focus: ignore; /* https://developer.mozilla.org/en/CSS/-moz-user-focus */
cursor: pointer;
position:absolute;
overflow: hidden; /* IE 6 :-( */
margin-top: 26px; /*if labelAlign "top" */
background-color: white;
}

This solution works for me quiet perfect.

lorezyra
26 Apr 2013, 12:36 AM
@mark,


This is much cleaner...

/**
* Creates the Element and DOM for the clear button
*/
createClearButtonEl: function() {
var animateWithClass = this.animateClearButton && this.animateWithCss3;
var labelAlign = "";

if(this.textField.labelAlign == 'top'){ labelAlign = "-labeltop"; }

this.clearButtonEl = this.textField.bodyEl.createChild({
tag: 'div',
cls: this.clearButtonCls + labelAlign
});
if(this.animateClearButton) {
this.animateWithCss3 = this.supportsCssTransition(this.clearButtonEl);
}
if(this.animateWithCss3) {
this.clearButtonEl.addCls(this.clearButtonCls + '-off');
}
else {
this.clearButtonEl.setStyle('visibility', 'hidden');
}
},

User 0815
26 Apr 2013, 6:34 AM
I think, all what it needs to correctly place the clearbutton icon are the instructions of this post from PHaroZ (http://www.sencha.com/forum/member.php?20757-PHaroZ) :

http://www.sencha.com/forum/showthread.php?132775-Ext.ux.form.field.ClearButton-Small-clear-button-icon-over-field&p=713053&viewfull=1#post713053

If you then change the line
clearButtonEl.alignTo(this.textField.bodyEl, 'tr-tr', [-1 * (right + 3), 5]);
with

clearButtonEl.alignTo(this.textField.inputEl, 'tr-tr', [-1 * (right + 3), 5]);
it should work with ExtJS 4.0.x, 4.1.x and 4.2.x (also with labelAlign: top).

Mark
27 Apr 2013, 10:28 PM
@lorezyra

I agree! :>

Mark
27 Apr 2013, 11:14 PM
@0815 Neat!

To use this solution I think it's not necessary to getTriggerWidth()
Therefor:

/* if (this.textField.triggerWrap) {
right += this.textField.getTriggerWidth();
}*/

anton.dimitrov
3 May 2013, 2:05 AM
Has anybody tried the plugin for fields inside a 'fieldset' or 'fieldcontainer'.
I get a very weird bug with FF that the button is positioned at the top right corner of the 'fieldcontainer'
instead in the field. I can't believe I am saying this but IE 9 actually works better than FF and doesn't show the bug, nor does Chrome.

I tested 4.1 and 4.2 but the behavior is the same.
I also tried the overwrite for 4.2 and the issue still presented itself.

Am I missing something? Has anybody encountered this behavior before ?

Link:

http://jsfiddle.net/ms4UC/10/

aghextjs
3 May 2013, 5:54 AM
Try adding layout: 'vbox' to your fieldset. I tried it quickly in your jsfiddle, and it worked... mostly. Give it a try and you'll see. I use this plugin (and have been since Stephen posted it) on fields within a fieldcontainer, and it works fine for me in Firefox, IE6, IE7, IE8 and Chrome, so it is possible!

anton.dimitrov
3 May 2013, 9:16 AM
10x for the replay!

Indeed using 'hbox' or 'vbox' layouts does the trick but
layouts 'auto', 'column', 'anchor' don't get the right position and maybe others as well.
I didn't test them all.

Have you used it any of the above layouts ?

aghextjs
3 May 2013, 11:31 AM
Just quickly checked my code. I'm using it either in vbox or hbox layouts, and primarily within "fieldcontainers" with hbox layouts. I haven't been following the updates in this thread very closely, but in case it is helpful, my version of the plugin is at https://gist.github.com/aghuddleston/5513157. I'm using it w/4.1.1.

zhangjian420
30 May 2013, 1:59 AM
I am looking for a long time,thank you very much

kaushalparik27
18 Nov 2013, 2:25 AM
I am trying to use this plugin in to one of my view js file but i am receiving this error: Cannot read property init of null. I have added ClearButton.js file in my project and added the script reference to main html file. What I am doing wrong here?

predator
1 May 2014, 4:15 AM
Hello,

I have noticed that after a field is set to read only the clear button is still present.

Here is my update:


init: function(textField) {
this.textField = textField;
if (!textField.rendered) {
textField.on('afterrender', this.handleAfterRender, this);
textField.on('writeablechange', this.handleReadOnly, this);
}
else {
// probably an existing input element transformed to extjs field
this.handleAfterRender();
}
},

//////

handleReadOnly: function(field, readonly, eOpts) {
var clearButtonEl = this.clearButtonEl;
if (!clearButtonEl) {
return;
}


if(readonly) {
clearButtonEl.destroy();
} else {
this.createClearButtonEl(); //'re'-create the button el.
}


},

/////

repositionClearButton : function() {
var clearButtonEl = this.clearButtonEl;
if (!clearButtonEl || this.textField.readOnly) {
return;
}
// var right = 0;
// if (this.fieldHasScrollBar()) {
// right += Ext.getScrollBarWidth();
// }
// if (this.textField.triggerWrap) {
// right += this.textField.getTriggerWidth();
// }
// console.log('RIGHT: '+right);
// console.log(-1 * (right + 3));
// console.log(right - 22);
// clearButtonEl.alignTo(this.textField.bodyEl, 'tr-tr', [-1 * (right + 3), 5]);
clearButtonEl.alignTo(this.textField.inputEl, 'tr-tr', [-5, 6]);
},

valio
18 Jun 2014, 12:17 AM
Just quickly checked my code. I'm using it either in vbox or hbox layouts, and primarily within "fieldcontainers" with hbox layouts. I haven't been following the updates in this thread very closely, but in case it is helpful, my version of the plugin is at https://gist.github.com/aghuddleston/5513157. I'm using it w/4.1.1.

Thanks!

There's some deprecated stuff in the code

replace Ext.getScrollbarWidth() with Ext.getScrollbarSize().width()
remove this.textField.addEvents('clear'); [not necessary anymore]
Why are lines 405-411 commented out?

Probably we should consider putting up a separate Github repo. It appears to me as if the original devs are not active anymore.

aghextjs
18 Jun 2014, 5:51 AM
Thanks!

Why are lines 405-411 commented out?



See post #25 at http://www.sencha.com/forum/showthread.php?132775-Ext.ux.form.field.ClearButton-Small-clear-button-icon-over-field&p=791942&viewfull=1#post791942. It basically says this:


In addition to PHaroZ changes above for 4.1.0, I commented out the following in updateClearButtonVisibility:

snip...

Otherwise, when in Chrome in 18 or Firefox 11, if I moused over a field with no width set and managed by a hbox layout, the field would add extra padding to the right. For a combobox, it would look combo box, clearbutton, whitespace, triggerfield. But, removing above worked for me. I looked at in IE 8, Chrome 18 and Firefox 11. One disclaimer, I only have single line text fields, combo boxes or date fields using the clearbutton.