Tuesday, January 16th, 2007

ResizingTextArea Prototype Component

Category: Component, Prototype, Rails

<>p>Richard McMahon has wrapped the oft-seen resizable text areas in a simple Prototype component ResizingTextArea:

JavaScript

javascript
< view plain text >
  1. var ResizingTextArea = Class.create();
  2.  
  3. ResizingTextArea.prototype = {
  4.     defaultRows: 1,
  5.  
  6.     initialize: function(field)
  7.     {
  8.         this.defaultRows = Math.max(field.rows, 1);
  9.         this.resizeNeeded = this.resizeNeeded.bindAsEventListener(this);
  10.         Event.observe(field, "click", this.resizeNeeded);
  11.         Event.observe(field, "keyup", this.resizeNeeded);
  12.     },
  13.  
  14.     resizeNeeded: function(event)
  15.     {
  16.         var t = Event.element(event);
  17.         var lines = t.value.split('\n');
  18.         var newRows = lines.length + 1;
  19.         var oldRows = t.rows;
  20.         for (var i = 0; i < lines.length; i++)
  21.         {
  22.             var line = lines[i];
  23.             if (line.length >= t.cols) newRows += Math.floor(line.length / t.cols);
  24.         }
  25.         if (newRows > t.rows) t.rows = newRows;
  26.         if (newRows < t.rows) t.rows = Math.max(this.defaultRows, newRows);
  27.     }
  28. }

UJS Rule

  1. < % apply_behaviour "textarea", "new ResizingTextArea(this);" %>

It responds to keystrokes by parsing the text value into lines, accounts for a bit of line wrapping, and ensures that the number of rows presented grows (and shrinks) to match what has been typed in. The solution is best suited where the text entry is likely to be in the 0-50 line range.

Related Content:

Posted by Dion Almaer at 7:52 am
10 Comments

+++--
3.4 rating from 42 votes

10 Comments »

Comments feed TrackBack URI

The problem is that this does a lot of math based on the Col parameter of the text area which is not accurate when the text area is resized with CSS.

Comment by tobi — January 16, 2007

Re-written for jquery:

$.fn.ResizeArea = function() {
var defaultRows = 1;
var resizeNeeded = function () {
var lines = $(this).val().split('\n');
var newRows = lines.length + 1;
var oldRows = $(this).attr('rows');
for (var i = 0; i = $(this).attr('cols'))
newRows += Math.floor(line.length / $(this).attr('cols'));
}
if (newRows > $(this).attr('rows'))
$(this).attr('rows',newRows);
if (newRows

Comment by Chris Burnett — January 16, 2007

try this again.

$.fn.ResizeArea = function() {
var defaultRows = 1;
var resizeNeeded = function () {
var lines = $(this).val().split('\n');
var newRows = lines.length + 1;
var oldRows = $(this).attr('rows');
for (var i = 0; i = $(this).attr('cols'))
newRows += Math.floor(line.length / $(this).attr('cols'));
}
if (newRows > $(this).attr('rows'))
$(this).attr('rows',newRows);
if (newRows

Comment by Chris Burnett — January 16, 2007

oh well.

Comment by Chris Burnett — January 16, 2007

Does this really have anything to do with ajax? it’s javascript counting characters…

Comment by boodie — January 16, 2007

This is a pretty simple and easy way to make text areas grow when need be. Came in pretty handy for my app and i made a quick demo since a few people asked for it.

http://jasonmoser.com/ajax

Comment by Jason Moser — January 16, 2007

Does not exactly work as intended with non-strict rendering in Gecko / WebKit browsers. Perhaps a little more testing is needed.

Comment by Morgan Roderick — January 17, 2007

FYI, if you’re using the nightly WebKit build or Safari 3.0, you don’t need any javascript magic to get resizable textareas. They’re standard fare… every textarea you encounter on the web can be resized as needed. WebKit may have turned the preference for this off by default, but if you enter the following command in the terminal, I think this is the command I issued some time ago to turn resizable textareas on:

defaults write com.apple.safari WebKitTextAreasAreResizable boolean true

Cheers,
Leland

Comment by Leland Scott — January 17, 2007

I did this one some time ago inspired by a JSAN widget.

It uses styles for calculating the height. And has been tested in IE 6/7,Safari and Firefox, although it might need some refactoring you might find it useful.


ResizeableTextarea = Class.create();
ResizeableTextarea.prototype = {
initialize: function(element, options) {
this.element = $(element);
this.size = Element.getStyle(this.element, 'height').match(/^\d+/).first()*1;
this.options = Object.extend({
inScreen: false,
resizeStep: 10,
minHeight: this.size,
}, options || {});
Event.observe(this.element, "keyup", this.resize.bindAsEventListener(this));
if ( !this.options.inScreen ) {
this.element.style.overflow = 'hidden';
}
this.element.setAttribute("wrap","vitual");
},
resize : function(){
this.shrink();
this.grow();
},
shrink : function(){
if ( this.size this.element.clientHeight ) {
if ( this.options.inScreen && (20 + this.element.offsetTop + this.element.clientHeight) > document.body.clientHeight ) {
return;
}
this.size += 1;
this.element.style.height = (this.options.resizeStep + this.size)+'px';
this.grow();
}
}
}

Then just add


onfocus="new ResizeableTextarea(this);"

to the textarea you want to resize.

Comment by Bermi — January 22, 2007

Seems like WordPress ate my code, so I’ve here is a direct link to the Javascript Textarea Resizer

Comment by Bermi — February 21, 2007

Leave a comment

You must be logged in to post a comment.