Site > Fuzzy Search > Add path highlights

This commit is contained in:
brunosimon
2017-08-29 00:38:28 +02:00
parent 923d3558f6
commit e0d2d449d1
4 changed files with 91 additions and 30 deletions
+17 -8
View File
@@ -15,22 +15,29 @@ export default
content: { type: Object } content: { type: Object }
}, },
data()
{
return {
matchingPositions: []
}
},
computed: computed:
{ {
visible() visible()
{ {
let visible = true
// Get and clean search // Get and clean search
const search = this.$store.state.files.search.replace(/\ /g, '').toLowerCase() const search = this.$store.state.files.search.replace(/ /g, '').toLowerCase()
// If no search value, return true // If no search value, return true
if(search === '') if(search !== '')
{ {
return true
}
// Set up fuzzy search // Set up fuzzy search
const text = this.content.data.path.full const text = this.content.data.path.full.replace(/^\.\//, '')
let searchPosition = 0 let searchPosition = 0
this.matchingPositions = []
// Go through each character in the text // Go through each character in the text
for(let n = 0; n < text.length; n++) for(let n = 0; n < text.length; n++)
@@ -39,15 +46,17 @@ export default
if(searchPosition < search.length && text[n].toLowerCase() === search[searchPosition]) if(searchPosition < search.length && text[n].toLowerCase() === search[searchPosition])
{ {
searchPosition += 1 searchPosition += 1
this.matchingPositions.push(n - this.content.data.path.directory.length + 1)
} }
} }
if(searchPosition !== search.length) if(searchPosition !== search.length)
{ {
return false visible = false
}
} }
return true return visible
} }
}, },
@@ -2,7 +2,9 @@
<a href="#" class="name" :style="{ paddingLeft:depth * 20 + 'px' }" @click.prevent="onNameClick"> <a href="#" class="name" :style="{ paddingLeft:depth * 20 + 'px' }" @click.prevent="onNameClick">
<file-icon class="icon" :extension="content.data.extension"></file-icon> <file-icon class="icon" :extension="content.data.extension"></file-icon>
<span class="text"> <span class="text">
{{ content.name }} <template v-for="(letter, key) in content.name">
<span :style="matchingPositions.indexOf(key) !== -1 ? 'font-weight:bold;' : ''">{{ letter }}</span>
</template>
</span> </span>
</a> </a>
</div> </div>
@@ -14,28 +14,76 @@ export default
props: props:
{ {
depth: { type: Number, default: 0 }, depth: { type: Number, default: 0 },
directory: { type: String, default: '' },
content: { type: Object } content: { type: Object }
}, },
data() data()
{ {
return { return {
open: true open: true,
matchingPositions: []
} }
}, },
computed: computed:
{ {
fullPath()
{
return `${this.directory}${this.content.name}`
},
files() files()
{ {
const files = this.content.files.sort((fileA, fileB) => fileA.name < fileB.name ? -1 : 1) const files = this.content.files.sort((fileA, fileB) => fileA.name < fileB.name ? -1 : 1)
return files return files
}
}, },
created() visible()
{ {
let visible = false
const totalCount = this.content.files.length
let visibleCount = 0
for(const $child of this.$children)
{
if($child.visible === true)
{
visibleCount++
}
}
if(visibleCount > 0)
{
visible = true
}
// Get and clean search
const search = this.$store.state.files.search.replace(/ /g, '').toLowerCase()
// If no search value, return true
if(search !== '')
{
// Set up fuzzy search
const text = this.fullPath.replace(/^\.\//, '')
let searchPosition = 0
this.matchingPositions = []
// Go through each character in the text
for(let n = 0; n < text.length; n++)
{
// If match a character in the search, highlight it
if(searchPosition < search.length && text[n].toLowerCase() === search[searchPosition])
{
searchPosition += 1
this.matchingPositions.push(n - this.directory.length + 2)
}
}
}
return visible
}
}, },
methods: methods:
@@ -1,13 +1,15 @@
<div> <div v-show="visible">
<a href="#" class="name" :style="{ paddingLeft:depth * 20 + 'px' }" @click.prevent="onNameClick"> <a href="#" class="name" :style="{ paddingLeft:depth * 20 + 'px' }" @click.prevent="onNameClick">
<file-icon class="icon" extension="folder-active" v-show="open"></file-icon> <file-icon class="icon" extension="folder-active" v-show="open"></file-icon>
<file-icon class="icon" extension="folder" v-show="!open"></file-icon> <file-icon class="icon" extension="folder" v-show="!open"></file-icon>
<span class="text"> <span class="text">
{{ content.name }} <template v-for="(letter, key) in content.name">
<span :style="matchingPositions.indexOf(key) !== -1 ? 'font-weight:bold;' : ''">{{ letter }}</span>
</template>
</span> </span>
</a> </a>
<div v-show="open"> <div v-show="open">
<files-tree-folder v-for="folder of content.folders" :key="folder.name" :content="folder" :depth="depth + 1"></files-tree-folder> <files-tree-folder class="js-child" v-for="folder of content.folders" :key="folder.name" :content="folder" :depth="depth + 1" :directory="fullPath + '/'"></files-tree-folder>
<files-tree-file v-for="file of files" :key="file.data.path.full" :content="file" :depth="depth + 1"></files-tree-file> <files-tree-file class="js-child" v-for="file of files" :key="file.data.path.full" :content="file" :depth="depth + 1"></files-tree-file>
</div> </div>
</div> </div>