I have this:
function cool(){
function alsocool(){
}
}
And I run the cool() on button click:
$(selector).on('click', function(){
cool();
}
How can I run the cool() and the alsocool() from the same click? Note that I don't want to do:
function cool(){
function alsocool(){
}
alsocool();
}
If I do :
$(selector).on('click', function(){
cool(); alsocool();
}
it doesn't work.
Is it possible to run a function inside a function on the same call?
EDIT:
I DO WANT to pass cool() since obviously alsocool() is not recognized once its inside function cool() BUT cool(); is passed from many selector thus I want to know from which selector is passed and take the appropriate action.
Example I want something like this:
function cool(){
// If this was called by button1, run alsocool() else bypass it
function alsocool(){
}
// some code goes here
}
$("#button1").on('click', function(){
cool(); alsocool();
// If button1 clicked, run cool AND alsocool
}
$("#button2").on('click', function(){
cool(); // If button2 clicked, run cool ONLY.
}
The answer is simple: It is impossible.
The inner function is local to the containing function's scope so unless that function calls it, it cannot be called at all.
If you want both functions to be reachable from outside, define alsocool outside cool, i.e. on the same level as cool.
As per your comment, here's a way that would use a parameter to determine if the inner function should be called or not:
function cool(callInner){
function alsocool(){
}
if(callInner) {
alsocool();
}
}
If you do
function cool() {
function alsocool() { ... }
}
Then 'alsocool' only exists while the cool() function is executing. It will not be externally accessible.
You'd want:
function cool() { ... }
function alsocool() { ... }
$(selector).click(function() {
cool();
alsocool();
}):
The problem is that because you've defined the function alsocool within cool, it's visibility is limited to that scope.
Because of this, you can only call the function alsocool from within cool.
You can, of course, move the declaration of alsocool outside of cool, and this will still allow you to call alsocool from within cool, but you will loose access to the scope of cool from within alsocool.
You could also limit the invocation of alsocool inside cool depending on a parameter passed, if this is a viable option for you;
function cool(alsoAlsoCool){
function alsocool(){
}
if (alsoAlsoCool) {
alsocool();
}
}
// cool(true) will call it, but cool() or cool(false) won't.
You can't do that. alsocool only exists inside cool, the click handler has no idea alsocool exists.
If you don't want to call alsocool from inside cool, then you're gonna have to make alsocool global.
I don't understand why you want to do that, but you can do this :
function cool()
{
arguments.callee.alsoCool = function() {
alert("also cool");
};
alert("cool");
}
$("#b").click(function() {
cool();
cool.alsoCool();
});
Live demo: http://jsfiddle.net/ENqsZ/
Alternatively, as a Rocket suggested, you can do this :
function cool()
{
alert("cool");
return function() {
alert("also cool");
};
}
$("#b").click(function() {
var alsoCool = cool();
alsoCool();
});
Related
Please check out my diagram, and the pseudo-code below. I'm trying to figure out how to pass a function between two event listeners.
Basically, I want to execute some code if "Availability" is less than 0, OR when a user clicks "confirm" in a bootstrap dialog. If the Availability is greater than 0, you'll get the special bootstrap dialog.
I'm trying to avoid writing the same code twice. I'm also trying to avoid using trigger $("#btnConfirm").trigger("click", fn1); --- my assumption is that there is a sexier way, like a callback, or something...
So.... how do I get the code I want to execute into the other 'button click' event listener --OR-- how do I return "btnConfirm" back to the event listener that called the dialog?
$("#Select").on("change", function(e) {
fn1 = function() {
//stuff I want to do
};
//a check that must be passed
currAvail = $("#Availability").val();
if (currAvail > 0) {
//show a message, "Are you sure you want to make the thing?"
//if YES, execute fn1()
//fn1() needs to be available to btnConfirm click listener
// use trigger("click", fn1) ????
} else {
//execute the code
fn1();
};
});
$("#btnConfirm").on("click", function(e, param1) {
//Ok, well, they said YES...
//so I need to execute fn1();
});
Since the requirement is to call fn1() in both cases, you can separate the logic out into a method and call when it is needed
function fn1() {
//code to execute on no goes here
}
$("#Select").on("change", function(e) {
let currAvail = $("#Availability").val();
if (currAvail > 0) {
//show modal window
} else {
//execute the code
fn1();
};
});
$("#btnConfirm").on("click", function(e, param1) {
fn1()
});
Why not just move the function definition to outside the change callback?
$("#Select").on("change", function(e) {
//a check that must be passed
currAvail = $("#Availability").val();
if (currAvail > 0) {
//show a message, "Are you sure you want to make the thing?"
//if YES, execute fn1()
//fn1() needs to be available to btnConfirm click listener
// use trigger("click", fn1) ????
} else {
//execute the code
fn1();
};
});
$("#btnConfirm").on("click", function(e, param1) {
//Ok, well, they said YES...
//so I need to execute fn1();
});
// Function move to here.
function fn1() {
//stuff I want to do
};
I have to control the timeline of an animation for html5 canvas. I made all buttons and edited all codes. strangely all buttons execute the same function.
this.stop()
//---------------------------------------------------------//
this.letterA.addEventListener("click", fl_MouseClickHandler.bind(this));
function fl_MouseClickHandler()
{
this.gotoAndPlay(32);
}
//---------------------------------------------------------//
//---------------------------------------------------------//
this.letterB.addEventListener("click", fl_MouseClickHandler.bind(this));
}
function fl_MouseClickHandler()
{
this.gotoAndPlay(212);
}
Please read about function hoisting; the function statements are hoisted to the top-of-the-scope, so that your code is equivalent to
function fl_MouseClickHandler() {
this.gotoAndPlay(32);
}
function fl_MouseClickHandler() {
this.gotoAndPlay(212);
}
...
this.stop()
this.letterA.addEventListener("click", fl_MouseClickHandler.bind(this));
this.letterB.addEventListener("click", fl_MouseClickHandler.bind(this));
One solution would be to use function expressions:
var that = this;
this.letterA.addEventListener("click", function () { that.gotoAndPlay(32); });
or if you insist to use bind
this.letterA.addEventListener("click", (function () { this.gotoAndPlay(32); }).bind(this));
From what I can tell, you are binding the same function to two different button click events. You have two different definitions of this same function. One is most likely being written over the other and therefore both buttons will call fl_MouseClickHandler which will call gotoAndPlay with the same timestamp.
Quick fix could be just to change the name of fl_MouseClickHandler:
function fl_MouseClickHandlerA() {
this.gotoAndPlay(32);
}
function fl_MouseClickHandlerB() {
this.gotoAndPlay(212);
}
this.letterA.addEventListener("click", fl_MouseClickHandlerA.bind(this));
this.letterB.addEventListener("click", fl_MouseClickHandlerB.bind(this));
Also, you should watch how you use "this" as you may not be scoped to what you think.
I feel like this is one of those problems you only run into after too little sleep or too many coffees...
I have an element
<a id="blah" href="#">somethinghere.com</a>
I define a function
function test(){
alert('hi');
};
I try to attach the function as a click-handler(https://jsfiddle.net/8r1rcfuw/30/):
$('#blah').on('click', test());
and load the page, and the handler executes immediately - without any clicks.
However when I just use an anonymous function as a handler(https://jsfiddle.net/8r1rcfuw/36/) :
$('#blah').on('click', function(){
alert('hi');
});
it works fine
Doing both (https://jsfiddle.net/8r1rcfuw/39/):
$('#blah').on('click', function(){
test();
});
function test(){
alert('hi');
}
seems to work fine - but seems a little redundant.
This feels like something I've done 1000 times before - what gives?
The event handler has to be a function, and you are passing the result of a function to it:
$('#blah').on('click', test());
is the same as:
$('#blah').on('click', undefined); //As your funcion doesn't return anything
Think of it as a function is a value, you can do:
var myFunction = function() {
alert("Hi");
}
or
function myFunction() {
alert("hi");
}
And then:
$('#blah').on('click', myFunction); //Without invocation!
or using an anonymous function:
$('#blah').on('click', function() {
alert("Hi");
});
You can also use object of function :
var temp=function test() {
alert('hi');
}
$('#blah').on('click', temp);
Try :
$('#blah').on('click', test); // your function name only
Updated Fiddle
I have a panel widget with a button. Clicking the button should execute some global actions related to all such widgets and after that execute some local actions related to this widget instance only. Global actions are binded in a separate javascript file by CSS class like this:
var App = function ()
{
var handleWidgetButton = function ()
{
$('.widgetBtn').on('click', function (e)
{
// do smth global
});
return {
init: function ()
{
handleWidgetButton();
}
};
}
}();
jQuery(document).ready(function()
{
App.init();
});
And in the html file local script is like this:
$("#widgetBtn1234").click(function (e)
{
// do smth local
});
Currently local script is executed first and global only after while I want it to be the opposite. I tried to wrap local one also with document.ready and have it run after global but that doesn't seem to change the execution order. Is there any decent way to arrange global and local jQuery bindings to the same element?
The problem you're having comes from using jQuery's .ready() function to initialize App, while you seem to have no such wrapper in your local code. Try the following instead:
var App = function ()
{
var handleWidgetButton = function ()
{
$('.widgetBtn').on('click', function (e)
{
// do smth global
});
return {
init: function ()
{
handleWidgetButton();
}
};
}
}();
$(function()
{
App.init();
});
Then in your local JS:
$(function() {
$("#widgetBtn1234").click(function (e)
{
// do smth local
});
});
Note that $(function(){}) can be used as shorthand for $(document).ready(function(){});. Also, make sure your JS file is located before your local JS, as javascript runs sequentially.
Alternatively, you can use setTimeout() to ensure everything's loaded properly:
(function executeOnReady() {
setTimeout(function() {
// Set App.isInitialized = true in your App.init() function
if (App.isInitialized) runLocalJs();
// App.init() hasn't been called yet, so re-run this function
else executeOnReady();
}, 500);
})();
function runLocalJs() {
$("#widgetBtn1234").click(function (e)
{
// do smth local
});
};
How about this instead:
var widget = $("#widgetBtn1234").get(0);//get the vanilla dom element
var globalHandler = widget.onclick; //save old click handler
// clobber the old handler with a new handler, that calls the old handler when it's done
widget.onclick = function(e){
//do smth global by calling stored handler
globalHandler(e);
//afterward do smth local
};
There might be a more jqueryish way to write this, but I hope the concept works for you.
-------VVVV----keeping old answer for posterity----VVVV--------
Why not something like this?
var App = function ()
{
var handleWidgetButton = function ()
{
$('.widgetBtn').on('click', function (e)
{
// do smth global
if(this.id === 'widgetBtn1234'){
//do specific things for this one
}
});
return {
init: function ()
{
handleWidgetButton();
}
};
}
}();
Please excuse any syntax errors I might have made as I haven't actually tested this code.
Check out my simple JQ extension I created on jsbin.
http://jsbin.com/telofesevo/edit?js,console,output
It allows to call consequentially all defined personal click handlers after a global one, handle missed handlers case if necessary and easily reset all personal handlers.
How do you call function lol() from outside the $(document).ready() for example:
$(document).ready(function(){
function lol(){
alert('lol');
}
});
Tried:
$(document).ready(function(){
lol();
});
And simply:
lol();
It must be called within an outside javascript like:
function dostuff(url){
lol(); // call the function lol() thats inside the $(document).ready()
}
Define the function on the window object to make it global from within another function scope:
$(document).ready(function(){
window.lol = function(){
alert('lol');
}
});
Outside of the block that function is defined in, it is out of scope and you won't be able to call it.
There is however no need to define the function there. Why not simply:
function lol() {
alert("lol");
}
$(function() {
lol(); //works
});
function dostuff(url) {
lol(); // also works
}
You could define the function globally like this:
$(function() {
lol = function() {
alert("lol");
};
});
$(function() {
lol();
});
That works but not recommended. If you're going to define something in the global namespace you should use the first method.
You don't need and of that - If a function is defined outside of Document.Ready - but you want to call in it Document.Ready - this is how you do it - these answer led me in the wrong direction, don't type function again, just the name of the function.
$(document).ready(function () {
fnGetContent();
});
Where fnGetContent is here:
function fnGetContent(keyword) {
var NewKeyword = keyword.tag;
var type = keyword.type;
$.ajax({ .......
Short version: you can't, it's out of scope. Define your method like this so it's available:
function lol(){
alert('lol');
}
$(function(){
lol();
});
What about the case where Prototype is installed with jQuery and we have noconflicts set for jQuery?
jQuery(document).ready(function($){
window.lol = function(){
$.('#funnyThat').html("LOL");
}
});
Now we can call lol from anywhere but did we introduce a conflict with Prototype?