creating a webtrend function to remove duplication using js apply and call

649 views Asked by At

I have a bunch of webtrend tags to pass to the webtrend server using dcsMultitrack which is pretty simple but there is a lot of duplication of code let say :

1. var args = ["DCSext.name","a", "DCSext.title", "random"]; //etc ...

than selector

2. $("a", "#main").bind("click", function(){
  do some extra stuff.....
  dcsMultitrack.apply(this, args);
})

***

Edit:


$("a", "#main").bind("mouseover", function(){
          do some extra stuff.....
          dcsMultitrack.apply(this, args);
        })
         or maybe 
       $("#main").delegate("mouseover", function(){
          do some extra stuff.....
          dcsMultitrack.apply(this, args);
        })
    etc....

As of no.1 let say I have some common params commonlogs=[]; which will be available for every selector and common ones but there will be additional params case by case than I do not want to repeat those common logs. Moreover, the arguments value I am passing is based based on some dom elements, let's say I am grabbing a value from a dom, let's say color of the selector, name of a player etc. so basically this will have to inside the same context.

case:  $("#selector").bind("click", function(){
          var playername = $(this).parent().text(),
              title = $(this).closest('tr').find(".title").text(); etc etc..
         args = ["DCSext.name", palyername, "DCSext.title", title, etc ];
         dcsMultitrack.apply(this, args);
});

Edit2: to clarify :

 $("#selector1").bind("change", function(){
       var val1 = someval1, val2= someval2, //etc.
            args = ["DCSext.something", val1, "DCSext.title", val2]; //
       dcsMultitrack(this, args);
    });

    $("#selector2").bind("mouseover", function(){
       var val3 = someval1, val4= someval2, //etc.
            args2 = ["DCSext.something", val3, "DCSext.title", val4]; //
       dcsMultitrack(this, args2);
    });

note: args there are some common params let say var commonargs = ["DCSext.common", one, /*etc*/];

1, 2 is repeated all across since values are different, but is there a way to remove the duplication of all this code? I want to extract into a single function and pass only the selector and additional values.

Moreover another issue is:

var context = "#main,#main2";

$(context).delegate("a", "click", function(){
  something ....
 dcsMultitrack.apply(this, args);
});

This works perfectly but can I pass an array instead of a string as context and extract into an function ?

something like

var context = ["#main", "#main2"];

Please let me know if require more clarification .

1

There are 1 answers

6
Peter-Paul van Gemerden On

Your first problem (the code duplication) is easily solved by creating a function:

function bindClick(target, args) {
    target.bind("click", function(){
        // do some extra stuff.....
        dcsMultitrack.apply(this, args);
    });
}

var args = ["DCSext.name","a", "DCSext.title", "random"]; //etc ...
bindClick($("a", "#main"), args);

var otherArgs = ["other", "args"];
bindClick($("a.other"), otherArgs); 

// etc.

Edit: if the way you bind to events differs from one set of args to another, you can create a function that returns another function:

function createCallback(args) {
    return function() {
        // do some extra stuff...
        dcsMultitrack.apply(this, args);
    };
}

And use that to create the callback for .bind():

var args = ["DCSext.name","a", "DCSext.title", "random"]; //etc ...
var callback = createCallback(args);
target.bind("click", callback);

This works because a closure is created so that the anonymous function that is returned by createCallback will still have access to the args parameter, even after createCallback has returned and its scope has closed.


Edit 2: in response to your edited question; why don't you just do this:

function myCallback() {
     var playername = $(this).parent().text(),
         title = $(this).closest('tr').find(".title").text(),
         // etc, etc..
         args = ["DCSext.name", palyername, "DCSext.title", title, /* etc. */ ];

     dcsMultitrack.apply(this, args);
}

And use this callback when binding to events:

$("#selector").bind("click", myCallback);
$("#otherSelector").delegate('mouseover', myCallback);

This will work fine, since this will always point to the DOM element which triggered the event. If there's anything else you've missed in your question, but which differs from case to case, just use a function-that-returns-a-function (like I described) and pass whatever is variable as a parameter.

Hope this helps.


Your second problem is even simpler. Just use Array.join():

var context = ["#main", "#main2"];
var contextString = context.join(','); // '#main,#main2'