Skip to content Skip to sidebar Skip to footer

Javascript - Fixing Searching System?

Down below, there's two pieces of codes. For infinite scroll & search system. Everything works, but the problem with the search system is that, if I search something, then it m

Solution 1:

Overview

First off, I have no visibility to the

...messes up positioning of the cards or boxes...

since I do not know what your CSS consists of so I simply made some guesses on that. I suspect it may be due to the actual rendering of your items somehow. To assist in this I removed all the CSS from the injected markup as injecting those "style" attributes is not best practice and frankly difficult to debug as you seem to have experienced. I made an attempt but you will need to adjust the CSS I have provided as it simply does not have all yours in it.

To assist with this, I simply did a "replace" with the current page rather than append each time and then face the challenge of end of scroll/start and deal with the search disruption of that.

I removed the injection of duplicate id on the button and instead used a class injection instead. This will resolve the issue of the invalid HTML which would cause unexpected results at some point that would be very difficult to debug.

The more difficult issue is the dynamic nature of your items array when searching the on-page object list. This I have addressed by creation of a "view candidate list called currentSearch which I have taken the liberty of adding to a name called myApp.data as myApp.data.currentSearch.

Speaking of the namespace, I did that to avoid multiple global objects. I also did that with my custom functions as a best practice.

Here is my sample markup that I used:

<div id="search">
  <input id="SearchItemsFromList"type="text" />
</div>
<ul id="inventory">
</ul>

CSS

Here is the CSS which in great part was extracted from the style properties. I took the liberty of naming them poorly as first-style-thing class, second-style-thing etc. which simply coordinate to the injected sequence of elements. This has the additional benefit of reducing the injection string size as well.

.li-style-thing {
  padding: 8px;
  font-weight: bold;
  font-size: 13.5px;
}

.first-style-thing {
  margin: 0%;
  min-height: 295px;
  width: 245.438px;
  border-radius: 0px;
  height: 295px;
  box-shadow: inset 0px0px25px2px#232323;
  border: 1px solid black;
}

.second-style-thing {
  text-decoration: underline;
  text-align: left;
  font-size: 14.5px;
  color: #E8E8E8;
  font-family: Roboto;
  position: relative;
  right: -3px;
}

.third-style-thing {
  text-align: left;
  color: #E8E8E8;
  font-family: Roboto;
  position: relative;
  left: 3px;
}

.fourth-style-thing {
  position: relative;
  padding: 0%;
  top: -33px;
}

.fifth-style-thing {
  position: relative;
  top: -129px;
  background: rgba(0, 0, 0, 0.15);
  display: block;
  height: 163px;
}

.sixth-style-thing {
  font-size: 22.5px;
  font-family: Arial Black;
  color: #E8E8E8;
}

.seventh-style-thing {
  font-weight: normal;
  font-size: 12px;
  font-family: Roboto;
  font: bold;
}

.eighth-style-thing {
  position: relative;
  left: -5px;
  top: 50px;
}

.ninth-style-thing {
  position: relative;
  right: -5px;
  top: 50px;
}

.btn {
  position: relative;
  display: block;
  height: 1.5em;
  width: 5em;
  color: cyan;
  background-color: blue;
  font-weight: bold;
  text-align: center;
  padding-top: 0.5em;
  margin: 1em;
  text-decoration: none;
  text-transform: uppercase;
}

#inventory {
  display: block;
  position: relative;
  top: 1em;
  left: 0em;
  border: solid lime 1px;
}

#inventoryli {
  background-color: #888888;
}

#inventoryli {
  display: inline-block;
  float: left;
}

.purchaseButton {
  right: -8em;
  top: 0;
}

#search {
  height: 4em;
  width: 100%;
  background-color: #00aaaa;
  padding: 1em;
}

Code:

About the code, note the items object which I simply made from reverse engineering your injection code and likely needs adjusted to your exact object properties.

