Caspert Caspert - 4 months ago 8
jQuery Question

How to send a value with a function within each function?

I use the jQuery

each
function to call mouse events on hover:

$('.entry .post-entry a').each(function(){
root.setDimensions(this);
$(this).on("mouseenter", root.mouseEnter);
$(this).on("mousemove", root.mouseMove);
$(this).on("mouseleave", root.mouseLeave);
$(this).on("click", root.onClick);
});


This works great, but I need to send the index of the item to these functions. The problem is, when I add the function marks:
()
at the end of each function, the function will be called after the page load, but I doesn't want this.

I know one method to send a variable to the function using parameters. But to use these, you should make use of the braces, like so:

$('.entry .post-entry a').each(function(index){
var index = index;
root.setDimensions(this);
$(this).on("mouseenter", root.mouseEnter(index));
$(this).on("mousemove", root.mouseMove(index));
$(this).on("mouseleave", root.mouseLeave(index));
$(this).on("click", root.onClick(index));
});


How can I send a value without calling the function directly?

Answer

Try using bind():

$('.entry .post-entry a').each(function(index){
    var index = index;
    root.setDimensions(this);
    $(this).on("mouseenter", root.mouseEnter.bind(this, index));
    $(this).on("mousemove", root.mouseMove.bind(this, index));
    $(this).on("mouseleave", root.mouseLeave.bind(this, index));
    $(this).on("click", root.onClick.bind(this, index));
 });

With bind() you can bind(duh) a scope for the function(1st parameter) and then the parameters it will receive (2nd and forward param) when executed.


In fact what @RoryMcCrossan said is true: It isn't nice to bind events whitin a loop. The best practice is to bind them with one selection. But, he proposed to use index() inside the event, what can or cannot be a good ideia, depending on the frequency those events will be called. For that you can mix both methods, using bind() and index() togheter, but not repeating them:

$.fn.onWithIndex = function(eventType, callback) {
    $(this).on(eventType, function(e) {
    var $el = $(this),
            index = $el.data("index") ? $el.data("index") : $el.index();

    $el.data("index", index);
    callback.call(this, index, e);
  });
};

// Use
$(".posts a").onWithIndex("mouseenter", root.mouseEnter);

This function is a sample of how to do it. If you need those kind of events a lot, it could be a nice way to go. It run a event wrapper where it checks for a save index in the element's data, if not found, then it runs index(). Remeber that this function is a sample and does not work with the selector parameter like original on() does, e.g.: $('...').on("mouseenter", "another-selector", function() { .. }); - that won't works.

Demo