0

I have some filters that are being displayed as checkboxes on my website. Each time someone checks or unchecks one of these inputs I either want to add or remove the filter to/from the URL. I have this mostly working, but the problem comes when removing the last filter in the list.

Here's an example:

var getUrlParameter = function getUrlParameter(sParam) {
    var sPageURL = window.location.search.substring(1),
        sURLVariables = sPageURL.split('&'),
        sParameterName,
        i;

    for (i = 0; i < sURLVariables.length; i++) {
        sParameterName = sURLVariables[i].split('=');

        if (sParameterName[0] === sParam) {
            return sParameterName[1] === undefined ? true : decodeURIComponent(sParameterName[1]);
        }
    }
};

$(function () {
    var colors = getUrlParameter('colors');
    var currentUrl = location.href;
    
    $('input[type="checkbox"]').change(function () {
      var inputVal = $(this).val();
      
      if (this.checked) {
        // Add filter to URL params
        colors = getUrlParameter('colors');
        if (!colors) {
          // No filters exist yet
          currentUrl += '?colors=' + inputVal;
        } else {
          // At least one filter exists
          currentUrl += ',' + inputVal;
        }
        console.log(currentUrl);
        window.history.pushState("object or string", "Title", currentUrl);
      } else {
        // Remove filter from URL params
        currentUrl = currentUrl.replace(inputVal + ',', '');
        console.log(currentUrl);
        window.history.pushState("object or string", "Title", currentUrl);
      }
    });
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="filters">
  <label><input type="checkbox" value="blue" />Blue</label>
  <label><input type="checkbox" value="red" />Red</label>
  <label><input type="checkbox" value="green" />Green</label>
</div>

This works if the color is first(if there or other filters) or in the middle of the list of filters, since it matches my replace(), wondering how I can do this dynamically so that it will remove both the color and the comma if necessary or remove the colors= altogether if none are checked.

For example, if all 3 colors are checked the url would look like this:

http://example.net?colors=blue,red,green

If you then remove blue it should look like this:

http://example.net?colors=red,green

If you then remove green it would look like this:

http://example.net?colors=red

And finally, removing red would look like this:

http://example.net
1
  • 1
    Here's a solution without manual parsing: jsfiddle.net/khrismuc/416rfngb Commented Oct 1, 2019 at 21:25

2 Answers 2

4

You'll want to split your colors into an array and then merge it back again at the end.

$(function () {
    var colors = getUrlParameter('colors');
    var currentUrl = location.href;

    $('input[type="checkbox"]').change(function () {
      var inputVal = $(this).val();
      var colorsQuery = getUrlParameter('colors') || "";
      //Split into an array after each `,`
      colors = colors.split(",");
      if (this.checked) {
        //Add to our current colors
        colors.push(inputVal);
      } else {
        // Remove from our current colors
        const index = colors.indexOf(inputValue);
        colors.splice(index, 1);
      }
      colorString = "";
      if(colors.length){
         //Merge back into a string with a `,`
         colorString = "?colors=" + colors.join(",")
      }
      window.history.pushState("object or string", "Title", currentUrl + colorString);
    });
});

It's much easier to work with arrays in this instance so we just split and join to convert to and from an string to array.

For adding its easy we can just push onto our array

To remove a color we find out where it is in our colors array. Then using splice remove it from our array.

Sign up to request clarification or add additional context in comments.

1 Comment

I voted up here, but the answer is very JS-ey and jQuery-ful. Our logic works out very similar, but for posterity it's there to be more vanilla-JS friendly and probably performant.
1

I'd seperate adding and removing objects, and the logic to get your querystring.

You'll see here two basic events:

  1. Update an object based on the current checkbox (Binding directly to the state is even better!)
  2. Generating the string based off of current values.

var colors = {
  'red': false,
  'blue': false,
  'green': false
};

update = function(color) {
  colors[color] = !colors[color];

}

getParams = function() {
  var setQuery = false;
  var expr = [];
  for (var color in colors) {
    if (colors[color]) {
      expr.push(color);
      setQuery = true;
    }
  }

  if (setQuery) {
    console.log("www.example.com" + "?colors=" + expr.join(","));
  } else {
    console.log("www.example.com");
  }
}
<input type="checkbox" onchange="update('red')" /> Red
<input type="checkbox" onchange="update('blue')" /> Blue
<input type="checkbox" onchange="update('green')" /> green

<button type="button" onclick="getParams()">Get params</button>

Comments

Your Answer

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

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.