Note the debounce function which addresses an issue where you might fire the scroll/mouse wheel events too often. I added a "throttle" which you might use instead, borrowed from here: https://remysharp.com/2010/07/21/throttling-function-calls Speaking of, I added the "wheel" event to the "scroll" event so that if you are at the top/bottom of the scroll the mouse wheel can also fire the scroll when no scroll actually occurs. I did not address other possible challenges such as the down/up arrow when the scroll is at the top/bottom; I will leave that up to you to address based upon your needs.

Note that upon a "search" event when typing, I reset the currentSearch list.

I left some console.log in place which you can remove - but allows you to see the page and some event fire logging.

Here is a sample so you can try this all out https://jsfiddle.net/MarkSchultheiss/hgfhh2y7/3/

var myApp = myApp || {};
myApp.data = {
  currentSearch: [],
  pageStart: 0,
  pageEnd: 0,ma
  perPage: 3,
  page: 0,
  lastScroll: 0,
  scrollDelay: 250,
  outputContainer: $('#inventory'),
  excludes: ['Operation Phoenix Case Key', 'CS:GO Case Key', 'Winter Offensive Case Key', 'Revolver Case Key', 'Operation Vanguard Case Key', 'Operation Wildfire Case Key', 'Shadow Case Key', 'Operation Breakout Case Key', 'Chroma Case Key', 'Huntsman Case Key', 'Falchion Case Key', 'Chroma 2 Case Key']
};

myApp.func = {
  contains: function(myArray, searchTerm, property) {
    var found = [];
    var len = myArray.length;
    for (var i = 0; i < len; i++) {
      if (myArray[i][property].toLowerCase().indexOf(searchTerm.toLowerCase()) > -1) found.push(myArray[i]);
    }
    return found;
  },
  paginate: function(items) {
    myApp.data.pageStart = myApp.data.perPage * myApp.data.page;
    myApp.data.pageEnd = myApp.data.pageStart + myApp.data.perPage;
    if (myApp.data.pageEnd > items.length) {
      myApp.data.pageEnd = items.length;
      myApp.data.pageStart = myApp.data.pageEnd - myApp.data.perPage >= 0 ? myApp.data.pageEnd - myApp.data.perPage : 0;
    }
    console.log("Page:" + myApp.data.page + " Start:" + myApp.data.pageStart + " End:" + myApp.data.pageEnd + " max:" + items.length);
    return items;
  },
  debounce: function(fn, delay) {
    var timer = null;
    returnfunction() {
      var context = this,
        args = arguments;
      clearTimeout(timer);
      timer = setTimeout(function() {
        fn.apply(context, args);
      }, delay);
    };
  },
  throttle: function(fn, threshhold, scope) {
    threshhold || (threshhold = 250);
    var last,
      deferTimer;
    returnfunction() {
      var context = scope || this;
      var now = +newDate,
        args = arguments;
      if (last && now < last + threshhold) {
        // hold on to itclearTimeout(deferTimer);
        deferTimer = setTimeout(function() {
          last = now;
          fn.apply(context, args);
        }, threshhold);
      } else {
        last = now;
        fn.apply(context, args);
      }
    }
  },
  renderItems: function(pageItems) {
    // $("#inventory").html("");console.log('renderStart Items:' + pageItems.length);
    console.log(myApp.data.pageStart + ":" + myApp.data.pageEnd);
    var renderList = pageItems.filter(function(itemValue) {
      return !!(myApp.data.excludes.indexOf(itemValue) == -1)
    }).slice(myApp.data.pageStart, myApp.data.pageEnd);
    console.log(renderList);
    var newContent = "";
    renderList.forEach(function(item, index, arr) {
      var message = 'BitSkins Price: $' + Math.round((item.bprice * 1));
      if (item && item.price !== null) {
        if (item.bprice === '') {
          message = 'Item never sold on BitSkins!';
        }
        if (myApp.data.excludes.indexOf(item.name) == -1) {
          newContent += "<li class='col 2 zoomIn animated'><div class='card item-card waves-effect waves-light first-style-thing' id='" + item.id + "'><div class='iteam second-style-thing' >" + item.name + "</div><div class='condition third-style-thing'>" + item.condition + "</div><div class='center-align fourth-style-thing' ><img title='" + item.originalname + "' draggable='false' src='https://steamcommunity-a.akamaihd.net/economy/image/" + item.iconurl + "/235fx235f'></div><div class='secondarea fifth-style-thing'><div class='buyer-price center-align sixth-style-thing'>$" + Math.round(item.price) + "<div class='bitskinscomp seventh-style-thing'>" + message + "</div></div><a class='btn waves-effect waves-light eighth-style-thing' href='" + item.inspect + "' target='_blank'>Inspect</a><a class='btn waves-effect waves-light purchaseButton'>Cart</a></div></li>";
        }
      }
      myApp.data.outputContainer.html(newContent);
    });

  }
};

