0

I have a txt document with a definition first and then a meaning with ; in between :

Apple;blabla. Pear; blah blah. Banana; blahblie.

And now I want to write that if you search an input in an html file on "Apple" you will find "blabla". But I don't know which program I would do best and how?

mplungjan
  • 169,008
  • 28
  • 173
  • 236
  • 2
    Could you share more details and code sample? – Ivan Kharkivskyi Jun 25 '21 at 12:55
  • 1
    Welcome to Stack Overflow! Visit the [help], take the [tour] to see what and [ask]. Please first ***>>>[Search for related topics on SO](https://www.google.com/search?q=javascript+read+text+file+site%3Astackoverflow.com)<<<*** and if you get stuck, post a [mcve] of your attempt, noting input and expected output using the [`[<>]`](https://meta.stackoverflow.com/questions/358992/ive-been-told-to-create-a-runnable-example-with-stack-snippets-how-do-i-do) snippet editor. – mplungjan Jun 25 '21 at 12:57

2 Answers2

0

Have a look at this

You need to load the file. You can use fetch for that

const defFile = `Apple;blabla. Pear; blah blah. Banana; blahblie.`
const pairs = defFile.match(/([a-zA-Z0-9_ ]+)+; ?([a-zA-Z0-9_ ]+)+\./g)
const dl = document.getElementById("def")
const search = document.getElementById("search");
dl.innerHTML = pairs.map(pair => {
  const [dd, dt] = pair.split(";")
  return `<dd class="hide">${dd.trim()}</dd><dt  class="hide">${dt.trim()}</dt>`
}).join("");

search.addEventListener("input", function() {
  const s = this.value.toLowerCase();
  const dds = dl.querySelectorAll("dd");
  dds.forEach(dd => {
    const show = s && dd.textContent.toLowerCase().includes(s);
    dd.classList.toggle("hide", !show)
    dd.nextElementSibling.classList.toggle("hide", !show)
  })
})
.hide {
  display: none
}
<input type="text" id="search" autocomplete="off" />
<dl id="def"></dl>
mplungjan
  • 169,008
  • 28
  • 173
  • 236
0

To get the text contents of the file,you can use a element and have an event listener on it so it can tell when a file is added. With this, you can get the file as it will be the first (0th) item in the file input e.g. textFileInput.files[0] and you can get the text from it by using .text() on it. This will be an asynchronous operation so you have to use await (i.e. await textFileInput.files[0].text();)

If you are certain that the word will always contain no spaces or characters such as . or ; as you are current using them as delimiters, you can use them to split the objects into arrays with .split(), (e.g. "abc!def!ghi".split('!') separates the string wherever it find an '!' into an array: ["abc", "def", "ghi"]), we can also uses this to separate your text into an array of "word; defintion" strings and further split those where there is a ';' present. We can then store the words and definitions in a JS object, which will allow you to access them by the keys, in this case the words themselves as such: object.wordName or `object['wordName'].

You can add a new key:value pair to an object by doing object['newWord'] = 'definition of newWord';, then you can access the definition of newWord with const textDefinitionOfNewWord = object['newWord'];

Now you can have a search box paired with either a button that runs a function, or an event listener (I have demonstrated below) for when any key is pressed while in the search box. If when accessing the object['word'], it returns a non-null value, there is a definition stored that you can output.

// dictionary will store the text later, after it is uploaded
// definitionObject will store words and definitions, accessible by word
let dictionary = "";
let definitionObject = {};

const textFileInput = document.querySelector('#textFileInput');
const textFileOutput = document.querySelector('#textFileOutput');

const searchInput = document.querySelector('#searchInput');
const definitionOutput = document.querySelector('#definitionOutput');


textFileInput.addEventListener('change', async function () {
    // set dictionary to be the text from the file
    dictionary = await textFileInput.files[0].text();
    // set textFileOutput text content to loaded text forom file just so we can see it
    textFileOutput.textContent = dictionary;
    
    // splits into array based on where a dot and a space is found
    // in this case ["Apple;blabla", "Pear; blah blah", "Banana; blahblie."]
    // we can remove the . at the end as well as the extra spaces later
    const definitionArray = dictionary.split('. ');

    for (const definitionPair of definitionArray) {
      // split defintion word;definition into ["word", "definition"]
      let splitDefinition = definitionPair.split(';');
      let word = splitDefinition[0]; // word will be the 0th item in splitDefinition
      let definition = splitDefinition[1]; // definition will be the 1st item in splitDefinition

      // we can add the words and definitions to an object so they can be accessed easily.
      // trim to remove whitespace + toLowerCase so it is lower case
      // we make it lower case so that when searching, we can lower the input and assert with that

      // the .replace(/[^_\W]+/g), ' ') replaces non alphanumeric characters with a space,
      // any spaces on either side will get remove due to the trim()
      
      // e.g. defintionObject['apple'] = 'blabla';
      definitionObject[word.trim().toLowerCase()] = definition.replace(/\W+/g, ' ').trim();
    }
        // Listen for whenever the text a key is pressed whilst in search box
    // if there is a result, return it, else clear
    
    // may want to replace this with a button that is pressed and then calls the function rather than every keyup
    searchInput.addEventListener('keyup', function () {
    // check search input after trimming and lowering if it exists in the definition object
    // ("  Banana  " becomes "banana")
    // show definition if found, else empty the definition
      if (definitionObject[searchInput.value.trim().toLowerCase()]) {
                definitionOutput.textContent = definitionObject[searchInput.value.trim().toLowerCase()];
      } else {
        definitionOutput.textContent = '';
      }
    });
});
textarea { width: 100%; height: fit-content; }
<!DOCTYPE html>
  <html lang="en">
  <head>
      <meta charset="UTF-8">
      <meta http-equiv="X-UA-Compatible" content="IE=edge">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <title>Search from dictionary</title>
  </head>
  <body>
    <input id="textFileInput" name="textFileInput" type="file">
    <p>
     Loaded text so we can be sure the text is loaded correctly: 
    </p>
    <textarea id="textFileOutput" readonly></textarea>

    Word to search: <input id="searchInput" name="searchInput" type="text">
    <p>
    Definition: <span id="definitionOutput"></span>
    </p>
    
  </body>
</html>
Alvie Mahmud
  • 194
  • 1
  • 10