.change() only running once and not at click - javascript

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)

Related

Call back when using pre-defined function

I've declared a new function. Then I'm calling that function later. How do I run code only if the function I'm calling has completed.
this is my code
var callLogin = function() {
$(document).ready(function() {
if(document.getElementById("userLoggedIn") === null) {
$(".cover").fadeIn(200);
$(".sixPinInputContainer").fadeIn(200);
$("#pageBody").css("overflow", "hidden");
$('.sixPinInput').first().focus();
};
})
};
Then This is where I call It. The problem is that it's running the .load before it calls my pin container so even if pin is incorrect it runs code.
if (startBtn) {
callLogin()
$("#" + rowID).load("eventHandlersPHP/updateStart.php", {
roomID: id }, function(data, status) {
$("#notStartedCount").load("eventHandlersPHP/jobsNotStartedCount.php");
})
};
This is documented pretty well here. You could create some sort of action that'll trigger the one function, then it can call the other. Also, this will probably be a more helpful place for what it is you're trying to do.
-Gonzo

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.

Monkey-patching a named function that's called immediately

A script I'm loading is misbehaving. It's got a structure like this:
function bad_function() {
...
}
/* randomly generated stuff */
bad_function();
How do I modify the behavior of bad_function if it's called immediately at the end of the script? I thought of creating a silently read-only property on window before loading the script, but this throws a TypeError: Identifier 'bad_function' has already been declared exception when the above script is executed:
Object.defineProperty(window, 'bad_function', {
value: function() {
/* my monkey-patched code */
}
});
How do I monkey-patch this function?
While this isn't an answer to my question in general, I was able to monkey patch my specific function by patching a global function like encodeURIComponent that was called inside of my function, performing the necessary changes, and throwing an exception to prevent the rest of the original function from running.
var old_encodeURIComponent = window.encodeURIComponent;
window.encodeURIComponent = function() {
// If this function is used in multiple places, look for variables in
// the current scope to determine if this is the right spot to start
// monkey patching.
if (typeof a === 'undefined' || typeof b === 'undefined') {
return old_encodeURIComponent.apply(this, arguments);
}
// You now have access to the variables in the scope of your target
// function. If your monkey patching is just a simple tweak, you're all set
// Otherwise, do what you need to do and throw an exception to stop the
// rest of the code from running
throw 'goodbye';
};
It's not nice, but all I can think to do is to load the script via ajax instead of putting it in a <script> tag, manipulate the result string to call your own version of the function (or "rename" bad_function so it doesn't override your version), then put that in a <script> tag and append it to your page:
An example using jQuery for simplicity:
function good_function() {
alert("I am good");
}
$.ajax({
url: '/echo/html/',
type: 'POST',
data: {
html: "function bad_function() { alert('hahaha'); } bad_function();",
delay: 0
},
success: function(data) {
console.log(data);
// comment this line to see the original
data = data.replace('bad_function();', 'good_function();')
var newScript = $('<script type="text/javascript" />').text(data);
$('body').append(newScript);
}
});
Working JSFiddle

Jquery passing a function to a function

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.

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(); }

Categories