Restructure, improive keyboard input handling, debouncing

This commit is contained in:
Daniel Triendl 2020-10-20 17:47:54 +02:00
parent 204d5837c5
commit d49b934c9a

View File

@ -1,146 +1,233 @@
// ==UserScript== // ==UserScript==
// @name 3CX TAPI // @name 3CX TAPI
// @version 1 // @author Daniel Triendl
// @grant GM.xmlHttpRequest // @namespace http://cp-solutions.at
// @include https://192.168.0.154:5001/webclient* // @copyright Copyright 2020 CP Solutions GmbH
// @include https://cpsolution.my3cx.at:5001/webclient* // @version 2
// @downloadURL http://scootaloo.cp-austria.at/gitlist/3cx_tapi.git/raw/master/3CX_TAPI.user.js // @grant GM.xmlHttpRequest
// @require https://cdn.jsdelivr.net/gh/CoeJoder/waitForKeyElements.js@v1.2/waitForKeyElements.js // @include https://192.168.0.154:5001/webclient*
// @include https://cpsolution.my3cx.at:5001/webclient*
// @downloadURL http://scootaloo.cp-austria.at/gitlist/3cx_tapi.git/raw/master/3CX_TAPI.user.js
// @require https://cdn.jsdelivr.net/gh/CoeJoder/waitForKeyElements.js@v1.2/waitForKeyElements.js
// ==/UserScript== // ==/UserScript==
console.log('TAPI init'); console.log('TAPI init');
function fireChangeEvents(element) { const debounce = (func, wait) => {
var changeEvent = null; let timeout;
changeEvent = document.createEvent("HTMLEvents");
changeEvent.initEvent("input", true, true);
element.dispatchEvent(changeEvent);
console.debug('input event dispatched for element: ' + element.id);
changeEvent = document.createEvent("HTMLEvents");
changeEvent.initEvent("keyup", true, true);
element.dispatchEvent(changeEvent);
console.debug('keyup event dispatched for element: ' + element.id);
changeEvent = document.createEvent("HTMLEvents");
changeEvent.initEvent("change", true, true);
element.dispatchEvent(changeEvent);
console.debug('change event dispatched for element: ' + element.id);
}
function removeSearchResults() { return function executedFunction(...args) {
var resultList = document.getElementById('tapiResults'); const later = () => {
if (resultList) { clearTimeout(timeout);
resultList.parentNode.removeChild(resultList); func(...args);
} };
}
var doSearch = function () { clearTimeout(timeout);
var search = document.getElementById('tapiSearchInput'); timeout = setTimeout(later, wait);
var searchText = search.value.trim(); };
if (searchText == '') {
removeSearchResults();
return;
}
console.log('Searching TAPI');
GM.xmlHttpRequest({
method: 'GET',
url: 'http://cpatapi.cpsrvweb2016.cp-austria.at/search?query=' + encodeURIComponent(searchText),
onload: function (response) {
console.log('TAPI Search response', response);
var contacts = JSON.parse(response.responseText);
console.log('TAPI Contacts', contacts);
removeSearchResults();
resultList = document.createElement('ul');
resultList.id = 'tapiResults';
resultList.classList.add('search-nav-absolute');
resultList.classList.add('search-nav-ul');
document.getElementById('tapiSearchBox').appendChild(resultList);
resultList.innerHTML = '';
for (var i = 0; i < contacts.length; i++) {
var li = document.createElement('li');
li.classList.add('search-result');
li.classList.add('pointer');
li.onmouseover = function () {
this.classList.add('bg-light');
};
li.onmouseout = function () {
this.classList.remove('bg-light');
};
li.contact = contacts[i];
li.onclick = function () {
var contact = this.contact;
var searchInput = document.getElementsByName('searchByNumberInput');
if (searchInput.length > 0) {
searchInput[0].value = contact.tD_NUMBER_TAPI;
searchInput[0].focus();
fireChangeEvents(searchInput[0]);
}
};
li.style.listStyle = 'outside none none'; // display: flex; align-items: center;
var resultText = document.createElement('div');
resultText.classList.add('search-result-txt');
li.appendChild(resultText);
var line1 = document.createElement('div')
line1.appendChild(document.createTextNode(contacts[i].tD_NAME));
resultText.appendChild(line1);
var line2 = document.createElement('div')
line2.appendChild(document.createTextNode(contacts[i].tD_NUMBER_TAPI));
resultText.appendChild(line2);
resultList.appendChild(li);
}
}
});
}; };
waitForKeyElements('div.nav-search', (element) => { const tapi = {
console.log('Create TAPI Search'); fireChangeEvents: (element) => {
var changeEvent = null;
changeEvent = document.createEvent("HTMLEvents");
changeEvent.initEvent("input", true, true);
element.dispatchEvent(changeEvent);
console.debug('input event dispatched for element: ' + element.id);
changeEvent = document.createEvent("HTMLEvents");
changeEvent.initEvent("keyup", true, true);
element.dispatchEvent(changeEvent);
console.debug('keyup event dispatched for element: ' + element.id);
changeEvent = document.createEvent("HTMLEvents");
changeEvent.initEvent("change", true, true);
element.dispatchEvent(changeEvent);
console.debug('change event dispatched for element: ' + element.id);
},
var form = document.createElement('form'); removeSearchResults: () => {
form.style.width = '200px'; var resultList = document.getElementById('tapiResults');
form.style.float = 'right'; if (resultList) {
form.style.marginRight = '20px'; resultList.parentNode.removeChild(resultList);
}
tapi.currentSearchText = '';
},
var searchBox = document.createElement('div'); dial: (item) => {
searchBox.classList.add('contact-search-box'); console.log(item);
searchBox.id = 'tapiSearchBox'; var contact = item.contact;
form.appendChild(searchBox); var searchInput = document.getElementsByName('searchByNumberInput');
if (searchInput.length > 0) {
searchInput[0].value = contact.tD_NUMBER_TAPI;
searchInput[0].focus();
var searchWrapper = document.createElement('div'); tapi.fireChangeEvents(searchInput[0]);
searchWrapper.classList.add('search-input-wrapper'); }
searchWrapper.style.position = 'relative'; },
searchBox.appendChild(searchWrapper);
var search = document.createElement('input'); selectResult: (resultLi) => {
search.id = 'tapiSearchInput'; var items = document.getElementsByClassName('tapi-search-result');
search.classList.add('padder'); for (var item of items) {
search.classList.add('rounded'); item.classList.remove('bg-light');
search.classList.add('bg-light'); item.classList.remove('tapi-search-result-selected');
search.classList.add('no-border'); }
search.classList.add('contact-search-box');
search.placeholder = 'TAPI Suche';
search.onfocus = doSearch;
search.onkeyup = doSearch;
search.onblur = function () {
console.log('TAPI Search exit');
setTimeout(function () {
console.log('TAPI clear search results');
removeSearchResults();
}, 500);
};
searchWrapper.appendChild(search);
var icon = document.createElement('span'); resultLi.classList.add('bg-light');
icon.classList.add('fa'); resultLi.classList.add('tapi-search-result-selected');
icon.classList.add('fa-search'); },
icon.classList.add('form-control-feedback');
icon.style.color = 'grey';
searchWrapper.appendChild(icon);
element.appendChild(form); currentSearchText: '',
}, false);
doSearch: debounce(() => {
var search = document.getElementById('tapiSearchInput');
var searchText = search.value.trim();
if (searchText == '') {
tapi.removeSearchResults();
return;
} else if (searchText == tapi.currentSearchText) {
return;
}
console.log('Searching TAPI');
GM.xmlHttpRequest({
method: 'GET',
url: 'http://cpatapi.cpsrvweb2016.cp-austria.at/search?query=' + encodeURIComponent(searchText),
onload: function (response) {
console.log('TAPI Search response', response);
var contacts = JSON.parse(response.responseText);
console.log('TAPI Contacts', contacts);
tapi.removeSearchResults();
tapi.currentSearchText = searchText;
var resultList = document.createElement('ul');
resultList.id = 'tapiResults';
resultList.classList.add('search-nav-absolute');
resultList.classList.add('search-nav-ul');
document.getElementById('tapiSearchBox').appendChild(resultList);
resultList.innerHTML = '';
for (var i = 0; i < contacts.length; i++) {
var li = document.createElement('li');
li.classList.add('tapi-search-result');
li.classList.add('search-result');
li.classList.add('pointer');
li.onmouseover = function () {
tapi.selectResult(this);
};
li.contact = contacts[i];
li.onclick = function () {
tapi.dial(this);
}
li.style.listStyle = 'outside none none'; // display: flex; align-items: center;
var resultText = document.createElement('div');
resultText.classList.add('search-result-txt');
li.appendChild(resultText);
var line1 = document.createElement('div')
line1.appendChild(document.createTextNode(contacts[i].tD_NAME));
resultText.appendChild(line1);
var line2 = document.createElement('div')
line2.appendChild(document.createTextNode(contacts[i].tD_NUMBER_TAPI));
resultText.appendChild(line2);
resultList.appendChild(li);
}
}
});
}, 200),
doSearchKeyDown: (ev) => {
var items;
if (ev.key == 'ArrowUp') {
items = document.getElementsByClassName('tapi-search-result-selected');
if (items.length > 0) {
var prev = items[0].previousSibling;
}
if (!prev) {
items = document.getElementsByClassName('tapi-search-result');
if (items.length > 0) {
prev = items[items.length - 1];
}
}
if (prev) {
tapi.selectResult(prev);
prev.scrollIntoView(true);
}
} else if (ev.key == 'ArrowDown') {
items = document.getElementsByClassName('tapi-search-result-selected');
if (items.length > 0) {
var next = items[0].nextSibling;
}
if (!next) {
items = document.getElementsByClassName('tapi-search-result');
if (items.length > 0) {
next = items[0];
}
}
if (next) {
tapi.selectResult(next);
next.scrollIntoView(false);
}
} else {
tapi.doSearch();
}
},
createSearchBox: (element) => {
console.log('Create TAPI Search');
var form = document.createElement('form');
form.style.width = '200px';
form.style.float = 'right';
form.style.marginRight = '20px';
form.onsubmit = function () {
var items = document.getElementsByClassName('tapi-search-result-selected');
if (items.length > 0) {
tapi.dial(items[0]);
}
return false;
};
var searchBox = document.createElement('div');
searchBox.classList.add('contact-search-box');
searchBox.id = 'tapiSearchBox';
form.appendChild(searchBox);
var searchWrapper = document.createElement('div');
searchWrapper.classList.add('search-input-wrapper');
searchWrapper.style.position = 'relative';
searchBox.appendChild(searchWrapper);
var search = document.createElement('input');
search.id = 'tapiSearchInput';
search.autocomplete = 'off';
search.classList.add('padder');
search.classList.add('rounded');
search.classList.add('bg-light');
search.classList.add('no-border');
search.classList.add('contact-search-box');
search.placeholder = 'TAPI Suche';
search.onfocus = tapi.doSearch;
search.onkeydown = tapi.doSearchKeyDown;
search.onblur = function () {
console.log('TAPI Search exit');
setTimeout(function () {
console.log('TAPI clear search results');
tapi.removeSearchResults();
}, 500);
};
searchWrapper.appendChild(search);
var icon = document.createElement('span');
icon.classList.add('fa');
icon.classList.add('fa-search');
icon.classList.add('form-control-feedback');
icon.style.color = 'grey';
searchWrapper.appendChild(icon);
element.appendChild(form);
}
};
waitForKeyElements('div.nav-search', tapi.createSearchBox, false);