Unable to modify Coffeescript's global variables in a JQuery listener - coffeescript

Today I was migrating some of my javascript code into coffeescript and got stuck in something really silly but even though I didn't know how to make it work.
I wanted to update the value of a global variable when a click event was triggered, have a look at the code below to see one of my guesses
Here's the code
#activeObject = null
# Some other code
$ ->
$('#header').click ->
if !headerSelected
showMenu '#header-menu', event
else
#activeObject = "#header"
showMenu '#menu-style-header', event
Unfortunately even though the click event was triggered the variable was not getting updated.
I came up with a work around. I created a function that set the value of the variable and called it instead of the assignment and this time it worked.
I just wanted to know why I wasn't able to do it the other way. For me it was a simple operation and it seemed silly to define a new function just for this.

Your problem is that # (AKA this) inside the click handler isn't the same as it is outside so this:
#activeObject = null
and this:
#activeObject = "#header"
are referring to two different activeObjects. You should be able to bind everything with => to get the right this:
$ =>
$('#header').click =>
#...
or better (IMHO), just refer to window.activeObject directly in both places so that it is obvious to everyone that you're referring to a global variable:
window.activeObject = null
$ ->
$('#header').click ->
if !headerSelected
showMenu '#header-menu', event
else
window.activeObject = "#header"
showMenu '#menu-style-header', event
Alternatively, you could stop using globals altogether in favor of, perhaps, a data attribute:
$ ->
$('#header').data 'activeObject', null
$('#header').click ->
if !headerSelected
showMenu '#header-menu', event
else
$(#).data 'activeObject', '#header'
showMenu '#menu-style-header', event

I think the confusion is about the usage of #, which is basically just a shortcut for this.
If you compile your code and see what CoffeeScript compiler it produces, the confusion becomes clear
this.activeObject = null;
$(function() {
return $('#header').click(function() {
if (!headerSelected) {
return showMenu('#header-menu', event);
} else {
this.activeObject = "#header";
return showMenu('#menu-style-header', event);
}
});
});
if activeObject is global you whould reference to it
window.activeObject = null
and
window.activeObject = "#header";
in both occurences in this code, cause one might be tempted to use it without window in second occurence, but that will cause a new local variable to be implecitly defined.
Generally when starting with CoffeeScript, its usefull to try small snipets like this in
http://coffeescript.org/ on the Try Now Tab

Related

Working with Scala Option

I have been changing a lot of my Scala code recently to avoid instantiating variables with null and instead using Option. For example, I previously had:
var cxn: RepositoryConnection = null
cxn = repo.getConnection()
//do something with the connection, then close it
cxn.close()
Now, my code looks more like this.
var cxn = None : Option[RepositoryConnection]
cxn = Some(repo.getConnection())
//do something with the connection, then close it
Now the problem I have is when I want to call a method associated with the RepositoryConnection type. I try:
cxn.close()
and see this error:
value close is not a member of Option[org.openrdf.repository.RepositoryConnection]
Now, when I was using null, this operation worked just fine, because cxn was a RepositoryConnection object, not an Option[RepositoryConnection]. Is there an easy way to call the close() method now that I am using Option?
You have a few options. (Sorry about the pun.) The most straight forward is probably...
cxn.map(_.close())
But perhaps you need to do something else if cxn is None. Then you could do something like...
cxn.fold(logger.reportStatus())(_.close())
Since your variable is Option[Something], you can not call instanceOfSomethingOpt.methodOfInstance()
Instead do instanceOfSomethingOpt.map(realInstance => realInstance.methodOfInstance())
In your case, it'd be
cxn.map(realConnection => realConnection.close())
//or to make it shorter
cxn.map(_.close())
You should really give a look at Option api.
cxn.map(_.close())
is one way, in case close() returns something you might beed.
cxn.foreach(_.close())
is another way, if close() is not doing much (side-effect).
val cxn = Some(repo.getConnection())
for (c <- cxn) yield {
//do something with the connection
c.close()
}
Alternatively you can wrap the getConnection with Either or Try depending on how you want to handle errors see http://blog.xebia.com/try-option-or-either/

Is there a way to "watch" a variable in google chrome?

Basically, I want to add a breakpoint every time a given closure variable is changed. Is there any way to do this?
I don't think there's currently a way to directly watch variables, but if you can put the closure variable in an object, then you can use Object.observe() to observe that object for changes. (Object.observe can only observe objects)
This requires you to have Experimental Javascript enabled - chrome://flags/#enable-javascript-harmony.
(function(){
var holder = {
watchedVariable: "something"
};
Object.observe(holder, function (changes) {
// returns an array of objects(changes)
if ( changes[0].name === "watchedVariable" ) {
debugger;
}
});
})()

Coffeescript translation

If I have this javascript:
function I_did_something(){
this.test.assertExists('#selector', 'exists');
}
casper.then(I_did_something);
The problem is that casper is using call to call the then method meaning that I cannot do something like this:
#I_did_something = ->
#assertExists('#selector', 'exists')
casper.then #I_did_something
Because this does not refer to the global object.
Can anyone suggest how I would translate this into coffeescript without using the window object preferably?
You can use a fat arrow (=>) to bind the function to the current this:
#I_did_something = =>
#assertExists('#selector', 'exists')
That has a similar effect to:
that = #
#I_did_something = ->
that.assertExists('#selector', 'exists')
and I think that's what you're after.

Coffeescript and markup based JS execution

From another thread here I found this great tutorial on markup based JS execution
Garber-Irish solution:
http://www.viget.com/inspire/extending-paul-irishs-comprehensive-dom-ready-execution/.
I'm checking out how I can do parts of this in Coffeescript.
This works OK:
SITENAME.surveys.show = ->
alert "Hello CoffeeScript"
Which renders out:
SITENAME.surveys.show = function() {
return alert("Hello CoffeeScript");
};
This one is not so happy:
SITENAME.surveys.new = ->
alert "Hello CoffeeScript"
SITENAME.surveys["new"] = function() {
return alert("Hello CoffeeScript");
};
I'm new to Coffeescript and doing a codeschool.com course on it now.
I guess the "new" keyword is special for coffeescript.
Is there any workaround for this?
Thanks!
new is special in JavaScript and CoffeeScript is aware of this so it's emitting code that will actually work even though it's bad practice to name methods using reserved keywords.
If you need to use new, you can use [] to define the function:
SITENAME.surveys['new'] = ->
alert "Hello CoffeeScript"
and to call it:
SITENAME.surveys['new']()
Demo: http://jsfiddle.net/ambiguous/Y3qnt/
A quick review of your link suggests that you'll be accessing the function with something like:
controller = 'surveys'
action = 'new'
SITENAME[controller][action]()
So it doesn't matter what the methods are called as you'll always be referring to them by their (string) name anyway.

; expected but <place your favourite keyword here> found

I'm trying to write a class for a scala project and I get this error in multiple places with keywords such as class, def, while.
It happens in places like this:
var continue = true
while (continue) {
[..]
}
And I'm sure the error is not there since when I isolate that code in another class it doesn't give me any error.
Could you please give me a rule of thumb for such errors? Where should I find them? are there some common syntactic errors elsewhere when this happens?
It sounds like you're using reserved keywords as variable names. "Continue", for instance, is a Java keyword.
You probably don't have parentheses or braces matched somewhere, and the compiler can't tell until it hits a structure that looks like the one you showed.
The other possibility is that Scala sometimes has trouble distinguishing between the end of a statement with a new one on the next line, and a multi-line statement. In that case, just drop the ; at the end of the first line and see if the compiler's happy. (This doesn't seem like it fits your case, as Scala should be able to tell that nothing should come after true, and that you're done assigning a variable.)
Can you let us know what this code is inside? Scala expects "expressions" i.e. things that resolve to a particular value/type. In the case of "var continue = true", this does not evaluate to a value, so it cannot be at the end of an expression (i.e. inside an if-expression or match-expression or function block).
i.e.
def foo() = {
var continue = true
while (continue) {
[..]
}
}
This is a problem, as the function block is an expression and needs to have an (ignored?) return value, i.e.
def foo() = {
var continue = true
while (continue) {
[..]
}
()
}
() => a value representing the "Unit" type.
I get this error when I forget to put an = sign after a function definition:
def function(val: String):Boolean {
// Some stuff
}