0

I have a textarea , when I press any key or by copy-pasting the content.

I wanted to get the array of content as per rows.

.text {
  overflow: hidden;
  font-size: 5vh;
  text-align: center;
  line-height: 1.5;
}
<textarea class="text" autofocus></textarea>

enter image description here

I have simply added the text and I am Not clicking enterKey while going to next line. It automatically goes to next line as Overflow: hidden is added.

Now I must get the array like this:-

["Sarah and Ira drove to "],

["the store Samantha, "],

["Elizabeth, and Joan are "],

["on the committees"].

By every update in content, the array should be updated too.

I have tried with split("\n") approach, it didn't worked. while trying Split approach, I am getting full value.

"Sarah and Ira drove to the store Samantha, Elizabeth, and Joan are on the committees"

I wanted the array of content as per rows with clicking enterKey/ without clicking enterKey. By both ways it should work.

Anyone have any ideas?

Note:- My main motive is actually get the array of content as per rows and put the same content(array of rows) in textbox object of fabricjs.

Explaining:- I have a Textarea of HTML and a textbox object in canvas of fabricjs .

I have added some content in textarea of HTML.

Now I have to save(put/show) that content(Same content written in Textarea of HTML with same rows and text) into textbox object of fabricjs.

  • are those lines created with entering? or just a new line started coz there's no place left on the upper one? split with `\n` should word if there's a real new line break – Yosi Leibman Jun 14 '22 at 11:39
  • @YosiLeibman Those are not created with entering. Those are just a new line started coz there's no place left on the upper one – Ameet deadpool Jun 14 '22 at 11:40
  • so there's no new line to filter by :( what you can do is just insert new lines automatically every X words or so (count the spaces) – Yosi Leibman Jun 14 '22 at 11:44
  • @YosiLeibman pardon me but I didn't understand your approach. – Ameet deadpool Jun 14 '22 at 11:48
  • manually concat `\n` into the value after every 3 words – Yosi Leibman Jun 14 '22 at 11:52
  • @YosiLeibman But there might be only one word say a big word for one row. Or say I wrote a whole paragraph and deleted some text in between. Then it will be not applicable – Ameet deadpool Jun 14 '22 at 11:57
  • 1
    This is practically not possible afaik. Theoretically, you could get the textarea width and set event handlers for textarea / window resize. Set a default width for each character. Calculate the max pixel length of a "sentence", then upon reaching the width of the area, loop back towards the latest space character to start splitting into an array. The problem with this approach though is that it'll be extremely unreliable. Visitors can zoom in / out, miscalculations on some characters etc. – icecub Jun 14 '22 at 12:04
  • 1
    Not to mention that you'll get in trouble the moment someone starts typing a single word that's wider than the total width of the textarea. I'm not sure what exactly you're trying to achieve in the end, but I'm fairly sure that your current approach to the problem isn't going to work. Perhaps it'll be better if you edit your question and explain what you're trying to achieve in the end, so more realistic solutions can be brought up. – icecub Jun 14 '22 at 12:08
  • @icecub Lets say we can add resize: none css for not zooming in/out. After this , is it still not practically possible? – Ameet deadpool Jun 14 '22 at 12:09
  • You can disable the resizing of the element, but you can't disable the browser's zoom function. Just hold Ctrl on your keyboard and scroll up or down. Your browser will start zooming in / out the webpage you're looking at (and therefor change the pixel length). – icecub Jun 14 '22 at 12:10
  • @icecub yes you are correct – Ameet deadpool Jun 14 '22 at 12:11
  • You can do it with some fiddling around in JS. On each character input see if the height of the textarea should change, then collect up the string somewhere else with a newline character added in it. See https://stackoverflow.com/questions/454202/creating-a-textarea-with-auto-resize to help with the first part. – A Haworth Jun 14 '22 at 12:11
  • @AHaworth I checked with this approach already, By this lets say I am deleting a middle word of a row, the content changes and then we can't get the correct result(array of content as per rows). – Ameet deadpool Jun 14 '22 at 12:15
  • Yes, better to have a button which user clicks when they are ready to submit or whatever, then you use the gradual filling of the textarea to note when a newline is inserted. – A Haworth Jun 14 '22 at 12:18
  • @icecub I have edited the question and that's my motive. – Ameet deadpool Jun 14 '22 at 13:21
  • I was wondering, is it ok to use jQuery for this? With browser inconsistencies, I keep running into issues trying it pure JS – icecub Jun 14 '22 at 13:22
  • @icecub You can try with jQuery but it would be more preferable with JS. You can put answer with jQuery , then I will try that approach with JS. – Ameet deadpool Jun 14 '22 at 13:27
  • For some strange reason, the snippet here doesn't seem to work properly with the code I've written. But here's the jsFiddle with a working example: https://jsfiddle.net/3h6kr1fu/ Should probably note that it bugs out when resizing to a bigger size because I forgot to empty the array everytime. Just add that to the input event handler and you're good to go – icecub Jun 14 '22 at 14:10
  • @icecub I have added code for emptying the array every time when input event occurs. But it works for only first row not for 2nd or 3rd row. – Ameet deadpool Jun 14 '22 at 14:37
  • @icecub you can try to copy and paste a big sentence or write manually a sentence. There will be only 2 element in array in console showing. First element is first row(that's correct) and second is whole remaining sentence(that's not correct). – Ameet deadpool Jun 14 '22 at 14:41
  • Ah right.. I didn't take into account situations where a single line could end up on more than 2 lines. Unfortunately I don't have time left right now. I might continue working on that some time later. But most of the work is already done. All you really have to do is change it up a little so it considers longer lines. – icecub Jun 14 '22 at 14:50
  • Had some more time to work on it: https://jsfiddle.net/3h6kr1fu/1/ Solved the issue with long lines ending up on more than 2 lines, but discovered 2 new issues that I can't wrap my head around. At least, not right now. If a space character ends up exactly at the last position before a new line, the array ends up wrong. If a single word is longer than the entire line, it splits at the wrong position. I think I've already done quite a lot for you though, so I leave the final straws up to you. – icecub Jun 14 '22 at 15:43
  • And here's the final update where I've put comments into the JS code explaining how it works. That should make it easier for you to work on it: https://jsfiddle.net/3h6kr1fu/2/ – icecub Jun 14 '22 at 15:56
  • @icecub Thank you very much , I will look into the fiddle. If I get any doubt, I will get back to you. I will look into that space character and single word is longer than the entire line issues. – Ameet deadpool Jun 15 '22 at 02:15

