I found this example of mixins in coffeescript faq but it seems like it doesn't work.
Am I missing something here?
extend = (obj, mixin) ->
for name, method of mixin
obj[name] = method
include = (klass, mixin) ->
extend klass.prototype, mixin
class Button
onClick: -> alert "click"
class Events
include Button, Events
(new Events).onClick()
# => Uncaught TypeError: Object #<Events> has no method 'onClick'
fiddle
You are missing the fact that onClick is defined on the prototype of Button,
and that you did not set the arguments with the right order in the include function
extend = (obj, mixin) ->
for name, method of mixin
obj[name] = method
include = (klass, mixin) ->
extend klass.prototype, mixin
class Button
onClick: -> alert "click"
class Events
include Events,Button.prototype
(new Events).onClick()
see the "fiddle"
So the mixin snippet works pretty well.
Related
I can't find a way to create custom events with scala-js. For instance, with js you can create a custom event like the following (taken from here):
var event = new CustomEvent('build', { 'detail': elem.dataset.time });
However, there is no constructor for CustomerEvent or Event in scala-js that accept arguments. Also, subclassing either such as:
class DrawEvent extends Event {
override def `type` = "draw"
}
leads to
Uncaught TypeError: undefined is not a function
when trying to construct via new DrawEvent()
Any ideas?
To instantiate javascript classes in ScalaJs you have to use js.Dynamic.newInstance:
This should work for your use case:
val event = js.Dynamic.newInstance(js.Dynamic.global.CustomEvent)("build", js.Dynamic.literal(detail = elem.dataset.time)).asInstanceOf[js.dom.CustomEvent]
There is more info available at the remarks portion (all the way at the bottom) of:
http://www.scala-js.org/doc/calling-javascript.html
Here is the same solution using some imports to make it shorter
import js.Dynamic.{ global => g, newInstance => jsnew, literal => lit }
val event = jsnew(g.CustomEvent)("build", lit(detail = elem.dataset.time)).asInstanceOf[js.dom.CustomEvent]
If you want to stay in the typed DOM (assuming you are talking about the scala-js-dom library), you can do:
new CustomEvent().initCustomEvent('build', false, false, elem.dataset.time)
The constructor you are using is actually only specified in DOM 4 (see MDN).
I have a "class" in coffee script whose instance variables I want to initialize with instance methods that return a value via a callback, but it doesn't work as I had hoped:
EventEmitter = require('events').EventEmitter
class MyClass extends EventEmitter
constructor: ->
#datamember: setDatamember()
setDatamember: ->
someFunction (response) ->
#datamember = response
#emit 'init'
getDatamember: ->
return #datamember
----
myObj = new MyClass
myObj.on 'init', ->
console.log myObj.getDatamember
The result I get suggests that "this" in setDatamember is referring to something different from what "this" refers to in the object instance. If I explicitly call myObj.setDatamember, I get the expected result, but is there any way to call on a set method -- specifically one that sets the data member via a callback -- in the constructor? I've looked through the docs, as well as various other sources of coffeescript info (e.g. this one), and I haven't found anything that touches upon this.
Try using a fat arrow for the anonymous function:
setDatamember: ->
someFunction (response) =>
#datamember = response
#emit 'init'
Also, you'll need to call the correct function in the constructor:
constructor: ->
#setDatamember()
In general, avoid fat arrows on methods - the way Coffee-Script implements this does some bad things to memory usage. Also, it will rarely be necessary.
However, anonymous functions that refer to this will almost always need fat arrows. this is not held in closure like normal variables, and will only be set by binding (Function.prototype.bind) or by calling it as an object method (obj.myMethod() will set this to obj in myMethod).
Try using fat arrows on everything except the constructor:
class MyClass
constructor: ->
#setDatamember()
setDatamember: =>
someFunction (response) =>
#datamember = response
getDatamember: =>
return #datamember
However, you also look to have someFunction in there as an asynchronous function, so you'll never be able to just do
mc = new MyClass
console.log mc.datamember
Because that doesn't wait for someFunction to return before accessing mc.datamember.
I am using Coffeescript and I'm testing using Sinon.js. When testing a method that invokes the method it overwrites, how can I stub the call to super()?
E.g., the method I want to test (a backbone.js model):
class Whatever extends Model
validate: (attributes) ->
validationErrors = super(attributes)
...
validationErrors
In the example, I want to make sure that super() is invoked with the given attributes and that validate returns the validation errors super() returns.
Like this:
it 'calls super and returns its result', ->
whatever = new Whatever()
attributes = sinon.stub()
superValidateStub = sinon.mock(Whatever.__super__)
superValidateStub.expects('validate').withExactArgs(attributes).returns('VALIDATION_RESULT')
expect(whatever.validate(attributes)).to.eql('VALIDATION_RESULT')
superValidateStub.verify()
Hope this helps anyone.
Hi I'm new to Js and Coffeescript, here's a situation I feel difficult to refer the property of parent object which is App in the following example
App =
init: ->
this.foo = 'bar'
this.bindEvent()
bindEvent: ->
$('#test').click(this.show)
show: ->
alert this.foo
App.init()
I think the fat arrow may do the trick but once I've changed to show: =>, this in the context of show method refers to the window object, instead of App object that I want to
. Anybody can tell me how to do it right?
http://jsfiddle.net/kZpHX/
When you define your show function, # (AKA this) actually is window so
show: => console.log(#)
will bind show to window. The problem is that you're simply defining an object so there isn't anything to bind to: you aren't defining a class so this is window. You could refer to App explicitly like this:
App =
#...
show: -> alert(App.foo)
Demo: http://jsfiddle.net/ambiguous/3sRVh/
The this.foo in init will do the right thing because saying App.init() sets up the expected this.
You could also hook up the desired this manually:
bindEvent: ->
$('#test').click => #show()
# or
bindEvent: ->
_this = # # JavaScript style
$('#test').click -> _this.show()
Demos: http://jsfiddle.net/ambiguous/byL45/, http://jsfiddle.net/ambiguous/MT8fG/
Or you could create a class for your App instead:
class App
constructor: ->
#foo = 'bar'
#bindEvent()
bindEvent: ->
$('#test').click(#show)
show: =>
console.log(#foo)
new App
That way your show: => will behave the way you expect it to.
Demo: http://jsfiddle.net/ambiguous/byatH/
Say I'm declaring a class Game.
class #Game
constructor: ->
#id = Game.generateNewGameId() # <---
player1: null
player2: null
#generateNewGameId: -> "blahblah23"
Here, I'm using generateNewGameId as Game.generateNewGameId().
Is this the right way or is there a better way? I've tried using this::generateNewGameId() but the scope's different.
If you really want generateNewGameId to be a class method then you can use #constructor to get at it:
Returns a reference to the Object function that created the instance's prototype. Note that the value of this property is a reference to the function itself [...]
So something like this:
class Game
constructor: ->
#id = #constructor.generateNewGameId()
#generateNewGameId: ->
"blahblah23"
Note that this will do The Right Thing if you subclass Game:
class C extends Game # With an override of the class method
#generateNewGameId: ->
'pancakes'
class C2 extends Game # or without
Demo (open your console please): http://jsfiddle.net/ambiguous/Vz2SE/
I think the way you are accessing it is OK. You can also do #constructor.generateNewGameId() if you don't want to write Game.generateNewGameId() for some reason, but i'd prefer the later. Update: as #mu is too short mentions, the #constructor allows you to get the constructor of the instance, which can be differ from Game (in a subclass) so it has greater flexibility; if that flexibility is required in this case, definitely go for that :)
If the generateNewGameId function will not be accessed from outside the Game class, you can use a private function instead of a class method:
class #Game
gameIdCounter = 0
generateNewGameId = -> gameIdCounter++
constructor: ->
#id = generateNewGameId()
player1: null
player2: null
console.log (new Game).id # -> 0
console.log (new Game).id # -> 1
Example at coffeescript.org.
There both gameIdCounter and generateNewGameId are private variables inside the Game class.