Auto minimising text in textarea with javascript - javascript

I've got a textarea where the user inputs there data, but as they add it when the cursor gets to the end it reduces the size of the font. All works quite well but I cannot seem to set a limit on how small it goes. Also is there any way I can set the point at which the text starts to go small, because the text tends to disappear at the end before shrinking? Please could someone help with this, seem to be pulling my hair out on this one?
function textAreaChange(){
var textArea1 = document.getElementById("textarea");
var sizeText1 = document.getElementById("size_text");
while (textArea1.scrollWidth > textArea1.clientWidth)
{
var fs = parseFloat(textArea1.style.fontSize) - 1;
textArea1.style.fontSize = fs + 'px';
sizeText1.value = (fs | 0) + 'px';
document.getElementById("a1").innerHTML = ((parseInt(textArea1.style.fontSize))/textboxscale);
sizeText1.value = ((parseInt(textArea1.style.fontSize))/textboxscale);
}
}
textAreaChange();
Thanks in advance.
Davetoff
Right I have added the if (fs>15) to this code, but now it lock up when it gets to 15:
function textAreaChange(){
var fss = 15;
var textArea1 = document.getElementById("textarea");
var sizeText1 = document.getElementById("size_text");
while (textArea1.scrollWidth > textArea1.clientWidth)
{
var fs = parseFloat(textArea1.style.fontSize) - 1;
if (fs >15){
textArea1.style.fontSize = fs + 'px';
sizeText1.value = (fs | 0) + 'px';
document.getElementById("a1").innerHTML = ((parseInt(textArea1.style.fontSize))/textboxscale);
sizeText1.value = ((parseInt(textArea1.style.fontSize))/textboxscale);
} else {
textArea1.style.fontSize = fss + 'px';
sizeText1.value = (fss | 0) + 'px';
document.getElementById("a1").innerHTML = fss + 'px';
}
}
}
Please help really appreciated spent a couple of days on this now and my head is beginning to hurt:
Thanks.
Davetoff

After the line where you assign "fs", just add a statement to make sure that if fs is too small, you don't assign it to the textArea1 font size, something like:
if (fs > 7) //only perform statements below if fs > 7
{
...
}

Right found the problem, indeed the answer was to add the if statement, however I was being a fool as I had a scale factor in there that was causing all sorts of problems, also I've added a keycode in there to stop additional key inputs when the end of the text area is reached, updated code below:
function textAreaChange(){
var fss = <?=$min_text_size?>*textboxscale;
var textArea1 = document.getElementById("textarea");
var sizeText1 = document.getElementById("size_text");
if (textArea1.scrollWidth > (textArea1.clientWidth))
{
var fs = parseFloat(textArea1.style.fontSize) - (2);
if (fs >(14*textboxscale)){
textArea1.style.fontSize = (fs) + 'px'; //this is the textarea style
document.getElementById("a1").innerHTML = (parseInt(textArea1.style.fontSize)/textboxscale); //this is some text to show the user what size the text is
sizeText1.value = ((parseInt(textArea1.style.fontSize))/textboxscale); //this is a slider I put to chage the text height manually (input range)
} else{
textArea1.style.fontSize = (fss) + 'px';
document.getElementById("a1").innerHTML = fss/textboxscale;
sizeText1.value = fss /textboxscale;
if (event.keyCode == 8, 32) {
event.preventDefault();
}
}
}
}
However the keycode 8,32 works well in IE but not in Firefox, any additional help would be really appreciated?
D

Related

How to make fontSize of text area increase by 2 in javascript?

