2

Well, I don't know any other way to ask this. So, Here is an example:

element.onclick = myfunction(50, 3);

function myfunction(event, offset, space){
    event.preventDefault();
    // do some stuff here with offset & space
}

Now when I call this function it cannot recognize my "event" object because the other function parameters conflicts with it, I know that the function should be called as (callback) but I need the parameters to do somethings for me, So how to do this?

I need to use my function with more than one element, So each of them will get different (offset & space) value.

Brian Tompsett - 汤莱恩
  • 5,753
  • 72
  • 57
  • 129
Hamed Adil
  • 473
  • 1
  • 7
  • 15

1 Answers1

2

First, I'll show where is your mistake. You're overridding onclick with this:

element.onclick = myfunction(50, 3);

This expression actually means that you call myfunction, then save the returned value into element.onclick. If you want to assign a function, you should write it as the following:

element.onclick = myfunction;

Now I'll list some of the ways to pass data to the event handler.

Scope

You can use JavaScript's scope feature:

var a = 50, b = 3;

element.onclick = function (e) {
  // use e(event), a, or b just normally
};

For example

(function () {
  var element, offset = 1, space = 2;

  element = document.getElementById('x');

  element.onclick = function (e) {
    console.log('onclick', offset, space);
  };

  // Modify the scope variables every second
  window.setInterval(function () { offset++; space++; }, 1000);
})();

bind()

If you want different offset and space values for different handlers within the same scope, you can bind() them:

element.onclick = function (o, s, evt) {
  // Note, `this` variable is a reference to `element`.
  console.log('onclick', o, s);
}.bind(element, offset, space);

Note, that the arguments are passed by value(i.e. their values will not be changed within the handler), unless they are objects. However, if you bind an object, the object will be still bound to the scope:

var nodeX, nodeY;

nodeX = document.getElementById('x');
nodeY = document.getElementById('y');

nodeX.onclick = function (y, evt) {
  console.log(y.id);
}.bind(nodeX, nodeY);

// Modify nodeY.id after 5 seconds
window.setInterval(function () { nodeY.id = 'modifiedY'; }, 5000);

The click handler will log y, if the user clicks on nodeX in the first 5 seconds. After the first 5 seconds modifiedY will be logged.

Of course, you can bind static values as well:

someFunction.bind(element, 1, 2);

Custom properties

You can also set the values as the element properties(see this):

element.myData = {offset: 50, space = 3};

then use within the callback:

element.onclick = function (e) {
  var target;

  if (!e) var e = window.event;

  target = e.target || e.srcElement;

  // Use target.myData.offset, target.myData.space
};

Here we assign anonymous function as element's click event handler.

The event handler normally accepts an event argument. However, Microsoft defined its own rules, where the event argument is stored in window.event. So we assign e to window.event, if e is undefined.

If Microsoft had followed W3C standards, we would have used only e.target as the event target. But the company defined its own property called srcElement. So we pick one of them by means of the OR operator:

target = e.target || e.srcElement;

Since the event target is a reference to the object that dispatched the event, then it becomes a reference to our element node. Consequently, we can get any element property including myData: target.myData.

Community
  • 1
  • 1
Ruslan Osmanov
  • 20,486
  • 7
  • 46
  • 60
  • Thanks for your answer.. I need to use the same function with different element's onclick, but each element will get different (offset and space). – Hamed Adil May 06 '16 at 12:25
  • @HamedAdil, added another option to the answer. However, I'd recommend using the scope, if possible(and it's more often possible, than not). – Ruslan Osmanov May 06 '16 at 12:41
  • Thank you for your answer, However I didn't understand how this solution works. – Hamed Adil May 06 '16 at 20:49