Scope issue inside a custom object - javascript

I think I am having a scope visibility issue I can't figure out exactly: when I log the variable displayatonce I get back the right result, but as I try to use the buttons I get nothing in return. I have also tried to log this.navbuttons but all I get is an empty set... I really don't get what's wrong with this code.
<!-- html code -->
<div id="nav">
Previous
Next
</div>
/* Js Script with jQuery */
(function() {
var NewsNavigator = {
init: function(config) {
this.navbuttons = config.navbuttons;
this.displayatonce = config.displayatonce;
this.counter = 0;
this.showNews();
this.enableNav();
},
showNews: function() {
console.log(this.displayatonce);
},
enableNav: function() {
console.log(this.navbuttons);
this.navbuttons.on('click', function() {
console.log("clicked");
});
}
};
NewsNavigator.init({
displayatonce: 3,
navbuttons: $('div#nav').find('a')
});
})();

That is happening because as you are using (function())(); which executes the function immediately, maybe it's running the code before the dom is ready
everything is working fine in the below demo
DEMO
Put all your code inside document ready or at least call the initialize method inside doc ready block like
$(function(){
NewsNavigator.init({
displayatonce: 3,
navbuttons: $('div#nav').find('a')
});
});
Read more about Javascript self executing Anonymous function here
Javascript self executing function "is not a function"
or
http://markdalgleish.com/2011/03/self-executing-anonymous-functions/

You're using jQuery too soon, specifically before the DOM is ready to be searched.
Here is fiddle demonstrating this: http://jsfiddle.net/w7KaY/ (JavaScript is placed in <head>, so init() is invoked pretty early) while here (http://jsfiddle.net/w7KaY/1/), the call to init() is encapsulated in an event handler for jQuery's DOM-ready event.

Make sure the html elements are there in the DOM. I don't see any issue with the script other than the fact you have to use the bind method for binding to events.
this.navbuttons.bind('click', function() {
console.log("clicked");
});

Related

How do I use a function as a variable in JavaScript?