I have textarea that I want to add 2 to its text font size every time a button is clicked. I wrote this code but not working.
My HTML code is
function makebold() {
alert(document.getElementById("input-text").style.fontSize);
var currentfontsize = document.getElementById("input-text").style.fontSize;
console.log(currentfontsize);
var current = parseInt(currentfontsize);
console.log(current);
var updatedfontsize = current + 2;
console.log(updatedfontsize);
var newfont = updatedfontsize;
console.log(newfont);;
document.getElementById("input-text").style.fontSize = newfont;
}
<fieldset>
<legend>Text</legend>
<textarea name="input-text" id="input-text" cols="30" rows="4"></textarea>
</fieldset>
<fieldset>
<legend>Decoration</legend>
<button id="button1" onclick="makebold()">Bigger Decorations!</button><br>
<input type="checkbox" onclick="displayalert()" name="bling" id="bling" value="Bling">Bling
</fieldset>
Can anyone please help?
Use this way to get the font size:
var currentfontsize = window.getComputedStyle(document.getElementById("input-text")).fontSize;
And update your last line
document.getElementById("input-text").style.fontSize = newfont+'px';
You are not adding px to the font. Without px it won't work.
Working Fiddle
https://jsfiddle.net/3napv795/
function increaseFont(elem, inc) {
const val = window.getComputedStyle(elem).getPropertyValue("font-size"); // gets font-size in string format
const currentSize = parseFloat(val); // removes 'px'
elem.style.fontSize = currentSize + inc + "px"; // set new size by adding increment to current font size
}
Usage:
const button = document.getElementById("button1");
button.addEventListener("click", () => increaseFont(button, 2))
Adding an initial font-size will solve the problem:
function makebold(){
alert(document.getElementById("input-text").style.fontSize);
//add initial font-size
document.getElementById("input-text").style.fontSize = '10px';
var currentfontsize = document.getElementById("input-text").style.fontSize;
console.log(currentfontsize);
var current = parseInt(currentfontsize);
console.log(current);
var updatedfontsize = current + 2;
console.log(updatedfontsize);
var newfont = updatedfontsize;
console.log(newfont);;
document.getElementById("input-text").style.fontSize = newfont;
}
Correcting your code while updating to a newer syntax ....
JS
const textarea = document.getElementById("input-text");
function makebold() {
let fontUnit = "px"; // setting a unit for font size
let increment = 2; // increase the font size by 2 px/rem/em etc ..
// Getting current font size
let currentfontsize = window.getComputedStyle(textarea).fontSize;
currentfontsize = parseInt(currentfontsize);
// getting final value
const updatedfontsize = currentfontsize + increment + fontUnit;
textarea.style.fontSize = updatedfontsize;
}

Word Wrap detection in JavaScript

