-1

I want to display a max of 13 words as a preview of what is written in each note, and if there is more text, then replace that text with three dots.

As an example: This is a user saved note and I'm limited to displaying thirteen words...

What I currently have is simply a full parsing of the JSON object no matter how large it is, however, I need to limit the length.

I have tried using Javascript string methods and did not succeed in making this work.

 return (
        <div className="notes">
            <div className="notes_header">
                <p>You have {numberOfNotes} notes</p>
            </div>

            <div>
               {notes.map((val) => {
                   return <div key={val.id} onClick={() => Logic.selectNote(val.note, val.id)}><ReactQuill className="note" value={JSON.parse(val.note)} readOnly={true}  /></div>
               })}
            </div>
        </div>
    )
}

This is the output after I parse val.note

0: {insert: "This is a user note.\n"}
Arcanus
  • 642
  • 5
  • 20
  • Related: https://stackoverflow.com/questions/1199352/smart-way-to-truncate-long-strings/ – jarmod Aug 04 '21 at 19:55
  • Split the string on whitespace, take up to 13 elements of the resulting array, re-join them with space, append an ellipsis. – jarmod Aug 04 '21 at 19:57
  • The code you presented has little relation to the question, which is a pure string manipulation question. The rendering is irrelevant. – trincot Aug 04 '21 at 19:59
  • IMHO the question is too broad and therefore it's unclear what you're actually asking. Are you asking how to parse JSON until a specific delimiter? Are you asking how to truncate a string? Do you want to replace `JSON.parse(val.note)` with a more efficient function? What is `val.note`? – Thomas Sablik Aug 04 '21 at 19:59
  • @jarmod I just looked over that and it is not exactly related because I cannot apply a string method to a parsed JSON object. I tried, however I am not sure why. – Arcanus Aug 04 '21 at 20:00
  • @ThomasSablik Yes I want to replace JSON.parse with a more efficient function which can allow me to restrict the number of words to 13. ```val.note``` is simply the note saved by the user previously, being mapped out. – Arcanus Aug 04 '21 at 20:02
  • There is no function in Vanilla JS that can solve your problem. You could either search for a more flexible JSON library or write your own. Douglas Crockford describes how to implement a JSON parser: https://github.com/douglascrockford/JSON-js But to be honest I don't think it makes sense. The basic JSON will probably be faster than your implementation even with the overhead. – Thomas Sablik Aug 04 '21 at 20:05
  • You're ultimately displaying the string representation of an object, no? You seem to be implying that it's a string containing a saved note. Do what you need to stringify the note, then truncate/ellipsize it. – jarmod Aug 04 '21 at 20:07
  • Maybe you can find helpful resources: https://github.com/burningtree/awesome-json – Thomas Sablik Aug 04 '21 at 20:10

2 Answers2

1

Assuming that val.note is a simple string:

const maxWords = 13
const note = JSON.parse(val.note)
words = note.split(/(?=\W)/) // 1
const notePreview = words.length > maxWords ? [...words.slice(0, maxWords), '...'].join('') : note // 2

In line 1, you split the note text before each word boundaries (the (?=) is a positive look-ahead regex pattern). In line 2, you check if this gave you more words than you want. If yes, you create a new array with the number of words you want, add the ellipsis and join it to a string. If not, you simply use the note text.

juxtapos
  • 26
  • 3
0

Here is a function that can truncate or clip text. It clips the input text after a given number of words and adds "..."

/**
 * Generates teaser text for your note by limiting it to a certain number of words
 * @param {string} note     Your note or input text
 * @param {number} maxWords The max number of words to allow in the output
 **/
const clipTextByWordCount = (note, maxWords) => {
    if(note.indexOf(' ') === -1) {
        return note;
    }
    
    let words = (note.split(' ')).filter((w, i) => i < maxWords);
    return words.join(' ') + '...';
};

First you want to parse your json from a string into an object using the JSON.parse(jsonString) method, then you want to get the full note text from that parsed object.

I could be more helpful here if I could tell the structure of your JSON from your example code, but it's not clear based on your example.

Once you know how to retrieve the full note text from your parsed object, you want to pass that full note text into clipTextByWordCount(text, 10) to get the truncated text to display to the user.

Here's an example of usage:

const noteJson = "{\"id\": 5, \"val\": \"this is a whole bunch of words that I am typing for you to read right now\"}";
const val = JSON.parse(noteJson);
let displayText = clipTextByWordCount(val.note, 10); // "this is a whole bunch of words that I am..."
TxRegex
  • 2,347
  • 21
  • 20