var items = [{
  id: "123",
  name: "freddy Beer",
  condition: "worn",
  originalname: "beer stein",
  price: 10.22,
  bprice: "34.33",
  iconurl: "-9a81dlWLwJ2UUGcVs_nsVtzdOEdtWwKGZZLQHTxDZ7I56KU0Zwwo4NUX4oFJZEHLbXH5ApeO4YmlhxYQknCRvCo04DEVlxkKgpot7HxfDhjxszJemkV08u_mpSOhcjnI7TDglRc7cF4n-T--Y3nj1H6-hBrMW_3LIOWdlU_MlGDqwO6wrvq15C6vp-bnHY36SAm4XbYl0SwhgYMMLJqUag1Og",
  inspect: "http://example.com/myinspect/4"
}, {
  id: "123",
  name: "freddy Beer",
  condition: "worn",
  originalname: "beer stein",
  price: 10.22,
  bprice: "34.33",
  iconurl: "-9a81dlWLwJ2UUGcVs_nsVtzdOEdtWwKGZZLQHTxDZ7I56KU0Zwwo4NUX4oFJZEHLbXH5ApeO4YmlhxYQknCRvCo04DEVlxkKgpot7HxfDhjxszJemkV08u_mpSOhcjnI7TDglRc7cF4n-T--Y3nj1H6-hBrMW_3LIOWdlU_MlGDqwO6wrvq15C6vp-bnHY36SAm4XbYl0SwhgYMMLJqUag1Og",
  inspect: "http://example.com/myinspect/4"
}, {
  id: "123",
  name: "freddy Beer",
  condition: "worn",
  originalname: "beer stein",
  price: 10.22,
  bprice: "34.33",
  iconurl: "-9a81dlWLwJ2UUGcVs_nsVtzdOEdtWwKGZZLQHTxDZ7I56KU0Zwwo4NUX4oFJZEHLbXH5ApeO4YmlhxYQknCRvCo04DEVlxkKgpot7HxfDhjxszJemkV08u_mpSOhcjnI7TDglRc7cF4n-T--Y3nj1H6-hBrMW_3LIOWdlU_MlGDqwO6wrvq15C6vp-bnHY36SAm4XbYl0SwhgYMMLJqUag1Og",
  inspect: "http://example.com/myinspect/4"
}, {
  id: "123",
  name: "freddy Beer",
  condition: "worn",
  originalname: "beer stein",
  price: 10.22,
  bprice: "34.33",
  iconurl: "-9a81dlWLwJ2UUGcVs_nsVtzdOEdtWwKGZZLQHTxDZ7I56KU0Zwwo4NUX4oFJZEHLbXH5ApeO4YmlhxYQknCRvCo04DEVlxkKgpot7HxfDhjxszJemkV08u_mpSOhcjnI7TDglRc7cF4n-T--Y3nj1H6-hBrMW_3LIOWdlU_MlGDqwO6wrvq15C6vp-bnHY36SAm4XbYl0SwhgYMMLJqUag1Og",
  inspect: "http://example.com/myinspect/4"
}, {
  id: "123",
  name: "Operation Phoenix Case Key",
  condition: "worn",
  originalname: "Operation Phoenix Case Key",
  price: 10.22,
  bprice: "34.33",
  iconurl: "-9a81dlWLwJ2UUGcVs_nsVtzdOEdtWwKGZZLQHTxDZ7I56KU0Zwwo4NUX4oFJZEHLbXH5ApeO4YmlhxYQknCRvCo04DEVlxkKgpot7HxfDhjxszJemkV08u_mpSOhcjnI7TDglRc7cF4n-T--Y3nj1H6-hBrMW_3LIOWdlU_MlGDqwO6wrvq15C6vp-bnHY36SAm4XbYl0SwhgYMMLJqUag1Og",
  inspect: "http://example.com/myinspect/4"
}, {
  id: "234",
  name: "Johnson Wax",
  condition: "waxy",
  originalname: "Ear wax",
  price: 2244.22,
  bprice: "",
  iconurl: "-9a81dlWLwJ2UUGcVs_nsVtzdOEdtWwKGZZLQHTxDZ7I56KU0Zwwo4NUX4oFJZEHLbXH5ApeO4YmlhxYQknCRvCo04DEVlxkKgpot7HxfDhjxszJemkV08u_mpSOhcjnI7TDglRc7cF4n-T--Y3nj1H6-hBrMW_3LIOWdlU_MlGDqwO6wrvq15C6vp-bnHY36SAm4XbYl0SwhgYMMLJqUag1Og",
  inspect: "http://example.com/myinspect/4"
}, {
  id: "45245",
  name: "Door Knob | Green",
  condition: "green tint",
  originalname: "Green door knob",
  price: 35.68,
  bprice: "",
  iconurl: "-9a81dlWLwJ2UUGcVs_nsVtzdOEdtWwKGZZLQHTxDZ7I56KU0Zwwo4NUX4oFJZEHLbXU5A1PIYQNqhpOSV-fRPasw8rsQEl9Jg9SpIW1KgRrg6GGJWRBtI-ykYTak6WhN76JlWgFsJN1j72SotWiigbi-0BqYjuncdDDdRh-Pw9UqwY-SA",
  inspect: "http://example.com/myinspect/4"
}, {
  id: "45245red",
  name: "Door Knob | Red",
  condition: "red tint",
  originalname: "Red door knob",
  price: 35.68,
  bprice: "",
  iconurl: "-9a81dlWLwJ2UUGcVs_nsVtzdOEdtWwKGZZLQHTxDZ7I56KU0Zwwo4NUX4oFJZEHLbXU5A1PIYQNqhpOSV-fRPasw8rsQEl9Jg9SpIW1KgRrg6GGJWRBtI-ykYTak6WhN76JlWgFsJN1j72SotWiigbi-0BqYjuncdDDdRh-Pw9UqwY-SA",
  inspect: "http://example.com/myinspect/4"
}, {
  id: "45245red",
  name: "Door Knob | Red",
  condition: "red tint",
  originalname: "Red door knob",
  price: 35.68,
  bprice: "",
  iconurl: "-9a81dlWLwJ2UUGcVs_nsVtzdOEdtWwKGZZLQHTxDZ7I56KU0Zwwo4NUX4oFJZEHLbXU5A1PIYQNqhpOSV-fRPasw8rsQEl9Jg9SpIW1KgRrg6GGJWRBtI-ykYTak6WhN76JlWgFsJN1j72SotWiigbi-0BqYjuncdDDdRh-Pw9UqwY-SA",
  inspect: "http://example.com/myinspect/4"
}, {
  id: "45245blue",
  name: "Door Knob | Blue",
  condition: "blue tint",
  originalname: "Blue door knob",
  price: 35.68,
  bprice: "",
  iconurl: "-9a81dlWLwJ2UUGcVs_nsVtzdOEdtWwKGZZLQHTxDZ7I56KU0Zwwo4NUX4oFJZEHLbXU5A1PIYQNqhpOSV-fRPasw8rsQEl9Jg9SpIW1KgRrg6GGJWRBtI-ykYTak6WhN76JlWgFsJN1j72SotWiigbi-0BqYjuncdDDdRh-Pw9UqwY-SA",
  inspect: "http://example.com/myinspect/4"
}, {
  id: "45245Brown",
  name: "Door Knob | Brown",
  condition: "brown tint",
  originalname: "Brown door knob",
  price: 35.68,
  bprice: "34.23",
  iconurl: "-9a81dlWLwJ2UUGcVs_nsVtzdOEdtWwKGZZLQHTxDZ7I56KU0Zwwo4NUX4oFJZEHLbXU5A1PIYQNqhpOSV-fRPasw8rsQEl9Jg9SpIW1KgRrg6GGJWRBtI-ykYTak6WhN76JlWgFsJN1j72SotWiigbi-0BqYjuncdDDdRh-Pw9UqwY-SA",
  inspect: "http://example.com/myinspect/4"
}, {
  id: "45245Malt",
  name: "Beer malt  | Brown",
  condition: "brown tint",
  originalname: "Brown Beer Malt ",
  price: 35.68,
  bprice: "34.23",
  iconurl: "-9a81dlWLwJ2UUGcVs_nsVtzdOEdtWwKGZZLQHTxDZ7I56KU0Zwwo4NUX4oFJZEHLbXH5ApeO4YmlhxYQknCRvCo04DEVlxkKgpot7HxfDhjxszJemkV08u_mpSOhcjnI7TDglRc7cF4n-T--Y3nj1H6-hBrMW_3LIOWdlU_MlGDqwO6wrvq15C6vp-bnHY36SAm4XbYl0SwhgYMMLJqUag1Og",
  inspect: "http://example.com/myinspect/4"
}, {
  id: "4Beef",
  name: "Beefeaters Mug   | Brown",
  condition: "new tint",
  originalname: "Brown Beefeaters mug",
  price: 35.68,
  bprice: "34.23",
  iconurl: "-9a81dlWLwJ2UUGcVs_nsVtzdOEdtWwKGZZLQHTxDZ7I56KU0Zwwo4NUX4oFJZEHLbXH5ApeO4YmlhxYQknCRvCo04DEVlxkKgpot7HxfDhjxszJemkV08u_mpSOhcjnI7TDglRc7cF4n-T--Y3nj1H6-hBrMW_3LIOWdlU_MlGDqwO6wrvq15C6vp-bnHY36SAm4XbYl0SwhgYMMLJqUag1Og",
  inspect: "http://example.com/myinspect/4"
}];

