not understanding what is going on here; anonymous function with jQuery object - javascript

Sorry to ask a naive question but I'm trying to figure out the best way to structure a bunch of code into something that is easier to manage
I wanted to put events and their responses into 'controllers' for different sections of site. I was looking through the book Javascript Web Applications and saw some promising stuff like this (p5 - my comment for what I thing I understand):
var controller={}; // ok- an object literal
(Controller.users = function($){ // creating an anonymous function; I don't get the dollar sign since it seems to work fine without it
var jtClick= function(){
alert('you clicked on me!');
};
$(function(){
$('#view').on('click',jtClick);
});
})(jQuery);
but I also noticed that this did the same thing:
var controller={};
(Controller.users = function(){
var jtClick= function(){
alert('you clicked on me!');
};
$(function(){
$('#view').on('click',jtClick);
});
})();
So do I need to pass jQuery as part of my anonymous function? Is this changing how scope is going to be handled? I updated the title to remove 'fully' since I don't think I'm getting much of this
thx in advance

This is a self-invoking function and allows you to safely use jQuery with other libraries that use $ as a library object/variable.
$ in the above example is nothing but the jQuery object that is being passed while invoking the function.

Related

how to call a custom jquery function without attaching it to something

new to writing a function in jquery, just testing the waters.
I have this just to to demo:
(function ( $ ) {
$.fn.update_notifications = function( options ) {
// This is the easiest way to have default options.
var settings = $.extend({
// These are the defaults.
user_id: 0,
}, options );
alert('test');
};
}( jQuery ));
Which I include in a JS file included before the tag. What I want to know, is how to actually call it inside my html?
I was thinking something like:
<script type="text/javascript">
jQuery.update_notifications({
user_id: 1
});
</script>
But that tells me "jQuery.update_notifications is not a function"
You want to call it on selected element like this:
$("some_element").update_notifications();
You can find more here at the official documentation.
No, the function is not part of the jquery object, but of its fn child object
$.fn.update_notifications();
However, it doesnt make sense to add something to the jquery prototype if youre not doing sth jqueryobjectbased
To fix the issue you simply need to change $.fn.update_notifications to $.update_notifications. The $.fn namespace is used for attaching functions to instances of jQuery objects.
(function($) {
$.update_notifications = function(options) {
var settings = $.extend({
user_id: 0,
}, options);
console.log('test');
};
}(jQuery));
jQuery.update_notifications({
user_id: 1
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
That being said, your example is a little redundant as you've just wrapped the existing $.extend() function without adding any real logic - although I assume this is a work in progress.
If your function has nothing to do with any DOM elements, i would suggest you not to pollute jQuery. You can very well declare this function some where else (page, separate JS file etc.).
But if you still want to do this, you can try these
$.update_notifications();
or
$(window).update_notifications();
or
$(document).update_notifications();
Why are you exactly extending the Jquery object?
Usually, lacking a valid reason to do so you would simply write a function inside your script.
Let's assume you have a valid reason and proceed:
Once you bind your function to $ or better create object like $.custom and bind the function (and rest of custom things you wanna bind to Jquery) you can use it like a normal function - only prefix it with $.custom
Not sure I understand your question but are you searching how to run that function from HTML other than using jquery?
Are you asking for an example like this?
<p id="onThis" onclick="$.custom.yourFunctionName()">Click me.</p>
That is obtrusive JS code and is not best practice when dealing with Jquery.
You wanna bind that function to element with on or click handler when document is ready:
$(document).ready( function() {
$('#onThis').on('click', function here);
// OR //
$('#onThis').click(function here);
});
If there is no reason to bind it to jQuery, don't do it you are only implying to someone reading your code something that doesn't exist ;)

Don't understand Javascript function syntax

I'm looking through a website's source code because I'm trying to learn to some basic Javascript. I understand the first part:
function count() {
...
}
I know that the function is called count, and doesn't take any arguments. The next function I don't understand:
$(function(){
...
});
Is the function called 'function'? And why is there a '$' symbol at the beginning. I've tried searching the internet, but google just ignores the '$'s and brackets and just searches for 'function'.
In addition, another thing I don't understand; the website has a single button that, when pressed, plays an audio file. The button is set up like so:
<a href="javascript:void()" id="button">
<img src="img/button.png" border="0">
</a>
What does javascript:void() do?
I'm sorry this isn't really a programming question, but I'm trying to learn Javascript and i figured I might have a look what other people are doing.
$ is the name (actually a reference to) of a function defined by the very popular jQuery library.
$( ) is calling the $ function
Inside the parenthesis you have an anonymous function definition.
$(function(){ console.log('test'); });
is pretty much the same as:
function nameNotImportant() { console.log('test'); }
$(nameNotImportant);
but it's more concise and you don't have to think of a name for that function.
As you probably noticed, nameNotImportant is not called. A reference to it is passed as parameter to the $ function to do as it wants with it, including call it. That is exactly what the $ function does when passed a function as parameter to it: it calls that function when the DOM is ready to be interacted with.
<a href="javascript:void()">
When an <a>nchor is clicked, the default action performed by the browser is to navigate to its href attribute. If you want it to not do that, you have to somehow interfere with the mechanism, for example by setting the href attribute to execute some javascript code that does nothing. I wouldn't consider it an example of good programming, but that is what it is used for.
I'm assuming you know that $ is an alias to jQuery.
$(function() {
// ...
});
is passing an anonymous function to the $ function, which can take a callback function. This function is run when the DOM is ready, so the more verbose form of this is
$(document).ready(function() {
// ...
});
In addition,
javascript:void()
is used to simply return undefined for a URL--aka the browser does not navigate to a page when you click on the link. javascript:void() is often used to allow the developer to bind JavaScript click events to the <a> tag.

What must an external JavaScript file look like to avoid global variables and methods?

I have the following piece of code on my page:
<script src="/Assets/JavaScripts/myJavaScript.js" type="text/javascript"></script>
<script type="text/javascript">
testAlert();
</script>
And in myJavaScript.js I have the following:
(function () {
function testAlert() {
alert('test alert');
}
})();
It's not calling testAlert. Not sure what I am doing wrong here? I'm trying to avoid global variables and methods. I did something similiar in jQuery and it worked, it just required a $ at the start of the external file. Can somebody please explain what I am doing wrong here and how to make sure I follow best practices?
I put your code in my environment and checked, I got error in mozila error console.
So, Please check it there.
you should put only below javascript function in myjavascript.js file.
function testAlert() {
alert('test alert');
}
Your function in the js-file isn't returning anything. To avoid global variables you could create one global namespace (-like) variable:
var myNS = (function () {
function testAlert() {
alert('test alert');
}
return {testAlert:testAlert};
}());
Now you can use myNS.testalert() in your inline javascript.
JS is made in such a way that you really can't totally avoid globals. (Well, you can, sort of. If you never give anything a name. But that tends to cause more problems than it solves.) When you call testAlert from some other script, you're operating under the assumption that testAlert is global. If it weren't, you couldn't just call it from anywhere like that.
You can minimize the chance of collision, though, by adding your stuff to an object that serves as a namespace, like so:
// don't clear it out if it already exists.
// that way all of your scripts can use your namespace, if you want.
// what you're really trying to protect against, are strangers picking names
// like yours.
if (!window.myNamespace) myNamespace = {};
// example function
myNamespace.testAlert = function() { alert("test alert"); };
myNamespace.testAlert();
This way, the only name that has a good chance of conflicting is myNamespace.
I was going to show an example of a namespaced global...but ya know what? A namespaced global is still a global. Global variables are something you want to try and get rid of in most cases.
You need some sort of global variable so that you can access the method you're looking for. The fact that you have <script>testAlert()</script> means you expect testAlert() to be defined in the global namespace.
What I like to do (especially when using YUI, which you have tagged this question with), is to create a global object that acts as a utility class.
var page = {
init: function() {
// Do some initialization...
},
testAlert: function() {
alert("Test Alert");
}
};
After you do that, you can use the single global "page" variable to access everything you need.
// e.g.
page.testAlert();
// or...
Y.on("domready", page.init, page);
Again, for the second example I'm assuming you're using YUI, since you tagged this question with it.

Is this a smart way to organize code in jQuery?

for the longest time I was writing all my code inside like this ...
$(document).ready(function(){
$('.show_module').click(function(){
});
...
});
putting all sorts of click handlers in there. But recently I was introduced to a new way of doing things and I wanted to get a feel for if its a smart way of going about it.
the idea is to have all the handlers in related functions and then have minimal code in document.ready above.
So for example ...
$(document).ready(function(){
page_handler(); // other functions follow
});
function page_handler(){
$('.show_module').click(function(){
});
...
}
This seems to allow organization of related handlers in functions and use document.ready as more of an initializer.
I know in JavaScript functions and variables are 'hoisted' before code starts executing so
do_something();
function do_something(){
}
works for this reason, since the function is ready to use before do_something() is actually called, even though it appears before the actual function definition.
I was wondering if the same thing happens here and how 'good' this idea/way of doing things is.
That will expose all your handlers to the global (window) scope, which may lead to clashes.
I prefer to do this...
(function($) {
// Anything you do in here won't be attached to window.
var a;
// If you must have something global, set it explicitly
window.doSomething = function() { ... }
// We can also use $ for jQuery here, even if we have used jQuery.noConflict()
$('body')...
})(jQuery);
It depends on:
Do you want to reuse the functions?
- If yes, your structure is a good way to do it
How long is your code?
- If your code is not too long and not use anywhere else. I think you don't need to break it into functions.
I always put the functions before the document ready:
$(document).ready(function() { ... });
Which I would write in short-hand:
$(function() { ... });
Ideally it is better to have just one initialiser like above. This may be useful for you too if you want to write extensions/plugins in jQuery context.

How do I call another function in the same javascript namespace?

I like to organize my javascript in namespace style like below. What I want to know : is there another (shorter?) way to call myFirstFunction() from mySecondFunction()? I tried this.myFirstFunction() and it's not working so maybe there's some kind of mysterious trick here that I don't know.
var myNameSpace = {
myFirstFunction: function(){
alert("Hello World!");
},
mySecondFunction: function(){
myNameSpace.myFirstFunction();
}
}
Thanks for your help as usual, people of SO! :)
As written in your example code, this.myFirstFunction() would work. Your code is likely simplified to illustrate your problem, so it would probably help to see the actual code to tell why it doesn't work with this.
One possible reason that it fails would be if the code where you call this.myFirstFunction() is inside a closure. If so, this would be a reference to the closing function, not your namespace and would therefore fail. See here for a contrived example based on your code to see what I mean. Again, having a look at the actual code would probably be helpful to diagnose what's going on.
Your suggestion to use 'this' should work. i.e.:
var myNameSpace = {
myFirstFunction: function(){
alert("Hello World!");
},
mySecondFunction: function(){
this.myFirstFunction();
}
}
Result:
myNameSpace.mySecondFunction() // "Hello World!".
If you want it to be shorter maybe you should consider the following pattern:
Javascript Design Pattern Suggestion
basically for your example:
var myNameSpace = (function()
{
function _myFirstFunction(){
alert("Hello World!");
}
function _mySecondFunction(){
_myFirstFunction();
}
return {
MyFirstFunction : _myFirstFunction,
MySecondFunction : _mySecondFunction
};
})();
I find this to be the cleanest pattern, also providing "private/public" variables in javascript that's otherwise pretty much impossible
In some cases the this keyword should work fine. If you explicitly call myNameSpace.mySecondFunction() then this.myFirstFunction() will execute as intended.
If you are using myNameSpace.mySecondFunction as an event handler it likely will not. In the case of an event handler you would need some way to refer to the namespace you want to use. A lot of JavaScript frameworks provide a way to define what the this keyword refers to. For example, in MooTools you can do myNameSpace.mySecondFunction.bind(myNameSpace) which will cause this to refer to myNameSpace inside mySecondFunction. If you are not using a framework you could make your event handler an anonymous function like:
document.getElementById('myId').addEventListener('click', function(e) {
myNameSpace.mySecondFunction.call(myNameSpace);
});
For more information on the call method I would refer to the MDC page for the call function or you could use apply which behaves similarly to call but passing an array of arguments for the second paramter rather than having a varargs like approach for additional parameters.
All of these suggestions are predicated on defining your namespace as #Harnish suggested:
var myNameSpace = {
myFirstFunction: function(){
alert("Hello World!");
},
mySecondFunction: function(){
this.myFirstFunction();
}
}
For more information about JavaScript function binding I'd highly suggest reading Justin's article on Function scope and binding in JavaScript
If you are attaching to event:
possible issue could be if you are attaching Namespace's function to event, like:
$(el).on("click", nameSpace.myFunc);
....
nameSpace = {
myFunc: function(){
this.anotherFunc();
}
}
that will throw error.
Solution 1
You may change this.anotherFunc() with nameSpace.anotherFunc()
Solution 2
You might change
$(el).on("click", nameSpace.myFunc);
// to ----->
$(el).on("click", function(){ nameSpace.myFunc(); } );

Categories

Resources