概述
首先,我无法看到
...弄乱了卡片或盒子的位置...
因为我不知道你的 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)
})