A Lesson in DRY Learned with jQuery


While working on a credit card entry form I decided to add a dynamic block of XHTML to highlight the credit card that is entered by the user, while graying out others. In this code, I attempt to retrieve an image object in the DOM using simple string comparison based on the input of a text field.

    var $card = getCardByNumber($(this).val());
    if($card) {
        lowlightCards();
        highlightCard($card);
    } else {
        highlightCards();
    }

If nothing is found, we ensure that all the cards are highlighted. If a card object is found, gray them all out, but highlight the “found” card.

all_cards_on 
The display when no numbers match the card type pattern.

visa_card_on 
The display when a number matches the Visa card type pattern.

The two functions that gray out all the cards, or subsequently highlight all the cards, originally looked like this. They were very similar and “Don’t Repeat Yourself” (DRY) was screaming out loud. Time to refactor!

    function highlightCards() {
        $(".creditcardicon[src^='/Content/images/']").each(function() {
            highlightCard($(this));
        });
    }
    function lowlightCards() { 
        $(".creditcardicon[src^='/Content/images/']").each(function() {
            lowlightCard($(this));
        });
    }

These worked and I could have left them alone, but a lot of my recent work in C# of passing around Funcs and Actions made it clear to me that there was only one difference here. A difference that JavaScript is totally able to remedy. I’ll just pass into a single function, the difference, which is another function. Good ole’ JavaScript!

    function eachCard(action) {
        $(".creditcardicon[src^='/Content/images/']").each(function() { action($(this)); });
    }
Ignoring Testing can be Explained, but Never Excused