4

If I want to share some JavaScript function between different files under app/assets/javascript what would be the best way to I organise the directory structure?

Let's say I have shared.js.coffee

sharedFunction = ->
  'Hello '

Now, how can I use it in some other place? Like here, in welcome.js.coffee

welcome = (name) ->
  sharedFunction() + name

How can I make shared.js.cofee always be loaded first?

I tried to put it in the very beginning of application.js, but it doesn't change anything. Seems shared file loading too long, and welcome manages to start executing and notice that sharedFunction is not defined.

Misha Slyusarev
  • 1,353
  • 2
  • 18
  • 45

4 Answers4

7

I do it in this way:

  • Ensure you require the file in application.js before anything else, expecially before require_tree
  • Export the functions (in my case a class, so it's namespaced)

Example: (Suppose we have application.js and shared.js.coffee at same level)

application.js

//= require ./shared
//= require_tree .

shared.js.coffee

class MyNamespace
  @mySharedFunc: () ->
    doSomething()

root             = exports ? this
root.MyNamespace = MyNamespace

You can now easily access in your other coffeescript files the function by referencing it in this way MyNamespace.mySharedFunc()

P.S.

The misterious thing about exports is explained very well in this stackoverflow question: How do I define global variables in CoffeeScript?

Community
  • 1
  • 1
Francesco Belladonna
  • 11,361
  • 12
  • 77
  • 147
  • what the last two lines do exactly? I just on studying Coffee namespaces and saw the following way of defining a namespace *window.MyNamespace = {}*. Is that the same thing here? – Misha Slyusarev Dec 13 '13 at 09:53
  • As I typed in the **P.S.**, read this link: http://stackoverflow.com/questions/4214731/coffeescript-global-variables – Francesco Belladonna Dec 13 '13 at 11:41
5

In application.js, load shared first:

//= require shared
//rest of code

and in shared, if its that necessary, make your variable accessible globally:

@sharedFunction = ->
  'Hello '

Notice its a bad practice too have such global variables, at least try to keep them in namespaces.

apneadiving
  • 114,565
  • 26
  • 219
  • 213
  • That global variable tag made the trick! So it seems for me that each js.coffee file comes separated from the others. Put sharedFunction into a regular .js file also works. I'm confused. – Misha Slyusarev Dec 13 '13 at 09:04
  • yes, its the basics of coffeescript, each file is wrapped in a function. You have to explictly tell what should be accessible globally – apneadiving Dec 13 '13 at 09:12
  • 1
    can I make use of sharedFunction out of this wrapper function without making it global variable? – Misha Slyusarev Dec 13 '13 at 09:15
  • using //require could do the trick, but having a tooolset within a global namespace is ok – apneadiving Dec 13 '13 at 09:21
0

Basically functions loaded earlier can be used later. But in this case the reason your function not working is very simple: You forget to execute it.

Simply replace

sharedFunction + name

With

sharedFunction() + name

And it's done.

Billy Chan
  • 24,625
  • 4
  • 52
  • 68
-1

Best would be to only ever include one JS file. You can split it between different assets if your asset pipeline knows how to paste them together, but it is inferior to send different JavaScript to different pages. It seems counterintuitive to send a bigger file, especially for every page, but caching turns this on its head: your JS file should only be loaded once. This also automatically means you will have access to all your functions from any of your pages.

Amadan
  • 191,408
  • 23
  • 240
  • 301