hadith_ui/components/hadith/AutoComplation.vue
2025-02-17 16:33:06 +03:30

489 lines
12 KiB
Vue

<template>
<UInput
v-model="value"
placeholder="هوشمند جستجو کنید..."
:ui="{
trailing: '',
root: ['hadith-search-root'],
base: ['hadith-search-input'],
}"
:loading="loading"
trailing-icon="i-lucide-search"
autocomplete="on"
autofocus
highlight
@blur="onBlur"
@change="onChange"
@update:modelValue="onUpdateModel"
>
</UInput>
</template>
<script>
import { mapState } from "pinia";
import searchApi from "../../apis/searchApi.js";
import { useCommonStore } from "@stores/commonStore";
export default {
props: {
placeholder: {
default: "جستجو در هزاران محتوای قوانین و مقرارت",
},
contentKey: {
default: "qasection",
},
entityTheme: {
default: false,
},
showAppendSearchButton: {
default: true,
},
showPrepend: {
default: false,
},
showAppend: {
default: true,
},
textSearch: {
default: "",
},
modeInit: {
default: 0,
},
searchDomain: {
default() {
return [];
},
},
listAutocomplate: {
default() {
return [];
},
},
},
emits: ["getAutoComplateList"],
watch: {
modeInit(newVal = 1) {
this.mode = newVal;
},
textSearch(newVal) {
this.localTextSearch = newVal;
},
},
beforeMount() {
// this.inputPopupState = this.inputPopupState;
},
mounted() {
this.localTextSearch = this.textSearch;
if (window.localStorage.getItem([this.historySearchRecent])) {
try {
this.historySearch = JSON.parse(
window.localStorage.getItem([this.historySearchRecent])
);
} catch (e) {
window.localStorage.removeItem([this.historySearchRecent]);
}
}
},
beforeDestroy() {
window.removeEventListener("resize", this.handleResize);
window.removeEventListener("load", this.handleResize);
document.removeEventListener("click", this.handleClickOutside);
},
data() {
return {
loading: false,
value: "",
localListAutocomplate: [],
typingTimer: undefined,
doneTypingInterval: 800,
localTextSearch: "",
historySearch: [],
inputPopupState: 0,
mode: 1,
tagLiSelected: null,
inputfocused: false,
isLastKeyCodeArrow: false,
historySearchRecent: "historysearchrecent",
};
},
computed: {
...mapState(useCommonStore, ["domainActiveGetter"]),
},
methods: {
// on input changed
onUpdateModel() {
console.info("onUpdateModel");
},
// on input blur
onBlur() {
// console.info("onblue");
},
// on button click
onChange() {
console.info("onChange");
},
/**
* تنظیم آیتم انتخاب‌ شده و شروع جستجو.
* @param {Object} navItem - آیتم انتخاب‌شده.
*/
setDomainField(navItem) {
this.$emit("onSetDomainField", navItem);
// this.prevSearchStart();
},
async getAutoComplateList() {
this.localListAutocomplate = [];
if (this.localTextSearch == "") return;
let index_key = this.contentKey;
if (!index_key) return;
let url = searchApi.search.autoComplate;
url = url.replace("{{appname}}", buildName());
url = url.replace("{{index_key}}", index_key);
url = url.replace("{{filter}}", "q=" + this.localTextSearch);
try {
const { $api } = useNuxtApp();
const response = await $api(url, {
baseURL: repoUrl(),
});
this.localListAutocomplate = response.hits?.hits;
this.inputPopupState = 3;
} catch (err) {}
},
onKeyDown() {
clearTimeout(this.typingTimer);
this.typingTimer = undefined;
},
/**
* کنترل تایمر تکمیل خودکار و ارسال کوئری.
* تایمر فعلی را پاک می‌کند و یک تایمر جدید با یک تاخیر مشخص تنظیم می‌کند تا کوئری را ارسال کند.
*/
toggleAutocomplete(event) {
// برای کلید حرکت پایین درخواست اضافی نرود
if (
event.keyCode === 40 ||
event.keyCode === 38 ||
event.keyCode === 13
) {
this.isLastKeyCodeArrow = event.keyCode === 40 || event.keyCode === 38;
return;
}
this.isLastKeyCodeArrow = false;
if (!this.inputfocused && this.inputPopupState === 3) {
return;
}
if (this.typingTimer) {
clearTimeout(this.typingTimer);
this.typingTimer = undefined;
} else {
this.typingTimer = setTimeout(() => {
this.getAutoComplateList();
this.typingTimer = undefined;
}, this.doneTypingInterval);
}
},
setInputFocus() {
this.inputfocused = true;
// this.inputPopupfocused=false
},
/**
* شروع جستجو را کنترل می‌کند.
* @event prevSearchStart
*/
prevSearchStart(event) {
if (
this.isLastKeyCodeArrow &&
event.keyCode === 13 &&
this.inputPopupState != 0
) {
this.selectAutocomplate2();
this.isLastKeyCodeArrow = false;
return;
}
this.tagLiSelected = null;
this.inputPopupState = 0;
this.addHistorySearch(this.localTextSearch);
let tt = myEncodeQuery(this.localTextSearch);
this.$emit("onSearchStart", tt);
// this.searchStart(tt);
},
/**
*نمایش سابقه جستجو.
*/
showHisory() {
setTimeout(() => {
if (this.localTextSearch == "") this.inputPopupState = 1;
else {
this.inputPopupState = 0;
this.tagLiSelected = null;
}
}, 100);
},
/**
* کنترل کلیک‌های خارج از المان.
*/
keyupdiv(event) {
// 13:enter
// 8:backspace
if (this.inputfocused == false) return;
if (this.inputPopupState == 0 || this.inputPopupState == 2) return;
var el = "";
el =
this.inputPopupState == 1
? this.$refs["his_ul"]
: this.$refs["auto_complate_ul"];
if (!el || !el.firstChild) return;
const selectItem = (item) => {
this.tagLiSelected = item;
this.tagLiSelected?.classList.add("selected");
this.tagLiSelected?.focus();
};
// 40: arrow down
// 38: arrow up
if (this.inputfocused == true && event.keyCode === 40) {
if (this.tagLiSelected) {
this.tagLiSelected?.classList.remove("selected");
const next = this.tagLiSelected?.nextSibling || el.firstChild;
selectItem(next);
} else {
selectItem(el?.firstChild);
}
} else if (this.inputfocused == true && event.keyCode === 38) {
if (this.tagLiSelected) {
this.tagLiSelected?.classList.remove("selected");
const prev = this.tagLiSelected?.previousSibling || el.lastChild;
selectItem(prev);
} else {
selectItem(el?.lastChild);
}
}
// 46: delete
else if (this.inputfocused == true && event.keyCode === 46) {
let index = this.tagLiSelected?.getAttribute("data-key");
this.removeHistorySearch(index);
}
},
onClickOutside() {
if (this.inputPopupState == 1 || this.inputPopupState == 3) {
this.inputPopupState = 0;
this.tagLiSelected = null;
}
},
selectAutocomplate(item) {
this.tagLiSelected = null;
this.inputPopupState = 0;
this.localTextSearch = item;
this.$emit("onSearchStart", this.localTextSearch);
// this.$emit("onSearchStart", {
// textSearch: this.localTextSearch,
// searchItem: item,
// });
},
selectHistorySearch(item) {
this.localTextSearch = item;
this.$emit("onSearchStart", this.localTextSearch);
},
removeHistorySearch(x) {
this.tagLiSelected = null;
this.historySearch.splice(x, 1);
this.saveHistorySearch();
},
saveHistorySearch() {
const parsed = JSON.stringify(this.historySearch);
window.localStorage.setItem([this.historySearchRecent], parsed);
},
getHighlightAutocomplate(item) {
if (!item) return "";
let html = "";
let key = "title";
if (this.contentKey == "qasection" || this.contentKey == "rgsection") {
key = "qanon_title";
if (item?.highlight[key]) html = item.highlight[key][0];
if (!html) {
let key1 = key + ".ph";
if (item?.highlight[key1]) html = item.highlight[key1][0];
}
if (!html) {
let key1 = key + ".fa";
if (item?.highlight[key1]) html = item.highlight[key1][0];
}
let key2 = "ts_date";
if (item?._source[key2]) {
html += `<span style="color: #a7a098;"> - تاریخ: ${item._source[key2]}</span>`;
}
}
if (this.contentKey == "sanad") {
Object.values(item?.highlight).forEach((element, index) => {
html += element[0];
});
}
return html;
},
addHistorySearch(newSearch = "") {
if (newSearch == "") {
return;
}
var index = this.historySearch.indexOf(newSearch);
if (index != -1) {
this.historySearch.splice(index, 1);
}
this.historySearch.unshift(newSearch);
this.saveHistorySearch();
},
saveHistorySearch() {
const parsed = JSON.stringify(this.historySearch);
window.localStorage.setItem([this.historySearchRecent], parsed);
},
selectAutocomplate2(item) {
if (!item) {
if (this.localListAutocomplate.length) {
item = this.localListAutocomplate[this.tagLiSelected?.value];
}
}
let key = "title";
if (this.contentKey == "qasection" || this.contentKey == "rgsection")
key = "qanon_title";
this.inputfocused = false;
this.searchinput?.blur();
this.localTextSearch = item?._source[key];
this.$emit("onSearchStart", this.localTextSearch);
// this.$emit("onSearchStart", {
// textSearch: this.localTextSearch,
// searchItem: item,
// });
if (!item) {
this.localTextSearch = this.tagLiSelected?.innerText;
this.addHistorySearch(this.localTextSearch);
let tt = myEncodeQuery(this.localTextSearch);
this.$emit("onSearchStart", tt);
// this.$emit("onSearchStart", { textSearch: tt, searchItem: item });
}
this.inputPopupState = 0;
this.tagLiSelected = null;
},
},
};
</script>
<style>
.hadith-search-root {
width: 656px;
&::before {
content: "";
position: absolute;
left: 1em;
right: 1em;
top: 50%;
backdrop-filter: blur(60px);
background: linear-gradient(137.41deg, #ffffff -42.82%, #e5e0ff 87.9%);
filter: blur(60px);
/* transform: rotate(180deg); */
width: 626px;
height: 68px;
z-index: 1;
}
& > span {
z-index:3;
width: 48px;
height: 48px;
justify-content: center;
align-items: center;
padding: 0;
/* padding-bottom: 6px; */
border-radius: 50px;
/* border-bottom-width: 1px; */
background: linear-gradient(320.71deg, #b9fde0 6.56%, #e4f9f0 69.69%);
left: 12px;
top: 0;
bottom: 0;
margin: auto;
transition: all 0.2s ease-in-out;
&:hover {
transition: all 0.2s ease-in-out;
background: linear-gradient(320.71deg, #90ceb3 6.56%, #daf1e8 69.69%);
}
& > span {
width: 18px;
height: 18px;
/* border-width: 1.5px; */
/* border: 1.5px solid; */
/* border-image-source: linear-gradient(
102.02deg,
#4be8ae 7.38%,
#00a762 91.78%
); */
}
}
}
.hadith-search-input {
z-index: 2;
height: 72px;
justify-content: space-between;
padding-top: 12px;
padding-right: 24px;
padding-bottom: 12px;
padding-left: 12px;
border-radius: 12px;
border-width: 0.3px;
background-color: #fff;
border: 0.3px solid #e0e0e0;
box-shadow: 0px 1px 4px 0px #0000000d;
font-family: IRANSansX;
font-weight: 300;
font-size: 14px;
line-height: 21px;
letter-spacing: 0%;
text-align: right;
color: #a7acbe;
}
</style>