4umi.com/web/javascript/textarea

Line ’em up

Form Javascript

Longtime thought impossible, but now an undeniable fact: linenumbers with a textarea.

The idea and proof

Lines may be defined as any range of characters displayed with the same distance to the topborder of the element. These are however not the most interesting lines. If a program reports an error on line 7 for example, it uses the definition of lines as any range of characters from one 'end of line' meta-character to the next. In a textarea where such lines are allowed to wrap around, the numbering should reflect this. As it is momentarily not possible to detect wraps in any timely manner, the numbers are only displayed when wrapping is turned off. Toggle the wrap setting to see the effect.

The area

The script

The script...

function scrollit() {
 var o = gid( 'dyna' );
 o.style.top = '-' + tt.scrollTop + 'px';
 o.style.clip = 'rect(' + ( tt.scrollTop + 1 ) + 'px ' + o.scrollWidth + 'px ' + ( tt.scrollTop + tt.offsetHeight - 1 ) + 'px 0)';
}

function linenumbers() {
 var d = window.document,
  o = d.createElement( 'div' ),
  p = o.cloneNode( false ), s = '',
  i, max = 10 + tt.value.split( /\n/ ).length, w;
 for( i = 1; i<max; i++ ) { s+=i+'\n'; }
 o.id = 'stat';
 p.id = 'dyna';
 o.style.position = 'absolute';
 o.style.textAlign = 'right';
 o.style.fontFamily = getstyle( tt, 'font-family' );
 o.style.fontSize = getstyle( tt, 'font-size' );
 o.style.lineHeight = getstyle( tt, 'line-height' );
 o.style.marginTop = getstyle( tt, 'margin-top' );
 o.style.borderWidth = getstyle( tt, 'border-width' );
 o.style.paddingTop = getstyle( tt, 'padding-top' );
 o.style.borderRight = '2px outset white';
 o.style.top = getpos( tt ).y + 'px';
 if( ff.wrp.checked ) { o.className = 'hid'; }
 p.insertBefore( d.createTextNode( s ), null );
 o.insertBefore( p, null );
 tt.parentNode.insertBefore( o, tt );
 p.style.position = 'absolute';
 p.style.overflow = 'hidden';
 p.style.background = '#e4d8c8';
 p.style.whiteSpace = 'pre';
 w = p.scrollWidth;
 p.style.width = w + 'px';
 p.style.height = tt.offsetHeight + 'px';
 p.style.left = getpos( tt ).x - w + 'px';
}

function wrapta() {
 tt.wrap = ff.wrp.checked ? 'soft' : 'off';
 document.getElementById( 'stat' ).className = ff.wrp.checked ? 'hid' : '';
 scrollit();
}

var ff = document.forms.f, tt = ff.elements.txt;
tt.onscroll = scrollit;alert( addevent );
linenumbers();