Decoupling style from functionality - JavaScript and jQuery

We’ve all been there.  Working with a front-end developer/designer to get javascript functionality in place on an existing html/css layout.  We get half way through the functionality, depending on the in-place, style purposed, classes and ids.  As the layout gets adjusted, the css gets refined and restructured, all the progress you have made is all but canned, as you have to track down all the dependant DOM selectors and HTML structure that have changed.  This turns into a multi-round process with the UI programmer and designer stepping all over each other in order to work together towards the end goal of style and functionality.  In my experience there are a few things you can do as a javascript engineer to make this process less painful for yourself and your team.

The core of the problem is the multi-purposing of integral items.  In the above scenario you’re using the designer provided classes, ids, and structure that were intended purely for the purpose of style.  What happens when style goals/opinions change and shift?  Your functionality’s foundation changes and shifts.  In some cases, even the slightest changes can leave your previously flawless functionality limping.

Use your own prefixed classes

A good way to get away from this is to provide your own, functionality purposed, classes that are prefixed to indicate to the designer their intended purpose.  These should not be relied on for style, just as the non-prefixed classes should not be relied on to hook your javascript into the DOM.

Provided HTML

<div class="container grid8">  
    <ul class="ul1 horizontal">
        <li>List Item 1</li>
        <li>List Item 2</li>
    </ul>
</div>  

Bad - using style purposed classes/hooks

$('.container.grid8').stuff();
$('.ul1.horizontal').moreStuff();

Adjusting the HTML

<div class="container grid8 ui-specificContainer">  
    <ul class="ul1 horizontal ui-specificList">
        <li>List Item 1</li>
        <li>List Item 2</li>
    </ul>
</div>  

Good - using your own purposed classes/hooks

$('.ui-specificContainer').stuff();
$('.ui-specificList').moreStuff();

Selectors should be as ambiguous as possible

Minimizing the number of clauses contained within your selectors is a big step in the right direction.  In a perfect world your selector would only depend on a single condition to select what you want.  This does take some discretion and nuance, but as a general rule the less number of conditions your element has to qualify, the better.  Selectors should only be as specific as necessary.

If this will accomplish your goal.

$('.ui-targetedElement')

Then why have a selector that looks like this?

$('ul &gt; li a.ui-targetedElement')

This simply introduces unnecessary DOM structure dependencies into the functionality you are building, and you should be able to be proactive in this regard because you should be providing your own hooks (prefixed classes) at this point right?

Traverse the DOM as little as possible

On the heels of the last point, being in control of your own classes/hooks, you should be able to mostly avoid having to write code like this…

$('.selector').parent().parent().sibling('.siblingSelector').find('.targetSelector');

Code like this introduces as much (if not more) DOM structure dependency as the overly verbose selectors above.

Consider a modular approach - provide tools

Extend the HTMLElement prototype to add functionality to any selected DOM element.

HTMLElement.prototype.myPlugin = function() {

    // "this" being the HTMLElement
    // do some cool plugin stuff here

};

Read up on how to build jQuery plugins, which essentially does the same as the example above but uses the jQuery prototype instead of the native HTMLElement

(function( $ ) {
    $.fn.myPlugin = function() {

        // Do your awesome plugin stuff here

    };
})( jQuery );

These are great tools, even for specific functionality that might not be useful outside the project.  It allows you to give your designers and front-end developers tools they can easily implement and keep track of themselves, making everyone happier and more productive.