0

I have elements that when I click on them I need to run a function and that function needs to know what element was clicked on.

Example A:

var elements = $(".config-cell");
        for (var i = 0; i < elements.length; i++) {
            elements[i].addEventListener("click", function() {
                console.log("clicked");
            });
        }

When calling the function right there it works fine, however I don't know how to pass through the element to the function so it can use it.

So I tried using this method and found something strange.

Example B:

var elements = $(".config-cell");
        for (var i = 0; i < elements.length; i++) {
            elements[i].addEventListener("click", this.cellCrop());
        }

When simply calling the function located elsewhere I noticed when loading the window it just automatically fires the function and then it doesn't even add the event listener so any time you click after that nothing happens.


Bottom line I would like to be able to pass through the current element being clicked on and have it fire a function. But I would like to know out of curiosity why method B works the way it does.

Learned that it knows which to use because 'forEach' has a callback with parameters

.forEach(function callback(currentValue[, index[, array]])

For instance: How does this call back know what is supposed to be 'eachName' and 'index'

var friends = ["Mike", "Stacy", "Andy", "Rick"];
friends.forEach(function (eachName, index){
  console.log(index + 1 + ". " + eachName); // 1. Mike, 2. Stacy, 3. Andy, 4. Rick
});

And can you do this with .addEventListener instead of setting it as a var?

That being said is there a way to have it pass variables with your own function? Like:

var passthrough = 5;
            $(".config-cell").on("click", function(passthrough) {
                var five = passthrough;
                console.log(five);
            });
CTOverton
  • 616
  • 2
  • 9
  • 20

2 Answers2

1

Try this : You can make use of $(this)

$(".config-cell").on("click", function(){
   var clickedCell = $(this);// this refers to current clicked cell which can be used to get other details or write logic around it
});
Bhushan Kawadkar
  • 28,279
  • 5
  • 35
  • 57
1

First, this.cellCrop() calls the function, this.cellCrop passes it. So if you wanted to set the listener it would have been

elements[i].addEventListener("click", this.cellCrop);

Now to actually get the element clicked on inside the function you can do it a couple ways.

Using currentTarget / target from the event object that is automatically passed to event listeners

elements[i].addEventListener("click", function(event){
  //the actual element clicked on
  var target = event.target;
  //the element the event was set on, in this case whatever elements[i] was
  var currentTarget = event.currentTarget;
});
//same using jQuery
$(elements[i]).click(function(event){
  var target = event.target;
  var currentTarget = event.currentTarget;
});

Using the this keyword

elements[i].addEventListener("click", function(event){
  //this will refer to whatever elements[i] was
  var target = this;
});
//same using jQuery
$(elements[i]).click(function(event){
  var target = $(this);
});

This would apply the same with using object method:

obj = {
  cellCrop:function(event){
     var target = event.target;
     /* etc */
  },
  someOtherMethod:function(){
     //...
     elements[i].addEventListener("click",this.cellCrop);
     //or jQuery
     $(elements[i]).click(this.cellCrop);
     //...
  }
};
obj.someOtherMethod();

How does this call back know what is supposed to be 'eachName' and 'index'

Because documentation for the forEach method tells the person using it how it is going to be called. So you write the callback based on that documentation.

For instance the callback for forEach usually takes the form of

function callback(currentValue[, index[, array]])

Which means inside forEach() it is going to call your callback in this fashion

function forEach(callback){
  //`this` inside forEach is the array
  for(let i=0; i<this.length; i++){
     callback(this[i], i, this);
  }
}

As for passing arbitrary data to the function, there are a few ways it can be done:

Wrap a call to a function in an anonymous function and explicitly call the function with more arguments

obj = {
  cellProp:function(event,a,b,c){
    var element = event.currentTarget;
  }
}
//normal anonymous function
elements[i].addEventListener('click',function(e){
  obj.cellProp(e,1,2,3);
});
//fat arrow function
elements[i].addEventListener('click',e=>obj.cellProp(e,1,2,3))

In the above a, b and c will respectively contain the values 1,2 and 3

You can also use methods like bind which will change the thisArg(see this question to see more on that) of the function but also pass in arguments to the function

obj = {
   //note event comes last as bind, call, and apply PREPEND arguments to the call
   cellProp:function(a,b,c,event){
      //`this` will change depending on the first
      //argument passed to bind
      var whatIsThis = this;
      var element = event.target;
   }
}
//passing obj as the first argument makes `this` refer to 
//obj within the function, all other arguments are PREPENDED
//so a,b, and c again will contain 1,2 and 3 respectively.
elements[i].addEventListener('click', obj.cellProp.bind(obj,1,2,3) );

In the case of jQuery, you can also pass data in using an object at the time of setting up the event:

obj = {
  cellProp:function(event){
    var data = event.data;
    console.log(data.five);
  }
}

jQuery(elements[i]).click({five:5},this.cellProp);
Patrick Evans
  • 41,991
  • 6
  • 74
  • 87
  • One more quick question. So if you wanted to pass through say a number like '5' and then in that function reference that value as a variable like 'five' so that 'five = 5' how would you pass that variable through and reference it? My guess would be doing like 'function(event, 5)' but then how do you associate it with that varaible 'five'? – CTOverton Jul 11 '18 at 18:53
  • Added more in depth in the question at the bottom – CTOverton Jul 11 '18 at 19:10