3
\$\begingroup\$

According to the value of a dropdown menu I have to show/hide two panels. For option 'derive' and 'reject' I should show the comment panel, and just for the 'derive' panel I should also show a derivation panel. There are other

This works, but how could I refactor the code to make it shorter and more efficient without losing clarity?

 $("#formTabs").on( "change", "select.actions",function(){

        var parentContainer = $(this).closest("fieldset");

        if(this.value == "reject" || this.value == "derive"){
            parentContainer.find(".commentPanel").show();   
        } 
        // other 3 options where the panel should not show up.
        else { 
            parentContainer.find(".commentPanel").hide();
        }

        // Just for the derive option, a derivation panel must be shown.
        if(this.value == "derive"){ 
            parentContainer.find(".derivationPanel").show();
        } else {
            parentContainer.find(".derivationPanel").hide();            
        }       
    }); 
\$\endgroup\$

2 Answers 2

2
\$\begingroup\$

The only "efficiency" improvement I see is caching the result of the this.value == "derive" check to avoid evaluating the string comparison twice. The effect of this is close to nothing, on the other hand it's good to reduce the number of duplicated literals.

".commentPanel" and ".derivationPanel" are also duplicated literals, so it would be good to eliminate those too.

Lastly, I would recommend some minor style improvements:

  • Don't put a space between ( "change"
  • Put a space after the comma in "select.actions",function
  • Put a space between ){ in function(){, everywhere

Putting it together:

$("#formTabs").on("change", "select.actions", function() {

    var parentContainer = $(this).closest("fieldset");
    var commentPanel = parentContainer.find(".commentPanel");
    var derivationPanel = parentContainer.find(".derivationPanel");
    var isDerive = this.value == "derive";

    if (this.value == "reject" || isDerive) {
        commentPanel.show();   
    } else { 
        // other 3 options where the panel should not show up.
        commentPanel.hide();
    }

    // Just for the derive option, a derivation panel must be shown.
    if (isDerive) { 
        derivationPanel.show();
    } else {
        derivationPanel.hide();            
    }       
});

Note that by extracting the commentPanel, derivationPanel, isDerive variables you don't lose any efficiency at all, as all the right-hand sides would be evaluated in the code no matter what. This rewritten version is better, because of the string literals now appear only once, which eliminates typos, and if you need to change something, you can do it at a single place instead of two as in the original.

\$\endgroup\$
4
  • \$\begingroup\$ In the case of isDerive, declaring that extra variable does not produce any performance drawbacks? If not, why? \$\endgroup\$ Commented Oct 28, 2014 at 3:06
  • \$\begingroup\$ It's the opposite: it's the only thing in the above code that improves performance. Thanks to it, JavaScript can evaluate the expression this.value == "derive" once instead of twice. So one string comparison instead of 2 string comparisons. \$\endgroup\$
    – janos
    Commented Oct 28, 2014 at 6:15
  • \$\begingroup\$ Ok, but in the case that ´isDerive´ was evaluated just once in the code, the performance would be worst when declaring and assigning the value compared with evaluating in just inside the if statement? o declaring variables is near to costless? \$\endgroup\$ Commented Oct 28, 2014 at 13:15
  • 1
    \$\begingroup\$ The cost of a single (small) variable + 1 string comparison is surely smaller than the cost of no variables but 2 string comparisons. \$\endgroup\$
    – janos
    Commented Oct 28, 2014 at 13:53
1
\$\begingroup\$

If the panels are never dynamically recreated then you can move the code to find them outside the event handler so that you do not need to traverse the DOM each time the event is called.

You can also make the code shorter by using .toggle() rather than .show() and .hide().

var formTab  = $("#formTabs");
var fieldset = formTab.closest("fieldset");
var comments = fieldset.find(".commentPanel");
var derivations = fieldset.find(".derivationPanel");

formTab.on("change", "select.actions", function(){
        comments.toggle(this.value == "reject" || this.value == "derive");
        derivations.toggle(this.value == "derive");
    }); 
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.