Pierce McGeough
Pierce McGeough

Reputation: 3086

How to refactor jquery

I have buttons on the page that will activate and deactive settings. the Ids are the same bar their prefix e.g I have '#rl-activate', '#rl-deactivate', '#cl-activate', '#cl-deactivate' Is there a way to refactor this code so i am not doing it for every button on the page.

// rl activate
$('#rl-activate').click(function(){
  $('#rl-activate').hide();
  $('#rl-deactivate').show();
  $('#rl').val(50).prop('selected', true);
  $('#rl').prop('disabled', false).trigger('liszt:updated');
  displayCPM();
  newPrice();
  checkSettings();
});

// rl deactivate
$('#rl-deactivate').click(function(){
    $('#rl-deactivate').hide();
    $('#rl-activate').show();
    $('#rl').prop('disabled', true).trigger('liszt:updated');
    $('#rl').val('').trigger('liszt:updated');
    displayCPM();
    newPrice();
    checkSettings();
});

So for the next one all that changes will be the rl to cl to bm etc

Upvotes: 0

Views: 136

Answers (2)

Denys Séguret
Denys Séguret

Reputation: 382102

You can do this :

$('[id$="-activate"]').click(function(){
  var prefix = this.id.slice(0,2);
  $(this).hide();
  $('#'+prefix+'-deactivate').show();
  $('#'+prefix).val(50).prop('selected', true);
  $('#'+prefix).prop('disabled', false).trigger('liszt:updated');
  displayCPM();
  newPrice();
  checkSettings();
});

$('[id$="-deactivate"]').click(function(){
    var prefix = this.id.slice(0,2);
    $(this).hide();
    $('#'+prefix+'-activate').show();
    $('#'+prefix).prop('disabled', true).trigger('liszt:updated');
    $('#'+prefix).val('').trigger('liszt:updated');
    displayCPM();
    newPrice();
    checkSettings();
});

This uses the "attribute ends with" selector.

An alternate solution would have been to change the HTML to use classes ("activate", "deactivate") and a data-attribute ("cl", "rl").

Upvotes: 2

jfriend00
jfriend00

Reputation: 707218

Following the DRY principle, you can factor some of the code into a common function, use a duplication style that jQuery uses a lot in its own code and leverage jQuery chaining a little more:

 function clickCommon(itemToHide, itemToShow) {
    $(itemToHide).hide()
    $(itemToShow).show();
    displayCPM();
    newPrice();
    checkSettings();
 }

 ["#rl", "#cl"].each(function(pref) {

     $(pref + "-activate").click(function() {
         clickCommon(this, pref + "-deactivate");
         $(pref).val(50).prop('selected', true)
            .prop('disabled', false).trigger('liszt:updated');
     });

     $(pref + "-deactivate").click(function() {
         clickCommon(this, pref + "-activate");
         $(pref).prop('disabled', true).trigger('liszt:updated');
             .val('').trigger('liszt:updated');
     });
 });

Techniques used:

  1. Factor common code between the activate and deactivate clicks into a common function
  2. Use .each() to iterate prefixes from an array (jQuery does this a lot internally in its implementation)
  3. Use this when possible rather than refinding the current element
  4. Construct the activate and deactivate id values in code for each prefix
  5. Use jQuery chaining for all methods called on a common jQuery selector

Upvotes: 1

Related Questions