X-Git-Url: http://source.bookstackapp.com/bookstack/blobdiff_plain/bbf13e9242051b0002aa6e0d2e67b78dbe006779..HEAD:/resources/js/components/entity-selector.js diff --git a/resources/js/components/entity-selector.js b/resources/js/components/entity-selector.js deleted file mode 100644 index 1496ea89e..000000000 --- a/resources/js/components/entity-selector.js +++ /dev/null @@ -1,188 +0,0 @@ -import {onChildEvent} from "../services/dom"; -import {Component} from "./component"; - -/** - * Entity Selector - */ -export class EntitySelector extends Component { - - setup() { - this.elem = this.$el; - this.entityTypes = this.$opts.entityTypes || 'page,book,chapter'; - this.entityPermission = this.$opts.entityPermission || 'view'; - - this.input = this.$refs.input; - this.searchInput = this.$refs.search; - this.loading = this.$refs.loading; - this.resultsContainer = this.$refs.results; - this.addButton = this.$refs.add; - - this.search = ''; - this.lastClick = 0; - this.selectedItemData = null; - - this.setupListeners(); - this.showLoading(); - this.initialLoad(); - } - - setupListeners() { - this.elem.addEventListener('click', this.onClick.bind(this)); - - let lastSearch = 0; - this.searchInput.addEventListener('input', event => { - lastSearch = Date.now(); - this.showLoading(); - setTimeout(() => { - if (Date.now() - lastSearch < 199) return; - this.searchEntities(this.searchInput.value); - }, 200); - }); - - this.searchInput.addEventListener('keydown', event => { - if (event.keyCode === 13) event.preventDefault(); - }); - - if (this.addButton) { - this.addButton.addEventListener('click', event => { - if (this.selectedItemData) { - this.confirmSelection(this.selectedItemData); - this.unselectAll(); - } - }); - } - - // Keyboard navigation - onChildEvent(this.$el, '[data-entity-type]', 'keydown', (e, el) => { - if (e.ctrlKey && e.code === 'Enter') { - const form = this.$el.closest('form'); - if (form) { - form.submit(); - e.preventDefault(); - return; - } - } - - if (e.code === 'ArrowDown') { - this.focusAdjacent(true); - } - if (e.code === 'ArrowUp') { - this.focusAdjacent(false); - } - }); - - this.searchInput.addEventListener('keydown', e => { - if (e.code === 'ArrowDown') { - this.focusAdjacent(true); - } - }) - } - - focusAdjacent(forward = true) { - const items = Array.from(this.resultsContainer.querySelectorAll('[data-entity-type]')); - const selectedIndex = items.indexOf(document.activeElement); - const newItem = items[selectedIndex+ (forward ? 1 : -1)] || items[0]; - if (newItem) { - newItem.focus(); - } - } - - reset() { - this.searchInput.value = ''; - this.showLoading(); - this.initialLoad(); - } - - focusSearch() { - this.searchInput.focus(); - } - - showLoading() { - this.loading.style.display = 'block'; - this.resultsContainer.style.display = 'none'; - } - - hideLoading() { - this.loading.style.display = 'none'; - this.resultsContainer.style.display = 'block'; - } - - initialLoad() { - window.$http.get(this.searchUrl()).then(resp => { - this.resultsContainer.innerHTML = resp.data; - this.hideLoading(); - }) - } - - searchUrl() { - return `/ajax/search/entities?types=${encodeURIComponent(this.entityTypes)}&permission=${encodeURIComponent(this.entityPermission)}`; - } - - searchEntities(searchTerm) { - this.input.value = ''; - const url = `${this.searchUrl()}&term=${encodeURIComponent(searchTerm)}`; - window.$http.get(url).then(resp => { - this.resultsContainer.innerHTML = resp.data; - this.hideLoading(); - }); - } - - isDoubleClick() { - const now = Date.now(); - const answer = now - this.lastClick < 300; - this.lastClick = now; - return answer; - } - - onClick(event) { - const listItem = event.target.closest('[data-entity-type]'); - if (listItem) { - event.preventDefault(); - event.stopPropagation(); - this.selectItem(listItem); - } - } - - selectItem(item) { - const isDblClick = this.isDoubleClick(); - const type = item.getAttribute('data-entity-type'); - const id = item.getAttribute('data-entity-id'); - const isSelected = (!item.classList.contains('selected') || isDblClick); - - this.unselectAll(); - this.input.value = isSelected ? `${type}:${id}` : ''; - - const link = item.getAttribute('href'); - const name = item.querySelector('.entity-list-item-name').textContent; - const data = {id: Number(id), name: name, link: link}; - - if (isSelected) { - item.classList.add('selected'); - this.selectedItemData = data; - } else { - window.$events.emit('entity-select-change', null) - } - - if (!isDblClick && !isSelected) return; - - if (isDblClick) { - this.confirmSelection(data); - } - if (isSelected) { - window.$events.emit('entity-select-change', data) - } - } - - confirmSelection(data) { - window.$events.emit('entity-select-confirm', data); - } - - unselectAll() { - const selected = this.elem.querySelectorAll('.selected'); - for (const selectedElem of selected) { - selectedElem.classList.remove('selected', 'primary-background'); - } - this.selectedItemData = null; - } - -} \ No newline at end of file