216 lines
7.0 KiB
JavaScript
216 lines
7.0 KiB
JavaScript
class SelectorBase {
|
|
find(selector, parent) {
|
|
const p = parent || document
|
|
return parent.querySelector(selector)
|
|
}
|
|
|
|
findAll(selector, parent, callback) {
|
|
const p = parent || document,
|
|
result = parent.querySelectorAll(selector)
|
|
result.forEach((e, i) => {
|
|
callback(e, i)
|
|
})
|
|
return result;
|
|
}
|
|
|
|
set(obj) {
|
|
obj = obj || {};
|
|
const element = document.createElement(obj.tagName || 'div')
|
|
if (obj.type) element.type = obj.type
|
|
if (obj.className) element.className = obj.className
|
|
if (obj.innerHTML) element.innerHTML = obj.innerHTML
|
|
if (obj.name) element.name = obj.name
|
|
if (obj.value) element.value = obj.value
|
|
if (obj.events) {
|
|
Object.keys(obj.events).forEach(event => {
|
|
element.addEventListener(event, e => {
|
|
obj.events[event](element)
|
|
})
|
|
})
|
|
}
|
|
if (obj.attributes) {
|
|
Object.keys(obj.attributes).forEach(attr => {
|
|
element.setAttribute(attr, obj.attributes[attr])
|
|
})
|
|
}
|
|
if (obj.parent) obj.parent.appendChild(element)
|
|
return element
|
|
}
|
|
|
|
toggleClass(e, classFrom, classTo) {
|
|
e.classList.remove(classFrom)
|
|
e.classList.add(classTo)
|
|
}
|
|
|
|
toggleOpen(e) {
|
|
if (e.classList.contains('open-autocomplete')) {
|
|
e.classList.remove('open-autocomplete')
|
|
} else {
|
|
e.classList.add('open-autocomplete')
|
|
}
|
|
}
|
|
|
|
request(url, query, callback) {
|
|
const xhr = new XMLHttpRequest()
|
|
xhr.responseType = 'json'
|
|
xhr.open('get', `${url}?${query}`)
|
|
xhr.onload = () => {
|
|
callback(xhr.response)
|
|
}
|
|
xhr.send()
|
|
}
|
|
}
|
|
|
|
class SearchBoxRemote extends SelectorBase {
|
|
constructor(selector, obj) {
|
|
super();
|
|
this.set({
|
|
tagName: 'link',
|
|
parent: document.head,
|
|
attributes: {href: '/_public/assets/css/search-box-remote.css', rel: 'stylesheet'}
|
|
})
|
|
document.querySelectorAll(selector).forEach(element => {
|
|
new SearchBoxRemoteInitial(element, obj)
|
|
})
|
|
}
|
|
}
|
|
|
|
class SearchBoxRemoteInitial extends SelectorBase {
|
|
url
|
|
q
|
|
id
|
|
columns
|
|
selected
|
|
hidden
|
|
searchBoxContainer
|
|
inputSearch
|
|
autocompleteList
|
|
|
|
constructor(selector, obj) {
|
|
super();
|
|
obj = obj || {};
|
|
this.url = obj.url || null
|
|
this.q = obj.q || 'q'
|
|
this.id = obj.id || 'id'
|
|
this.columns = obj.columns || null
|
|
this.init(selector)
|
|
}
|
|
|
|
init(e) {
|
|
if (e.dataset && e.dataset.sbrName) {
|
|
this.hidden = this.set({
|
|
tagName: 'input',
|
|
type: 'hidden',
|
|
name: e.dataset.sbrName,
|
|
value: e.dataset.sbrValue,
|
|
parent: e.parentNode
|
|
})
|
|
e.setAttribute('readonly', true)
|
|
e.classList.add('pointer')
|
|
e.parentNode.classList.add('relative')
|
|
this.selected = e
|
|
e.addEventListener('click', () => {
|
|
if(!event.target.classList.contains('clear-button') && !event.target.classList.contains('add-button')) {
|
|
this.setSearchBox(e.parentNode)
|
|
}
|
|
})
|
|
this.setDefaultSelected()
|
|
}
|
|
}
|
|
|
|
setSearchBox(container) {
|
|
if (container.classList.contains('open-autocomplete')) {
|
|
container.classList.remove('open-autocomplete')
|
|
container.querySelector('.search-box-container').remove()
|
|
} else {
|
|
this.searchBoxContainer = this.set({className: 'search-box-container', parent: container})
|
|
this.inputSearch = this.set({
|
|
tagName: 'input', attributes: {
|
|
class: 'input-search',
|
|
placeholder: 'Търси ...',
|
|
}, parent: this.searchBoxContainer
|
|
})
|
|
this.inputSearch.focus();
|
|
if ((window.innerHeight - this.searchBoxContainer.getBoundingClientRect().top) < 500) {
|
|
this.searchBoxContainer.classList.add('up-position')
|
|
this.setAutocompleteList('prepend')
|
|
} else {
|
|
this.searchBoxContainer.classList.add('down-position')
|
|
this.setAutocompleteList('append')
|
|
}
|
|
container.classList.add('open-autocomplete')
|
|
}
|
|
}
|
|
|
|
setAutocompleteList(type) {
|
|
this.autocompleteList = this.set({className: 'autocomplete-list autocomplete-image-list'})
|
|
if (type === 'prepend') this.searchBoxContainer.insertBefore(this.autocompleteList, this.inputSearch)
|
|
if (type === 'append') this.searchBoxContainer.append(this.autocompleteList)
|
|
this.inputSearch.addEventListener('keydown', () => {
|
|
this.keyDown()
|
|
})
|
|
this.inputSearch.addEventListener('keyup', () => {
|
|
this.keyUp()
|
|
})
|
|
}
|
|
|
|
setDefaultSelected() {
|
|
if(this.hidden.value) {
|
|
this.request(this.url, `${this.id}=${this.hidden.value}`, e => {
|
|
if(e.settlement_id) {
|
|
this.selected.value = `${e.name}`;
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
setAutocompleteValues(data) {
|
|
const $this = this
|
|
this.autocompleteList.innerHTML = ''
|
|
data.forEach(e => {
|
|
const resultRow = this.set({
|
|
className: 'autocomplete-value',
|
|
innerHTML: `${e.name}`,
|
|
parent: this.autocompleteList,
|
|
events: {
|
|
click: function () {
|
|
$this.hidden.value = e.object_id;
|
|
$this.searchBoxContainer.parentNode.classList.remove('open-autocomplete')
|
|
$this.searchBoxContainer.remove();
|
|
$this.selected.innerHTML = resultRow.innerHTML + '<div class="flex flex-center top5">' +
|
|
'<div class="add-button" onclick="addSelected()"><i class="la la-plus-circle"></i> Добави</div>' +
|
|
'<div class="clear-button" onclick="clearSelected()"><i class="la la-remove"></i>Изчисти</div></div>'
|
|
$this.selected.querySelector('.row-result').classList.add('panel-result-selected')
|
|
}
|
|
}
|
|
})
|
|
})
|
|
}
|
|
|
|
|
|
keyDown() {
|
|
this.autocompleteList.innerHTML = ''
|
|
}
|
|
|
|
keyUp() {
|
|
if (this.inputSearch.value.length > 0) {
|
|
this.request(this.url, `${this.q}=${this.inputSearch.value}`, data => {
|
|
if (data && data.length > 0) {
|
|
this.setAutocompleteValues(data)
|
|
this.autocompleteList.classList.add('visible')
|
|
} else {
|
|
this.closeAutocomplete()
|
|
}
|
|
})
|
|
} else {
|
|
this.closeAutocomplete()
|
|
}
|
|
}
|
|
|
|
closeAutocomplete() {
|
|
this.autocompleteList.classList.remove('visible')
|
|
this.autocompleteList.innerHTML = ''
|
|
}
|
|
}
|
|
|