Brigand
Brigand

Reputation: 86230

How do I create a jQuery plugin in CoffeeScript?

On How to Create a Basic Plugin there is a section titled Protecting the $ Alias and Adding Scope.

The $ variable is very popular among JavaScript libraries, and if you're using another library with jQuery, you will have to make jQuery not use the $ with jQuery.noConflict(). However, this will break our plugin since it is written with the assumption that $ is an alias to the jQuery function. To work well with other plugins, and still use the jQuery $ alias, we need to put all of our code inside of an Immediately Invoked Function Expression, and then pass the function jQuery, and name the parameter $:

In JavaScript, this wrapper looks like this:

(function ( $ ) {
  // do stuff
  return this;
})(jQuery)

How can this be translated into CoffeeScript?

Upvotes: 1

Views: 105

Answers (2)

hpaulj
hpaulj

Reputation: 231385

This coffeescript:

$ = jQuery
### do stuff ###

compiles to:

// Generated by CoffeeScript 1.6.3
(function() {
  var $;
  $ = jQuery;
  /* do stuff*/
}).call(this);

I think the effect is the same, ensuring that $ points to jQuery regardless of what $ is in the calling environment.

This is what the author of Coffeescript recommends in Writing a jquery plugin in coffeescript - how to get "(function($)" and "(jQuery)"?

To get closer to the original pattern (do is still something of a blackbox to me)

do ($=jQuery) ->
  ### do stuff  ###
  @

'bare' compiles to:

// Generated by CoffeeScript 1.6.3
(function($) {
  /* do stuff*/

  return this;
})(jQuery);

Upvotes: 2

Brigand
Brigand

Reputation: 86230

At first it's non-obvious. Here's the skeleton.

$.fn.ourFunction = do ($=jQuery) -> (opts) ->
  # do stuff
  @

It compiles to this:

$.fn.ourFunction = (function($) {
  return function(opts) {
    return this;
  };
})(jQuery);

We could also split this into several lines for clarity.

$.fn.ourFunction = do ($=jQuery) ->
  (opts) ->
    # do stuff
    @

Our first line uses the do syntax, which runs a function initially. We can also specify parameters (e.g. $), and their values (e.g. jQuery).

$.fn.ourFunction = do ($=jQuery) -> 

Our second line creates a function, which is returned. Remember, everything in CoffeeScript is an expression, so we don't need to say return (opts) -> (but you can).

(opts) ->

Then, there's of course the body of our code, where the actual work happens. One trick that I left out of the initial code is to use the => operator to maintain scope. Inside our scroll handler, we can force this to remain our targeted object. We could call $('#something').ourFunction() and we effectively call $('#something').something() in our scroll handler.

$.fn.ourFunction = do ($=jQuery) ->
  (opts) ->
    $(window).scroll =>
      this.something()
      @something()
    @

Our last line is simply the @ character. This allows chaining, because we're returning this. Alternatively, if our last line calls another chainable method on this, we don't need to make it explicit.

$.fn.flash = do ($=jQuery) -> (opts) ->
  @animate(opacity: 0).delay()
   .animate({opacity: 1})

Upvotes: 1

Related Questions