coffeescript snippets

Firebugx.js for CoffeeScript

Tagged firebugx.js, coffeescript  Languages javascript
try
  window.console = window.console or {}
  names = [ 
    "log", "debug", "info", "warn", "error", "assert", "dir", 
    "dirxml", "group", "groupEnd", "time", "timeEnd", "count", 
    "trace", "profile", "profileEnd"
  ]
  nada = ->
  for name in names
    window.console[name] = window.console[name] or nada

Zombie.js + CoffeeScript example

Tagged coffeescript, zombie.js  Languages javascript
#
# Run:
# coffee -w test.coffee http://localhost:3000
#
# Installation:
#
# npm install coffee zombie
#
# Uses:
#
# Zombie
# http://zombie.labnotes.org/API
#
# CoffeeScript
# http://coffeescript.org/documentation/docs/command.html
#
# assert:
# http://nodejs.org/docs/v0.3.1/api/assert.html
#
Browser = require("zombie")
assert = require('assert')

class SignUpTest
  constructor: (@base_url) ->
    @url = @base_url + "/users/new"
    console.log @url
    this.run()
  run: ->
    browser = new Browser()
    browser.on "error", (error) ->
      console.error "Error: " + error
      #console.dir("Errors:", browser.errors)
    browser.visit @url, (error, browser) =>
      assert.ok browser.success
      rand = Math.floor(Math.random() * 10000)
      email = "jesus#{rand}@localhost"
      console.log email
      browser.fill('#input-email', email)
      browser.fill('#input-password', 'jes')
      browser.fill('#input-password-confirmation', 'jes')
      #console.log browser.html()
      browser.pressButton 'Sign up', ->
        assert.ok browser.success

url = process.argv[2] # e.g. http://localhost:3000
new SignUpTest(url)

ZeroClipboard example on how to use multiple copy buttons and load data through Ajax

Tagged zeroclipboard, coffeescript  Languages javascript
$ ->
  $('.copy-button').click (e) ->
    e.preventDefault()

  clip = new ZeroClipboard $('.copy-button'),
    moviePath: "/swf/ZeroClipboard.swf"

  clip.on 'mousedown', (client) ->
    link = $(this)
    $.ajax
      url: link.attr("href") + ".json"
      success: (content) ->
        console.debug('Copied to clipboard: ' + content)
        clip.setText content
      async: false

  clip.on 'complete', (client, args) ->
    link = $(this)
    link.find('.text').html('Copied…')

A Reusable JavaScript Modal Dialog Based on Bootstrap Modal

Tagged coffeescript, bootstrap, modal, javascript  Languages coffeescript

The Coffeescript class:

root = exports ? this

class Modal
  constructor: (options = {}) ->
    @options = options
    @id = options.id ? 'modal-dialog-' + Math.round((Math.random() * 1000))
    @dom_id = "##{@id}"
    @onPrimaryButton = options.onPrimaryButton ? ->
    @onSecondaryButton = options.onSecondaryButton ? ->
    @template = options.template ? HandlebarsTemplates['modal'](id: @id)
    @render()

  render: ->
    $('body').append(@template)
    @modal = $(@dom_id)
    _this = this
    @modal.find('.btn-primary').on 'click', ->
      _this.onPrimaryButton(this)
    @modal.find('.btn-secondary').on 'click', ->
      _this.onSecondaryButton(this)

  setButtonText: (primary, secondary) ->
    @modal.find('.btn-primary').html(primary)
    @modal.find('.btn-secondary').html(secondary)

  setTitle: (title) ->
    @modal.find('.title').html(title)

  setBody: (body) ->
    @modal.find('.body').html(body)

  show: ->
    @modal.modal('show')

  hide: ->
    @modal.modal('hide')

root.Modal = Modal

The view (bootstrap 2.3.2):

<div class="modal hide fade" id="{{id}}">
  <div class="modal-header">
    <button aria-hidden="true" class="close" data-dismiss="modal" type="button"> &times;</button>
    <h3 class="title"></h3>
  </div>
  <div class="modal-body body">
  </div>
  <div class="modal-footer">
    <button class="btn btn-secondary" data-dismiss="modal">Cancel</button>
    <button class="btn btn-primary" data-dismiss="modal">Ok</button>
  </div>
</div>

Usage, e.g.:

