Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • Home
  • SEARCH
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 7949025
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: June 4, 20262026-06-04T01:52:51+00:00 2026-06-04T01:52:51+00:00

I’m writing a JS webapp client. User can edit list/tree of text items (say,

  • 0

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?

  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-06-04T01:52:53+00:00Added an answer on June 4, 2026 at 1:52 am

    One thing that you can do is to use closures to hide the configuration parameter passing from the user:

    var mk_mover = function(direction){
         return function(){
             //stuff
         };
    };
    
    var move_up = mk_mover("up");
    var move_down = mk_mover("down");
    

    If you want to continue in this direction, it becomes basically a matter of deciding what is the best way to pass the parameters to the common implementation, and there is no single best solution for this.


    One possible direction to go is to use an OO style approach, passing a configuration “strategy” object to the implementation function.

    var mk_mover = function(args){
        var get_item = args.getItem,
            ins_next = args.insNext;
        return function(){
            var next = get_item.call(this);
            next && ins_next.call(this, next);
        };
     };
    
     var move_up = mk_mover({
         get_item : function(){ return this.getPrevious(); },
         get_next : function(x){ return this.insertBefore(x); }
     });
    
     var move_down = mk_mover({/**/});
    

    I prefer doing this when the strategy interface (the methods that differ between directions) is small and relatively constant and when you want to open up the possibility of adding new kinds of direction in the future.

    I also tend to use this when I know that neither the set of directions nor the kinds of methods will need to change much, since JS has better support for OO then for switch statements.


    The other possible direction to go is the enum approach that you used:

    var mk_mover = function(direction){
        return function(){
            var next = (
                direction === 'up' ? this.getNextItem() :
                direction === 'down' ? this.getPreviousItem() :
                null );
    
            if(next){
                if(direction === 'up'){
                    this.insertAfter(next);
                }else if(direction === 'down'){
                    this.insertBefore(next);
                }
            }
    
            //...
        };
    }
    

    Sometimes you can use neat objects or arrays instead of switch statements to make things prettier:

    var something = ({
        up : 17,
        down: 42
    }[direction]);
    

    While I have to confess that this is kind of clumsy, it has the advantage that if your set of directions is fixed early on, you now have lots of flexibility to add a new if-else or switch statement whenever you need to, in a self-contained manner (without needing to go add some methods to the strategy object somewhere else…)


    BTW, I think that the approach you suggested sits in an uncomfortable middle ground between the two versions I suggested.

    If all you are doing are switch inside your function depending on the value direction tag passed, its better to just do the switches directly in the spots you need to without having to refactor things into separate functions and then having to do lots of annoying .call and .apply stuff.

    On the other hand, if you went through the trouble of defining and separating the functions you can make it so that you just receive them directly from the caller (in the form of a strategy object) instead of doing the dispatching by hand yourself.

    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

link Im having trouble converting the html entites into html characters, (&# 8217;) i
For some reason, after submitting a string like this Jack’s Spindle from a text
I have a jquery bug and I've been looking for hours now, I can't
I have a string like this: La Torre Eiffel paragonata all’Everest What PHP function
I'm parsing an RSS feed that has an ’ in it. SimpleXML turns this
I need to clean up various Word 'smart' characters in user input, including but
I have a text area in my form which accepts all possible characters from
Does anyone know how can I replace this 2 symbol below from the string
I am writing an app with both english and french support. The app requests
I have a reasonable size flat file database of text documents mostly saved in

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.