I want to be able to put the code in one place and call it from several different events.
Currently I have a selector and an event:
$("input[type='checkbox']").on('click', function () {
// code works here //
});
I use the same code elsewhere in the file, however using a different selector.
$(".product_table").on('change', '.edit_quantity', function () {
// code works here //
});
I have tried following the advice given elsewhere on StackOverflow, to simply give my function a name and then call the named function but that is not working for me. The code simply does not run.
$(".product_table").on('change', '.edit_quantity', function () {
calculateTotals() {
// code does not work //
}
});
So, I tried putting the code into it's own function separate from the event and call it inside the event, and that is not working for me as well.
calculateTotals() {
// code does not work //
}
So what am I doing wrong ?
You could pass your function as a variable.
You want to add listeners for events after the DOM has loaded, JQuery helps with $(document).ready(fn); (ref).
To fix your code:
$(document).ready(function() {
$("input[type='checkbox']").on('click', calculateTotalsEvent)
$(".product_table").on('change', '.edit_quantity', calculateTotalsEvent)
});
function calculateTotalsEvent(evt) {
//do something
alert('fired');
}
Update:
Vince asked:
This worked for me - thank you, however one question: you say, "pass your function as a variable" ... I don't see where you are doing this. Can you explain ? tks. – Vince
Response:
In JavaScript you can assign functions to variables.
You probably do this all the time when doing:
function hello() {
//
}
You define window.hello.
You are adding to Global Namespace.
JavaScript window object
This generally leads to ambiguous JavaScript architecture/spaghetti code.
I organise with a Namespace Structure.
A small example of this would be:
app.js
var app = {
controllers: {}
};
You are defining window.app (just a json object) with a key of controllers with a value of an object.
something-ctlr.js
app.controllers.somethingCtlr.eventName = function(evt) {
//evt.preventDefault?
//check origin of evt? switch? throw if no evt? test using instanceof?
alert('hi');
}
You are defining a new key on the previously defined app.controllers.somethingCtlrcalled eventName.
You can invoke the function with ();.
app.controllers.somethingCtlr.eventName();
This will go to the key in the object, and then invoke it.
You can pass the function as a variable like so.
anotherFunction(app.controllers.somethingCtlr.eventName);
You can then invoke it in the function like so
function anotherFunction(someFn) { someFn();}
The javascript files would be structured like so:
+-html
+-stylesheets
+-javascript-+
+-app-+
+-app.js
+-controllers-+
+-something-ctlr.js
Invoke via chrome developer tools with:
app.controllers.somethingCtlr.eventName();
You can pass it as a variable like so:
$(document).ready(function() {
$('button').click(app.controllers.somethingCtlr.eventName);
});
JQuery (ref).
I hope this helps,
Rhys
It looks like you were on the right track but had some incorrect syntax. No need for { } when calling a function. This code should behave properly once you add code inside of the calculateTotals function.
$(".product_table").on('change', '.edit_quantity', function () {
calculateTotals();
});
$("input[type='checkbox']").on('click',function() {
calculateTotals();
});
function calculateTotals() {
//your code...
}
You could just condense it all into a single function. The onchange event works for both the check box and the text input (no need for a click handler). And jQuery allows you to add multiple selectors.
$('input[type=checkbox], .product_table .edit_quantity').on('change', function() {
console.log('do some calculation...');
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div class="product_table">
<input type="checkbox">
<input class="edit_quantity">
</div>

Which one happens first? WebComponentsReady or dom-change?

I just started on Polymer. There seems to be two events indicating content is ready:
// Listen for template bound event to know when bindings
// have resolved and content has been stamped to the page
app.addEventListener('dom-change', function() {
console.log('Our app is ready to rock!');
});
// See https://github.com/Polymer/polymer/issues/1381
window.addEventListener('WebComponentsReady', function() {
// imports are loaded and elements have been registered
});
I wonder if it is necessary to wrap them together and put the code inside, to make sure that the document is fully loaded before doing any script, for example:
app.addEventListener('dom-change', function() {
window.addEventListener('WebComponentsReady', function() {
// scripts go here
});
});
However, I don't know what is the correct way to do so in all browsers. If WebComponentsReady happens before dom-change, the inside script never execute.
Heck, this might not even be necessary because the polymer-starter-kit doesn't wrap them together. In that case, which types of script should go inside dom-change event and which types of script should go inside WebComponentsReady event?
Use the native ready callback as described here.
<script>
(function() {
Polymer({
is: 'example-element',
properties: {...},
ready: function() {
// access a local DOM element by ID using this.$
this.$.header.textContent = 'Hello!';
}
});
})();
</script>

Call function defined inside $(document).ready()

In and external JS file I have
$(document).ready(function() {
var example = function(){ alert("hello") }
});
and I want to call that function from my html, how would I do that?
<img src="..." ondblclick="example()" />
n.b. I'm aware of jquery dblclick() but curious about how to correctly do the above.
$(document).ready(function() {
window.example = function() {
alert("hello")
}
});
Or define it outside, if possible. It doesn't look like it has to be defined inside document ready at all.
The other solutions here will work, but structurally in your project, the best solution is to remove the event handling code from the HTML and hook up the event entirely via javascript (separate the HTML/JS). Since you already have jQuery in your project, this is very easy. To do that, all you need to do is to put some sort of identification on the image:
<img id="example" src="..." />
Then, in you can just hook up the event code in your ready() function like this
$(document).ready(function() {
$("#example").dblclick(function() {
alert("Hello");
});
});
This has the following advantages:
It creates no global variables - reducing the global namespace pollution.
It separates the HTML from the javascript which keeps all code governing the behavior in one compact spot and is usually a good thing
Using event listeners is a bit more scalable than using .ondblclick - allowing multiple different parts of code to use non-conflicting event handlers on the same object
Your function should be global (in fact, property of window object) if you want to access it from HTML. But best practice is to avoid global variables and functions, using namespace instead:
// let's publish our namespace to window object
if (!window.myNamespace){
// creating an empty global object
var myNamespace = {};
}
// and add our function to it
$(document).ready(function() {
myNamespace.example = function(){ alert("hello"); }
});
We can use it in HTML like this:
<img src="..." ondblclick="myNamespace.example()" />
The best option would be to simply define the function outside document.ready(). There is no reason defining the function within the $(document).ready() event is necessary, as if you call the function within the $(document).ready() function, the document is guarenteed to be ready.
However, you can also define the function on the global window object, like so:
$(document).ready(function() {
window.example = function(){ alert("hello") }
});
You can either move the function declaration outside of the DOM-ready handler:
function example(){ alert("hello") }
$(document).ready(function() {
// code
});
But the better solution is to keep JavaScript in your .js files and avoid the inline event handlers. Give your element an id and fetch it:
<img src="..." id="imgid" />
$(document).ready(function() {
document.getElementById("imgid").ondblclick = function(){ alert("hello") }
});
#Esailija has answered it correctly but if you want to keep it as it is then simply remove var and make it global.
var example;
$(document).ready(function() {
example = function() {
alert("hello")
}
});
If you do not put var the variable/function/object becomes global. Using var you were setting its context within document.ready function.

Creating an arguments and adding it to a click event

Hi I'm pretty new to javascript looking for some help on creating an argument and adding it to a click event in jquery
Heres a demo: http://jsfiddle.net/zidski/8VwAy/1/
Can someone help example what I have to do?
Thanks
First: Do not use arguments as a variable name, since every function already defines the arguments object.
Your code does not work, because you have injected the JavaScript through the onload setting in JSFiddle. This runs code after the document has loaded.
In the body section, you're calling a function which is not defined yet.
What happens?
Definition:
window.onload = function () {
// Defines window.demo.Alert...
}; ...
window.demo.Alert();
Calling order:
window.demo.Alert(); // Error: 'demo' is not defined.
window.onload = ...
Change onload to nowrap (head) to get your code to work: http://jsfiddle.net/8VwAy/7/
You can actually pass data to the event handler as the first parameter
$(".js-link").click("myne", function(e) {
alert(e.data);
alert("Hello world");
});
fiddle here http://jsfiddle.net/8VwAy/8/

Revealing module pattern with jQuery not working

I've been playing around with the revealing module patter. I originally started using the Singleton pattern but from reading around the module pattern seems to be the better option.
So i've tested the following:
var test = (function() {
var init = function () {
alert('hello');
};
return {
init: init
};
})();
and this works fine when calling
<script>test.init();</script>
However, i want to use jQuery so i tried:
var test = (function($) {
var init = function () {
$("#samplediv").html('test');
alert('hello');
};
return {
init: init
};
})(jQuery);
but this doesn't work. It does work when using:
<script>$(function() { test.init(); });</script>
How can i get it to work without the added jQuery when calling it?
Usually, anything that touches the DOM needs to done in the $(document).ready(fn) callback. $(fn) is a shortcut for this.
So the reason it doesn't work is because you are searching for DOM elements that don't exist yet. So you have 2 choices. Either you must use the $() wrapper, or find another way to run your code only after the DOM elements exist. Another way to do this is to move your script tag the bottom of the body tag so that the DOM elements can exist when it's ran.
<body>
<!-- your page elements here -->
<script>test.init();</script>
</body>

Categories