2019-10-23 17:04:54 +00:00
|
|
|
import Vue from "vue";
|
2019-11-21 17:43:56 +00:00
|
|
|
import { Component, Prop } from 'vue-property-decorator';
|
2019-10-30 10:25:56 +00:00
|
|
|
import debounce from 'lodash/debounce';
|
|
|
|
import rdrApi from '../search-results/dataservice';
|
|
|
|
|
2020-06-02 14:11:07 +00:00
|
|
|
interface SolrSettings {
|
|
|
|
core: string;
|
|
|
|
host: string;
|
|
|
|
}
|
|
|
|
declare var SOLR: SolrSettings;
|
2019-10-23 17:04:54 +00:00
|
|
|
|
|
|
|
@Component({})
|
|
|
|
export default class VsInput extends Vue {
|
2019-10-30 10:25:56 +00:00
|
|
|
|
|
|
|
@Prop()
|
|
|
|
title: string;
|
|
|
|
|
|
|
|
@Prop({ default: 'Search' })
|
|
|
|
placeholder: string;
|
|
|
|
|
|
|
|
display: string = "";
|
|
|
|
value = null;
|
|
|
|
error: string = null;
|
|
|
|
//search: null,
|
|
|
|
results: Array<any> = [];
|
|
|
|
// suggestions: Object = {};
|
|
|
|
//showResults: boolean = false;
|
|
|
|
loading: boolean = false;
|
|
|
|
isAsync: boolean = true;
|
|
|
|
items: Array<any> = [];
|
|
|
|
selectedIndex: number = null;
|
|
|
|
selectedDisplay = null;
|
|
|
|
isFocussed: boolean = false;
|
2020-06-02 14:11:07 +00:00
|
|
|
solrCore: string = SOLR.core;
|
|
|
|
solrHost: string = SOLR.host;
|
2019-10-30 10:25:56 +00:00
|
|
|
|
|
|
|
// get results() {
|
|
|
|
// return this.items;
|
|
|
|
// }
|
|
|
|
|
|
|
|
get showResults(): boolean {
|
|
|
|
return this.results.length > 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
get noResults(): boolean {
|
|
|
|
return Array.isArray(this.results) && this.results.length === 0
|
|
|
|
}
|
|
|
|
|
|
|
|
get isLoading(): boolean {
|
|
|
|
return this.loading === true
|
|
|
|
}
|
|
|
|
|
|
|
|
get hasError(): boolean {
|
|
|
|
return this.error !== null
|
|
|
|
}
|
|
|
|
|
|
|
|
get suggestions(): any[] {
|
|
|
|
var suggestion = {
|
|
|
|
titles: [],
|
|
|
|
authors: [],
|
|
|
|
subjects: []
|
|
|
|
};
|
|
|
|
|
|
|
|
for (let key in this.results) {
|
|
|
|
let obj = this.results[key];
|
|
|
|
|
|
|
|
if (obj["title_output"].toLowerCase().indexOf(this.display) !== -1) {
|
|
|
|
var title = obj["title_output"];
|
|
|
|
if (!suggestion["titles"].find(value => value === title)) {
|
|
|
|
suggestion.titles.push(title);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (this.find(obj["author"], this.display.toLowerCase()) !== "") {
|
|
|
|
var author = this.find(obj["author"], this.display.toLowerCase());
|
|
|
|
if (!suggestion["authors"].find(value => value === author)) {
|
|
|
|
suggestion.authors.push(author);
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
if (this.find(obj["subject"], this.display.toLowerCase()) != "") {
|
|
|
|
var subject = this.find(obj["subject"], this.display.toLowerCase());
|
|
|
|
if (!suggestion["subjects"].find(value => value === subject)) {
|
|
|
|
suggestion.subjects.push(subject);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
var suggestions = Array.prototype.concat(suggestion.titles, suggestion.authors, suggestion.subjects);
|
|
|
|
return suggestions;
|
|
|
|
}
|
|
|
|
|
|
|
|
// @Watch('items')
|
|
|
|
// onItemsChanged(val: Array<any>, oldVal: Array<any>) {
|
|
|
|
// this.results = val;
|
|
|
|
// this.loading = false;
|
|
|
|
// }
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Clear all values, results and errors
|
|
|
|
*/
|
|
|
|
clear() {
|
|
|
|
this.display = null;
|
|
|
|
// this.value = null
|
|
|
|
this.results = [];
|
|
|
|
this.error = null;
|
|
|
|
this.$emit('clear');
|
|
|
|
}
|
2019-10-23 17:04:54 +00:00
|
|
|
|
|
|
|
search() {
|
2019-10-30 10:25:56 +00:00
|
|
|
this.$emit("search", this.display);
|
|
|
|
}
|
|
|
|
|
|
|
|
searchChanged() {
|
|
|
|
this.selectedIndex = null
|
|
|
|
// Let's warn the parent that a change was made
|
|
|
|
// this.$emit("input", this.display);
|
|
|
|
if (this.display.length >= 2) {
|
|
|
|
this.loading = true;
|
|
|
|
this.resourceSearch();
|
|
|
|
} else {
|
|
|
|
this.results = [];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
resourceSearch = debounce(function () {
|
|
|
|
if (!this.display) {
|
|
|
|
this.results = []
|
|
|
|
return
|
|
|
|
}
|
|
|
|
this.loading = true;
|
|
|
|
// this.setEventListener();
|
|
|
|
this.request();
|
|
|
|
}, 200);
|
|
|
|
|
|
|
|
async request() {
|
|
|
|
try {
|
2020-06-02 14:11:07 +00:00
|
|
|
var res = await rdrApi.searchTerm(this.display, this.solrCore, this.solrHost);
|
2019-10-30 10:25:56 +00:00
|
|
|
this.error = null
|
|
|
|
this.results = res.response.docs;
|
|
|
|
this.loading = false;
|
|
|
|
} catch (error) {
|
|
|
|
this.error = error.message;
|
|
|
|
this.loading = false;
|
|
|
|
}
|
2019-10-23 17:04:54 +00:00
|
|
|
}
|
2019-10-30 10:25:56 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Register the component as focussed
|
|
|
|
*/
|
|
|
|
focus() {
|
|
|
|
this.isFocussed = true
|
|
|
|
}
|
|
|
|
/**
|
|
|
|
* Remove the focussed value
|
|
|
|
*/
|
|
|
|
blur() {
|
|
|
|
this.isFocussed = false
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Is this item selected?
|
|
|
|
* @param {Object}
|
|
|
|
* @return {Boolean}
|
|
|
|
*/
|
|
|
|
isSelected(key) {
|
|
|
|
return key === this.selectedIndex
|
|
|
|
}
|
|
|
|
|
|
|
|
onArrowDown(ev) {
|
|
|
|
ev.preventDefault()
|
|
|
|
if (this.selectedIndex === null) {
|
|
|
|
this.selectedIndex = 0;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
this.selectedIndex = (this.selectedIndex === this.suggestions.length - 1) ? 0 : this.selectedIndex + 1;
|
|
|
|
this.fixScrolling();
|
|
|
|
}
|
|
|
|
|
|
|
|
fixScrolling() {
|
|
|
|
const currentElement = this.$refs.options[this.selectedIndex];
|
|
|
|
currentElement.scrollIntoView({ behavior: 'smooth', block: 'nearest', inline: 'start' });
|
|
|
|
}
|
|
|
|
|
|
|
|
onArrowUp(ev) {
|
|
|
|
ev.preventDefault()
|
|
|
|
if (this.selectedIndex === null) {
|
|
|
|
this.selectedIndex = this.suggestions.length - 1;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
this.selectedIndex = (this.selectedIndex === 0) ? this.suggestions.length - 1 : this.selectedIndex - 1;
|
|
|
|
this.fixScrolling();
|
|
|
|
}
|
|
|
|
|
|
|
|
onEnter() {
|
|
|
|
if (this.selectedIndex === null) {
|
|
|
|
this.$emit('nothingSelected', this.display);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
this.select(this.suggestions[this.selectedIndex]);
|
|
|
|
this.$emit('enter', this.display);
|
|
|
|
}
|
|
|
|
|
|
|
|
select(obj) {
|
|
|
|
if (!obj) {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
this.value = obj; //(obj["title_output"]) ? obj["title_output"] : obj.id
|
|
|
|
this.display = obj;// this.formatDisplay(obj)
|
|
|
|
this.selectedDisplay = this.display
|
|
|
|
// this.$emit('selected', {
|
|
|
|
// value: this.value,
|
|
|
|
// display: this.display,
|
|
|
|
// selectedObject: obj
|
|
|
|
// })
|
|
|
|
this.$emit('input', this.value);
|
|
|
|
this.$emit("search", this.value);
|
|
|
|
// alert(this.value);
|
|
|
|
this.close();
|
|
|
|
}
|
|
|
|
|
|
|
|
formatDisplay(obj) {
|
|
|
|
if (obj.title_output.toLowerCase().indexOf(this.display) !== -1) {
|
|
|
|
return obj.title_output;
|
|
|
|
} else if (this.find(obj.author, this.display.toLowerCase()) !== "") {
|
|
|
|
var author = this.find(obj.author, this.display.toLowerCase());
|
|
|
|
return author;
|
|
|
|
} else if (this.find(obj.subject, this.display.toLowerCase()) != "") {
|
|
|
|
return this.find(obj.subject, this.display.toLowerCase());
|
|
|
|
} else {
|
|
|
|
return obj.id;
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2019-11-21 17:43:56 +00:00
|
|
|
private find(myarray, searchterm): string {
|
2019-10-30 10:25:56 +00:00
|
|
|
for (var i = 0, len = myarray.length; i < len; i += 1) {
|
|
|
|
if (typeof (myarray[i]) === 'string' && myarray[i].toLowerCase().indexOf(searchterm) !== -1) {
|
|
|
|
// print or whatever
|
|
|
|
return myarray[i];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return "";
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Close the results list. If nothing was selected clear the search
|
|
|
|
*/
|
|
|
|
close() {
|
|
|
|
if (!this.value || !this.selectedDisplay) {
|
|
|
|
this.clear();
|
|
|
|
}
|
|
|
|
if (this.selectedDisplay !== this.display && this.value) {
|
|
|
|
this.display = this.selectedDisplay;
|
|
|
|
}
|
|
|
|
this.results = [];
|
|
|
|
this.error = null;
|
|
|
|
//this.removeEventListener()
|
|
|
|
this.$emit('close');
|
|
|
|
}
|
2019-10-23 17:04:54 +00:00
|
|
|
}
|