suggestWindow
script.jsexport class suggestWindow{
constructor() {
this.box = document.createElement('div');
this.box.setAttribute('id', 'external-suggestion');
this.box.classList.add('form-group');
this.box.style.position = 'absolute';
this.container = document.createElement('div');
this.container.classList.add('dropdown');
this.box.appendChild(this.container);
this.items = document.createElement('ul');
this.items.classList.add('dropdown-menu');
this.items.style.whiteSpace='nowrap'; // 文字列を折り返さない
this.container.appendChild(this.items);
this.editor = document.getElementById('editor');
this.editor.appendChild(this.box);
}
// 入力補完window を開く
open() {
// 入力候補がなければ開かない
if (this.getItems().length == 0) return;
this.container.classList.add('open');
}
// 入力補完window を閉じる
close(cursor = null) {
//console.log('close the window.');
this.container.classList.remove('open');
this.items.textContent='';
if(!cursor) cursor = document.getElementById('text-input');
cursor.focus();
}
// 入力補完window の開閉判定
isOpen() {
return this.container.classList.contains('open');
}
// 入力候補に表示するアイテムを更新する
updateItems(items) {
const newList = document.createElement('ul');
newList.classList.add('dropdown-menu');
newList.style.whiteSpace='nowrap';
入力補完windowが長すぎる場合は、以下のコードをここに追記する
newList.style.maxHeight='calc(50vh - 100px)';
script.js
for(const item of items) {
let listItem = document.createElement('li');
listItem.classList.add('dropdown-item');
listItem.appendChild(item);
newList.appendChild(listItem)
}
this.items.replaceWith(newList);
this.items = newList; // これを書かないと置き換えが完了しない
}
getItems() {
return this.items.children;
}
// 入力補完windowの位置を更新する
reDraw(cursor) {
this.box.style.top = `${parseInt(cursor.style.top) + parseInt(cursor.style.height) + 3}px`;
this.box.style.left = `${parseInt(cursor.style.left)}px`;
}
// 現在focusがあたっている入力候補を返す
getFocusedItem() {
return this.items.querySelector(':focus');
}
hasFocus(){
return this.getFocusedItem() != null;
}
// 補完候補の先頭にfocusを当てる
selectFirstItem() {
this.items.firstElementChild.firstElementChild.focus();
//console.log('the first item is focused.');
}
// 最初の補完候補にfocusがあたっているかどうか
hasFirstItemFocus() {
//console.log(`selectedItem: ${this.getFocusedItem()}`);
return this.getFocusedItem()
== this.items.firstElementChild.firstElementChild;
}
// 次の補完候補に移動する
selectNextItem(cursor) {
// focusが当たっている要素を取得
const selectedItem = this.items.querySelector(':focus');
if(!selectedItem) {
this.selectFirstItem();
return;
}
if(selectedItem == this.items.lastElementChild) {
this.selectFirstItem();
return;
}
//selectedItem.nextElementSibling.firstElementChild.focus();
}
// 前の補完候補に移動する
selectPreviousItem(cursor) {
// focusが当たっている要素を取得
const selectedItem = this.items.querySelector(':focus');
if(!selectedItem) {
this.close();
return;
}
//selectedItem.previousElementSibling.firstElementChild.focus();
}
// 現在の選択候補の文字列を取得する
getCurrentItemString() {
const selectedItem = this.items.querySelector(':focus');
if(!selectedItem) {
return undefined;
}
return selectedItem.textContent;
}
}