1 Answers1

0

I made code that works. It can be optimized a lot, but it took me over an hour so I couldn't do it...

The most important parts are: In html use "rows" and "cols" to limit the size of the textarea. You may need to synchronize this size with the site's font-size.

In CSS just use resize: none

In JS I cut the text looking for spaces and then calculate how many characters fit in each of the lines.

  1. If the word fits on the line, add
  2. If it doesn't fit and is too big, cut it out and add the fragments.
  3. If it doesn't fit on the line create another line and add this word
  4. repeat until the text ends

let arraySync = [];

let textarea = document.querySelector('textarea');
textarea.addEventListener('keyup', event_);
textarea.addEventListener('select', event_);

function event_(event){
    let value = event.target.value;
    event.target.value = runTextarea(event.target, true);
  arraySync = runTextarea(event.target);
    console.log(arraySync);
};

function runTextarea(element, keyupOrSelect = false) {
    let text = element.value;
    let maxPerLine = 25;
    let result = [['']];
    let charactersOnLine = 0;
    let wordOnLine = 0;
    text = text.split(/\s+/).forEach(function(word) {
            let length;
            if (wordOnLine !== 0) {
                word = ' ' + word;
            };
            if (charactersOnLine + word.length <= maxPerLine) { // push the word
                wordOnLine++;
                charactersOnLine += word.length;
                result[result.length - 1][0] += word; // use array existing
            } else if (word.length > maxPerLine) { // split the word
                wordOnLine = maxPerLine - 1;
                charactersOnLine = 0;
                word = word.replace(/^\s/, ''); // remove the first space
                while (word.length > maxPerLine) {
                    let splittedWord = word.substring(0, maxPerLine - 1) + '-'; // split on maxLength
                    // add new line
                    wordOnLine = 1;
                    charactersOnLine = splittedWord.length;
                    result.push([splittedWord]);
                    word = word.substring(maxPerLine);
                };
                if (word.length > 0) {
                    // add new line
                    wordOnLine = 1;
                    charactersOnLine = word.length;
                    result.push([word]);
                };
            } else { // push the word
            word = word.replace(/^\s/, ''); // remove the first space
            wordOnLine = 1;
            charactersOnLine = word.length;
            result.push([word]);
        };
    });
    return keyupOrSelect ? result.join(' ') : result;
};
textarea {
  resize: none;
}
<textarea rows="7" cols="25">Lorem ipsum dolor sit, amet consectetur adipisicing elit. Beatae, placeat sunt veritatis temporibus quo nesciunt voluptates aliquam at iure. Ducimus vel, autem delectus deleniti magnam minus dignissimos aut odit doloremque?</textarea>
Luis Lobo
  • 489
  • 4
  • 7