How to add line numbers to code blocks
2004-11-29 19:56:46
I've just discovered how to add line numbers to code blocks inside preformatted text. I've used a javascript function that loops through all pre elements, and calls a regular expression that returns the number of lines in that block. Then, using innerHTML i just add a div containing the line numbers and style it using CSS. The javascript, that is part of a namespace (an object literal to provide encapsulation) is something like this:
// adds line numbers to code sections:
numberCodeTags : function(){
var PRE = document.getElementsByTagName('pre');
var nl = /\n+/mg;
for (var i = 0; i < PRE.length; i++) {
var t = PRE[i].innerHTML;
//mozilla/ff cannot select all lines of a code element
//that is inside a pre element:
if(document.addEventListener && !window.opera) {
Extras.getCodeText(PRE[i]);
}
//will only work in mozilla+op (IE replaces \n by a space so its useless):
var NL = Extras.getMatchArray(t,nl);
if(NL) {
var numeros = "";
for (var lineas = 1; lineas < NL; lineas++)
numeros += lineas +"\n";
PRE[i].innerHTML += "<div class='lines'>"+numeros+"</div>";
}
}
},
// matches a regexp to a string, returns array
getMatchArray : function(myString,myRegExp){
return myString.match(myRegExp).length;
},
// FF hack to make easier select all lines of a
//code element that is inside a pre element:
getCodeText : function(obj){
var color = CSS.getStyle(obj.firstChild,"color");
var bgcolor = CSS.getStyle(obj.firstChild,"backgroundColor");
if(bgcolor=="transparent") bgcolor="white";
obj.onmouseover = function(){
obj.firstChild.style.color = bgcolor;
obj.firstChild.style.backgroundColor = color;
}
obj.onmouseout = function(){
obj.firstChild.style.color = color;
obj.firstChild.style.backgroundColor = bgcolor;
}
},
CSS could be something similar to the following lines:
pre {
position: relative;
color: #913117;
padding: 0px 1em 0px 1em;
margin: 0px;
font-family: Courier, monospace;
font-size: 1em;
}
code {
font-variant: normal;
color: #913117;
}
pre code {
position: relative;
top: 0px;
left: 1.2em;
font-variant: normal;
color: #913117;
padding: 0px;
margin: 0px;
}
pre .lines {
position: absolute;
top: 1em;
left: 0px;
width: 1.2em;
padding: 0px;
margin: 0px 1.2em 0px 0px;
background: #913117;
color: white;
}
This technique seems to work in Mozilla and Opera only. IE replaces line feeds with spaces, so I simply ignored it. All other browsers degrade.
As stated in forst comment, Mozilla has a bug that doesnt let you select a block of code that is inside a preformated text. I tried to add a background color (only in Mozilla) onmouseover, this way block size is better seen. Apparently, if we start selection inside the free space outside the code block (the white space between numbers and code) you can select the code easily.