class Notifications
  constructor:  ->
    @modal = new Modal
      onPrimaryButton: $.proxy(@onItemDelete, this)
      onSecondaryButton: $.proxy(@onItemRead, this)
  onItemDelete: ->
    # do something when primary button was clicked
  onItemRead: ->
    # do something when secondary button was clicked

Getting Started With React.js and Rails

Tagged rails, coffeescript, components, react.js  Languages ruby

Why use React.js?

  • React ~35kb vs. Amber.js ~100kb
  • Easy to learn compared to Ember.js and Angular.js
  • Supports server-side rendering
  • Great performance
  • Angular.js documentation is horrible
  • Angular.js is the new EJB

Why shouldn't you use React.js?

  • React.js is difficult to integrate with JS libraries that move or create DOM elements, e.g. jQuery UI
  • React.js is still evolving. Expect API changes to break your app.

Installation

Gemfile:

gem 'active_model_serializers' # You probably want this gem too...
gem 'react-rails', '~> 1.0.0.pre', github: 'reactjs/react-rails'

From the console run:

bundle
rails g react:install

Make sure you have this in app/assets/javascript/application.js:

# ...
#= require react
# For the <div data-react-class...> syntax
#= require react_ujs
#= require_tree components

Add this to config/environments/production.rb

Rails.config.react.variant = :production

And this to config/environments/development.rb

Rails.config.react.variant = :development

Hello World

Create app/assets/javascripts/components/hello.jsx.coffee (note the file extension):

###* @jsx React.DOM ###

window.Hello = React.createClass
  render: ->
    <div>{this.props.name}</div>

app/views/layouts/application.html.erb

<html>
…
  <div data-react-class="Hello" data-react-props=<%= { name: 'John' }.to_json %>/>
or:
  <%= react_component 'Hello', name: 'John' %>
....
</html>

Troubleshooting

  • Unexpected token '<' Error

Did you forget to add this to the top of your React component file (.js.jsx)?

/** @jsx React.DOM */

or this to your CoffeeScript component (.jsx.coffee):

###* @jsx React.DOM ###
  • Target container is not a DOM element.

Does the DOM element exist?

Did you forget to call React.renderComponent in jQuery’s $(document).ready?

  • Adjacent XJS elements must be wrapped in an enclosing tag

Multiple nodes need a parent element:

<ul> // Doesn't work without <ul> wrapper
  <li></li>
  <li></li>
</ul>
  • Still doesn’t work?

react-rails is not stable; expect it to break.

Gotchas

Solutions: React.js Google Group React.js and jQuery sortable React.js and select2 React.js and Bootstrap Modal React.js and Kendo UI

  • You need to change the HTML "class" attribute to "className" in JSX

How to Use Rails I18n With JavaScript/CoffeeScript

Tagged rails, i18n, javascript, coffeescript  Languages javascript

Option 1: Include all translations

Your app/assets/javascripts/i18n.js.coffee.erb file:

root = exports ? this
I18n = <%= I18n.backend.send(:translations).to_json.html_safe %>
$ ->
  root.I18n = I18n[$('body').data('lang')]

Option 2: Include a limited set of translations

Your app/assets/javascripts/i18n.js.coffee.erb file:

root = exports ? this

I18n =
<%
I18n.available_locales.each do |lang|
  I18n.with_locale lang do
%>
  <%= lang %>:
    text: "<%= I18n.t("js.text") %>"
<%
  end
end
%>

$ ->
  root.I18n = I18n[$('body').data('lang')]

Include the Selected Locale in the Rails Layout

The view defines the user's selected locale:

<body data-lang="<%= I18n.locale %>">
...
</body>

How to Translate JavaScript Strings

We can now translate strings in a JavaScript file:

# remember to use $(document).ready...
alert(I18n.text)

CoffeeScript variable visibility

Tagged coffeescript  Languages coffeescript

This Coffeescript:

class Device
  x: 1 # Instance variable
  y = 2 # Private instance variable
  @z: 3 # Class variable

 # Address and name are instance variables
  constructor: (@address, @name) ->

gives us this JavaScript:

Device = (function() {
  var y;
  Device.prototype.x = 1;
  y = 2;
  function Device(address, name) {
    this.address = address;
    this.name = name;
  }
  return Device;
})();

and the following visibility:

dev = new Device('X', 'Y') # => Device {address: "X", name: "Y", x: 1}
dev.y # => undefined
Device.z # => 3