Jquery passing a function to a function - javascript

OK, i need some help,
i have a function inside a jquery plugin
var LoadPage = function (page, location, func){
$.ajax({
url: page,
success: function(data){
$(location).html(data); //Insert data into location
func
return true
},
});
}
i want to use it like this
Loadpage(
"api/page.php",
"#div_id",
$("#calander td.clickable").click(function() {
var day = $(this).attr("calendar-day");
console.log("clicked TD" + day);
LoadPage('/api/view_event.php?d='+day, settings.eventContainer);
})
);
or
Loadpage(
"api/page.php",
"#div_id",
function() {
var day = $(this).attr("calendar-day");
console.log("clicked TD" + day);
LoadPage('/api/php/calander/view_event.php?d='+day+'&m='+SelectedMonth+'&y='+SelectedYear, settings.eventContainer);
}
);
and then have it run that in the success: where var func is in it but unsure how to get this to work. please help internet.

There are three separate issues in your code:
1) If you want to execute the callback func in your success handler, then you need to add parens () after it as in func() as that is javascript's method of signifying that you want to execute a function.
var LoadPage = function (page, location, func){
$.ajax({
url: page,
success: function(data){
$(location).html(data); //Insert data into location
// add parens here after func
func();
return true
},
});
}
If you want the func argument to be optional, you can test for it before executing it like this:
var LoadPage = function (page, location, func){
$.ajax({
url: page,
success: function(data){
$(location).html(data); //Insert data into location
// add parens here after func to actually execute it
if (func) func();
return true
},
});
}
2) Then, you need to change how you call LoadPage() to pass it an actual function reference like this:
Loadpage(
"api/page.php",
"#div_id",
function() {
$("#calander td.clickable").click(function() {
var day = $(this).attr("calendar-day");
console.log("clicked TD" + day);
LoadPage('/api/view_event.php?d='+day, settings.eventContainer);
})
})
);
What you were passing it was the result of executing the .click function which is a jQuery object, not a function. Instead, you can wrap that in an anonymous function so you're passing a reference to that function. This is the opposite of the func(). You don't want parens after what you pass because you want to pass a reference to a function, not the result of executing the function now.
So, to summarize these two issues:
The statement:
func
is just a reference to a function. It doesn't actually execute the function. It is useful when you want to pass a reference to a function which will then call it LATER.
The statement:
func()
executes the function immediately. If you pass func() as an argument, then it will execute immediately (parens always mean to execute it now) and then pass the return value of that function (which is not what you want here).
3) You may also want to understand that the return true statement in your success handler does NOTHING. Because the ajax function is asychronous, your LoadPage() function just starts the ajax function and then returns immediately. Sometime later, the internals of the ajax engine calls your success handler. That return statement returns back into the interior of that ajax engine. It does NOT return from your LoadPage() function since that has already long since completed and returned nothing.
4) Possible fourth issue. Every time you call LoadPage(), you are going to add a new click handler to whatever objects this selector matches: "#calander td.clickable". If some of those objects existed previously, you will end up with multiple click handlers. In that case, you would either want to use delegated event handling so you could just install the click handler once ahead of time or you would need to remove the exist click handlers before installing the new ones or you would need to isolate only the newly added objects and only call it on them. If all "#calander td.clickable" are replaced by the previous code, then this would not be a problem.

Try this:
var LoadPage = function (page, location, func){
$.ajax({
url: page,
success: function(data){
$(location).html(data); //Insert data into location
func && func(); // this will execute func if it is passed as parameter
return true;
}
});
}
And use it in the second way.

Related

.change() only running once and not at click

