Skip to content

Instantly share code, notes, and snippets.

@ryanflorence
Created September 9, 2012 01:06
Show Gist options
  • Save ryanflorence/3681784 to your computer and use it in GitHub Desktop.
Save ryanflorence/3681784 to your computer and use it in GitHub Desktop.
Base CoffeeScript Class, surprisingly useful.
################################################################################
# script: Base.coffee
# author: Ryan Florence <rpflorence@gmail.com>
# license: MIT-Style License
#
# A surprisingly useful base class for CoffeeScript. Inspired by my old
# friend, MooTools Class. Provides default options, mixins, and custom events.
class Base
defaults: {}
constructor: (options) ->
@setOptions options
setOptions: (options) ->
@options = merge {}, @defaults, options
this
on: (event, handler) ->
@_events ?= {}
(@_events[event] ?= []).push handler
this
off: (event, handler) ->
for suspect, index in @_events[event] when suspect is handler
@_events[event].splice index, 1
this
trigger: (event, args...) ->
return this unless @_events[event]?
handler.apply this, args for handler in @_events[event]
this
@include = (objects...) ->
merge @prototype, objects...
this
##
# private helper
merge = (target, extensions...) ->
for extension in extensions
for own property of extension
target[property] = extension[property]
target
################################################################################
# Amazing testing framework
testData = total: 0, passed: 0
equal = (val, expected, message) ->
testData.total++
if val is expected
testData.passed++
console.log "ok #{message}"
else
console.log "not ok #{message}, expected #{val} to equal #{expected}"
report = ->
{total, passed} = testData
percent = (passed / total * 100).toFixed()
status = if passed is total then 'ok' else 'not ok'
console.log "\n#{status} #{passed}/#{total}, #{percent}%"
################################################################################
# The test suite
mixin = foo: -> 'foo'
mixin2 = bar: -> 'bar'
class Sub extends Base
@include mixin, mixin2
defaults:
a: 1
b: 2
sub = new Sub b: 3, c: 4
equal sub.options.a, Sub::defaults.a,
'set default options'
equal sub.options.b, 3,
'override defaults with instance options'
equal sub.options.c, 4,
'add instance options'
equal sub.foo(), mixin.foo(),
'include objects'
equal sub.bar(), mixin2.bar(),
'include multiple objects'
triggered = false
x = null
y = null
that = null
handler = (a, b) ->
triggered = true
x = a
y = b
that = this
sub.on 'some event', handler
sub.trigger 'some event', 1, 2
equal triggered, true,
'triggered an event'
equal x, 1,
'sent first argument to event handler'
equal y, 2,
'sent second argument to event handler'
equal that, sub,
'set context of event handler to object'
x = 0
sub.off 'some event', handler
sub.trigger 'some event'
equal x, 0,
'removed event handler'
a = false
b = false
sub.on 'multiple', -> a = true
sub.on 'multiple', -> b = true
sub.trigger 'multiple'
equal a, true,
'triggered one handler'
equal b, true,
'triggered two handlers'
report()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment