I add a click event handler to an element
$(".elem").click(function(){
$.post("page.php".function(){
//code1
})
})
And then I trigger a click event
$(".elem").click();
//code2
How can i make sure that code2 executes after code1 executes
(Ignoring WebWorkers) JavaScript runs on a single thread, so you can be sure that code2 will always execute after code1.
Unless your code1 does something asynchronous like an Ajax call or a setTimeout(), in which case the triggered click handler will complete, then code2 will execute, then (eventually) the callback from the Ajax call (or setTimeout(), or whatever) will run.
EDIT: For your updated question, code2 will always execute before code1, because as I said above an async Ajax callback will happen later (even if the Ajax response is very fast, it won't call the callback until the current JS finishes).
"How i make sure that code2 executes after code1 executes"
Using .click() with no params is a shortcut to .trigger("click"), but if you actually call .trigger() explicitly you can provide additional parameters that will be passed to the handler, which lets you do this:
$(".elem").click(function(e, callback) {
$.post("page.php".function(){
//code1
if (typeof callback === "function")
callback();
});
});
$(".elem").trigger("click", function() {
// code 2 here
});
That is, within the click handler test whether a function has been passed in the callback parameter and if so call it. This means when the event occurs "naturally" there will be no callback, but when you trigger it programmatically and pass a function then that function will be executed. (Note that the parameter you pass with .trigger() doesn't have to be a function, it can be any type of data and you can pass more than one parameter, but for this purpose we want a function. See the .trigger() doco for more info.)
Demo: http://jsfiddle.net/nnnnnn/ZbRJ7/1/
You can try writing this way:
$(".elem").live("click", function(){
//code1
})
// for newer jquery version from 1.9
$(".elem").on("click", function(){
//code1
})
And, your trigger will always execute as fired.
Wrap code2 in method and add it as a callback inside code1 so it will always get called after code1 executes
code2 = function(){/*code2*/};
$(".elem").click(function(){
//code1
code2();
})
Javascript execution is line by line. So whatever comes up, will be executed first. So adding the click code before the other method will work.
Plus if there is any async call, then take a flag which is set only when you get response.
var clicked = false;
$('#elem').click(function(){
// do some async process
clicked = true;
});
while (!clicked){ // do nothing }
// other function to be called
Or the second option will be, if using post method, set async = true in property.
Related
First of all, i need this to be capabe to run on I.E. 8 at least (work requirements) and i can't use jQuery or another library to reach this.
The "issue" is that there's a function onKeyDown with a preventDefault and a function triggered onChange, which never (or randomly) executes due to prevendefault (long to explain more). I't could be solved as i'm reading onChange value and i'm setting it as onPlay, then i delete onchange attribute and the behaviour is to check if changes exists when onBlur and i'm triggering onplay event from this control function if there are changes.
Well, onPlay event (and other multimedia events) are only supported on IE 9 and up, so i need to find a way to pass through this. i can't use other events as they could be used on somewhere and could cause issues.
My idea was to send onChange value as function parameter to control function and execute it instead on triggering onplay event, but is causing me headache, it simply does nothing when i'm trying to do it.
//this is a resume of the function:
function foo(obj){
var funcioChange = toString(obj.getAttribute('onChange'));
obj.setAttribute('onBlur', 'checkChanges("'+obj.getAttribute("id")+', '+ funcioChange+'")');
obj.removeAttribute('onChange', 0);
}
When onBlur:
function checkChanges(idinput, functOnChange){
if (foo){
functOnChange;
//another things
}
}
If the function doesn't have parameter/s or you need to put it/them later in another function, you can do
foo = yourFunction;
function2 (foo){
foo(param1, param2);
}
if you have to send the params with the function call:
foo = "yourFunction(param1, param2)";
function2 (foo){
foo;
}
What is the proper way to accomplish the following:
$("#btn").click(function1);
Calling the function:
function function1 (event) {
event.preventDefault();
}
This seems to work, however I don't understand how function1 understands what the event argument is referring to without it being passed in. Wouldn't a listener set up like this make more sense:
$("#btn").click(function1(event));
Here is a fiddle.
The .click() function in jQuery except as first parameter a function. In Javascript function are value, as well as a primitive value or an object. Functions are first-class citizens.
If you use function1(event) as a parameter, the function will be executed, because this is the semantic of the brachet after the function name. So the .click() jQuery function will receive the output of the function, which is not the expected type.
Passing the function name as a parameter means that you are passing the function (actually, a reference to the function), not the result of the function invocation. And the function will be called when the click event will be triggered. The function in this case is called "callback".
Callbacks are very importants in Javascript, since the event-driven behaviour is the main reason for using a client-side scripting.
The concept behind the callback system is
//the click function
function doSomething(callback){
//in your case the event is the argument that jQuery will prepare for you
var argument = produceTheArgument();
//doSomething is in charge to invoke the function, passing the argument
callback(argument);
}
//your function
function myCallback(argument){
//your function will consume the argument
}
//my callback is passed as a reference, not invoked
doSomething(myCallback);
you are subscribing to event and passing a reference to the function inside click listener - the jQuery event processor will just call your function in jQuery's context and will pass all parameters to it.
In your first example function1 knows that the event variable is, because JavaScript (and subsequently jQuery) passes the event information as a parameter.
This is the nature of JavaScript, not just jQuery. Consider the following:
document.getElementById('btn').addEventListener('click', function1, false);
function function1(e)
{
console.log(e);
}
JavaScript automatically calls function1 when #btn is clicked, and it automatically adds the event information as the first parameter. jQuery simply passes this information into its own methods as well, so that you have access to it.
According to jQuery's documentation:
The click event is sent to an element when the mouse pointer is over the element, and the mouse button is pressed and released. Any HTML element can receive this event.
Reference: http://api.jquery.com/click/
I've a javascript method defined as follows:
updtCrtEdtPage = function() {PrimeFaces.ab({source:'j_id_ev',formId:'j_id_es',process:'typeNewLOB_in lobIdForEdit j_id_ev',update:'createLOBFullPagePanel',oncomplete:function(xhr,status,args){prepareForCrtEdtFullPage();},params:arguments[0]});}
I want to execute certain method (afterComplete()) whenever this method has finished executing. (This method actually initiates an ajax request & appends the received HTML data on the DOM). So I want my afterComplete() method to be executed whenever ajax response has been received.
I cannot directly do like:
updtCrtEdtPage();
afterComplete();
as this would call the afterComplete() soon after ajax request is initiated & not completely finished executing yet.
Is there any JS/ jQuery way I could do that ?
You could pass afterComplete as a parameter so your function can call it when the ajax call is complete. Something like this...
updtCrtEdtPage = function(callback) {
PrimeFaces.ab({
source:'j_id_ev',
formId:'j_id_es',
process:'typeNewLOB_in lobIdForEdit j_id_ev',
update:'createLOBFullPagePanel',
oncomplete:function(xhr,status,args){
prepareForCrtEdtFullPage();
callback();
},
params:arguments[0]
});
}
updtCrtEdtPage(afterComplete);
Since you say you can't modify updtCrtEdtPage, but you can modify prepareForCrtEdtFullPage I'd suggest using a global variable to determine which callback function to call when the method is complete...
updtCrtEdtPageCallback = afterComplete;
and then in prepareForCrtEdtFullPage just add the last line...
updtCrtEdtPageCallback();
The first method is tidier, but the second will suffice for your particular situation.
your updtCrtEdtPage = function() has an oncomplete callback which is called when the ajax response has been received, add your afterComplete function in that callback and it will execute after the ajax request has been completed.
oncomplete:function(xhr,status,args){
prepareForCrtEdtFullPage();
afterComplete()
}
I have 2 javascript functions, the first being a function which loads ajax content (via another function), and a second which is a callback function. They look like:
function createReply(callBack){
ajaxPage('test.html', 'next-reply');
callBack();
}
function updateNext(){
document.getElementById('next-reply').id = "reply-item";
}
createReply(updateNext);
As you can see, I am calling the createReply() function and passing it the name of the callback function, in this case updateNext()
In the createReply() function, I am calling another function which loads content via ajax. When this function is complete, the callback is supposed to be executed. The callback changes the id of the div in which the ajax content is being loaded. This is where the problem is occuring
I am getting the error:
Uncaught TypeError: Cannot set property 'innerHTML' of null
Which is saying that it cannot change the content of the element with the id "next-reply" because it doesn't exist, and the reason it doesn't exist is because the callback function changes the id if that element. The intention is to have the callback fire after the ajax content has been loaded (ie; after the ajaxPage() function has been executed)
Can anyone see what the problem is? Is there a better way of implementing a callback function in plain javascript?
PS: no jQuery
As pointed out in the comments, this is due to the fact that AJAX calls happen asynchronously. The thread that createReply runs in continues to run before a response is returned from the server.
You'll need to re-factor ajaxPage to accept a reference to callback, and call it when the response is ready. Something like:
function createReply(callBack){
ajaxPage('test.html', 'next-reply', callBack);
}
Then, in ajaxPage:
function ajaxPage(url, id, callback){
//Do AJAX stuff
//When the response is returned:
if(callback) callback();
}
Right now you callback is executed right after the ajaxPage function. By right after I mean you do not wait for ajaxPage to return success. It is fired right after the ajax call goes out. It is very likely that it is not completed before your callback is fired.
How can I know that a callback event has fired? I have to perform an activity after the callback event has fired, should I put the code inside the callback function or is there some other way to know when the callback has fired? Even if I put the code of the activity after the statement making the javascript request I cant be sure that the code of the activity will be executed after the callback has fired?
You have to put it in the callback function. You can do this indirectly (e.g. the callback function calls another).
How can I know that a callback event has fired?
do something at the end of the callback. like calling the function that should be invoked after the callback.
I have to perform an activity after the callback event has fired, should I put the code inside the callback function or is there some other way to know when the callback has fired?
There is no other way to determine if a callback has been fired.
Even if I put the code of the activity after the statement making the javascript request I cant be sure that the code of the activity will be executed after the callback has fired?
by "javascript request" do you mean "ajax request". If so I would advise at doing it this way because it most probably will be fired before the callback. At most ajax requests are per definition asynchronous (Asynchronous JavaScript and XML = AJAX). And because of that the script won't wait for the response of the request to continue with itself. That is why you should use callbacks. Callbacks make sure that some code is called after something specified had happened.
How to know that a callback function
has fired?
You can simply put an alert in the callback function to know whether or not it has fired.
Code inside the callback function will fire anyway.
If you had a callback function like following:
setup(data, namespaces, eventHandler) {
$(this).resize(eventHandler);
});
You can pull your callback into another callback and take control before that function is called.
setup(data, namespaces, eventHandler) {
$(this).resize(() => {
console.log("calling eventHandler()")
eventHandler();
});
});