1

my code keeps telling me an object I have created is undefined.

I am loading in several JS files then calling functions but it errors

The error:

Uncaught TypeError: Cannot read property 'setListenUrl' of undefined

Here's the code:

<script src="{{ URL::asset('javascript/chat.js') }}"></script>

<script>
    $(function() {
        chatbox.setListenUrl('{{ URL::route('chat.listen') }}');
        chatbox.setSendURL('{{ URL::route('chat.send')  }}');

        @if(Auth::check())
        chatbox.setAuth(true);
        @endif

        @if(isset($game))
        chatbox.setGame('{{ $game }}');
        @endif

        chatbox.init();
    });
</script>

chat.js

var chatbox = {

...
}

Full script code http://pastebin.com/7LhWq01U

chat.js http://pastebin.com/nNgTtME1

4
  • 5
    So chatbox is clearly undefined, meaning your script isn't loading, or you did something wrong in it. Commented Jan 10, 2016 at 2:40
  • Can you please check whether your code is load by adding things like console.log in the end of your chat.js? Commented Jan 10, 2016 at 2:46
  • It is 100% loading, I added console.log in chat.js and before I called chat.setListenUrl and it appears in the right order. Commented Jan 10, 2016 at 3:14
  • Here's the URL if it helps 178.62.26.90/bwaf2/public Commented Jan 10, 2016 at 3:14

1 Answer 1

2

You are using chatbox in the object literal that you assign to chatbox, that doesn't work because chatbox isn't yet defined.
That uncaught error makes the execution of your entire chat.js script stop, which is why chatbox is also undefined in the following scripts.

So, beginning at line 17 of chat.js, you have to find a way to reference $chatbox in multiple places of your object.
This is a common problem in JavaScript when you would like to reference a previously defined property in an object literal. But the thing is that you can't, so for now the quickest fix would be to declare a $chatbox variable outside of your object and reference it from inside.

Since declaring global variables left and right is definitely bad practice, this problem can be better tackled in the following 2 ways:

Constructor functions

You create a constructor function and then make instances of the object with the keyword new. This provides encapsulation of the object initialization code and allows you to create multiple chatbox objects easily if you ever need it.

function Chatbox() {
     var $chatbox = $('.chatbox');
     this.$chatbox = $chatbox;
     this.$input = $chatbox.find('.input input');          
     //...
}

var chatbox = new Chatbox();

If you know you won't have multiple instances of your object though, the constructor pattern doesn't provide much and may just be an additional syntax burden, so you can use a lighter encapsulation technique:

Immediately invoked function expression (IIFE)

You put all your object initialization code in an anonymous function that returns the object at the end, and you invoke that function right in a variable declaration statement, which also provides encapsulation of any variables you need to declare when initializing your object.

var chatbox = (function() {
      var $chatbox = $('.chatbox');

      return {
           $chatbox: $chatbox,
           $input: $chatbox.find('.input input'),
           //           ^ This references the outer $chatbox variable, not this
           //             object's $chatbox property.
      };

})();
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.