I am trying to work out a way to detect wordwrap in a specific span tag inside a banner. If it wraps to 2 lines then increase the overall height of the container by 56px. There is also a sub headline (headline2) which also needs to increase (or decrease) the height by 40px.
I have written some basic JS code here which checks the div height of the span but its not great & also will only work for 3 lines.
// Variable banner heights
var hl11sub = 368;
var hl21sub = 448;
var hl31sub = 548;
var hl12sub = 416;
var hl22sub = 496;
var hl32sub = 576;
var hLFontSizeCSS = window.getComputedStyle(headlineText, null).getPropertyValue("font-size");
var hL2FontSizeCSS = window.getComputedStyle(headline2text, null).getPropertyValue("font-size");
var bannerHeightCSS = window.getComputedStyle(banner, null).getPropertyValue("height");
var headlineHeight = headlineText.offsetHeight;
var hL2HeadHeight = headline2text.offsetHeight;
var headHeight = headlineText.style.lineHeight = parseInt(hLFontSizeCSS) + 10 + "px";
var hL2Height = headline2text.style.lineHeight = parseInt(hL2FontSizeCSS) + 10 + "px";
// Text Height values
var hL1LineHeight = parseInt(headHeight); // 8 is line height & padding
var hL2LinesHeight = 140;
var hL3LinesHeight = 195;
// HL2 height values
var hL2TextOver1LineHeight = parseInt(hL2Height); // 8 is line height & padding
var hL2TextOver2LineHeight = 84;
if(hL2HeadHeight == hL2TextOver1LineHeight && headlineHeight == hL1LineHeight){
banner.style.height = hl11sub + "px";
}
else if(hL2HeadHeight == hL2TextOver1LineHeight && headlineHeight == hL2LinesHeight){
banner.style.height = hl21sub + "px";
}
else if(hL2HeadHeight == hL2TextOver1LineHeight && headlineHeight >= hL3LinesHeight){
banner.style.height = hl31sub + "px";
}
else if(hL2HeadHeight == hL2TextOver2LineHeight && headlineHeight == hL1LineHeight){
// Single headline with 2 lines sub
banner.style.height = hl12sub + "px";
}
else if(hL2HeadHeight == hL2TextOver2LineHeight && headlineHeight == hL2LinesHeight){
// 2 headlines with 2 lines sub
banner.style.height = hl22sub + "px";
}
else {
banner.style.height = hl32sub + "px";
// 3 headlines with 2 lines sub
It needs to only change the height of the banner depending on if the span words wrap once, twice, three times etc.
Any suggestions or help with this would be greatly appreciated.
Here is a very basic implementation on how to detect when a line is wrapped hopefully this gives you a good idea where to start and integrate it into your app.
Heres the docs for stuff used
https://developer.mozilla.org/en/docs/Web/API/EventTarget/addEventListener
https://developer.mozilla.org/en-US/docs/Web/API/Window/getComputedStyle
https://developer.mozilla.org/en-US/docs/Web/API/MutationObserver
You mentioned the height changing and you needing to know when its wrapped you can use a mutation observer to check when the style has changed then check if its wrapped.
Resize the demo window to see results
any questions i'll try get to them asap if i've misunderstood i'll happily change :)
const h1 = document.querySelector('h1');
const banner = document.querySelector('.banner');
//handles style changes on banner to check wrapping
const observer = new MutationObserver(mutations =>
mutations.forEach(mutationRecord => onLineWrapDoSomething())
);
observer.observe(banner, { attributes : true, attributeFilter : ['style'] });
// handles window resize events
window.addEventListener('resize', onLineWrapDoSomething)
function onLineWrapDoSomething() {
const { lineHeight } = getComputedStyle(h1);
const lineHeightParsed = parseInt(lineHeight.split('px')[0]);
const amountOfLinesTilAdjust = 2;
if (h1.offsetHeight >= (lineHeightParsed * amountOfLinesTilAdjust)) {
console.log('your h1 now wrapped')
} else {
console.log('your h1 on one line')
}
}
// shows it logs when style changes and it wraps, ignore the disgusting code below
setTimeout(() => {
banner.style.width = '50%'
setTimeout(() => {
banner.style.width = '100%'
}, 1500)
}, 1500)
.banner {
width: 100%;
}
h1 {
line-height: 1.5
}
<div class="banner">
<h1>This is some text that will eventually wrap</h1>
</div>

Text pagination inside a DIV with image

I want to paginate a text in some div so it will fit the allowed area
Logic is pretty simple:
1. split text into words
2. add word by word into and calculate element height
3. if we exceed the height - create next page
It works quite good
here is JS function i've used:
function paginate() {
var newPage = $('<pre class="text-page" />');
contentBox.empty().append(newPage);
var betterPageText='';
var pageNum = 0;
var isNewPage = false;
var lineHeight = parseInt(contentBox.css('line-height'), 10);
var wantedHeight = contentBox.height() - lineHeight;
for (var i = 0; i < words.length; i++) {
if (isNewPage) {
isNewPage = false;
} else {
betterPageText = betterPageText + ' ' + words[i];
}
newPage.text(betterPageText + ' ...');
if (newPage.height() >= wantedHeight) {
pageNum++;
if (pageNum > 0) {
betterPageText = betterPageText + ' ...';
}
newPage.text(betterPageText);
newPage.clone().insertBefore(newPage)
betterPageText = '...';
isNewPage = true;
} else {
newPage.text(betterPageText);
}
}
contentBox.craftyslide({ height: wantedHeight });
}
But when i add an image it break everything. In this case text overflows 'green' area.
Working fiddle: http://jsfiddle.net/74W4N/7/
Is there a better way to paginate the text and calculate element height?
Except the fact that there are many more variables to calculate,not just only the word width & height, but also new lines,margins paddings and how each browser outputs everything.
Then by adding an image (almost impossible if the image is higher or larger as the max width or height) if it's smaller it also has margins/paddings. and it could start at the end of a line and so break up everything again.basically only on the first page you could add an image simply by calculating it's width+margin and height+margin/lineheight. but that needs alot math to get the wanted result.
Said that i tried some time ago to write a similar script but stopped cause of to many problems and different browser results.
Now reading your question i came across something that i read some time ago:
-webkit-column-count
so i made a different approach of your function that leaves out all this calculations.
don't judge the code as i wrote it just now.(i tested on chrome, other browsers need different prefixes.)
var div=document.getElementsByTagName('div')[0].firstChild,
maxWidth=300,
maxHeigth=200,
div.style.width=maxWidth+'px';
currentHeight=div.offsetHeight;
columns=Math.ceil(currentHeight/maxHeigth);
div.style['-webkit-column-count']=columns;
div.style.width=(maxWidth*columns)+'px';
div.style['-webkit-transition']='all 700ms ease';
div.style['-webkit-column-gap']='0px';
//if you change the column-gap you need to
//add padding before calculating the normal div.
//also the line height should be an integer that
// is divisible of the max height
here is an Example
http://jsfiddle.net/HNF3d/10/
adding an image smaller than the max height & width in the first page would not mess up everything.
and it looks like it's supported by all modern browsers now.(with the correct prefixes)
In my experience, trying to calculate and reposition text in HTML is almost an exercise in futility. There are too many variations among browsers, operating systems, and font issues.
My suggestion would be to take advantage of the overflow CSS property. This, combined with using em sizing for heights, should allow you to define a div block that only shows a defined number of lines (regardless of the size and type of the font). Combine this with a bit of javascript to scroll the containing div element, and you have pagination.
I've hacked together a quick proof of concept in JSFiddle, which you can see here: http://jsfiddle.net/8CMzY/1/
It's missing a previous button and a way of showing the number of pages, but these should be very simple additions.
EDIT: I originally linked to the wrong version for the JSFiddle concept
Solved by using jQuery.clone() method and performing all calculations on hidden copy of original HTML element
function paginate() {
var section = $('.section');
var cloneSection = section.clone().insertAfter(section).css({ position: 'absolute', left: -9999, width: section.width(), zIndex: -999 });
cloneSection.css({ width: section.width() });
var descBox = cloneSection.find('.holder-description').css({ height: 'auto' });
var newPage = $('<pre class="text-page" />');
contentBox.empty();
descBox.empty();
var betterPageText = '';
var pageNum = 0;
var isNewPage = false;
var lineHeight = parseInt(contentBox.css('line-height'), 10);
var wantedHeight = contentBox.height() - lineHeight;
var oldText = '';
for (var i = 0; i < words.length; i++) {
if (isNewPage) {
isNewPage = false;
descBox.empty();
}
betterPageText = betterPageText + ' ' + words[i];
oldText = betterPageText;
descBox.text(betterPageText + ' ...');
if (descBox.height() >= wantedHeight) {
if (i != words.length - 1) {
pageNum++;
if (pageNum > 0) {
betterPageText = betterPageText + ' ...';
}
oldText += ' ... ';
}
newPage.text(oldText);
newPage.clone().appendTo(contentBox);
betterPageText = '... ';
isNewPage = true;
} else {
descBox.text(betterPageText);
if (i == words.length - 1) {
newPage.text(betterPageText).appendTo(contentBox);
}
}
}
if (pageNum > 0) {
contentBox.craftyslide({ height: wantedHeight });
}
cloneSection.remove();
}
live demo: http://jsfiddle.net/74W4N/19/
I actually came to an easier solution based on what #cocco has done, which also works in IE9.
For me it was important to keep the backward compatibility and the animation and so on was irrelevant so I stripped them down. You can see it here: http://jsfiddle.net/HNF3d/63/
heart of it is the fact that I dont limit height and present horizontal pagination as vertical.
var parentDiv = div = document.getElementsByTagName('div')[0];
var div = parentDiv.firstChild,
maxWidth = 300,
maxHeigth = 200,
t = function (e) {
div.style.webkitTransform = 'translate(0,-' + ((e.target.textContent * 1 - 1) * maxHeigth) + 'px)';
div.style["-ms-transform"] = 'translate(0,-' + ((e.target.textContent * 1 - 1) * maxHeigth) + 'px)';
};
div.style.width = maxWidth + 'px';
currentHeight = div.offsetHeight;
columns = Math.ceil(currentHeight / maxHeigth);
links = [];
while (columns--) {
links[columns] = '<span>' + (columns + 1) + '</span>';
}
var l = document.createElement('div');
l.innerHTML = links.join('');
l.onclick = t;
document.body.appendChild(l)

Javascript Cursor

I have the following script for a cursor trail, however the cursor image is appearing in the top left corner of the page and is not appearing as the cursor trail? What could be causing the script not to function correctly? I copied this script from: http://www.dynamicdrive.com/dynamicindex13/trailer.htm
I have tried editing the image paths(I originally used absolute paths to the images), I also tried disabling a previously used "plugin" which I was using for this trail
<script>
/******************************************
* Cross browser cursor trailer script- By Brian Caputo (bcaputo#icdc.com)
* Visit Dynamic Drive (http://www.dynamicdrive.com/) for full source code
* Modified Dec 31st, 02' by DD. This notice must stay intact for use
******************************************/
A=document.getElementById
B=document.all;
C=document.layers;
T1=new Array("wp-content/uploads/2012/10/meerkat1.gif",77,39,"wp-content/uploads/2012/07/meerkat2.gif",77,39,"wp-content/uploads/2012/10/meerkat3.gif",77,39,"wp-content/uploads/2012/10/meerkat4.gif",77,39,"wp-content/uploads/2012/10/meerkat5.gif",77,39,"wp-content/uploads/2012/10/meerkat6.gif",77,39)
var offsetx=15 //x offset of trail from mouse pointer
var offsety=10 //y offset of trail from mouse pointer
nos=parseInt(T1.length/3)
rate=50
ie5fix1=0;
ie5fix2=0;
rightedge=B? document.body.clientWidth-T1[1] : window.innerWidth-T1[1]-20
bottomedge=B? document.body.scrollTop+document.body.clientHeight-T1[2] : window.pageYOffset+window.innerHeight-T1[2]
for (i=0;i<nos;i++){
createContainer("CUR"+i,i*10,i*10,i*3+1,i*3+2,"","<img src='"+T1[i*3]+"' width="+T1[(i*3+1)]+" height="+T1[(i*3+2)]+" border=0>")
}
function createContainer(N,Xp,Yp,W,H,At,HT,Op,St){
with (document){
write((!A && !B) ? "<layer id='"+N+"' left="+Xp+" top="+Yp+" width="+W+" height="+H : "<div id='"+N+"'"+" style='position:absolute;left:"+Xp+"; top:"+Yp+"; width:"+W+"; height:"+H+"; ");
if(St){
if (C)
write(" style='");
write(St+";' ")
}
else write((A || B)?"'":"");
write((At)? At+">" : ">");
write((HT) ? HT : "");
if (!Op)
closeContainer(N)
}
}
function closeContainer(){
document.write((A || B)?"</div>":"</layer>")
}
function getXpos(N){
if (A)
return parseInt(document.getElementById(N).style.left)
else if (B)
return parseInt(B[N].style.left)
else
return C[N].left
}
function getYpos(N){
if (A)
return parseInt(document.getElementById(N).style.top)
else if (B)
return parseInt(B[N].style.top)
else
return C[N].top
}
function moveContainer(N,DX,DY){
c=(A)? document.getElementById(N).style : (B)? B[N].style : (C)? C[N] : "";
if (!B){
rightedge=window.innerWidth-T1[1]-20
bottomedge=window.pageYOffset+window.innerHeight-T1[2]
}
c.left=Math.min(rightedge, DX+offsetx);
c.top=Math.min(bottomedge, DY+offsety);
}
function cycle(){
//if (IE5)
if (document.all&&window.print){
ie5fix1=document.body.scrollLeft;
ie5fix2=document.body.scrollTop;
}
for (i=0;i<(nos-1);i++){
moveContainer("CUR"+i,getXpos("CUR"+(i+1)),getYpos("CUR"+(i+1)))
}
}
function newPos(e){
moveContainer("CUR"+(nos-1),(B)?event.clientX+ie5fix1:e.pageX+2,(B)?event.clientY+ie5fix2:e.pageY+2)
}
function getedgesIE(){
rightedge=document.body.clientWidth-T1[1]
bottomedge=document.body.scrollHeight-T1[2]
}
if (B){
window.onload=getedgesIE
window.onresize=getedgesIE
}
if(document.layers)
document.captureEvents(Event.MOUSEMOVE)
document.onmousemove=newPos
setInterval("cycle()",rate)
</script>
This will make an image follow the cursor. I originally used it as a bookmarklet, hence it all being javascript.
var hi = document.createElement("img");
var att = document.createAttribute("src");
var sty = document.createAttribute("style");
var alt = document.createAttribute("onclick");
var ide = document.createAttribute("id");
ide.value = "hi01";alt.value = "alert('Hi')";
att.value = "http://www.picgifs.com/clip-art/cartoons/pokemon/clip-art-pokemon-441770.jpg";
sty.value = "position: absolute;top: 0px;left: 0px;height: 100px;width: 100px;cursor:crosshair;";
hi.setAttributeNode(att);
hi.setAttributeNode(alt);
hi.setAttributeNode(sty);
hi.setAttributeNode(ide);document.body.appendChild(hi);
var scr = document.createElement("script");
var scratt = document.createAttribute("src");
scratt.value = "http://ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js";
scr.setAttributeNode(scratt);
document.body.appendChild(scr);
$("body").mousemove(function(e){
var a = e.pageX - 50;
var b = e.pageY - 50;
document.getElementById('hi01').style.left = a+'px';
document.getElementById('hi01').style.top = b+'px';
});

Find out the 'line' (row) number of the cursor in a textarea

I would like to find out and keep track of the 'line number' (rows) of the cursor in a textarea. (The 'bigger picture' is to parse the text on the line every time a new line is created/modified/selected, if of course the text was not pasted in. This saves parsing the whole text un-necessarily at set intervals.)
There are a couple of posts on StackOverflow however none of them specifically answer my question, most questions are for cursor position in pixels or displaying lines numbers besides the textarea.
My attempt is below, it works fine when starting at line 1 and not leaving the textarea. It fails when clicking out of the textarea and back onto it on a different line. It also fails when pasting text into it because the starting line is not 1.
My JavaScript knowledge is pretty limited.
<html>
<head>
<title>DEVBug</title>
<script type="text/javascript">
var total_lines = 1; // total lines
var current_line = 1; // current line
var old_line_count;
// main editor function
function code(e) {
// declare some needed vars
var keypress_code = e.keyCode; // key press
var editor = document.getElementById('editor'); // the editor textarea
var source_code = editor.value; // contents of the editor
// work out how many lines we have used in total
var lines = source_code.split("\n");
var total_lines = lines.length;
// do stuff on key presses
if (keypress_code == '13') { // Enter
current_line += 1;
} else if (keypress_code == '8') { // Backspace
if (old_line_count > total_lines) { current_line -= 1; }
} else if (keypress_code == '38') { // Up
if (total_lines > 1 && current_line > 1) { current_line -= 1; }
} else if (keypress_code == '40') { // Down
if (total_lines > 1 && current_line < total_lines) { current_line += 1; }
} else {
//document.getElementById('keycodes').innerHTML += keypress_code;
}
// for some reason chrome doesn't enter a newline char on enter
// you have to press enter and then an additional key for \n to appear
// making the total_lines counter lag.
if (total_lines < current_line) { total_lines += 1 };
// putput the data
document.getElementById('total_lines').innerHTML = "Total lines: " + total_lines;
document.getElementById('current_line').innerHTML = "Current line: " + current_line;
// save the old line count for comparison on next run
old_line_count = total_lines;
}
</script>
</head>
<body>
<textarea id="editor" rows="30" cols="100" value="" onkeydown="code(event)"></textarea>
<div id="total_lines"></div>
<div id="current_line"></div>
</body>
</html>
You would want to use selectionStart to do this.
<textarea onkeyup="getLineNumber(this, document.getElementById('lineNo'));" onmouseup="this.onkeyup();"></textarea>
<div id="lineNo"></div>
<script>
function getLineNumber(textarea, indicator) {
indicator.innerHTML = textarea.value.substr(0, textarea.selectionStart).split("\n").length;
}
</script>
This works when you change the cursor position using the mouse as well.
This is tough because of word wrap. It's a very easy thing to count the number of line breaks present, but what happens when the new row is because of word wrap? To solve this problem, it's useful to create a mirror (credit: github.com/jevin). Here's the idea:
Create a mirror of the textarea
Send the content from the beginning of the textarea to the cursor to the mirror
Use the height of the mirror to extract the current row
On JSFiddle
jQuery.fn.trackRows = function() {
return this.each(function() {
var ininitalHeight, currentRow, firstIteration = true;
var createMirror = function(textarea) {
jQuery(textarea).after('<div class="autogrow-textarea-mirror"></div>');
return jQuery(textarea).next('.autogrow-textarea-mirror')[0];
}
var sendContentToMirror = function (textarea) {
mirror.innerHTML = String(textarea.value.substring(0,textarea.selectionStart-1)).replace(/&/g, '&').replace(/"/g, '"').replace(/'/g, ''').replace(/</g, '<').replace(/>/g, '>').replace(/\n/g, '<br />') + '.<br/>.';
calculateRowNumber();
}
var growTextarea = function () {
sendContentToMirror(this);
}
var calculateRowNumber = function () {
if(firstIteration){
ininitalHeight = $(mirror).height();
currentHeight = ininitalHeight;
firstIteration = false;
} else {
currentHeight = $(mirror).height();
}
// Assume that textarea.rows = 2 initially
currentRow = currentHeight/(ininitalHeight/2) - 1;
//remove tracker in production
$('.tracker').html('Current row: ' + currentRow);
}
// Create a mirror
var mirror = createMirror(this);
// Style the mirror
mirror.style.display = 'none';
mirror.style.wordWrap = 'break-word';
mirror.style.whiteSpace = 'normal';
mirror.style.padding = jQuery(this).css('padding');
mirror.style.width = jQuery(this).css('width');
mirror.style.fontFamily = jQuery(this).css('font-family');
mirror.style.fontSize = jQuery(this).css('font-size');
mirror.style.lineHeight = jQuery(this).css('line-height');
// Style the textarea
this.style.overflow = "hidden";
this.style.minHeight = this.rows+"em";
var ininitalHeight = $(mirror).height();
// Bind the textarea's event
this.onkeyup = growTextarea;
// Fire the event for text already present
// sendContentToMirror(this);
});
};
$(function(){
$('textarea').trackRows();
});
This worked for me:
function getLineNumber(textarea) {
return textarea.value.substr(0, textarea.selectionStart) // get the substring of the textarea's value up to the cursor position
.split("\n") // split on explicit line breaks
.map((line) => 1 + Math.floor(line.length / textarea.cols)) // count the number of line wraps for each split and add 1 for the explicit line break
.reduce((a, b) => a + b, 0); // add all of these together
};
Inspired by colab's answer as a starting point, this includes the number of word wraps without having to introduce a mirror (as in bradbarbin's answer).
The trick is simply counting how many times the number of columns textarea.cols can divide the length of each segment between explicit line breaks \n.
Note: this starts counting at 1.

Categories