Unable to access object property of state object in state modification method (Javascript/jQuery)

0 votes
asked Jan 12 by user1629099

I'm working on a text analyzer in jQuery that returns word count, unique word count, average word length, and average sentence length.

I had it working (at least halfway, up to the unique word count functionality) before I realized my structure was horrible. So I refactored it...and now I'm having trouble getting it to work at all.

Basically, I receive TypeErrors and ReferenceErrors for the various object properties I'm attempting to access in each function, e.g. state.text, state.words, etc.

What am I doing wrong here? Something about the way I'm trying to access the state object, obviously -- but what, exactly, is beyond me.

Here is the index.js:

'use strict'

// state object

var state = {
    text: "",
    words: [],
    uniqueWords: [],
    sentences: [],
    wordLengths: [],
    sentenceLengths: []
}


//state modification functions

var getText = function(state) {
    state.text = $('user-text').val()
}

var getWords = function(state) {
    state.words = state.text.match(/[^_\W]+/g)
}

var getSentences = function(state) {
    state.sentences = state.text.match( /[^\.!\?]+[\.!\?]+/g )
}

var getUniqueWords = function(state) {
    for (var i = 0; i < state.words.length; i++) {
        if (state.uniqueWords.indexOf(words[i]) < 0) {
            state.uniqueWords.push(words[i])
        }
    }
}

var getWordCount = function(state) {
    var wordCount = state.words.length
    //should I add `wordCount` to `state`?
    return wordCount
}

var getUniqueWordCount = function(state) {
    var uniqueWordCount = state.uniqueWords.length
    //should I add `uniqueWordCount` to `state`?
    return uniqueWordCount
}

var getWordLengths = function(state) {
    for (var i = 0; i < state.words.length; i++) {
       state.wordLengths.push(state.words[i].length)
    }
}

var getAverageWordLength = function(state) { 
    var sum = state.wordLengths.reduce(function(a, b) {
        return a + b
    }, 0)
    var averageWordLength = sum/wordLengths.length
    return averageWordLength
}

var getSentenceLengths = function(state) {
    for (var i = 0; i < state.sentences.length; i++) {
        state.sentenceLengths.push(state.sentences[i].length)
    }
}

var getAverageSentenceLength = function(state) {
    var sum = state.sentenceLengths.reduce(function(a,b) {
       return a + b
    }, 0)
   var averageSentenceLength = sum/sentenceLengths.length
  return averageSentenceLength
}

// render functions

var renderWordCount = function(state, element) {
    $("dl").toggleClass('hidden')
    return element.append(wordCount)
}

var renderUniqueWordCount = function(state, element) {
    $("dl").toggleClass('hidden')
    return element.append(uniqueWordCount)
}

var renderAverageWordLength = function(state, element) {
    $("dl").toggleClass('hidden')
    return element.append(averageWordLength)
}

var renderAverageSentenceLength = function(state, element) {
    $("dl").toggleClass('hidden')
    return element.append(averageSentenceLength)
}

// event listener functions

$(function() {
    $('button').click(function() {
        event.preventDefault()
        getText(state)
        getWords(state)
        getSentences(state)
        getUniqueWords(state)
        getWordCount(state)
        getUniqueWordCount(state)
        getAverageWordLength(state)
        getSentenceLengths(state)
        getAverageSentenceLength(state)
        renderWordCount(state, $('.wordCount'))
        renderUniqueWordCount(state, $('uniqueWordCount'))
        renderAverageWordLength(state, $('averageWordLength'))
        renderAverageSentenceLength(state, $('averageSentenceLength'))
    })
})

And here is the index.html:

<!DOCTYPE html>
<html>
<head>
    <title>Text analyzer</title>
    <meta charset="utf-8">

    <link rel="stylesheet" type="text/css" href="https://cdnjs.cloudflare.com/ajax/libs/normalize/4.2.0/normalize.min.css">
    <link rel="stylesheet" type="text/css" href="main.css">
</head>
<body>
    <div class="container">
        <main>
            <h1>Text analzyer</h1>
            <p>Paste in text below, submit, and get some basic stats back.</p>
            <form class="js-form">
                <div>
                    <label for="user-text">Text to analyze</label>
                    <textarea cols="60" rows="20" id="user-text" name="user-text" placeholder="What have you got to say?" required></textarea>
                </div>
                <div>
                    <button type="submit">Analyze it!</button>
                </div>
            </form>

            <dl class="hidden text-report">
                <dt>Word count</dt>
                <dd class="wordCount"></dd>

                <dt>Unique word count</dt>
                <dd class="uniqueWordCount"></dd>

                <dt>Average word length</dt>
                <dd class="averageWordLength"></dd>

                <dt>Average sentence length</dt>
                <dd class="averageSentenceLength"></dd>
            </dl>
        </main>
    </div>
    <script src="jquery-3.1.1.js"></script>
<!-- <script src="app.js"></script> -->
    <script src="index.js"></script>
</body>
</html>

Thank you!

P.S. If you have any ideas about structuring the app, all thoughts are welcome; I especially am concerned about the way I'm calling all the functions one after another in the ready function at the end. That seems kinda messy for some reason.

Please log in or register to answer this question.

...