Javascript 中的高级搜索
Advanced search in Javascript
我尝试在项目中实现搜索栏。
当输入不匹配时,它应该只搜索条目并隐藏行。
这就是我所做的并且它正在工作。
_searchCalls() {
let rows = document.querySelector('call-journal').shadowRoot.querySelectorAll('#row')
let callEntries = document.querySelector('call-journal').shadowRoot.querySelectorAll('call-entry')
for(let i = 0; callEntries.length > i; i++) {
let tmp = callEntries[i].shadowRoot.querySelector('.callInfo')
let entries = tmp.textContent.toLowerCase()
let dates = callEntries[i].shadowRoot.querySelector('.dateWrapper').textContent
let userInput = this._getSearchInput().toLowerCase()
if(!(entries.includes(userInput) || dates.includes(userInput))) {
rows[i].classList.add('hide')
} else {
rows[i].classList.remove('hide')
}
}
}
我想扩展搜索。所以我写的 'Bill Gates' 有效,但当我写 'Gates Bill' 时无效。
任何帮助将不胜感激。
就像建议的第一条评论一样,听起来您正在尝试将搜索输入中的所有单词匹配到 rows/entries。
首先,要将输入分解为多个术语的数组,您可以使用 the String method .split(' ')
按空格拆分。例如:
"Bill Gates".split(' ')
这将导致数组看起来像 ['Bill', 'Gates']
然后,您可以遍历使用 .split()
创建的搜索词数组,并使用 the String .includes()
method 检查它们是否存在于 row/entry 中(就像您现在正在检查一样在 userInput
字符串上)。
反转你的逻辑。
而不是告诉每一行到show/hide,
让搜索框上的每一行监听change
/keyup
事件。
是的,这意味着 每行 。
Search: <input type="text" value="foo bar">
<row-item>qux, baz, foo, bar</row-item>
<row-item>corge, foo</row-item>
<row-item>baz, quuz, bar, quux, foo</row-item>
<row-item>baz, corge, bar, quuz</row-item>
<row-item>bar</row-item>
<row-item>corge, baz, quux</row-item>
<row-item>baz, corge</row-item>
<row-item>foo</row-item>
<row-item>bar, quux, corge, foo</row-item>
<style>
row-item { display: block }
</style>
<script>
customElements.define("row-item", class extends HTMLElement {
connectedCallback() {
document.querySelector("input")
.addEventListener("keyup",(evt) => this.match(evt.target.value));
this.match("foo bar"); // for testing!
}
match(search) {
let findWords = search.trim().split(" ");
let rowWords = new Set(this.innerHTML.split(/, /));
let matched = findWords.map(word => rowWords.has(word))
.filter(Boolean) // remove false values
.length == findWords.length;
this.style.backgroundColor = matched ? "lightgreen" : "lightcoral";
}
})
</script>
我尝试在项目中实现搜索栏。 当输入不匹配时,它应该只搜索条目并隐藏行。 这就是我所做的并且它正在工作。
_searchCalls() {
let rows = document.querySelector('call-journal').shadowRoot.querySelectorAll('#row')
let callEntries = document.querySelector('call-journal').shadowRoot.querySelectorAll('call-entry')
for(let i = 0; callEntries.length > i; i++) {
let tmp = callEntries[i].shadowRoot.querySelector('.callInfo')
let entries = tmp.textContent.toLowerCase()
let dates = callEntries[i].shadowRoot.querySelector('.dateWrapper').textContent
let userInput = this._getSearchInput().toLowerCase()
if(!(entries.includes(userInput) || dates.includes(userInput))) {
rows[i].classList.add('hide')
} else {
rows[i].classList.remove('hide')
}
}
}
我想扩展搜索。所以我写的 'Bill Gates' 有效,但当我写 'Gates Bill' 时无效。 任何帮助将不胜感激。
就像建议的第一条评论一样,听起来您正在尝试将搜索输入中的所有单词匹配到 rows/entries。
首先,要将输入分解为多个术语的数组,您可以使用 the String method .split(' ')
按空格拆分。例如:
"Bill Gates".split(' ')
这将导致数组看起来像 ['Bill', 'Gates']
然后,您可以遍历使用 .split()
创建的搜索词数组,并使用 the String .includes()
method 检查它们是否存在于 row/entry 中(就像您现在正在检查一样在 userInput
字符串上)。
反转你的逻辑。
而不是告诉每一行到show/hide,
让搜索框上的每一行监听change
/keyup
事件。
是的,这意味着 每行 。
Search: <input type="text" value="foo bar">
<row-item>qux, baz, foo, bar</row-item>
<row-item>corge, foo</row-item>
<row-item>baz, quuz, bar, quux, foo</row-item>
<row-item>baz, corge, bar, quuz</row-item>
<row-item>bar</row-item>
<row-item>corge, baz, quux</row-item>
<row-item>baz, corge</row-item>
<row-item>foo</row-item>
<row-item>bar, quux, corge, foo</row-item>
<style>
row-item { display: block }
</style>
<script>
customElements.define("row-item", class extends HTMLElement {
connectedCallback() {
document.querySelector("input")
.addEventListener("keyup",(evt) => this.match(evt.target.value));
this.match("foo bar"); // for testing!
}
match(search) {
let findWords = search.trim().split(" ");
let rowWords = new Set(this.innerHTML.split(/, /));
let matched = findWords.map(word => rowWords.has(word))
.filter(Boolean) // remove false values
.length == findWords.length;
this.style.backgroundColor = matched ? "lightgreen" : "lightcoral";
}
})
</script>