8

The coffeescript compiler is, for some reason, wrapping all of my .coffee files in a function when they are compiled. For example, if I have test.coffee:

class TestClass
    constructor: (@value) ->

    printValue: () ->
        alert(@value)

printAValue = () -> 
    test = new TestClass()
    test.printValue()

then I get test.js:

(function() {
  var TestClass, printAValue;
  TestClass = (function() {
    function TestClass(value) {
      this.value = value;
    }
    TestClass.prototype.printValue = function() {
      return alert(this.value);
    };
    return TestClass;
  })();
  printAValue = function() {
    var test;
    test = new TestClass();
    return test.printValue();
  };
}).call(this);

My simple html file won't work with this:

<html>
    <head>
        <script src="test.js"></script>
    </head>
    <body onload="printAValue()">
    </body>
</html>

I haven't worked with much JS before, and I wouldn't doubt the coffee compiler, but is the way it should work? How

DrPepper
  • 237
  • 2
  • 6
  • Try changing your coffeescript line to pass a value to the TestClass initializer -`test = new TestClass('hello world')` – arunkumar Aug 16 '11 at 17:34
  • See [my answer here][1] on sharing code between JS files/modules. [1]: http://stackoverflow.com/questions/6951438/accessing-document-within-coffeescripts-default-wrapper/6951641#6951641 – Peter Lyons Aug 16 '11 at 18:15
  • This is by far the most popular question asked about CoffeeScript on SO. See http://stackoverflow.com/q/6481986/66226, http://stackoverflow.com/q/4214731/66226, http://stackoverflow.com/q/5693211/66226... – Trevor Burnham Aug 16 '11 at 18:18

2 Answers2

9

See my answer here on sharing jS code between files/modules. Also FYI the wrapper function is by design to prevent unintentional global variables. You can disable with by passing --bare to the coffee compiler command line tool, but it is a best practice with good reason.

Community
  • 1
  • 1
Peter Lyons
  • 142,938
  • 30
  • 279
  • 274
7

Never add event listeners in HTML. Add them in your JavaScript, preferably in the same scope in which you define the event handler.

printAValue = () -> 
    test = new TestClass()
    test.printValue()

document.body.addEventListener('load', printAValue, false)

If you absolutely need to export something to the global scope, export to the window object:

window.printAValue = () -> 
    test = new TestClass()
    test.printValue()
katspaugh
  • 17,449
  • 11
  • 66
  • 103
  • Okay, thanks for solving that problem. But now I'm getting an issue where if I include multiple js files in my HTML, they aren't getting access to each others classes. Is that because they're all being defined in the some non-global scope, and that's where I'm looking for them? – DrPepper Aug 16 '11 at 17:50
  • 1
    Yes, they are all wrapped into a function. Create some global namespase object (`window.NS = {}`) and export your classes into that namespace (`NS.TestClasses = TestClasses`). The namespace will be accessible globally across files. – katspaugh Aug 16 '11 at 17:53
  • You can also replace `printAValue: ->` with `this.printAValue: ->` which is the same thing as `window.printAValue: ->` if you look at the thiss carefully. :-) – MarkovCh1 Aug 26 '11 at 00:04