【问题标题】:Javascript - Fixing searching system?Javascript - 修复搜索系统?
【发布时间】:2016-09-11 07:33:02
【问题描述】:

在下面,有两段代码。对于无限滚动和搜索系统。一切正常,但搜索系统的问题在于,如果我搜索某些内容,它会打乱cardsboxes 的定位。如果你搜索它们,它们应该在一条线上,但是那些有点高等等。我还添加了一张关于它的图片。第二个问题是,我的网站上有一个无限滚动,但我想我必须将搜索系统更改为从 JSON 数据搜索,这样它才能正常工作?我的意思是,您在搜索中输入一些内容,单击回车,然后它从 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();
        });
    }
});

【问题讨论】:

    标签: javascript jquery html css search


    【解决方案1】:

    概述

    首先,我无法看到

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

    因为我不知道你的 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 说到,我将“滚轮”事件添加到“滚动”事件中,这样如果您位于滚动鼠标的顶部/底部当实际没有滚动时,wheel 也可以触发滚动。我没有解决其他可能的挑战,例如滚动位于顶部/底部时的向下/向上箭头;我会根据您的需要留给您解决。

    请注意,在键入时发生“搜索”事件时,我会重置 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) })

    【讨论】:

    • 对不起,我没有添加 CSS 代码。我已经编辑了我的第一篇文章并添加了它。感谢您的大力帮助!
    猜你喜欢
    • 2013-09-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-08-17
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多