Shamoon
Shamoon

Reputation: 43491

How do I properly scope functions with CoffeeScript in browser?

(->
  jQuery ->
    globalThis = @
    $('#emailTypes').change ->
      globalThis.toggleEmailOptions()

  toggleEmailOptions = ->
    $('.emailTypeOptions').fadeOut 'fast', ->
      for emailType in $('#emailTypes').val()
        $("##{emailType}Options").fadeIn()


).call this

That's my .coffee file. However, the toggleEmailOptions function isn't in scope of the jQuery ready. How can I make it in scope?

Upvotes: 1

Views: 1683

Answers (3)

Trevor Burnham
Trevor Burnham

Reputation: 77416

There are a couple of problems here. One is that you seems to be assuming that @/this is the global object (window) from the jQuery callback. But it's easy to see that it isn't:

jQuery -> console.log @ is window  # false

Remember that callbacks can be called in whatever context the library wants. In this case, @ is document. And document.toggleEmailOptions doesn't exist.

Further, if you want toggleEmailOptions to be a global, you need to attach it to window (or @/this, since @ is window in the outermost scope of your file). That's because when you just write toggleEmailOptions = ..., CoffeeScript scopes it within the file using a var declaration. It's easy to see this by looking at the compiled JS: vars are always at the top of their scope. Fortunately, file scope is what you wanted anyway.

So basically: Don't overthink it! What you want is:

jQuery ->
  $('#emailTypes').change ->
    toggleEmailOptions()

and leave the rest as it is.

Upvotes: 0

Guillaume86
Guillaume86

Reputation: 14400

I think you don't need to wrap because coffeescript already do it, here's how I would rewrite your code:

jQuery ->
  toggleEmailOptions = ->
    $('.emailTypeOptions').fadeOut 'fast', ->
      for emailType in $('#emailTypes').val()
        $("##{emailType}Options").fadeIn()

  $('#emailTypes').change ->
    toggleEmailOptions()

Upvotes: 1

Marius Kjeldahl
Marius Kjeldahl

Reputation: 6824

From http://jashkenas.github.com/coffee-script/

The usual caveats about CoffeeScript apply — your inline scripts will run within a closure wrapper, so if you want to expose global variables or functions, attach them to the window object.

Or bind to exports if you're using node.js .

For your example, it becomes:

window.toggleEmailOptions = ->

Upvotes: 2

Related Questions