diff --git a/static/js/catalog.js b/static/js/catalog.js new file mode 100644 index 0000000..0a209ee --- /dev/null +++ b/static/js/catalog.js @@ -0,0 +1,38 @@ +var typingTimer; +var doneTypingInterval = 500; + +var app = new Vue({ + el: '#app', + delimiters: ['${', '}'], + data: { + prevTerms: {}, + searchTerms: {}, + hits: {}, + }, + methods: { + run_search(qid) { + var terms = this.searchTerms[qid]; + if (terms == this.prevTerms[qid]) { + return; // no change + } + this.prevTerms[qid] = terms; + if (terms.length < 3) { + this.hits[qid] = []; + return; + } + + var vm = this; + + fetch(lookup_url + '?terms=' + encodeURI(terms)) + .then((res) => res.json()) + .then((data) => { + vm.hits[qid] = data.hits; + }) + }, + search(event) { + var qid = event.target.dataset.qid + clearTimeout(typingTimer); + typingTimer = setTimeout(this.run_search, doneTypingInterval, qid); + } + } +}); diff --git a/templates/catalog.html b/templates/catalog.html index 47c64e9..2212bf5 100644 --- a/templates/catalog.html +++ b/templates/catalog.html @@ -21,8 +21,34 @@ {% block title %}{{ title }}{% endblock %} +{% block style %} +<style> +.autocomplete { + /*the container must be positioned relative:*/ + position: relative; + display: inline-block; +} + +.autocomplete-items { + position: absolute; + z-index: 99; + /*position the autocomplete items to be the same width as the container:*/ + top: 100%; + left: 0; + right: 0; +} +.autocomplete-items div { + cursor: pointer; + background-color: #fff; +} + + + +</style> +{% endblock %} + {% block content %} - <div class="p-2"> + <div class="p-2" id="app"> <h1>{{ self.title() }}</h1> {% for item in items %} <div class="card mb-3"> @@ -39,6 +65,25 @@ </p> {{ item_detail(item.entity) }} + + <div class="autocomplete w-100"> + <input class="form-control-lg my-2 search" data-qid="{{item.qid}}" autocomplete="off" @input="search" v-model.trim="searchTerms['{{ item.qid}}']" /> + + <div v-if="hits.{{item.qid}} && hits.{{item.qid}}.length" id="item-list" class="autocomplete-items"> + <div v-for="hit in hits.{{item.qid}}"> + <div> + <a href="#">${ hit.label }</a> + <span v-if="hit.alt_label">(${ hit.alt_label })</span> + — ${ hit.count } existing paintings + (${ hit.qid }) + <a :href="'https://www.wikidata.org/wiki/' + hit.qid">view on Wikidata</a> + </div> + <div v-if="hit.description"> + <div class="description">${ hit.description }</div> + </div> + </div> <! -- end for --> + </div> + </div> </div> </div> </div> @@ -47,3 +92,11 @@ </div> {% endblock %} + +{% block script %} +<script> + var lookup_url = {{ url_for('depicts_lookup') | tojson }}; +</script> +<script src="{{ url_for('static', filename='vue/vue.js') }}"></script> +<script src="{{ url_for('static', filename='js/catalog.js') }}"></script> +{% endblock %}