JavaScript nested functions : how to avoid loops - javascript

I am creating a little javascript/jQuery application with differents steps.
For that I am using a js file with different functions.
At the top of the file I call my first function.
Inside my first function I call a second function when clicking on a button.
Inside the second function I'd like to call back the first one, but "outside" the second one : I mean I don't want the first function to be run inside the second one, because of looping effects...
myFirstFunction();
function myFirstFunction() {
// some code
$('myButton').click(function() {
mySecondFunction();
}
}
function mySecondFunction() {
// some code
$('myOtherButton').click(function() {
myFirstFunction();
}
}
I don't know if this is possible, may be I'd better use objects or else, but I'm pretty new to Javascript...
Thanks in advance for your help.

You can use single event handler there:
var handler = myFirstFunction;
$('myButton').click(function() { handler(); });
function myFirstFunction() { handler = mySecondFunction; }
function mySecondFunction() { handler = myFirstFunction; }
That handler will call either one of your functions.
Update: Or if these are two distinct buttons then
$('myButton').click( mySecondFunction );
$('myOtherButton').click( myFirstFunction );

You're right that it's good to avoid nesting functions within eachother for reasons that you mentioned it might get messy. I'm sure somebody else can weight in, but if you want to stick in vanilla JS i would create a variable that you modify the state of and have a conditional statement determine what function to run.
var state = 1;
function handler(){
if(state == 1){
myFirstFunction();
state = 2;
}
else if(state == 2){
mySecondFunction();
state = 1;
}
}
Then have your myButton execute the handler() function.

Related

Can I use a parent function's parameter to name its child function?

I have a parent function with a single parameter.
I want to use this parameter in the naming of a couple child functions.
Can this be done?
function A(red) {
function redBall() {
stuff
}
function redHat() {
stuff
}
}
This is a more specific example of what I am trying to create.
I would run this function many times, which is why I need the child functions to have unique names based on the parameter provided.
function name(parameter) {
let parameterThis = '"' + parameter + 'This"';
let parameterThat = '"' + parameter + 'That"';
let $button = '$(".button.' + parameter + '")';
function parameterEnter() {
document.getElementById(parameterThis).style.opacity = "1";
document.getElementById(parameterThat).style.display = "block";
}
function parameterLeave() {
document.getElementById(parameterThis).style.opacity = "0";
document.getElementById(parameterThat).style.display = "none";
}
$button.hover(parameterEnter,parameterLeave);
}
TLDR: renaming functions isn't what you really want.
You don't need to make your functions named differently for it to work. That's not how programming is supposed to work. Instead, try to generalize what you're trying to do, so that it can be applied to whatever you pass in. Like, if you need it to do different things in certain cases, add another parameter to the function. Or, if you need unique things to happen for each element, make your function take enter/leave callback functions as arguments. Even if you did programmatically set the function names, you'd have a hard time calling them anyways, because you wouldn't know what they were called.
You could do something like this :
functionA (boolean condition)
{
if (condition)
fonctionB();
else
fonctionC();
}
functionB()
{
// Stuff
}
functionC()
{
// Stuff
}
If what you intend to do is to actually declare a function or another depending of a parameter, I don't think that's possible. But I don't really get why you would want to do that, and perhaps we could help you better if you were more accurate on that matter.
You can try like this, maybe simpler than passing arguments?
var foo = function() {
this.a = function () {
console.log('A function');
}
this.b = function() {
console.log('B function');
}
return this;
}
Then call function you want like this for example
foo().a();
EDIT:
I missunderstood your code, If I understand correctly now, you want to pass purely a string and then call function with such name immediately?
Well, you can do it using eval() but many people advise to stay away from using it, anywhere here it is:
function foo(whatFunction) {
function a() {
console.log('a function');
}
function b() {
console.log('b function')
}
eval(whatFunction)();
}
So then call it foo('b') for example
Seems like the answer to my actual question is no, judging by how everyone has responded.
I'll have to keep thinking on it and find another way to simplify my code.

Remove event listener from an element with parameters

I'd like to remove an event listener from an element but its function has to take a parameter and it seems to not work. I was trying to find a solution on internet but anyone seems to have the same problem as me.
The role of the function is to simply change the visibility of the element
It doesn't make much sense to remove the listener immediatly but it's only for the example.
function createHoverEqElts() {
slotElts.forEach(function(slot, i) {
if(existValueElts[i].value == "true") {
let infoElt = document.createElement('div');
infoElt.style.position = "relative";
infoElt.style.bottom = "71px";
slot.appendChild(infoElt);
slotListenersElts.push(infoElt);
slot.addEventListener('mouseover', _slotListener(infoElt));
slot.removeEventListener('mouseover', _slotListener(infoElt));
slot.addEventListener('mouseout', function() {
infoElt.style.visibility = "hidden";
});
}
});
}
let _slotListener = function(elt) {
return function() {
elt.style.visibility = "visible";
}
}
I think your problem is that you return a function for some reason. You should pass a function that does something. Try this.
let _slotListener = function(elt) {
elt.style.visibility = "visible";
}
And then do this. In this scenario, you can also pass null instead of this, try either one.
slot.addEventListener('mouseover', _slotListener.bind(this, infoElt));
Since your function returns an anonymous function, you lose its reference. removeEventListener needs the same occurrence to work properly.
In other words _slotListener(infoElt) == _slotListener(infoElt) will always return false, so removeEventListener('event', _slotListener(infoElt)) will never work.
Store the function returned by _slotListener() somewhere and use it back to remove the event. In your example, it could be in a variable. In a more complex example, it could be in an object with some kind of reference or in a property in the DOM element.
var callback = _slotListener(infoElt); // save reference
slot.addEventListener('mouseover', callback);
slot.removeEventListener('mouseover', callback);
The reason you cannot remove the event listener effectively is because the function that you are passing to addEventListener is not the same as the function that you are passing to removeEventListener. JavaScript cannot compare two functions that have the exact same contents and tell they are the same function. Every single time you call _slotlistener, it creates a new function that is not the same as functions that were previously returned by _slotlistener. Instead, the proper way to do this would be to assign the result of _slotlistener to a variable, and then pass that variable into addEventListener and removeEventListener. For example,
var myListenerFunc = _slotListener(elt);
slot.addEventListener("mouseover", myListenerFunc);
slot.removeEventListener("mouseover", myListenerFunc);

Add event listener of a method present in another js file

I am accessing few methods written in another js file. So i'm accessing them like this:
file1:
function minit() {
this.addval = function(val1, val2) {
return val1 + val2;
}
function autoexecute(d) {
//do something here//
//raise event//
}
};
file2:
var con = new minit();
var result = con.addval(2, 3);
/*
con.autoexecute(function(d) { //Wanna do something like this
alert(d);
});
*/
Above things are working as expected, getting result..
Now, Suppose autoexecute(d) method is invoking automatically after a time interval. How can i know if the method is executed ?
So that, I want to create an event(in file2) of autoexecute(d)(in file1).
UPDATE:
I hope this example will help you to understand the issue..
company.js //this is the main file which will be used as a reference in ui.html
function hello(personname) { //this method will invoke automatically after 1 minute..
}
ui.html
<script src="company.js"></script>
<script>
$(document).ready(function() {
function bye(personame) { //this method will be called automatically if hello method invoked.... personame is the argument passed from hello method//
alert("comany.js -> hello function is executed");
}
});
</script>
You can only do this if the functions have the same scope (global scope is the best case scenario). If the autoexecute function has local scope then you cannot to do it.
In essence, override the original function like this...
// keep a reference to the original function
var _autoexecute = autoexecute;
// override the original function with your new one
function autoexecute(d) {
alert("before autoexecute"); // fired before the original autoexecute
_autoexecute(d); // call the original autoexecute function
alert("after autoexecute"); // fired after the original autoexecute
}
Now, whenever autotexecute is called it will call your new function which can handle both before and after events, as well as calling the original function. Just remove the (horrible) alerts and replace with event handlers as required.
To my knowledge, and someone should correct me if I am wrong, there is no way (at least without some library) to detect a function being fired in javascript. Function executions do not fire an event that other functions can 'handle' in that that sense.
In your example you wanted a function to automatically fire after the other function has fired, all you need to do is call the function you want to fire at the end of the one that was "fired" in the first place. Confusing but hope this helps.
function handler(){
alert("main function was fired!");
}
function main(){
//Code of main goes here and then at the end just add:
handler();
}
Now when your "main" has finished its work it will call upon the handler function.
Regardless of where you define the handler function, which can be a different file or same file, so long as it is reachable from within the main's scope, it will be fired at the end of it. It can even be declared after main has been declared, so long as it is declared before main is fired.

Cache a variable exclusively on a function

Is there a way to cache a global variable for a function within a group of functions, without calling that function directly from another?
For example, if I have a group of functions wrapped in a parent function like this:
function parentFunction() {
var myVariable;
someDiv.addEventListener('click', function (e) {
myVariable = e.target;
});
anotherDiv.addEventListener('click', function (e) {
// use myVariable without it changing when the above is fired again.
});
}
The global variable is declared at the start, it is given a value in the first function, which carries over to the second for use.
But how can I stop it from continually updating in the second function, if the first function fires again?
Could I add another event-listener inside the second function to check if the first fires again and ensure the variable doesn't change?
You can set the variable only once in the first function:
someDiv.addEventListener('click', function (e) {
if (!clickedLink) {
clickedLink = e.target;
}
});
Or, you can apply any logic you want there. Sometimes, saving state like this in a semi-global for later use in a different event handler is a warning sign that you might have a design issue. If you explain more about what you're really trying to do, we could offer an opinion on whether there's a better way to solve your design issue.
Not sure if I fully understand the question. If you want to have two distinct bindings, you need two variables. Maybe so:
function parentFunction() {
var myVariable, anotherVariable;
someDiv.addEventListener('click', function (e) {
myVariable = e.target;
if (!anotherVariable) {
anotherVariable = e.target;
}
});
anotherDiv.addEventListener('click', function (e) {
// use anotherVariable
});
}

Javascript: Possible to pass function commands to another function via a variable?

Ok hopefully this come across correctly. I am building a universal javascript function that will build a menu and then also build the functions that each menu item would call. To do this, I need to pass a list of the commands to be called for each option.
So for example:
var thecall = 'alert("hi, this works");';
function myfunction(thecall)
{
//In here I want to excute whatever commands is listed in variable thecall
.....
}
I'm sure doing it this way is completely stupid, but I don't know how else to do this.
Basically, I need my function to perform other functions on a variable basis.
Thanks!!
I made it a bit fancier to show you how you can use it.
var thecall = function(name){alert("hi " + name + ", this works");};
function myFunction(function_ref)
{
function_ref('Mark');
}
myFunction(thecall);
You can execute arbitrary strings of JavaScript using eval(), but that is not the best solution for you here (it's almost never the best solution).
Functions in JavaScript are themselves objects which means you can store multiple references to the same function in multiple variables, or pass function references as parameters, etc. So:
var thecall = function() {
alert("hi, this works");
};
function myfunction(someFunc) {
someFunc(); // call the function that was passed
}
myfunction(thecall); // pass reference to thecall
Note that when passing the reference to the thecall function there are no parentheses, i.e., you say thecall not thecall(): if you said myfunction(thecall()) that would immediately call thecall and pass whatever it returned to myfunction. Without the parentheses it passes a reference to thecall that can then be executed from within myfunction.
In your case where you are talking about a list of menu items where each item should call a particular function you can do something like this:
var menuItems = [];
function addMenuItem(menuText, menuFunction) {
menuItems.push({ "menuText" : menuText, "menuFunction" : menuFunction });
}
function test1() {
// do something
}
addMenuItem("Test 1", test1);
addMenuItem("Test 2", function() { alert("Menu 2"); });
// and to actually call the function associated with a menu item:
menuItems[1].menuFunction();
Notice the second menu item I'm adding has an anonymous function defined right at the point where it is passed as a parameter to addMenuItem().
(Obviously this is an oversimplified example, but I hope you can see how it would work for your real requirement.)
I think your looking for the eval function.
var code= 'alert("hi, this works");';
eval(code);

Categories

Resources