user6659397
user6659397

Reputation:

How to shorten these jQuery functions?

I have these 3 jQuery functions that basically do the same thing, but they are a tiny bit different (width of window, and class that is removed/toggled)

I need the functionality of all these 3 functions, but want to somehow combine them/shorten them into one function. I've tried to but my code keeps breaking Can anyone help to shorten them?

Here are the 3 functions

jQuery(document).ready(function($) {
  $('.exampleimg').click(function() {
    $('.about').hide(600);
    if (($(window).width() > 670) && ($(this).hasClass('exampleimgopen'))) {
      $(this).removeClass('exampleimgopen');
    } else if ($(window).width() > 670) {
      $('.exampleimg').removeClass('exampleimgopen');
      $(this).addClass('exampleimgopen');
    }
  });
});

jQuery(document).ready(function($) {
  $('.exampleimg').click(function() {
    $('.about').hide(600);
    if (($(window).width() < 670) && ($(this).hasClass('exampleimgopen2'))) {
      $(this).removeClass('exampleimgopen2');
    } else if ($(window).width() < 670) {
      $('.exampleimg').removeClass('exampleimgopen2');
      $(this).addClass('exampleimgopen2');
    }
  });
});

jQuery(document).ready(function($) {
  $('.exampleimg').click(function() {
    $('.about').hide(600);
    if (($(window).width() < 540) && ($(this).hasClass('exampleimgopen3'))) {
      $(this).removeClass('exampleimgopen3');
    } else if ($(window).width() < 540) {
      $('.exampleimg').removeClass('exampleimgopen3');
      $(this).addClass('exampleimgopen3');
    }
  });
});

Upvotes: 0

Views: 84

Answers (2)

nem035
nem035

Reputation: 35501

I need the functionality of all these 3 functions, but want to somehow combine them/shorten them into one function.

Generally, a good approach when refactoring similar functions is to create a single factory function that will take your variable data as arguments and return a function that has access to that data via its closure.

function myFactory(conditionFunc, windowWidth, cssClass) {
  return function() {
    $('.about').hide(600);
    var windowCondition = conditionFunc($(window).width(), windowWidth);
    if (windowCondition && ($(this).hasClass(cssClass))) {
      $(this).removeClass(cssClass);
    } else if (windowCondition) {
      $('.exampleimg').removeClass(cssClass);
      $(this).addClass(cssClass);
    }
  }
}

Then you can call this function 3 times to build your functions:

// helper methods that will perform '<' or '>' on window width
var lessThan = function(a, b) { return a < b; };
var greaterThan = function(a, b) { return a > b; };

var func1 = myFactory(greaterThan, 670, 'exampleimgopen');
var func2 = myFactory(lessThan, 670, 'exampleimgopen2');
var func3 = myFactory(lessThan, 540, 'exampleimgopen3');

Which you can then pass each into their corresponding listeners.

$('.exampleimg').click(func1);
$('.exampleimg').click(func2);
$('.exampleimg').click(func3);

The advantage of doing things this way is that you only write a single function which then creates different versions of your listener callback functions, based on the data you give to it.

Upvotes: 3

Tibrogargan
Tibrogargan

Reputation: 4603

I think is maybe closer to what you wanted, although it's unclear what you wanted to have happen when the width was < 540. Might want to use if .. then ... else instead

jQuery(document).ready(function($) {
    $('.exampleimg').click(function() {
        var width = $(window).width();
        var classes = [];
        if (width < 540) {
            classes.push('exampleimgopen3');
        }
        if ($(window).width() < 670) {
            classes.push('exampleimgopen2');
        }
        if ($(window).width() >= 670) {
            classes.push('exampleimgopen');
        }
        classes.forEach(function(class) {
            $('.exampleimg').removeClass(class);
            if (!$(this).hasClass(class)) {
                $(this).addClass(class);
            }
        });
    });
});

Upvotes: 0

Related Questions