106 lines
3.8 KiB
JavaScript
106 lines
3.8 KiB
JavaScript
console.log("Hello, world!");
|
|
|
|
tag_suggestion_list = {
|
|
list_element: null,
|
|
suggestion_elements: [],
|
|
}
|
|
|
|
var lel = document.createElement('div');
|
|
|
|
/**
|
|
* Stolen from medium.com/@jh3y
|
|
* returns x, y coordinates for absolute positioning of a span within a given text input
|
|
* at a given selection point
|
|
* @param {object} input - the input element to obtain coordinates for
|
|
* @param {number} selectionPoint - the selection point for the input
|
|
*/
|
|
function getCursorXY(input, selectionPoint){
|
|
const {
|
|
offsetLeft: inputX,
|
|
offsetTop: inputY,
|
|
} = input
|
|
// create a dummy element that will be a clone of our input
|
|
const div = document.createElement('div')
|
|
// get the computed style of the input and clone it onto the dummy element
|
|
const copyStyle = getComputedStyle(input)
|
|
for (const prop of copyStyle) {
|
|
div.style[prop] = copyStyle[prop]
|
|
}
|
|
// we need a character that will replace whitespace when filling our dummy element if it's a single line <input/>
|
|
const swap = '.'
|
|
const inputValue = input.tagName === 'INPUT' ? input.value.replace(/ /g, swap) : input.value
|
|
// set the div content to that of the textarea up until selection
|
|
const textContent = inputValue.substr(0, selectionPoint)
|
|
// set the text content of the dummy element div
|
|
div.textContent = textContent
|
|
if (input.tagName === 'TEXTAREA') div.style.height = 'auto'
|
|
// if a single line input then the div needs to be single line and not break out like a text area
|
|
if (input.tagName === 'INPUT') div.style.width = 'auto'
|
|
// create a marker element to obtain caret position
|
|
const span = document.createElement('span')
|
|
// give the span the textContent of remaining content so that the recreated dummy element is as close as possible
|
|
span.textContent = inputValue.substr(selectionPoint) || '.'
|
|
// append the span marker to the div
|
|
div.appendChild(span)
|
|
// append the dummy element to the body
|
|
document.body.appendChild(div)
|
|
// get the marker position, this is the caret position top and left relative to the input
|
|
const { offsetLeft: spanX, offsetTop: spanY } = span
|
|
// lastly, remove that dummy element
|
|
// NOTE:: can comment this out for debugging purposes if you want to see where that span is rendered
|
|
document.body.removeChild(div)
|
|
// return an object with the x and y of the caret. account for input positioning so that you don't need to wrap the input
|
|
return {
|
|
x: inputX + spanX,
|
|
y: inputY + spanY,
|
|
}
|
|
}
|
|
|
|
function display_suggestions(elem, sugg, event){
|
|
console.log("sugg:",sugg);
|
|
//Check that the value hasn't change since we fired
|
|
//off the request
|
|
recent = elem.value.split(";").pop().trim();
|
|
if(recent == sugg[0]){
|
|
var sugx, sugy = getCursorXY(elem,elem.value.length);
|
|
console.log("Looking at position to display suggestions:",sugx, sugy);
|
|
for(var i in sugg){
|
|
console.log("Displaying suggestion:",sugg[i]);
|
|
lel.setAttribute('style',`left: $(sugx)px; top: $(sugy)px;`);
|
|
}
|
|
}
|
|
}
|
|
|
|
function hint_tags(elem, event){
|
|
//Get the most recent tag
|
|
recent = elem.value.split(";").pop().trim();
|
|
if(recent.length > 0){
|
|
console.log("Most recent tag:",recent);
|
|
//Ask the server for tags that look like this
|
|
xhr = new XMLHttpRequest();
|
|
xhr.open("GET", "/_api?call=suggest&data=" + recent);
|
|
xhr.onreadystatechange = function(e){
|
|
if(xhr.readyState === 4){
|
|
console.log("Event:",e);
|
|
suggestions = xhr.response.split(";");
|
|
console.log("suggestions:",suggestions);
|
|
display_suggestions(elem,suggestions, event);
|
|
|
|
}
|
|
}
|
|
xhr.send()
|
|
}
|
|
}
|
|
|
|
function init(){
|
|
tag_el_list = document.getElementsByName("tags");
|
|
console.assert(tag_el_list.length == 1);
|
|
tag_el = tag_el_list[0];
|
|
tag_el.onkeyup = function(event){
|
|
console.log("Looking at tag:", event);
|
|
console.log("And element:",tag_el);
|
|
hint_tags(tag_el, event);
|
|
}
|
|
}
|
|
document.addEventListener("DOMContentLoaded",init,false);
|