Search code examples
javascriptruby-on-railsrubycoffeescript

Coffeescript - How to convert a javascript into coffeescript in ruby on rails?


I have a button in my views in test.html.erb as follows

<button  id="Todo_full" onclick="showFullscreen(this);">Full size</button>

and its javascript is as follows:

    function showFullscreen(event)
    {
    var elem = document.getElementById('card_' + event.id);

        if (elem.requestFullscreen) {
        return elem.requestFullscreen();
        }
        else if (elem.mozRequestFullScreen) 
        {

        /* Firefox */
        return elem.mozRequestFullScreen();
        }
    } 

When I keep the javascript code at the below of the test.html.erb file it works fine. And when I convert this code into coffeescript through http://js2.coffee/ and keep the code in app/assets/javascript/test.coffee which is as follows:

showFullscreen = (event) ->
  elem = document.getElementById('card_' + event.id)
  if elem.requestFullscreen
    return elem.requestFullscreen()
  else if elem.mozRequestFullScreen

    ### Firefox ###

    return elem.mozRequestFullScreen()
  return

It shows an error in console

Uncaught ReferenceError: showFullscreen is not defined
    at HTMLButtonElement.onclick ((index):384)

Even when I use window.onload = -> at the top of coffeescript's code I get the same error in console.

Thank you


Solution

  • The issue you're running into is the different scoping between JS and CoffeeScript. To get your code working, you need to scope your function globally on window or the CoffeeScript shorthand @.

    From the CoffeeScript docs:

    If you’d like to create top-level variables for other scripts to use, attach them as properties on window.

    Which for your function would look like:

    # Using window
    window.showFullscreen = (event) ->
      elem = document.getElementById('card_' + event.id)
      ...
    
    # Or using @
    @showFullscreen = (event) ->
      elem = document.getElementById('card_' + event.id)
      ...
    

    The CoffeeScript @ is shorthand for this in JavaScript. So, in your example, because you're defining the function at the top level window scope window == @. Keep in mind that within your functions the scope will be different and window != @, and instead @ will be scoped to whatever this is inside of your function. This blog post has a nice explanation:

    Speaking of this, CoffeeScript has a shortcut for it, the @ symbol. It's easy to write this off as meaningless syntactical sugar, but it is useful. First, constructor parameters prefixed with @ are converted into properties:

     # CoffeeScript
     class User
       constructor: (@id) ->
    
     // JavaScript
     function User(id) {
       this.id = id;
     }
    

    Beyond this though, it's a nice way to define class method:

     # CoffeeScript
     class User
       constructor: (@id) ->
    
        @findById: (id) =>
        ...
    
     // JavaScript
     function User(id) {
       this.id = id;
      }
     User.findById = function() {};
    

    Neither @ nor the fat arrow => mean that you don't have to worry about the current meaning of this (or its alias @). They aren't silver bullets, which isn't to say that they don't add value.