Este asunto ya lo habíamos debatido varias veces, pero hasta donde recuerdo nos faltó una versión de "texto con líneas virtuales numeradas". Por "líneas virtuales" se entiende a las que se hacen con
wrapping o ajuste de línea : si la fuente o la ventana cambian de tamaño, los "renglones" se van a cortar en otra palabra y la cantidad total de líneas va a cambiar.
Así que este engendro carece de sentido práctico; los números no pueden servir de referencia para nadie, porque cambian para cada navegador, para cada resolución y configuración. Pero el desafío estaba bueno, así que desempolvé viejas carpetas y terminé de darle forma a alguno de los experimentos que se sugirieron por acá. Como éste
Código HTML:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3c.org/TR/1999/REC-html401-19991224/loose.dtd">
<html>
<head>
<meta http-equiv=Content-Type content="text/html; charset=utf-8">
<title>NUMERA LÍNEAS 1.</title>
<script type="text/javascript">
var hoja, numerado, altura, numLinea, espera;
var texto0 = ""; // GUARDA TEXTO ORIGINAL
var texto1 = []; // TEXTO CON ETIQUETAS SEPARADAS
var separador = "¥Ñ"; // CADENA QUE NO SE REPITA EN TEXTO (PARA SEPARAR TAGS)
function inicia() {
hoja = document.getElementById("pagina");
numerado = document.getElementById("regla");
/* LIMPIA LA BARRA CON NÚMEROS DE LÍNEA */
numerado.innerHTML = "";
/* REINICIA NUMERACIÓN DE LÍNEAS */
numLinea = 1;
/* REINICIA DISTANCIA AL TOP DE CADA ESPACIO
(PARA CALCULAR NUEVA LÍNEA) */
altura = 0;
/* EXTRAE TEXTO ORIGINAL */
texto0 = hoja.innerHTML;
/* COPIA TEXTO Y RODEA ETIQUETAS CON separador */
texto1 = texto0.replace(/</g,separador+"<").replace(/>/g,">"+separador);
/* CORTA LA COPIA DEL TEXTO SEPARANDO "TAGS" Y "CONTENIDO DE TEXTO"
EN ARRAY */
texto1 = texto1.split(separador);
numera0();
}
function numera0() {
/* RECORRE TODOS LOS ELEMENTOS DEL ARRAY DE "TEXTO + TAGS" */
for(b=0; b<texto1.length; b++) {
/* SI NO EMPIEZA CON "<" Y TERMINA CON ">" ... */
if(texto1[b].match(/^</) == null && texto1[b].match(/>$/) == null){
/* ... NO ES TAG, Y ENTONCES PONE SUS CARACTERES "ESPACIO" EN UN span */
texto1[b] = texto1[b].replace(/\x20/g,"<span> </span>");
}
}
/* UNE EL TEXTO SEPARADO EN EL ARRAY Y LO METE EN LUGAR DEL TEXTO
ORIGINAL */
hoja.innerHTML = texto1.join("");
numera1();
}
function numera1() {
var espacios = hoja.getElementsByTagName("span");
/* CUENTA LOS span DEL TEXTO*/
var totEspacios = espacios.length;
/* RECORRE UNO A UNO TODOS LOS span DEL TEXTO */
for(s=0; s<totEspacios; s++) {
/* SI LA DISTANCIA DE ESTE "span CON ESPACIO" AL TOP ES MAYOR A
LA DEL ANTERIOR ...*/
if(espacios[s].offsetTop > altura){
/* ... GUARDA LA NUEVA DISTANCIA EN VARIABLE altura */
altura = espacios[s].offsetTop;
/* CREA UN ELEMENTO div ... */
var orden = document.createElement("div");
/* QUE CONTIENE EL NÚMERO DE ORDEN DE LÍNEA numLinea */
var nuevoNum = document.createTextNode(numLinea + ".");
/* Y LO INSERTA EN EL div */
orden.appendChild(nuevoNum);
/* LE DA UNA CLASE */
orden.setAttribute("class", "linea");
/* HACE AL div "NO-SELECCIONABLE" PARA IEXPLORER */
orden.setAttribute("unselectable", "on");
/* LE ASIGNA LA MISMA DISTANCIA AL TOP QUE LA LÍNEA QUE NUMERA */
orden.style.top = altura +"px";
/* Y LO INSERTA EN LA REGLA PARA LA NUMERACIÓN */
numerado.appendChild(orden);
/* SUMA "1" PARA EL SIGUIENTE NÚMERO DE LÍNEA */
numLinea++
}
}
/* CUANDO TERMINA DE NUMERAR TODO EL TEXTO, REEMPLAZA EL CONTENIDO
MARCADO, POR EL TEXTO ORIGINAL */
hoja.innerHTML = texto0;
}
onload = inicia;
</script>
<style type="text/css">
body {background-color: silver; color: black; font-size: 18px;
font-family: arial, helvetica, sans-serif; }
h1 {font-size: 1.6em; }
#parrafos {background-color: white; font-size: 1em; padding: 0.5em;
margin-left: 2em; position: relative; }
#regla {font-size: 1em; position: absolute; left: -2.1em; top: 0.2em;
width: 2em; }
h2 {font-size: 2.2em; }
.linea {position: absolute; font-size: 0.8em; width: 2em; left: 0;
top: 0; background-color: black; color: yellow; text-align: right;
user-select: none; }
acronym {text-decoration: underline;
text-underline-position: auto-pos; }
</style>
</head>
<body onresize = "inicia()" /* RECALCULA NÚMEROS DESPUÉS DE UN resize */>
<h1>Texto con líneas virtuales numeradas.</h1>
<div id="parrafos">
<div id="pagina">
<h2>Latino. </h2>
<p>La palabra "latino" para nombrar a los criollos y amerindios es una
reducción de "latinoamericano"; y tiene su origen en la <strong>Guerra
de Troya</strong>, para terminar en el intento napoleónico de
desembarcar en <strong>México</strong> o <strong>Argentina</strong>
extendiendo sus conquistas al <em>Nuevo Continente</em>. </p>
<p>Cuando <strong>Eneas</strong> (el de <em>La Enéida</em>) regresa
con su hijo <strong>Ascanio</strong> del <strong>Asia Menor</strong>
hasta <strong>Europa</strong>, conoce a <strong>Lavinia</strong>, hija
del rey <strong>Latinio</strong>, y se casa con ella quedándose en su
territorio. Allí comienzan a reunirse todos los soldados que vuelven
de la guerra, fundando una ciudad llamada <strong>Lacio</strong>, en
la actual <strong>Italia</strong>, por
<acronym title="Nombre geográfico tomado del de una persona.">
eponimia</acronym> con el nombre del suegro de <strong>Eneas</strong>. </p>
<p>Sus habitantes fueron los latinos "originales", y formaron parte de
los míticos pueblos fundadores de <strong>Roma</strong>, otra ciudad
que después se convertiría en un imperio, dominando desde
<strong>Italia</strong> hasta <strong>Antioquía</strong> y
<strong>Lusitania</strong>. </p>
<p>Si bien para el s.XV este imperio ya no existía, su influencia aún
se encontraba en la cultura y el idioma que dio origen a las lenguas
romances como el francés, rumano, español, portugués o italiano. </p>
<p>Cuando los nuevos imperios coloniales conquistaron
<strong>América</strong>, trajeron sus idiomas herederos del latín
que, exceptuando a algunas colonias inglesas u holandesas, se
extendieron por todo el continente. El más difundido es el castellano,
que se habla donde hubo colonias españolas (desde
<strong>California</strong> hasta la <strong>Tierra del Fuego</strong>)
; le sigue el portugués, que se habla en el <strong>Brasil</strong>; y
en mucha menor medida el francés, ya que sus posesiones eran
principalmente islas caribeñas. </p>
<p>Después de que los ejércitos de <strong>Napoleón</strong>
invadieron <strong>España</strong> y <strong>Portugal</strong>, el
próximo movimiento a mediano plazo sería hacerse de sus colonias.
Pero había una cuestión menor, casi una formalidad ¿cómo llamaría la
<strong>Francia Imperial</strong> a sus nuevas tierras?. El nombre más
usual era <strong>Hispanoamérica</strong>, porque la mayor parte era
española; si le sumamos a <strong>Brasil</strong>, el nombre sería
<strong>Iberoamérica</strong>. Pero <strong>Francia</strong> no cabía
por ningún lado, así que inventaron el muy creativo nombre de
<strong>Latinoamérica</strong>, aprovechando que el francés, al igual
que el español y el portugués, son idiomas provenientes del latín. </p>
<p>Esta denominación es la que se usa todavía para llamar al
subcontinente, y "latinoamericano" —con su forma apocopada "latino"—
a sus habitantes. </p>
</div>
<div id="regla"></div>
</div>
</body>
</html>
Aunque tiene algunos comentarios para el JS, aprovecho el post y los amplío. El modo poco ortodoxo de ubicar la coordenada "y" de cada una de las líneas es "marcar" sus caracteres de espacio y comparar distancias al
top del documento desde el primero al último marcados. Cada vez que el
offsetTop aumenta sabemos que el texto bajó una línea; y aprovechamos ese valor para posicionar una capa a la izquierda con el número que le corresponda.
El escript reconoce etiquetas, y no pone marcas de
span dentro de sus atributos. Pero tiene al menos un
bug. Si en una misma línea hay fuentes de 2 alturas distintas, para el escript son 2 líneas distintas.
De momento no se me ocurre cómo arreglarlo. Lo que sí voy a hacer es mejorar la presentación de los números (p.e. que queden sobre el mismo "renglón" y no como un superíndice), porque una utilidad que se me aparece ahora es usarlo en imprimibles.
(Sí, ya sé, las páginas web no son para imprimir, pero ...)
Texto en dos columnas cuantos lineas de texto tengo en un div? numeracion de lineas en página