For a given text element, use a text range to find the end of the first line, and then wrap the remaining text in a child div. Repeat recursively using the child div for the next iteration.
This works cross browser: http://jsfiddle.net/gilly3/CmguZ/4/
This is easiest in IE thanks to textRange.moveToPoint(x, y) :
function indent(div) { var rng = document.body.createTextRange(); rng.moveToElementText(div); var x = rng.getBoundingClientRect().right; rng.collapse(); var rect = rng.getBoundingClientRect(); var y = rect.bottom; rng.moveToPoint(x - 1, y - 1); rng.moveEnd("textedit"); var html = "<div class=\"indent\">" + rng.text + "</div>"; rng.pasteHTML(html); div = $(".indent", div)[0]; rng.moveToElementText(div); var pos = rng.getBoundingClientRect(); if (pos.bottom > rect.bottom) { indent(div); } }
In other browsers, you need to iterate over the text to find where the line wraps around:
function indent(div) { var rng = document.createRange(); rng.selectNodeContents(div); var len = rng.toString().length; var start = rng.toString().search(/.\s/); if (start < 0) return; var txt = div.childNodes[0]; rng.setEnd(txt, start); var startRect = rng.getBoundingClientRect(); var rect; for (var i = start + 1; i < len; i++) { rng.setEnd(txt, i); rect = rng.getBoundingClientRect(); if (rect.bottom > startRect.bottom) { rng.setStart(txt, i-1); rng.setEnd(txt, len); div = document.createElement("div"); div.className = "indent"; rng.surroundContents(div); indent(div); break; } } }
gilly3 Aug 30 '11 at 23:13 2011-08-30 23:13
source share