Javascript - 修复搜索系统?

时间:2016-05-15 12:17:02

标签: javascript jquery html css search

在下面,有两段代码。对于无限滚动&搜索系统。一切正常,但搜索系统的问题是,如果我搜索某些东西,那么它会混淆cardsboxes的位置。他们应该在一条线上,如果你搜索它们,但是那些稍微等等。我也添加了一张关于它的图片。第二个问题是,我的网站上有一个无限卷轴,但我想我必须将搜索系统更改为从JSON数据中搜索,这样才能正常工作?我的意思是,你在搜索中键入内容,单击enter然后从JSON搜索匹配,然后在container中显示它们。我希望我对我的问题足够清楚,我希望有人可以帮助我解决它:)。谢谢大家! :)

这里还有一些CSS:

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

zmd-hierarchical-display - 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();
        });
    }
});

1 个答案:

答案 0 :(得分:0)

<强>概述

首先,我无法看到

  

...弄乱卡片或盒子的位置......

因为我不知道你的CSS是什么所以我只是对此做了一些猜测。我怀疑这可能是由于你的物品以某种方式实际渲染。为了协助这一点,我从注入的标记中删除了所有CSS,因为注入那些“样式”属性并不是最佳实践,并且坦率地难以调试,因为您似乎经历过。我做了一个尝试,但你需要调整我提供的CSS,因为它根本没有你的CSS。

为了帮助解决这个问题,我只是对当前页面进行“替换”,而不是每次都附加,然后面对滚动/开始结束的挑战并处理搜索中断。

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

更难的问题是在搜索页面上的对象列表时,items数组的动态特性。我通过创建一个名为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) })