PDA

View Full Version : Just another elastic Textarea



Jochen
8 Jun 2010, 4:22 AM
Inspired by this elastic textarea script http://sixrevisions.com/javascript/build-an-elastic-textarea-with-ext-js/ (http://sixrevisions.com/javascript/build-an-elastic-textarea-with-ext-js/)I wrote a ElasticTextArea ux and found its worth sharing.

It works even with long lines of text as it uses the css word-wrap.

Any suggestions and experiences welcome!



Ext.ns("Ext.ux.form");
/**
* @class Ext.ux.form.ElasticTextArea
* Elastic textarea resizing to content height.
* tested and found working fine w/ExtJS 3.2.1 (ff3.6, ie7+8, iron(chrome) 4)
*
* On render, a div is created outside the body.
* The div's content gets updated to the textareas on keyup, then the textarea gets resized to div's size
*
* additional config options
* minHeight (int): minimum height of textarea. set to 0 to disable, defaults to 18
* maxHeight (int): maximum height of textarea. set to 0 to disable, defaults to 500
* addHeight (int): additional pixels to text height 18
*/
Ext.ux.form.ElasticTextArea = Ext.extend(Ext.form.TextArea, {

minHeight : 18 ,
maxHeight : 500 ,
addHeight : 20,
enableKeyEvents : true,

// private
lastTextHeight : -1,

elasticize : function() {
var el = this.getEl();

//clean up text area contents from html specialchars and replace newlines by <br>'s
this.div.update(
el.dom.value.replace(/<br \/>&nbsp;/, '<br />')
.replace(/<|>/g, '&lt;')
.replace(/&/g,"&amp;")
.replace(/\n/g, '<br />&nbsp;')
);

// get the div height
var textHeight = this.div.getHeight();
if (textHeight == this.lastTextHeight) return;
this.lastTextHeight = textHeight;

//enforce text area maximum and minimum size
if ( (textHeight > this.maxHeight ) && (this.maxHeight > 0) ){
textHeight = this.maxHeight ;
el.setStyle('overflow', 'auto');
} else {
el.setStyle('overflow', 'hidden');
};

if ( (textHeight < this.minHeight ) && (this.minHeight > 0) ) {
textHeight = this.minHeight ;
};

//resize the text area
el.setHeight(textHeight + this.addHeight , true);
},



listeners: {

// be tidy, cleanup
destroy: function() {
if (this.div) this.div.remove();
},

// create div and install key listeners
render: function() {
var dh=Ext.DomHelper,
el = this.getEl(),
styles = el.getStyles('padding','padding-top', 'padding-bottom', 'padding-left', 'padding-right', 'line-height', 'font-size', 'font-family', 'font-weight', 'font-style'),
w = el.getWidth();

styles.width = w +'px' ;

this.div = dh.append(Ext.getBody() || document.body, {
'id':this.id + '-preview-div',
'tag' : 'div',
'style' : 'position: absolute; top: -100000px; left: -100000px; word-wrap: break-word;'
}, true);

//apply the text area styles to the hidden div
dh.applyStyles(this.div, styles);

//recalculate the div height on each key stroke
el.on('keyup', this.elasticize, this);

this.elasticize()
}
}
});

swarnendude
8 Jun 2010, 7:06 AM
And what would be the reason for not using Ext TextArea's grow feature?



var txtArea = new Ext.form.TextArea({
grow : true,
growMin : 100,
growMax : 300
});

Jochen
8 Jun 2010, 7:29 AM
Ehrm, the only reason was that I didn't know that feature:o

Shame on me.. only the growing of the textarea is not animated using the grow-option, but that's easy to extend.

If I could i would delete this thread now;)

Jochen
8 Jun 2010, 8:18 AM
.. and the scrollbar-flickering can be avoided if the textareas overflow is set to hidden
and in autoSize() when changing height to auto again if content does not fit:


if(h != this.lastHeight){
this.lastHeight = h;
this.el.setHeight(h,true);
if ( h>= this.growMax ) el.setStyle('overflow', 'auto');
this.fireEvent("autosize", this, h);
}