I'm writing a JS webapp client. User can edit list/tree of text items (say, a todo list or notes). I manipulate DOM with jQuery a lot.
User can navigate the list up and down using keyboard (similar to J/K keys in GMail), and perform several other operations. Many of these operations have mirror "up" / "down" functionality, e.g.
$.fn.moveItemUp = function() {
    var prev = this.getPreviousItem();
    prev && this.insertBefore(prev);
    // there's a bit more code in here, but the idea is pretty simple,
    // i.e. move the item up if there's a previous item in the list
}
$.fn.moveItemDown = function() {
    var next = this.getNextItem();
    next && this.insertAfter(next);
    // ....
}
Now this pattern of having two almost identical functions is repeated in several places in my code because there are many operations on the list/tree of items that are pretty much symmetrical.
QUESTION: How do I refactor this elegantly to avoid code duplication?
The trivial way I came up with so far is to use .apply()...
$.fn.moveItem = function(direction) {
        var up = direction === 'up',
            sibling = up ? this.getPreviousItem() : this.getNextItem(), 
            func = up ? $.fn.insertBefore : $.fn.insertAfter;
        // ...
        if (! sibling) { return false; }
        func.apply(this, [ sibling ]);
        // ...
    };
The benefit is easier maintenance when structure of other elements of the code requires changing moveUp/moveDown. I've already needed to slightly change the code multiple times, and I always need to keep in mind that I need to do it in two places...
But I'm not happy with the "unified" version, because:
- Implementation is more complicated than simple moveUp/moveDown, hence in the future it may NOT be so easy to maintain afterall. I like simple code. All these parameters, ternary operations, .apply() tricks in every function that's supposed to go "up" and "down"...
- Not sure if it's safe to refer to jQuery.fn.* functions explicitly (after all they're supposed to be used by applying them to jQuery object $('...').*)
How do you solve those "almost identical code" situations when working with DOM or similar structure?
 
     
     
    