I’m slightly chuffed by this, I was doing something and build Vue.js based search from a statically created index.
The fun part was storing/passing a “category” variable from the page’s HTML to the Vue app, and only slightly problematic by using Pelican to generate the site.
Pelican uses {{}}
for tempalte variables, same as Vue, so I had to reconfigure Vue’s delimiters (hence the ||
around item.message
)
Passing the category from the static HTML to Vue
- The
searchmeta
app is defined in thediv#searchmeta
tag. - The
data-category
attribute of thediv#searchmeta
tag is generated by Pelican. It’s used on the categories pages, so that search only shows the in-category ports. searchapp.getCategory()
looks for the attribute and sets it tosearchapp.category
Generating the search data
I generate a list of the pages, like [ "tcp/1", "udp/53" ]
etc, and it’s stored as a static JSON file in the Pelican theme. In this case as /theme/searchdata.json
.
I’m sure I could do this with Pelican automagically, but I was already pretty done with yak-shaving at that point. I was converting portDB from Jekyll to Pelican, because I … had to fix some other thing that didn’t need fixing. It’s yaks all the way down.
Searching
searchapp.portFiltered()
, which takes the search string from theinput#searchTerm
element.- As that’s updated, it re-generates the the
<template v-for
tag and its contents.
<div class="wrapper main" id="searchmeta" name="searchmeta" data-category="{{category}}">
<input type="text" id="searchTerm" name="searchTerm" placeholder="Port # Search" v-model="portFilter"/>
<ol>
<template v-for="item in portFiltered.slice(0, 20)">
<li style="list-style-type: none;">
<a :href="'/'+item.message+'/'">| item.message |</a></li>
</template>
</ol>
</div>
var searchapp = new Vue({
delimiters: ['|', '|'],
el: '#searchmeta',
data: {
ports: [
{ message: "loading"},
],
portFilter: '',
category: '',
},
created () {
this.updateData();
},
computed: {
portFiltered() {
if ( this.getCategory() != "" && this.portFilter != "" ) {
return this.ports.filter(port => {
const portToMatch = port.message.toLowerCase();
return portToMatch.includes(this.getCategory()) && portToMatch.includes(this.portFilter);
}).reverse();
}
return [];
},
},
methods: {
getCategory: function() {
const result = this.$el.getAttribute("data-category");
if (result != undefined) {
return result;
}
return "";
},
updateData: function() {
axios
.get("/theme/searchdata.json", headers={'crossDomain': true})
.then(res => {
let data = res.data.map(function(el) {
return { "message" : el.toLowerCase() };
});
this.ports = data.reverse();
});
}
}
})