Background: I was making a chrome extension that injects movie ratings into theatres' showtimes pages. The problem I was duplicating a lot of code calling similar but just slightly different functions. Sometimes I wanted to do an $(el).prepend
, sometimes $(el).append
, or $(el).after
, or $(el).find('something').prepend
, or $(el).closest('something').prepend/append/after
.
An example of an instance of a function I'm trying to generalize/abstract:
$('.FFEC-Display').each(function(i, el){
var title = $(el).find('h3').text().replace(blacklistRegexp, '').trim();
/* can ignore the three lines below, they are always the same
var tomato = findTomato(title, tomatoes);
var classes = ["poster-width", "overlay"];
var templateData = tomato ? prepareData(tomato, classes) : { query: title, classes: namespaceClasses(classes) };
*/
$(el).find('.movie-link').prepend(Handlebars.templates.ratings(templateData)); //this is the line that gives me trouble
});
Another instance:
$('.MovieItemsRotator .item').each(function(i, el){
var title = $(el).find('.Title').text().replace(blacklistRegexp, '').trim();
/* you can ignore the code in here
var tomato = findTomato(title, tomatoes);
var classes = ["overlay", "overlay-poster"];
var templateData = tomato ? prepareData(tomato, classes) : { query: title, classes: namespaceClasses(classes) };
*/
$(el).prepend(Handlebars.templates.ratings(templateData));
});
I have three more instances of very similar functions, and plan on adding more. Full code page here on GitHub
One of the half-joking answers in my SO question inspired me to write a solution using strings of function names, iteratively called on $(el)
to solve the problem.
It started out as an exercise just because it seemed like too fun a solution not to try and write, but now I'm feeling more tempted to actually use the code, as opposed to this other one, which seems much more readable/maintainable. Hopefully people with more experience can give me some advice.
The code in question:
json = [
{target: '.FFEC-Display', title : 'h3', actions : [{action: 'find', target: '.movie-link'}, 'prepend']},
{target: '.MovieItemsRotator .item', title: '.Title', actions: ['prepend']}
];
$.each(json, function(index, j){
$(j.target).each(function(i, el){
var title = $(el).find(j.title).text().replace(blacklistRegexp, '').trim();
/* you can ignore the code in here
var tomato = findTomato(title, tomatoes);
var classes = ["poster-width", "overlay"];
var templateData = tomato ? prepareData(tomato, classes) : { query: title, classes: namespaceClasses(classes) };
*/
var abomination = $(el);
$.each(j.actions, function(k, action){
if(typeof action === "string") {
abomination = abomination[action]();
} else {
abomination = abomination[action.action](action.target);
}
});
abomination(Handlebars.templates.ratings(templateData));
});
});