3

I created a function that makes buttons because I have to make several:

makeButton(function, "text")

The parameters are the function it will be calling "onclick" and the text that will show on the button.

Now I have two of them calling the same function but I want the function to behave in one way if one calls and other way if the other is calling.

I tried to call the function like this:

makeButton(function(flag = true), "text")

And then in the function:

if(flag == true) doSomething;
else doSomethingElse;

Maybe this won't work, but the thing is when I create the button like this:

makeButton(function(flag = true), "text")

It executes the function when creating the button, and I wanted it to execute only onclick.

Other thing I thought was in the function:

if(buttonA) do something;
if(buttonB) do somethingElse;

But I need the function to know which button has called for it...

Do you have any suggestion to do this in other way? Only simple JavaScript please!

The function looks like this:

function makeButton(function, text){
  var button = document.createElement('BUTTON');
  var btTxt = document.createTextNode(text);
  button.style.color = '#006633';
  button.style.fontWeight = 'bold';
  button.onclick = function;
  button.appendChild(btTxt);
  button.style.margin = '5px';
  document.body.appendChild(button);
}
Brian Tompsett - 汤莱恩
  • 5,753
  • 72
  • 57
  • 129
razoes
  • 183
  • 11

4 Answers4

2

As you stated, the code:

makeButton(myFunction(flag = true), "text")

Is unfit for purpose because it executes the function rather than passing it as an argument. Instead, use the bind() function:

makeButton(myFunction.bind(null, true), "text")

This will pass your onclick function as an argument, with its first argument set to true. This can act as your flag:

function myFunction (flag) {
    if (flag) //do something
    else //do something else
}
jonny
  • 3,022
  • 1
  • 17
  • 30
  • Sorry for asking, but I realy am a begginer. `bind()` function isn't jQuery? I'm asking because I'm only allowed to use simple JavaScript. Thanks – razoes Jul 01 '15 at 16:39
  • `bind()` is pure javascript. See more details [here](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/bind) – jonny Jul 01 '15 at 16:41
2

Your function already knows which button it was triggered by through the this keyword. You can see here on this JSFiddle (open the console) that simply by using the this keyword in the bound function we can see the function knows which button clicked it.

var buttonFunctionOne = function() {
    console.log(this);
}
var buttonFunctionTwo = function() {
    console.log(this);
}

makeButton(buttonFunctionOne,'button one');
makeButton(buttonFunctionOne,'button two');
makeButton(buttonFunctionTwo,'button three');

The neatest solution for data is to bind it to the element using data-* attributes, rather than binding a function with a parameter. See a working example here, with the console open again.

function makeButton(functionIn, text, flag){
  var button = document.createElement('BUTTON');
  var btTxt = document.createTextNode(text);
  button.onclick = functionIn;
  button.setAttribute('flag', flag); # flag now set as a data attribute
  button.appendChild(btTxt);
  document.getElementById('js-out').appendChild(button);
}

var buttonFunctionOne = function() {
    console.log(this);
}
var buttonFunctionTwo = function() {
    console.log(this);
}

# flag state passed into make button as a third param
makeButton(buttonFunctionOne,'button one', '1');
makeButton(buttonFunctionOne,'button two', '0');
makeButton(buttonFunctionTwo,'button three', '1');

Now you have an independent identifier to work with on your elements as well as the this keyword which will give you access to all the inherited functions and values unique to the clicked button.

PS, I took your hardcoded styles out of the js, it's not recommended for reasons beyond the scope of this answer (store the styles in a class selector in css and add and remove this class from elements with js). See here for how to manipulate classes in pure javascript.

Community
  • 1
  • 1
Toni Leigh
  • 4,830
  • 3
  • 22
  • 36
1

You'll want to pass a wrapper function.

Assuming your "actual" function is called handler():

function handler(flag) {
  if (flag) {
    // etc.
  }
}

You can do this:

makeButton( function() { handler(true);  }, "button A");
makeButton( function() { handler(false); }, "button B");

Those anonymous functions will be called on their respective button's click.

Paul Roub
  • 36,322
  • 27
  • 84
  • 93
  • The wrapper function is unnecessary. See my answer. – jonny Jul 01 '15 at 16:29
  • 1
    @JonathanBrooks: Making people learn `bind()` is unnecessary. See mine. :-) Seriously, though, there are multiple valid approaches here. We have different ideas of the most-readable version. You may also feel that yours is more efficient (profile that and let me know if there's a meaningful difference). I imagine mine is more approachable to someone trying to grasp how function parameters work. – Paul Roub Jul 01 '15 at 16:37
  • haha sorry dude I didn't mean to come off like an idiot. Now that you mention it, you're totally right...maybe not ideal for someone who doesn't understand the whole `this` scoping problem, yikes! Thanks for putting me in my place, the internet makes me hostile :) – jonny Jul 01 '15 at 16:39
1

You could use event.target to get the info of the button that has been clicked. Then you can access id, or whichever attribute of the clicked button.

function handler(){
    console.log(event.target);
}
Julien Grégoire
  • 16,864
  • 4
  • 32
  • 57