How I Made Etymologizer, Part 2

In a previous post I explained how I made the Rails API for my Etymologizer app. Now for the next part – the AngularJS front-end component that interacts with the Rails API, gets the correct type of data, and displays it to the user.

For example, the user might type in We hold these truths to be self-evident: that all men are created equal:

etymologizer-user-input

Here is the code that takes the input:

<form ng-submit="getEtymologies()">
    <textarea ng-model="inputText" ng-model-options="{ updateOn: 'submit' }" class="form-control" rows="3" cols="50" id="textArea" placeholder="Enter text here"></textarea>
    <button class="btn btn-primary">
    Show etymology
    </button>
</form>

When the user submits the form, two things happen: the “getEtymologies” function gets called, and the data model updates. (The “ng-model-options” directive means that instead of updating immediately upon the user’s typing some text, it waits until the event specified by “updateOn” occurs – here, the submission of the form.)

The “getEtymologies” function is contained in the controller. (Here’s the whole function.) This function interacts with the Rails API, but before that, it does a few things:

  • creates an empty array to contain the data of all words;
  • calls a “sanitize” function that removes any punctuation, non-letters, line breaks and extra spaces via the JavaScript replace method;
  • combines the words into a space-separated string, which will be the params that get passed to the Rails API;
  • sets “loading” to true, which triggers the display of a spinner on the page while the user waits for the job to complete (via the “ng-show” directive here).

After these preliminaries, it uses $http.get to send the params to┬áthe Rails API, with resourceURL previously assigned as the API’s URL:

    $http.get($scope.resourceURL, {
      params: { words: $scope.wordParams }
    })

The response it gets back contains a JSON object for each word typed by the user. The function then iterates through each object, calling three functions each time, but only if the response contains relevant data. The conditionality is expressed with the ternary operator:

this.entry_list.entry ? etymology = etymologyService.findEtymology(this) : etymology = null;

etymology ? etymology = etymologyService.getValidHTML(etymology) : etymology = null;

etymology ? language = originLanguageService.getLanguage(etymology) : language = null;

The functions are contained in a separate services.js file. The findEtymology function digs through the data to find the etymology; the getValidHTML function adds appropriate HTML for displaying on the page; and the getLanguage function determines which language the word comes from by looking for the appropriate keyword in the etymology. (It assigns the newest language first; for example, if a word comes from Latin via Greek, it will be classified as Latin, which is newer than Greek; if a word comes from Anglo-French via Latin, it will be classified as Anglo-French, which is newer than Latin.)

Once it’s found all the appropriate data, the function creates a hash entry for each word, which will be added to the array of etymologies. Finally, now that the data is ready for display, it sets “loading” to false, so the spinner disappears and makes way for the color-coded etymology results.

Back in home.html, the AngularJS code displays the appropriate color for each word. The color classes are defined in the CSS, and ng-class=”entry.language” assigns the correct class for each word’s color.

The final chunk of code displays the detailed etymology of a word when the user mouses over the word.

I enjoyed creating this app, and perhaps eventually I’ll add more features!

Leave a Reply

Your email address will not be published. Required fields are marked *