Javascript-修复搜索系统

Javascript - Fixing searching system?

本文关键字:系统 搜索 Javascript-      更新时间:2023-09-26

下面有两段代码。对于无限滚动&搜索系统。一切都正常,但搜索系统的问题是,如果我搜索某个东西,就会打乱cardsboxes的定位。如果你搜索的话,它们应该在一行,但它们有点高等等。我还添加了一张关于这方面的图片。第二个问题是,我的网站上有一个无限滚动,但我认为我必须更改搜索系统以从JSON数据进行搜索,这样它才能正常工作?我的意思是,你在搜索中键入一些东西,点击回车,然后它从JSON中搜索匹配项,然后在container中显示它们。我希望我对自己的问题足够清楚,我希望有人能帮助我解决它:)。感谢大家!:)

这里还有一些CSS:

main.css-http://pastebin.com/Tgds0kuJ

zmd分层显示-http://pastebin.com/Fn5JBpaQ

具体化-http://pastebin.com/ZxSGZtc8

这是正常作品的图片:http://prntscr.com/b3yrwa

如果我搜索它们,下面是图片:http://prntscr.com/b3yrub

这是无限卷轴&卡片

var perPage = 50;
function paginate(items, page) {
    var start = perPage * page;
    return items.slice(start, start + perPage);
}
var condition = '';
function renderItems(pageItems) {
    pageItems.forEach(function(item, index, arr) {
        var message = 'BitSkins Price: $' + Math.round(item.bprice) + '';
        if (item.price !== null) {
            if (item.bprice === '') {
                message = 'Item never sold on BitSkins!';
            }
            if (item.name != 'Operation Phoenix Case Key' && item.name != 'CS:GO Case Key' && item.name != 'Winter Offensive Case Key' && item.name != 'Revolver Case Key' && item.name != 'Operation Vanguard Case Key' && item.name != 'Operation Wildfire Case Key' && item.name != 'Shadow Case Key' && item.name != 'Operation Breakout Case Key' && item.name != 'Chroma Case Key' && item.name != 'Huntsman Case Key' && item.name != 'Falchion Case Key' && item.name != 'Chroma 2 Case Key') {
                $("#inventory").html($("#inventory").html() + "<li class='col 2 zoomIn animated' style='padding:8px;font-weight:bold;font-size:13.5px'><div class='card item-card waves-effect waves-light' style='margin:0%;min-height:295px;width:245.438px;border-radius: 0px;height: 295px;box-shadow: inset 0px 0px 25px 2px #232323;border: 1px solid black' id='" + item.id + "'><div class='iteam' style='text-decoration: underline;text-align: left;font-size: 14.5px;color: #E8E8E8;font-family: Roboto;position: relative;right: -3px;'>" + item.name + "</div><div class='condition' style='text-align: left;color: #E8E8E8;font-family: Roboto;position: relative;left: 3px;'>" + item.condition + "</div><div class='center-align' style='position: relative;padding:0%;top: -33px;'><img title='"" + item.originalname + "'" draggable='false' src='https://steamcommunity-a.akamaihd.net/economy/image/" + item.iconurl + "/235fx235f'></div><div class='secondarea' style='position: relative;top: -129px;background: rgba(0, 0, 0,0.15);display: block;height: 163px;'><div class='buyer-price center-align' style='font-size:22.5px;font-family: Arial Black;color:#E8E8E8'>$" + Math.round(item.price) + "<div class='bitskinscomp' style='font-weight: normal;font-size:12px;font-family: Roboto;font: bold;'>" + message + "</div></div><a class='btn waves-effect waves-light' style='position:relative;left:-5px;top:50px' href='" + item.inspect + "' target='_blank'>Inspect</a><a class='btn waves-effect waves-light' style='position:relative;right:-5px;top:50px' id='purchaseButton'>Cart</a></div></li>");
            }
        }
    });
}
var win = $(window);
var page = 0;
renderItems(paginate(items, page));
win.scroll(function() {
    if ($(document).height() - win.height() == win.scrollTop()) {
        page++;
        renderItems(paginate(items, page));
    }
});

JavaScript搜索系统

$('#SearchItemsFromList').keyup(function() {
    var valThis = $(this).val().toLowerCase();
    if (valThis === "") {
        $('#inventory > li > div').show();
    } else {
        $('#inventory > li > div').each(function() {
            var text = $(this).text().toLowerCase();
            (text.indexOf(valThis) >= 0) ? $(this).show(): $(this).hide();
        });
    }
});

概述

首先,我看不到

搞砸了卡片或盒子的位置。。。

因为我不知道你的CSS是由什么组成的,所以我只是猜测了一下。我怀疑这可能是由于您的物品的实际渲染。为了帮助实现这一点,我从注入的标记中删除了所有CSS,因为注入这些"样式"属性并不是最佳实践,坦率地说,正如您所经历的那样,很难调试。我做了一个尝试,但你需要调整我提供的CSS,因为它根本没有你的所有内容。

为了帮助做到这一点,我只是用当前页面进行了"替换",而不是每次都追加,然后面临滚动/启动结束的挑战,并处理由此造成的搜索中断。

我删除了按钮上重复id的注入,而是使用了类注入。这将解决无效HTML的问题,该问题会在某个时候导致非常难以调试的意外结果。

更困难的问题是在搜索页面上的对象列表时项目数组的动态特性。我通过创建一个名为currentSearch的"视图候选列表"来解决这一问题,我可以自由地将其添加到名为myApp.data的名称中作为myApp.data.currentSearch

说到名称空间,我这样做是为了避免多个全局对象。我还将自定义函数作为最佳实践。

这是我使用的示例标记:

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

CSS

以下是CSS,它在很大程度上是从样式属性中提取的。我冒昧地将它们命名为first-style-thing类、second-style-thing等,它们只是与注入的元素序列相协调。这还有减少注入管柱尺寸的额外好处。

.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 0px 0px 25px 2px #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;
}
#inventory li {
  background-color: #888888;
}
#inventory li {
  display: inline-block;
  float: left;
}
.purchaseButton {
  right: -8em;
  top: 0;
}
#search {
  height: 4em;
  width: 100%;
  background-color: #00aaaa;
  padding: 1em;
}

代码:

关于代码,请注意items对象,我只是通过反向工程您的注入代码创建的,可能需要根据您的确切对象属性进行调整。

请注意debounce函数,它解决了一个问题,即您可能过于频繁地触发滚动/鼠标滚轮事件。我添加了一个"油门",你可以使用它,从这里借来:https://remysharp.com/2010/07/21/throttling-function-calls说到这里,我在"滚动"事件中添加了"滚轮"事件,这样,如果你在滚动的顶部/底部,鼠标滚轮也可以在实际没有发生滚动时触发滚动。我没有解决其他可能的挑战,例如当滚动位于顶部/底部时的向下/向上箭头;我会让你根据自己的需要来解决这个问题。

请注意,在键入时发生"搜索"事件时,我会重置currentSearch列表。

我保留了一些console.log,您可以将其删除,但允许您查看页面和一些事件触发日志。

这是一个示例,所以您可以尝试所有这些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;
    return function() {
      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;
    return function() {
      var context = scope || this;
      var now = +new Date,
        args = arguments;
      if (last && now < last + threshhold) {
        // hold on to it
        clearTimeout(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/down
  if ($(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));

最后要注意的是,代码中有一个很长、很难维护的条件,我添加了一个带有排除项的数组来替换它,然后代码将其与过滤器一起使用:.filter(function(itemValue) { return !!(myApp.data.excludes.indexOf(itemValue) == -1) })