I've got a JS file that's automatically run through an HTML script. A function putToggleCall() is supposed to run every time one of the many toggles is clicked but instead it only runs once, before the document is even ready(based on my other functions). I know this from the console.log() inside my function. The goal is to simplify the code so that all the bootstrap toggles can use one PUT call function on change (i.e. onclick).
var toggles = {
"#rando": "random/url",
etc..
};
function putToggleCall(toggle_id) {
var value = $(toggle_id).prop("checked") ? 1:0;
console.log(value)
$.ajax({
url: BASE_URL + toggles[toggle_id],
type: "PUT"
}).done(
).fail(function(data,textStatus,errorThrown) {
alert(errorThrown);
});
};
for (var i = 0; i < Object.keys(toggles).length;i++) {
var toggle_id = Object.keys(toggles)[i]
$(toggle_id).change(putToggleCall(toggle_id));
})
You're calling the function, not referencing it.
You either need a wrapping anonymous function
$(toggle_id).change(function() {
putToggleCall(toggle_id)
});
or just reference the function
$(toggle_id).change(putToggleCall);
and find another way to pass the data (hint: it's available as this.id, or even just this in the function)

Facing issue in using $.when().then() function

I need to make sure that getValue() is called only after execution of SetValueForVariable(). I cannot modify BindValue() or SetValueForVariable().
I tried $.when(BindValue()).then(getValue());. (As i cannot change the already existing flow)
It works some times but sometimes it shows the previously set value.
I need to call getValue on $(document).ready(). How do I make sure getValue() is only called after execution of SetValueForVariable().
//This function is inturn making call to SetValueForVariable() which is written in another file
//Cannot Change this
function BindValue() {
SetValueForVariable()
}
function getValue()
{
$.ajax({
url: getRoutePath("GetPath/GetPath1"),
type: "GET",
async: true,
success: function (data) {
debugger;
data = JSON.parse(data)
$('#txtBox').text(data.Count);
});
}
//Written in another file
//Cannot change this function
function SetValueForVariable() {
//this fucntion is making server call the server method sets value of a Session Variable
$.ajax({
url: getRoutePath("SetPath/SetPath1"),
type: "GET",
async: true,
....
});
}
You could redefine BindValue, calling the original BindValue in your new definition after ensuring that getValue has been called.
Pseudo code
var originalBindValue = BindValue;
BindValue = function() {
if getValue has been called
originalBindValue();
else
call getValue and then originalBindValue() in getValue success / failure callback
}
I think this would work around your cannot modify BindValue limitation - you don't actually need access to BindValue code here.

Why does Javascript need an anonymous function to delay execution?

In my application I need to conduct an IP lookup as a prerequisite to proceeding with execution of another function that needs that data. Originally, I called the function as follows:
$(document).ready(function(){
var ipUrl = "myURL?callback=?";
$.getJSON(ipUrl, function(data) {
window.ip = data['ip'];
console.log("inside function" + window.ip);
}).done(printIp());
});
function printIp() {
console.log("function is done " + window.ip);
}
However, this outputs as
function is done undefined
inside function <ip_address>
I.e. the printIp() function is called before the $.getJSON is actually complete.
If however, I wrap the printIp() call within an anonymous function as follows:
$.getJSON(ipUrl, function(data) {
window.ip = data['ip'];
console.log("inside function" + window.ip);
}).done(function() {
printIp();
});
I get:
inside function <ip_address>
function is done <ip_address>
As I would expect. What is going on here? Why do I need to wrap the function call in an anonymous function?
your code says
}).done(printIp());
what this does is calling printIp and using the result of the function call as an argument to the done method.
what you actually want is passing the function as a done handler. use }).done(printIp); to do this instead.
You are executing printIp right away. Try it without the ():
$.getJSON(ipUrl, function(data) {
window.ip = data['ip'];
console.log("inside function" + window.ip);
}).done(printIp);
pass the function without parantheses, otherwise you are calling it right away:
.done(printIp)

Listen for a function to be called JavaScript

