1

I'm writing a twitter aggregator and I need some help on solving the error 'Uncaught ReferenceError: sqTweetData is not defined.' It looks like console is pointing me to my for loop. I have set up a partial that is compiled and loaded in #main-content using underscore js.

For Loop Code

<!-- Main Content -->
<main class="main">
    <div class="container-flex" id="main-content"></div>
</main> <!-- End Main Content -->

<!-- Current Tweet Partials -->
<script id="active-tweet-partial" type="underscore/template">
    <section class="tweetFlexItem">

    <% for (var i = 0; i < sqTweetData.length; i++) { %>
        <div class="activeTweet">
            <div class="activeTweet__avatar"><img src="<%= sqTweetData[ i ].user.profile_image_url %>"></div>
            <div class="activeTweet__wrapper">
                <div class="activeTweet__name"> <%= sqTweetData[ i ].user.name %> </div>
                <div class="activeTweet__message"><%= sqTweetData[ i ].text %></div>
            </div>
        </div>
    <% } %>

    </section>
</script>

home.js Compiling Code

var Home = (function() {

var sqTweetData = {
    user: [{
        profile_image_url : "assets/avatar.png",
        name : "@johnsnow"
    }],
    text : "Someone once said that I know nothing..."
};

console.log("this is sqTweetData", sqTweetData);

// Partials
var tweetPartial = $('#active-tweet-partial').html();
    tweetPartialCompiled = _.template( tweetPartial );

// DOM Handlers

// KICKSTART VIEW
function initHome() {

    // load main content
    $('#main-content').html(tweetPartialCompiled( sqTweetData ));

    // bind events

}
return {
    init: initHome
};

})();

The console.log on line 11 works just fine, so I'm assuming my variable object is set up correctly. There just seems to be a disconnect between the partial and the rest of the javascript.

Any thoughts?

u111937
  • 287
  • 4
  • 16
  • You're trying to access a variable that doesn't exist. The variable was declared in `Home` not in the global `window` – acupofjose Dec 09 '15 at 03:20

1 Answers1

1

This is a scoping issue. sqTweetData says it's undefined because it's exactly that. window["sqTweetData"] does not exist. When you declare a variable outside of a function it's inserted into the global namespace, in this case the browser window is the namespace.

Since you're declaring the variable inside of home using the var keyword, the variable will only be accessible within the Home function. So you'd have to add it as either a this.sqTweetdata and return it with the object, or add a separate getTweetData() that return the variable, or something along those lines.

Check out this answer that covers scoping very comprehensively: https://stackoverflow.com/a/500459/3629438

Yours falls under:

Advanced: Closure

var a = 1;

var six = (function() {   

  var a = 6;

  return function() {
    // JavaScript "closure" means I have access to 'a' in here,
    // because it is defined in the function in which I was defined.
    alert(a);   
  }; 
})();

EDIT:

In your case you would do something along the lines of

var Home = (function() {

// ....... //    

function getTweetData() {
   return sqTweetData;
}
return {
    init: initHome,
    get: getTweetData
};

})();
Community
  • 1
  • 1
acupofjose
  • 2,159
  • 1
  • 22
  • 40
  • Awesome, totally makes sense. How would I go about create a getTweetData() function to pass the data for global use? – u111937 Dec 09 '15 at 03:27
  • 1
    I think `tweetPartialCompiled({ sqTweetData: sqTweetData})` would be a more appropriate solution in the context of an Underscore template. Underscore mangles the template into a JavaScript function and uses [`with`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/with) to alter the scoping rules. – mu is too short Dec 09 '15 at 04:27
  • @muistooshort ah you are correct, I'm not as well versed in Underscore however and was answering from a standpoint of vanilla javascript – acupofjose Dec 09 '15 at 04:28