I am trying to do what seems like it should be simple, but for some reason is eluding me. I want to add a click event to a link in my tasks.js file like so:
$ ->
$('.cancel_task').click ->
$('#task_form').toggle
This renders out as:
(function() {
$(function() {
return $('.cancel_task').click(function() {
return $('#task_form').toggle;
});
});
}).call(this);
All I want is something like:
$('.cancel_task').click(function()
{
$('#task_form').toggle();
});
How do i accomplish this with coffescript and the rails 3.1 stack?
Coffee is supposed to wrap everything you do in a limited scope so you don't populate the world with globals. This is useful, unless you have, don't ignore this. At the top level, you can export with a this.something = "value".
Now your code above doesn't work because function calls need a paren when there are no parameters. This will make the two snip-its functionally the same. Functions are variables in JavaScript, so it just assumes you want to return that function instead of it's result without the parens.
$ ->
$('.cancel_task').click ->
$('#task_form').toggle()
Lastly, a Coffee function always returns the last value of the function. It's just how it works. So don't worry about the return statements, you can always ignore the results.
The second snippet you posted is the correct output from coffee, and the second and last snippets you posted are (in practical terms) functionally equivalent. If you want you can get rid of the top-level closure by using coffee's --bare option (this is documented) but otherwise you should not fret about CoffeeScript's output unless it's causing you problems.
Related
I need to identify the start and end of function definitions (blocks) in Javascript source code, using PHP. I don't need to parse the code, just literally know where the beginning and end of the Javascript code is if I've read it into a PHP string (using file_get_contents() for example, or some other way).
I need to only identify functions defined at the highest level within the global scope of the Javascript code, and also functions defined at that level for JQuery event callbacks, but I need to ignore more embedded functions in the code.
So, e.g.
function my_JS_func()
{
// some code
}
and
$('#button').onclick(click(function(e){
// some code
});
but I need to ignore the $.post callback function in here (but I would pick up func2 as a whole):
function func2()
{
$.post('myURL', {data: mydata}, function(data){
// ignore me
}
}
Obviously I need to identify the text: "function" (unless it's in a string literal for some reason) and I'm assuming I need to keep track of curly braces {} but otherwise, any ideas welcomed!
Many thanks for any suggestions! (Happy to use a PHP lib, 3rd party software or whatever)
I have ignored javascript forever. I started using jQuery a few years back so I could get by. But as I've started doing TDD more I decided yesterday to really dive into javascript (and possibly coffeescript after that).
In my ASP.NET Web Forms application I have many pages and currently most of those pages do not have a ton of javascript. I'm in the process of changing that. I'm using Jasmine with Chutzpah to create my tests.
I was moving along with my tests passing and failing as expected. But then I wanted to create a namespace so I wouldn't be trampling all over global space.
After reading this article:
http://enterprisejquery.com/2010/10/how-good-c-habits-can-encourage-bad-javascript-habits-part-1/
I decided to try and use the pattern from the Self-Executing Anonymous Function: Part 2 (Public & Private) section of the article. It appears to have the most flexibility and appears to encapsulate things very well.
I have a folder called /Scripts. Under that folder are some of the frameworks I'm using like jQuery, jasmine, (twitter) bootstrap and modernizr. I also have a subfolder called /Site where I am putting my code for the site in multiple files based on the page. (product.js, billing.js, etc.)
Under /Scripts/Site I added a subfolder to /Tests (or Specs) that have the files (product_test.js, billing_tests.js, etc.).
Without having namespaces everything is fine. I have a utility.js file I created with a padLeft helper function. I then used that global padLeft in another .js file. My tests all worked and I was happy. I then decided to figure out the namespace and changed my Scripts/Site/utility.js to look like:
(function (myns, $, undefined) {
//private property
var isSomething = true;
//public property
myns.something = "something";
//public method
myns.padLeft = function (str, len, pad) {
str = Array(len + 1 - str.length).join(pad) + str;
return str;
};
//check to see if myns exists in global space
//if not, assign it a new Object Literal
}(window.myns= window.myns|| {}, jQuery ));
Then in my Scripts/Site/Tests/utility_test.js I have
/// <reference path="../utility.js" />
describe("Namespace myns with public property something", function () {
it("Should Equal 'something'", function () {
expect(myns.something).toEqual('something');
});
});
With this extremely simple test I was expecting myns.something to come back with the string value of 'something'.
It doesn't. It comes back undefined.
So, how do I to use javascript namespace across multiple files?
Sorry for the long introduction, but I figured it may help explain the why of me doing it this way. I also put all of this because I'm open to hearing ideas about how this setup is totally wrong or partially wrong or whatever.
Thanks for taking the time to read this question.
UPDATE: SOLVED
Thank you all for your help. The most help came from the commenter #T.J. Crowder. I didn't know the jsbin tool existed and after being convinced that the code I put above was put into the tool and the results were right I knew something had to be off in my environment.
The link in the accepted answer also helped me out a lot. After seeing that the syntax and logic was consistent and working I just had to determine what was off about my setup. I'm embarrassed to say it was me passing in jQuery but in my test harness where I was trying to get this to work I wasn't actually using jQuery. This meant the module wasn't actually being loaded - so myns was never set.
Thanks everyone. Hopefully this may be helpful to someone in the future. If you use the above make sure you include the jQuery object. The other option is to not pass in jQuery and remove the $ from the param list.
Try putting your name space declaration outside of the function call:
myns = window.myns || {};
(function(myns, $, undefined) {
...
}(myns, jQuery));
Your existing syntax appears to be completely valid, but breaking that line out may help figure out what's going wrong with your variable scope.
Javascript does not have namespaces, i guess you have troubles with variable scopes and this is similar to other languages, what you are talking about are objects. You could use
window.myns.something
The first function is already adding your object to the window object, and the window object is accessible from anywhere.
Coffeescript gives the freedom to set or omit parentheses for functions calls. Like
alert 'Hi folks'
alert ('Hi folks')
are equal.
Now I am wondering, probably due to insufficient experience with coffeescript, its syntax and its aim to keep things simple, if it possible to add parentheses for a statement like the following. I know they aren't necessary.
define (require) ->
return 'goodbye'
Edit: If I apply the option to set parentheses in the same manner as for the alert statement, than I would assume this syntax shouldn't make any difference to the final js.
define ((require) ->
return 'goodbye'
)
define (require) ->
return 'goodbye'
would be equivalent to the JavaScript code
define(function(require) { return 'goodbye' })
That is, a function call to define with a function as its first (and only) argument. It is probably not what you expected the snippet to do when you asked your question.
Something I found very helpful when I played around with CoffeeScript was to try things out in the on-line "try CoffeeScript" dialogue on the CoffeeScript website. This allows you to see the JavaScript that a given snippet is compiled to, and immediately see what effect e.g. adding parentheses or changing indentation has on the resulting JavaScript code. I definitely recommend doing that. :-)
Edit to reflect the edit in the question:
Yes, adding parentheses around the function ((require) -> return 'goodbye') is valid, and doesn't alter the behaviour. Note however that "foo (bar)" and "foo(bar)" is parsed differently by the parser; in the former the parenthes denote precedence (priority, "regular parentheses"), and in the latter they are function invocation parentheses.
"foo bar", "foo(bar)", "foo (bar)" all do the same thing, but whereas "foo bar, baz" and "foo(bar, baz)" work fine, "foo (bar, baz)" is a syntax error.
Yes, you can wrap an anonymous function in parentheses.
I ran this simple script.
test.coffee
define = (func) -> func()
console.log define ((require) ->
return 'goodbye'
)
output:
goodbye
I am trying to understand how to "chain" JavaScript events together like jQuery does. I found a question here on S.O. that was similar to my goal, but I do not understand the code in the answer.
Code Source
(function( window, undefined ) {
...etc...
}(window)
What does that mean? What is it doing? It reminds me of Jquery's $(document).ready(){} function, but I don't know why this person wrapped his code in this anonymous function that passes window and undefined.
My ultimate goal is to figure out how to execute methods on an object by chaining methods together like jQuery. I know that jQuery already does this but I am looking into this primarily for growth as a developer.
It defines a function (using a function operator as opposed to a function statement). The parenthesis around it ensure that it is treated as the operator rather than the statement.
It then executes it immediately, passing window as an argument.
Essentially, this is the same as:
var myFunction = function( window, undefined ) {
...etc...
};
myFunction(window);
… but without the interstitial variable.
This has nothing to do with jQuery style function chaining, where each method effectively ends with return this (so calling a method on the return value of another method is the same as calling it on the original object).
When a function is called with fewer arguments than its signature contains, the trailing arguments are assigned the value undefined.
So the above is a roundabout way of getting hold of the undefined value even if some lunatic has redefined it by saying var undefined= 'hello';. (This is illegal anyway in ECMAScript Fifth Edition's ‘strict mode’, but JavaScript coders do some weird things sometimes.)
There isn't really a good reason for passing in window like this though... the traditional way to get window if you can't rely on window is to call a function directly and use this.
Either way, this is simply defensive coding against pathological author JavaScript. It's not something you should worry about whilst writing your own code (in any case there's no way you can stop every way someone might mess up their JS environment), and it's nothing to do with chaining.
Pouring over the release notes regarding jQuery 1.4, I came acrosss $.noop() which is:
Description: An empty function. (added in 1.4)
You can use this empty function when you wish to pass around a function that will do nothing.
Perhaps I'm missing something profound here, but what exactly is a practical use of passing around an empty function?
Code examples appreciated.
This function was proposed due to performance issues on embedded systems when using $.ajax, reported on the jQuery-Dev mailing list. You can see the thread.
Basically, they preferred to introduce and use this single empty function, rather than declaring empty anonymous functions all around.
Now this function is internally used in the ajax, event and offset modules.
You can give a look to the commit when it was introduced also.
If you have a function that accepts a function as a parameter, and you don't have any code to give it, you can pass $.noop.
I can't think of any such cases in jQuery where the parameter isn't optional in the first place, though.
Unlike writing function(){}, passing $.noop will not create a new function instance, saving a bit of memory. However, if whatever you're passing it to modifies the function object (eg, funcParam.id = 2), passing $.noop will mess things up.
Real World Example (well almost):
jQuery.fn.myAwesomeAjax = function(url, complete) {
return jQuery.ajax(url || this.url)
.complete(complete || jQuery.noop);
};
Use it instead of function (){}
Probably if some bad API requires a function as a parameter, and you don't want to do anything in it, this would be a framework-supported way of making that obvious.
I use a couple of plugins which require callbacks, but for some parts I don't actually want to use a certain callback. So, I put in function() {}.
noop is defined in the jQuery source as
noop: function() {}
so it will fit anywhere you'd use a blank function, such as the above example.
The only logical reason is if you're calling a function that does something AND calls another function, and you want the higher-level function to do its thing without calling a parameter function.
Most of the jQuery functions optionally take a parameter function, so you don't have to pass one in. Maybe there's one or two where that's not the case -- or maybe it's to assist developers with their custom code that behaves like this.
If a function requires you pass a function as an argument maybe? It's shorter to say do_something($.noop) than do_something(function(){}).
Although not by much...
...6 characters...
...yeah, that feature looks quite useless actually.
It can be useful if you have a function that supplies functions to other functions.
Example: You have a List of data. Each item has a Button that does something. The "something" can be different for every item. You have a "FunctionFactory" that takes in the item and returns a function. If you don't want the button to do something for whatever reason, then the cleanest way could be to return an empty function, as that way you know that your Factory ALWAYS returns a function.
I don't have a concrete example for jQuery, but I guess this could come in handy when used in an .each or .map block.
It's purely a convenience/replacement for function(){} in the context of where callbacks are required - I don't think I'll be using it anytime soon.
I bet the jQuery team had quite a laugh when they dropped it in though, also serves a comedic purpose.