Compare commits
6 Commits
Author | SHA1 | Date | |
---|---|---|---|
10c1a9185b | |||
060889df69 | |||
0ac9f4d4ae | |||
44628074c0 | |||
d49b934c9a | |||
204d5837c5 |
274
3CX_TAPI.user.js
274
3CX_TAPI.user.js
@ -1,7 +1,11 @@
|
|||||||
// ==UserScript==
|
// ==UserScript==
|
||||||
// @name 3CX TAPI
|
// @name 3CX TAPI
|
||||||
// @version 1
|
// @author Daniel Triendl
|
||||||
|
// @namespace http://cp-solutions.at
|
||||||
|
// @copyright Copyright 2020 CP Solutions GmbH
|
||||||
|
// @version 6
|
||||||
// @grant GM.xmlHttpRequest
|
// @grant GM.xmlHttpRequest
|
||||||
|
// @grant GM.notification
|
||||||
// @include https://192.168.0.154:5001/webclient*
|
// @include https://192.168.0.154:5001/webclient*
|
||||||
// @include https://cpsolution.my3cx.at: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
|
// @downloadURL http://scootaloo.cp-austria.at/gitlist/3cx_tapi.git/raw/master/3CX_TAPI.user.js
|
||||||
@ -10,66 +14,110 @@
|
|||||||
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
var doSearch = function() {
|
return function executedFunction(...args) {
|
||||||
|
const later = () => {
|
||||||
|
clearTimeout(timeout);
|
||||||
|
func(...args);
|
||||||
|
};
|
||||||
|
|
||||||
|
clearTimeout(timeout);
|
||||||
|
timeout = setTimeout(later, wait);
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
const tapi = {
|
||||||
|
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);
|
||||||
|
},
|
||||||
|
|
||||||
|
removeSearchResults: () => {
|
||||||
|
var resultList = document.getElementById('tapiResults');
|
||||||
|
if (resultList) {
|
||||||
|
resultList.parentNode.removeChild(resultList);
|
||||||
|
}
|
||||||
|
tapi.currentSearchText = '';
|
||||||
|
},
|
||||||
|
|
||||||
|
dial: (item) => {
|
||||||
|
console.log(item);
|
||||||
|
var contact = item.contact;
|
||||||
|
var searchInput = document.getElementsByName('searchByNumberInput');
|
||||||
|
if (searchInput.length > 0) {
|
||||||
|
searchInput[0].value = contact.tD_NUMBER_TAPI;
|
||||||
|
searchInput[0].focus();
|
||||||
|
|
||||||
|
tapi.fireChangeEvents(searchInput[0]);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
selectResult: (resultLi) => {
|
||||||
|
var items = document.getElementsByClassName('tapi-search-result');
|
||||||
|
for (var item of items) {
|
||||||
|
item.classList.remove('bg-light');
|
||||||
|
item.classList.remove('tapi-search-result-selected');
|
||||||
|
}
|
||||||
|
|
||||||
|
resultLi.classList.add('bg-light');
|
||||||
|
resultLi.classList.add('tapi-search-result-selected');
|
||||||
|
},
|
||||||
|
|
||||||
|
currentSearchText: '',
|
||||||
|
|
||||||
|
doSearch: debounce(() => {
|
||||||
var search = document.getElementById('tapiSearchInput');
|
var search = document.getElementById('tapiSearchInput');
|
||||||
var searchText = search.value.trim();
|
var searchText = search.value.trim();
|
||||||
if (searchText == '') {
|
if (searchText == '') {
|
||||||
|
tapi.removeSearchResults();
|
||||||
|
return;
|
||||||
|
} else if (searchText == tapi.currentSearchText) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
console.log('Searching TAPI');
|
console.log('Searching TAPI');
|
||||||
GM.xmlHttpRequest({
|
GM.xmlHttpRequest({
|
||||||
method: 'GET',
|
method: 'GET',
|
||||||
url: 'http://cpatapi.cpsrvweb2016.cp-austria.at/search?query=' + encodeURIComponent(searchText),
|
url: 'http://cpatapi.cpsrvweb2016.cp-austria.at/search?query=' + encodeURIComponent(searchText),
|
||||||
onload: function(response) {
|
onload: function (response) {
|
||||||
console.log('TAPI Search response', response);
|
console.log('TAPI Search response', response);
|
||||||
var contacts = JSON.parse(response.responseText);
|
var contacts = JSON.parse(response.responseText);
|
||||||
console.log('TAPI Contacts', contacts);
|
console.log('TAPI Contacts', contacts);
|
||||||
var resultList = document.getElementById('tapiResults');
|
tapi.removeSearchResults();
|
||||||
if (resultList) {
|
tapi.currentSearchText = searchText;
|
||||||
resultList.parentNode.removeChild(resultList);
|
|
||||||
}
|
|
||||||
|
|
||||||
resultList = document.createElement('ul');
|
var resultList = document.createElement('ul');
|
||||||
resultList.id = 'tapiResults';
|
resultList.id = 'tapiResults';
|
||||||
resultList.classList.add('search-nav-absolute');
|
resultList.classList.add('search-nav-absolute');
|
||||||
resultList.classList.add('search-nav-ul');
|
resultList.classList.add('search-nav-ul');
|
||||||
document.getElementById('tapiSearchBox').appendChild(resultList);
|
document.getElementById('tapiSearchBox').appendChild(resultList);
|
||||||
|
|
||||||
resultList.innerHTML = '';
|
resultList.innerHTML = '';
|
||||||
for(var i = 0; i < contacts.length; i++) {
|
for (var i = 0; i < contacts.length; i++) {
|
||||||
var li = document.createElement('li');
|
var li = document.createElement('li');
|
||||||
|
li.classList.add('tapi-search-result');
|
||||||
li.classList.add('search-result');
|
li.classList.add('search-result');
|
||||||
li.classList.add('pointer');
|
li.classList.add('pointer');
|
||||||
li.onmouseover = function() { this.classList.add('bg-light'); };
|
li.onmouseover = function () {
|
||||||
li.onmouseout = function() { this.classList.remove('bg-light'); };
|
tapi.selectResult(this);
|
||||||
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;
|
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');
|
var resultText = document.createElement('div');
|
||||||
resultText.classList.add('search-result-txt');
|
resultText.classList.add('search-result-txt');
|
||||||
@ -87,15 +135,60 @@ var doSearch = function() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
};
|
}, 200),
|
||||||
|
|
||||||
waitForKeyElements('div.nav-search', (element) => {
|
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');
|
console.log('Create TAPI Search');
|
||||||
|
|
||||||
var form = document.createElement('form');
|
var form = document.createElement('form');
|
||||||
form.style.width = '200px';
|
form.style.width = '200px';
|
||||||
form.style.float = 'right';
|
form.style.float = 'right';
|
||||||
form.style.marginRight = '20px';
|
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');
|
var searchBox = document.createElement('div');
|
||||||
searchBox.classList.add('contact-search-box');
|
searchBox.classList.add('contact-search-box');
|
||||||
@ -109,23 +202,20 @@ waitForKeyElements('div.nav-search', (element) => {
|
|||||||
|
|
||||||
var search = document.createElement('input');
|
var search = document.createElement('input');
|
||||||
search.id = 'tapiSearchInput';
|
search.id = 'tapiSearchInput';
|
||||||
|
search.autocomplete = 'off';
|
||||||
search.classList.add('padder');
|
search.classList.add('padder');
|
||||||
search.classList.add('rounded');
|
search.classList.add('rounded');
|
||||||
search.classList.add('bg-light');
|
search.classList.add('bg-light');
|
||||||
search.classList.add('no-border');
|
search.classList.add('no-border');
|
||||||
search.classList.add('contact-search-box');
|
search.classList.add('contact-search-box');
|
||||||
search.placeholder = 'TAPI Suche';
|
search.placeholder = 'TAPI Suche';
|
||||||
search.onfocus = doSearch;
|
search.onfocus = tapi.doSearch;
|
||||||
search.onkeyup = doSearch;
|
search.onkeydown = tapi.doSearchKeyDown;
|
||||||
search.onblur = function() {
|
search.onblur = function () {
|
||||||
console.log('TAPI Search exit');
|
console.log('TAPI Search exit');
|
||||||
setTimeout(function() {
|
setTimeout(function () {
|
||||||
console.log('TAPI clear search results');
|
console.log('TAPI clear search results');
|
||||||
var resultList = document.getElementById('tapiResults');
|
tapi.removeSearchResults();
|
||||||
console.log('TAPI tapiResults', resultList);
|
|
||||||
if (resultList) {
|
|
||||||
resultList.parentNode.removeChild(resultList);
|
|
||||||
};
|
|
||||||
}, 500);
|
}, 500);
|
||||||
};
|
};
|
||||||
searchWrapper.appendChild(search);
|
searchWrapper.appendChild(search);
|
||||||
@ -138,5 +228,91 @@ waitForKeyElements('div.nav-search', (element) => {
|
|||||||
searchWrapper.appendChild(icon);
|
searchWrapper.appendChild(icon);
|
||||||
|
|
||||||
element.appendChild(form);
|
element.appendChild(form);
|
||||||
}, false);
|
},
|
||||||
|
|
||||||
|
extractNumber: (s) => {
|
||||||
|
var match = /(\+?[0-9]+)/.exec(s);
|
||||||
|
if (!match) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
number = match[1];
|
||||||
|
|
||||||
|
if (number.startsWith('+')) {
|
||||||
|
number = number.replace('+', '00');
|
||||||
|
}
|
||||||
|
return number;
|
||||||
|
},
|
||||||
|
|
||||||
|
showCallNotification: (element) => {
|
||||||
|
var number = element.dataset.id;
|
||||||
|
console.log('TAPI call notification', number);
|
||||||
|
|
||||||
|
number = tapi.extractNumber(number);
|
||||||
|
if (!number) {
|
||||||
|
console.log('TAPI callerid no number found');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log('TAPI searching callerid for', number);
|
||||||
|
GM.xmlHttpRequest({
|
||||||
|
method: 'GET',
|
||||||
|
url: 'http://cpatapi.cpsrvweb2016.cp-austria.at/callerid/' + encodeURIComponent(number),
|
||||||
|
onload: function (response) {
|
||||||
|
console.log('TAPI callerid response', response);
|
||||||
|
var notification = {
|
||||||
|
text: number
|
||||||
|
};
|
||||||
|
if (response.status == 200) {
|
||||||
|
var callerId = JSON.parse(response.responseText);
|
||||||
|
if (callerId) {
|
||||||
|
notification.text = callerId.tD_NAME + '\r\n' + number;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
GM.notification(notification);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
callerIds: {},
|
||||||
|
|
||||||
|
showCallHistory: (element) => {
|
||||||
|
var span = element.querySelector('span');
|
||||||
|
var number = tapi.extractNumber(span.textContent);
|
||||||
|
if (!number) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (tapi.callerIds.hasOwnProperty(number)) {
|
||||||
|
span.textContent = tapi.callerIds[number].tD_NAME + ' ' + span.textContent;
|
||||||
|
} else {
|
||||||
|
GM.xmlHttpRequest({
|
||||||
|
method: 'GET',
|
||||||
|
url: 'http://cpatapi.cpsrvweb2016.cp-austria.at/callerid/' + encodeURIComponent(number),
|
||||||
|
context: span,
|
||||||
|
onload: function (response) {
|
||||||
|
var number = tapi.extractNumber(span.textContent);
|
||||||
|
var callerId = { 'tD_NAME': '' };
|
||||||
|
if (response.status == 200) {
|
||||||
|
callerId = JSON.parse(response.responseText);
|
||||||
|
}
|
||||||
|
tapi.callerIds[number] = callerId;
|
||||||
|
console.log('TAPI call histroy callerid response', number, response, callerId);
|
||||||
|
if (callerId.tD_NAME != '') {
|
||||||
|
var text = response.context.textContent;
|
||||||
|
response.context.textContent = callerId.tD_NAME;
|
||||||
|
var br = document.createElement('br');
|
||||||
|
var span2 = document.createElement('span');
|
||||||
|
span2.style.fontSize = "small";
|
||||||
|
span2.textContent = text;
|
||||||
|
response.context.parentNode.insertBefore(br, response.context.nextSibling);
|
||||||
|
response.context.parentNode.insertBefore(span2, response.context.nextSibling);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
waitForKeyElements('div.nav-search', tapi.createSearchBox, true);
|
||||||
|
waitForKeyElements('call-view', tapi.showCallNotification, false);
|
||||||
|
waitForKeyElements('.call-history-list call', tapi.showCallHistory, false);
|
||||||
|
Reference in New Issue
Block a user