I have the following functions that is called every 2 seconds to load some data. It registers the function [do] to do the stuff with the response. (the example is simplified).
function doRequest (){
$.ajax({ url: 'www.google.com.pe', success: function (response) {do(response)} });
}
function do (text){
var i = setInterval(doRequest, 2000);
}
I wonder if there is any way that I can create a function that is called every time the [do] function is called with out needing to add a call to the listener inside the do function. If there is any better way to do it with jQuery, like a plugin I'd appreciate the help.
[Edit] The idea is not whether it works or not. My question was about if I can add a custom listener to the "do" function which was already implemented. Something like addActionListener("do", "after", doSomeThingElse),sSo I could do some thing else just after the do function has finished.
First, your simplified version won't work, because you'd need to pass the do function instead of calling it.
function doRequest (){
$.ajax({ url: 'www.google.com.pe', success: _do });
}
But it sounds like you're asking how to run some other code every time do is invoked.
If do is only invoked inside the doRequest() function, then just add your other code to an anonymous function that invokes do at the right time.
function doRequest (){
$.ajax({ url: 'www.google.com.pe', success: function(response) {
// Run your other code
// or invoke another function.
_do(response);
} });
}
If you want it to be more generalized, you can create a function decorator that returns a function which invokes do after some other code.
function doFactory(fn) {
return function() {
fn.apply(this, arguments);
_do.apply(this, arguments);
}
}
then make functions like this:
var doFoo = doFactory(function() {
console.log("foo");
});
If your requirement is more specific of a pre-processing of response, you could rework it like this:
function doFactory(fn) {
return function(response) {
_do.call(this, fn.call(this, response));
}
}
Then have the fn manipulate and return response.
var doFoo = doFactory(function(response) {
return response + "foo";
});
If you want to keep existing code as it is, you could wrap do() in another function which in turn calls do() and your new function (say do_this_as_well()).
See the example below (I renamed do() to do_this() to avoid confusion around the reserved keyword do). This works because global functions are nothing but variables with function objects in them. These variables can be overwritten, in this case with a new function that calls the old one:
function do_this(response) { ... }
(function()
{
var previous=do_this;
do_this=function(response) { previous(response); do_this_as_well(); }
})();
Replace
success: do(response)
with
success: function(response) { do(response); do_this_as_well(); }

calling a javascript function (in original function) from called function?

Is there anyway to calling a function from another function .. little hard to explain. heres in example. One function loads html page and when ready it calls the original function.
I think i need to pass in a reference but unsure how to do this... if i set it to "this" - it doesn't seem to work
ANy ideas?
order.prototype.printMe = function(){
order_resume.loadthis("myTestPage.html", "showData");
}
order.prototype.testme= function(){
alert("i have been called");
}
//Then when in "loadthis" need to call
orderRsume.prototype.loadthis= function(){
// DO SOME STUFF AND WHEN LOADS IT ARRIVES IN OnReady
}
order.prototype.OnReady= function(){
/// NEED TO CALL ORIGINAL "testme" in other function
}
It's not clear for me what you really want to do. In JS functions are first-class objects. So, you can pass function as a parameter to another function:
Cook("lobster",
"water",
function(x) { alert("pot " + x); });
order.somefunc = function(){
// do stuff
}
order.anotherone = function(func){
// do stuff and call function func
func();
}
order.anotherone(order.somefunc);
And if you need to refer to unnamed function from it's body, following syntax should work:
order.recursivefunc = function f(){
// you can use f only in this scope, afaik
f();
};
I slightly changed the signature of your loadthis function aloowing it to be passed the order to actually load.
I also assumed that your doSomeStuff function accepts a callback function. I assumed that it may be an AJAX call so this would be trivial to call a callback function at the end of the AJAX call. Comment this answer if you need more info on how to fire this callback function from your AJAX call.
order.prototype.printMe = function(){
order_resume.load(this, "myTestPage.html", "showData");
}
order.prototype.testme= function(){
alert("i have been called");
}
//Then when in "loadthis" need to call
orderRsume.prototype.load = function(order, page, action){
// DO SOME STUFF AND WHEN LOADS IT ARRIVES IN OnReady
doSomeStuff(page, action, function()
{
order.OnReady();
});
}
order.prototype.OnReady= function(){
/// NEED TO CALL ORIGINAL "testme" in other function
this.testme();
}

Categories