views:

60

answers:

3

I'm looking at the example for the "click" event in the jQuery documentation here. I can refactor the two anonymous functions as follows and it still works:

$(document).ready(function(){
    $("p").hover(hilite, remove_hilite);
  });

  function hilite()
  {
    $(this).addClass("hilite");
  }

  function remove_hilite()
  {
    $(this).removeClass("hilite");
  }

However, what if I want to pass an argument to hilite? My first guess was that I should use an anonymous function like this. However, this does not seem to work, even when I'm using it without arguments:

$("p").hover(
    function()
    {
        hilite();
    }
    ,
    function()
    {
        remove_hilite();
    }
);

I also tried refactoring as follows, but this did not work either:

$(document).ready(function(){
    $("p").hover(hilite2, remove_hilite);
  });

  function hilite2(){
     return hilite();
  }

What is the proper way to do this? I feel like I have a big conceptual misunderstanding. In particular, I am unclear about how in my first refactoring, the this object is passed to the hilite function.

A: 

Why can't you simply call the $(this).addClass() method within the anonymous functions?

$("p").hover(
  function () {
    $(this).addClass("hilight");
  },
  function () {
    $(this).removeClass("hilight");
  }
);
Jonathan Sampson
Yes, that is the original function on the page I linked to. I am trying to explore how it can be refactored. In this case it's just a one-liner, but I anticipate having complex functions that I'd like to store in a separate file so that I can reuse in multiple web pages. Is it not possible to do this?
RexE
+2  A: 

You can encapsulate your hover function call into another function that accepts the 'className' parameter:

$.fn.hoverClass = function(className){
    return this.hover(function(){
        $(this).addClass(className);
    }, function(){
        $(this).removeClass(className);
    });
}

Then you can use it simply by this:

$('p').hoverClass('hilite');
CMS
+1  A: 

I think that what you want is a partial function application.

function partial(func /*, 0..n args */) {
  var args = Array.prototype.slice.call(arguments, 1);
  return function() {
    var allArguments = args.concat(Array.prototype.slice.call(arguments));
    return func.apply(this, allArguments);
  };
}

With the above function, you can now do the following:

$(document).ready(function(){
    var f = partial(hilite, "arg1", "arg2" /*etc...*/);
    $("p").hover(f, remove_hilite);
  });

Reference: http://stackoverflow.com/questions/321113

Andreas Grech