myApp.data.outputContainer.on('customRenderEvent', function() {
  myApp.func.renderItems(myApp.func.paginate(myApp.data.currentSearch));
});

$('#SearchItemsFromList').on('keyup', function() {
  var valThis = $(this).val();
  if (valThis === "") {
    // item-card// items hold the things to pageinate// currentSearch holds the filtered items
    myApp.data.currentSearch = items;
  } else {
    // "name" is the matching property in the object
    myApp.data.currentSearch = myApp.func.contains(items, valThis, "name");
  }
  myApp.data.outputContainer.trigger('customRenderEvent');
  console.log("keyup len:" + myApp.data.currentSearch.length);
}).trigger('keyup'); // trigger for initial display

$(window).on('scroll wheel', myApp.func.debounce(function(event) {
  // set the page on scroll up/downif ($(this).scrollTop() == 0) {
    myApp.data.page > 0 ? myApp.data.page-- : myApp.data.page = 0;
  } else {
    myApp.data.page++;
  }
  myApp.func.renderItems(myApp.func.paginate(myApp.data.currentSearch));
}, myApp.data.scrollDelay));

Final note on the code, you have a quite long, difficult to maintain conditional which I replaced by added an array with the exclusions and then the code uses it with a filter: .filter(function(itemValue) { return !!(myApp.data.excludes.indexOf(itemValue) == -1) })

Post a Comment for "Javascript - Fixing Searching System?"