In JavaScript, is it possible to obtain a specific line from a paragraph that is displayed on a page?
For example, here I'm trying to obtain the 3rd line of a paragraph as a string:
JavaScript:
//this function should return the specified line from the specified paragraph.
function getLine(paragraphId, lineNum){
//for example, getLine("sampleParagraph", 1); should return
// tore but year. An from mean on with when sing pain. Oh to as principles devonshire
}
HTML:
<p id = "sampleParagraph">
Instrument cultivated alteration any favourable expression law far nor. Both new like tore but year. An from mean on with when sing pain. Oh to as principles devonshire companions unsatiable an delightful. The ourselves suffering the sincerity. Inhabit her manners adapted age certain. Debating offended at branched striking be subjects.
</p>
Here it is on jsfiddle (showing how the paragraph is displayed): http://jsfiddle.net/RrXWW/
Demo 1: http://jsfiddle.net/LeTW6/2/
Demo 2: http://jsfiddle.net/LeTW6/3/
I'm using jQuery here for simplicity, but this would work with pure JavaScript. In fact, I'm using direct DOM access for performance in some parts.
(function () {
// wrap all words
$(".count").each(function () {
var obj = $(this);
var html = obj.html().replace(/(\S+\s*)/g, "<span>$1</span>");
obj.html(html);
});
var offset = 0; // keeps track of distance from top
var spans = $(".count span"); // collection of elements
function getLine(index) {
var top = 0,
buffer = [];
for (var i = 0; i < spans.length; i++) {
if (top > index) {
break; // quit once the line is done to improve performance
}
// position calculation
var newOffset = spans[i].offsetTop;
if (newOffset !== offset) {
offset = newOffset;
top++;
}
// store the elements in the line we want
if (top === index) {
buffer.push(spans[i]);
}
}
// buffer now contains all spans in the X line position
// this block is just for output purposes
var text = "";
for (var i = 0; i < buffer.length; i++) {
text += buffer[i].innerHTML;
}
$("#output").html(text);
}
var line = 3; // the line to select/highlight
getLine(line); // initial highlighting
// other recalculation triggers can be added here, such as a button click
// throttling to handle recalculation upon resize
var timeout;
function throttle() {
window.clearTimeout(timeout);
timeout = window.setTimeout(function () {
getLine(line);
}, 100);
}
$(window).on("resize", throttle);
})();
See also my answer for highlighting alternate lines in a variable width container.
If you want to use pure JavaScript to improve performance and so that you don't have to include jQuery, you can use this.
DEMO: http://jsfiddle.net/PX7cj/2/
function getLine(paragraphId, lineNum) {
lineNum--;
var elem = document.getElementById(paragraphId);
var spanChildren = elem.getElementsByTagName("span");
var paragraphText = elem.innerHTML.replace(/(\r\n|\n|\r)/gm, "");
var newParagraphText = "";
var words = [];
if (spanChildren.length === 0) {
words = paragraphText.split(" ");
for (var i = 0; max = words.length, i < max; i++)
newParagraphText += '<span>' + words[i] + "</span> ";
elem.innerHTML = newParagraphText;
}else{
for(var i=0; max = spanChildren.length, i<max; i++){
words[words.length] = spanChildren[i].innerHTML;
}
}
var lineCounter = 0;
var previousY = spanChildren[0].offsetTop;
var returnText = "";
var startReturning = false;
for (var i = 0; max = words.length, i < max; i++) {
if (spanChildren[i].offsetTop != previousY) lineCounter++;
if (lineCounter === lineNum) startReturning = true;
if (lineCounter !== lineNum && startReturning) return returnText.substring(0, returnText.length - 1);
if (startReturning) {
returnText += words[i] + " ";
if (i + 1 === words.length) return returnText.substring(0, returnText.length - 1);
}
previousY = spanChildren[i].offsetTop;
}
}
alert(getLine("sampleParagraph", 5));
alert(getLine("sampleParagraph", 4));
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With