import listEditor from 'wiki-list-editor'; import axios from 'axios'; import qs from 'querystring' import $ from 'jquery'; import search from './search'; import createPageSearch from './fuse'; import Mustache from 'mustache'; import 'jquery-contextmenu'; import getCaretCoordinates from './caret-position' import './styles.scss'; import '../node_modules/jquery-contextmenu/dist/jquery.contextMenu.css'; function addSaver(editor, saveUrl, page, beforeSave) { return { save() { return editor.save().then(outputData => { beforeSave() let data = { 'json': 1, 'p': page, 'summary': "", 'content': JSON.stringify(outputData), }; return axios.post(saveUrl, qs.encode(data)) }) } } } function Indicator(element, timeout) { let timeoutId; return { done() { timeoutId = setTimeout(() => { element.classList.add('hidden') }, timeout * 1000); }, setText(text) { if (timeoutId) { clearTimeout(timeoutId); timeoutId = null; } element.innerText = text; element.classList.remove('hidden') }, } } function addIndicator(editor, indicator) { return { save() { editor.save().then(() => { indicator.setText('saved!'); indicator.done(); }) } } } let holder = document.getElementById('editor'); if (holder) { let editor = listEditor(holder, JSON.parse(holder.dataset.input)); editor.on('change', function () { let element = document.getElementById('editor'); let indicator = Indicator(document.getElementById('save-indicator'), 2); let saveUrl = element.dataset.saveurl; let page = element.dataset.page; indicator.setText('has changes...'); addIndicator( addSaver(editor, saveUrl, page, () => indicator.setText('saving...')), indicator ).save() }) $(document).on('keydown', '#link-complete', function (event) { if (!$('#link-complete:visible')) { return true; } const $popup = $('#link-complete') if (event.key === 'Escape') { $popup.fadeOut() return false; } if (event.key === 'Enter') { const linkName = $popup.find('li.selected').text() $popup.trigger('popup:selected', [linkName]) $popup.fadeOut() return false } if (event.key === 'ArrowUp') { const selected = $popup.find('li.selected') const prev = selected.prev('li') if (prev.length) { prev.addClass('selected') selected.removeClass('selected') } return false; } if (event.key === 'ArrowDown') { const selected = $popup.find('li.selected') const next = selected.next('li'); if (next.length) { next.addClass('selected') selected.removeClass('selected') } return false } return true }) createPageSearch().then(function ({search}) { editor.on('start-editing', function (input) { const $lc = $('#link-complete') $lc.on('popup:selected', function (event, linkName) { let value = input.value let end = input.selectionEnd let start = value.lastIndexOf("[[", end) end += 2 let startAndLink = value.substring(0, start) + "[[" + linkName + "]]" input.value = startAndLink + value.substring(end) input.selectionStart = startAndLink.length input.selectionEnd = startAndLink.length input.focus() return true }) $(input).on('keydown', function (event) { const isVisible = $('#link-complete:visible').length > 0; const $lc = $('#link-complete') if (event.key === 'Escape' && isVisible) { $lc.fadeOut() return true } if (event.key === 'ArrowDown' && isVisible) { $lc.focus() $lc.find('li:first-child').addClass('selected') return false } return true }) $(input).on('keyup', function () { let value = input.value let end = input.selectionEnd let start = value.lastIndexOf("[[", end) let linkEnd = value.lastIndexOf("]]", end - 1) if (start < linkEnd) { return } let query = value.substring(start, end); let results = search.search(query) let pos = getCaretCoordinates(input, value.selectionEnd, {}) let off = $(input).offset() pos.top += off.top + pos.height pos.left += off.left const $lc = $('#link-complete') $lc.offset(pos) var template = document.getElementById('link-template').innerHTML; var rendered = Mustache.render(template, {results: results}, {}, ['[[', ']]']); $lc.html(rendered).fadeIn() }) }) editor.on('stop-editing', function (input) { $('#link-complete').off() }) }) $.contextMenu({ selector: '.marker', items: { copy: { name: 'Copy', callback: function (key, opt) { editor.copy(this).then(result => { console.log(result) }) } } } }); } let timeout = null; let searchInput = document.getElementById('search-input'); search(searchInput).then(searcher => { searchInput.addEventListener('keyup', function (e) { clearTimeout(timeout); if (e.key === 'Escape') { $(searchInput).val(''); $('#autocomplete').hide(); return; } timeout = setTimeout(function () { let query = $(searchInput).val() if (query === '') { let autocomplete = document.getElementById('autocomplete'); $(autocomplete).hide() return } $('#autocomplete').show() let result = searcher.search(query) const newpage = query.replace(/\s+/g, '_') var template = document.getElementById('result-template').innerHTML; var rendered = Mustache.render(template, {page: newpage, results: result}, {}, ['[[', ']]']); let autocomplete = document.getElementById('autocomplete'); autocomplete.innerHTML = rendered; }, 500) }) })