2

I want to chain both of my filters, to get a specific filter to my google map filter, if the filter markers by category has got the value, I want my filter by session to get the value from filter by category and then combined with my filter by session.

This is my code, filter by category and by session:

 // filter markers by category
  filterMarkers = function (category) {
      for (i = 0; i < gmarkers1.length; i++) {
          marker = gmarkers1[i];
          // If is same category or category not picked
          if (marker.category == category || category.length === 0) {
              marker.setVisible(true);

          }
          // categories don't match 
          else {
              marker.setVisible(false);
          }
      }
  }

  // filter markers by session
  filterMarkersx = function (session) {
      for (i = 0; i < gmarkers1.length; i++) {
          marker = gmarkers1[i];
          // If is same session or session not picked
          if (marker.session == session || session.length === 0) {

              marker.setVisible(true);


          }
          // session don't match 
          else {
              marker.setVisible(false);
          }
      }
  }

and this is my option select code to get value:

  <div class="controls">Filter By :
    <select id="type" onchange="filterMarkers(this.value);">
   <option value="">Merchant Grub</option>
   <option value="STARBUCKS">STARBUCKS</option>
   <option value="SIMPLY">SIMPLY</option>
   <option value="SHIHLIN">SHIHLIN</option>
   <option value="RE JUVE">RE JUVE</option>
   <option value="PUYO">PUYO</option>
   <option value="LOTTERIA">LOTTERIA</option>
   <option value="KFC">KFC</option>
   <option value="HOP HOP">HOP HOP</option>
   <option value="DOMINOS">DOMINOS</option>
   <option value="CIRCLE K">CIRCLE K</option>
   <option value="CHATIME">CHATIME</option>
   <option value="CFC">CFC</option>
   <option value="BURGER KING">BURGER KING</option>
   <option value="BREADLIFE">BREADLIFE</option>
   <option value="BAKMI GM">BAKMI GM</option>
   <option value=" AUNTIE ANNE'S">AUNTIE ANNE'S</option>
    </select>
  </div>

    <div class="controls">Filter By :
    <select id="type" onchange="filterMarkersx(this.value);">
   <option value="">IN SESSION</option>
   <option value="false">FALSE</option>
    <option value="">TRUE</option>
    </select>
  </div>

How can I chain both my filters ?

For example: If I choose starbucks in filter by category, and I choose false in filter by session, I can get the value starbucks false session.

Thanks in advance,

Kraken

ProgrammerPer
  • 1,125
  • 1
  • 11
  • 26
Kraken
  • 87
  • 8

1 Answers1

0

To me these functions filterMarkers and filterMarkersx are not really "filters", as they're altering gmarkers' items instead of returning a subset of this array. From the filtering point of view, I'd rewrite the code such as:

1. declare filtering functions

// returns a filtering function to be passed to Array.prototype.filter parameterized with `category`
var filterByCategory = function (category) {
  return function (marker) {
    return !category.length || marker.category == category;
  }
};

// returns a filtering function to be passed to Array.prototype.filter parameterized with `session`
var filterBySession = function (session) {
  return function (marker) {
    return !session.length || marker.session == session;
  }
};

By the way, since these are the exact same functions only changing the property being tested, you could factorize these into:

var filterBy = function (name, object) {
  return function (marker) {
    return !object.length || marker[name] == object;
  }
};

2. using the filters

// set all visibility to false for starters
gmarkers.forEach(function (m) {
  m.setVisible(false);
});
// apply chained filtering then set visibility to true on resulting subset
gmarkers
  .filter(filterBy('category', category)) // or .filter(filterByCategory(category))
  .filter(filterBy('session', session)) // or .filter(filterBySession(session))
  .forEach(function (marker) {
    marker.setVisible(true);
  });

This way you can control whether you chain filters or use only one of them.

UPDATE: clearer definition of usage

Now that we have the logics, we want to connect this piece of code to your HTML.

Let's wrap code from part "2. using the filters" in a function:

// assuming vanilla JS: binding the function to `document`
// (the purpose is just to make it callable from the HTML)
document.setMarkersVisibility = function () {
  // first, fetch data from both <select> (category and session)
  var selectCategory = document.getElementById('selectcategory');
  var selectSession = document.getElementById('selectsession');
  var category = selectCategory.options[selectCategory.selectedIndex].value;
  var session = selectSession .options[selectSession .selectedIndex].value;
  /* INSERT PART 2. CODE HERE */
};

Now we need to refactor the HTML, because both your <select> have the same value for id, which is wrong. And we need to call our new function. Given the code above, I named them selectcategory and selectsession:

<select id="selectcategory" onchange="setMarkersVisibility()">

and

<select id="selectsession" onchange="setMarkersVisibility()">

This should be all that is needed.

Stock Overflaw
  • 3,203
  • 1
  • 13
  • 14
  • really thanks for your help, you very kind, but since i replace my code with your code, this not working, really confused – Kraken Sep 02 '18 at 00:54
  • Did you update your HTML with a proper `onchange` call? I mean: the "using the filters" part is supposed to be wrapped in a function so that you can call it when the form changes - you got that, right? (Because here I understand "not working" as in "no effect and no error", right?) – Stock Overflaw Sep 02 '18 at 01:09
  • i i write html select like this – Kraken Sep 02 '18 at 01:20
  • `filterByCategory`, as per my in-code comments, _"returns a filtering function to be passed to Array.prototype.filter"_. Therefore no, it's not correct. I'm going to update my answer to clearly state the usage (too complicated in a comment), give me 15 minutes tops. – Stock Overflaw Sep 02 '18 at 01:26
  • Done editing, check the update, and if you want to toy around I tested the code with this (ugly) [JSFiddle](https://jsfiddle.net/g3cbuy5e/10/). However, I don't understand what you have in `gmarkers[].session`: the related ` – Stock Overflaw Sep 02 '18 at 01:57