400 lines
11 KiB
JavaScript
400 lines
11 KiB
JavaScript
let ws
|
|
let pointer, scroller, response, screenshotImg
|
|
let scrollLastTimestamp, scrollLastValue
|
|
let mousePosX, mousePosY, mouseInitPosX, mouseInitPosY
|
|
let isLive = false
|
|
let wsLock = false
|
|
let isPointerLive = false
|
|
let isScreenshotWaiting = null
|
|
let isPointerScreenshotWaiting = false
|
|
let emptyImg = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAIAAACQd1PeAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH4gIJDjc3srQk8gAAAB1pVFh0Q29tbWVudAAAAAAAQ3JlYXRlZCB3aXRoIEdJTVBkLmUHAAAADElEQVQI12P48+cPAAXsAvVTWDc6AAAAAElFTkSuQmCC"
|
|
|
|
function createWebSocketConnection() {
|
|
const protocol = location.protocol === 'https:' ? 'wss' : 'ws'
|
|
|
|
ws = new WebSocket(`${protocol}://${window.location.hostname}:${window.location.port}/ws`)
|
|
|
|
ws.addEventListener('open', function(event) {
|
|
document.querySelector('#disconneced').style.display = 'none'
|
|
unLock()
|
|
})
|
|
|
|
ws.addEventListener('close', function(event) {
|
|
unLock()
|
|
document.querySelector('#disconneced').style.display = 'block'
|
|
|
|
window.setTimeout(createWebSocketConnection, 5000)
|
|
})
|
|
|
|
ws.addEventListener('message', function(event) {
|
|
unLock()
|
|
let data = JSON.parse(event.data)
|
|
|
|
if (data.type === 'response') {
|
|
response.innerText = data.value
|
|
response.style.display = 'block'
|
|
|
|
window.setTimeout(function() {
|
|
response.style.display = 'none'
|
|
}, 2500)
|
|
|
|
return
|
|
}
|
|
|
|
if (data.type === 'volume') {
|
|
if (data.value.length) {
|
|
setVolume(parseInt(data.value))
|
|
}
|
|
|
|
return
|
|
}
|
|
})
|
|
}
|
|
|
|
function isLocked() {
|
|
return wsLock === true
|
|
}
|
|
|
|
function lock() {
|
|
wsLock = true
|
|
}
|
|
|
|
function unLock() {
|
|
wsLock = false
|
|
}
|
|
|
|
function send(message) {
|
|
if (isLocked()) {
|
|
return
|
|
}
|
|
|
|
lock()
|
|
|
|
ws.send(message)
|
|
}
|
|
|
|
function navigationClickHandler(e) {
|
|
if (e.target.getAttribute('href') === '#') {
|
|
return
|
|
}
|
|
|
|
Array.from(document.querySelectorAll('.pane')).forEach((item) => {
|
|
item.style.display = 'none'
|
|
})
|
|
|
|
document.querySelector(e.target.getAttribute('href')).style.display = 'block'
|
|
|
|
Array.from(document.querySelectorAll('#nav a')).forEach((item) => {
|
|
item.classList.remove('active')
|
|
})
|
|
|
|
e.target.classList.add('active')
|
|
}
|
|
|
|
function buttonClickHandler(e) {
|
|
send(e.target.getAttribute('data-msg'))
|
|
}
|
|
|
|
function shortcutClearClickHandler(e) {
|
|
document.querySelector('#shortcut-key').value = ''
|
|
|
|
Array.from(document.querySelectorAll('#shortcuts_special_keys input:checked')).forEach((item) => {
|
|
item.checked = false
|
|
item.change()
|
|
})
|
|
}
|
|
|
|
function shortcutSendClickHandler(e) {
|
|
let keys = []
|
|
let key = document.querySelector('#shortcut-key').value
|
|
|
|
Array.from(document.querySelectorAll('#shortcuts_special_keys input:checked')).forEach((item) => {
|
|
keys.push(item.value)
|
|
})
|
|
|
|
if (keys.length) {
|
|
if (key) {
|
|
keys.push(key)
|
|
}
|
|
|
|
send('{"type":"keys","value": "' + (keys.join(',').replace('"', '\\"')) + '"}')
|
|
}
|
|
}
|
|
|
|
function textClearClickHandler(e) {
|
|
document.querySelector('#text').value = ''
|
|
}
|
|
|
|
function textSendClickHandler(e) {
|
|
const keys = document.querySelector('#text').value
|
|
|
|
if (keys.length) {
|
|
send('{"type":"text","value": "' + (keys.replace('"', '\\"')) + '"}')
|
|
}
|
|
}
|
|
|
|
function textKeyUpHandler(e) {
|
|
const keys = document.querySelector('#text').value
|
|
|
|
if (e.keyCode === 13) {
|
|
send('{"type":"text","value": "' + (keys.replace('"', '\\"')) + '"}')
|
|
}
|
|
}
|
|
|
|
function liveTextKeyUpHandler(e) {
|
|
const value = e.target.value
|
|
const size = value.length
|
|
|
|
const messages = []
|
|
|
|
if (size > 0) {
|
|
messages.push('{"type":"text","value": "' + (value.replace('"', '\\"')) + '"}')
|
|
|
|
if (value[size-1] === ' ') {
|
|
messages.push('{"type":"key","value":"space"}')
|
|
}
|
|
}
|
|
|
|
if (e.keyCode === 8) {
|
|
messages.push('{"type":"key","value": "backspace"}')
|
|
} else if (e.keyCode === 13 && size === 0) {
|
|
messages.push('{"type":"key","value": "enter"}')
|
|
}
|
|
|
|
send(`{"type":"messages","value":[${messages.join(',')}]}`)
|
|
|
|
e.target.value = ''
|
|
}
|
|
|
|
function shortcutsSpecialKeysOnChangeHandler(e) {
|
|
Array.from(document.querySelectorAll('#shortcuts_special_keys input:checked')).forEach((item) => {
|
|
item.parentNode.classList.add('btn-primary')
|
|
item.parentNode.classList.remove('btn-secondary')
|
|
})
|
|
|
|
Array.from(document.querySelectorAll('#shortcuts_special_keys input:not(:checked)')).forEach((item) => {
|
|
item.parentNode.classList.add('btn-secondary')
|
|
item.parentNode.classList.remove('btn-primary')
|
|
})
|
|
}
|
|
|
|
function pointerClickHandler(e) {
|
|
send('{"type":"pointer","click":"left"}')
|
|
}
|
|
|
|
function scrollerTouchStartHandler(e) {
|
|
mouseInitPosY = e.targetTouches[0].pageY
|
|
}
|
|
|
|
function scrollerTouchMoveHandler(e) {
|
|
let touch = e.changedTouches[0]
|
|
let value = ((touch.pageY - mouseInitPosY > 0) ? 'down' : 'up')
|
|
let now = new Date().getTime()
|
|
|
|
if (touch.pageY === mouseInitPosY || value === scrollLastValue && scrollLastTimestamp !== null && now - scrollLastTimestamp < 200) {
|
|
return
|
|
}
|
|
|
|
scrollLastTimestamp = now
|
|
scrollLastValue = value
|
|
mouseInitPosY = touch.pageY
|
|
|
|
send('{"type":"scroll","value": "' + value + '"}')
|
|
}
|
|
|
|
function pointerTouchStartHandler(e) {
|
|
const touch = e.targetTouches[0]
|
|
mouseInitPosX = touch.pageX
|
|
mouseInitPosY = touch.pageY
|
|
}
|
|
|
|
function pointerLiveHandler(e) {
|
|
if (!e.target.checked) {
|
|
pointer.style.backgroundImage = ""
|
|
} else {
|
|
pointer.style.backgroundImage = `url("/capture?type=live&pointer=1&${Math.random()}")`
|
|
}
|
|
}
|
|
|
|
function pointerTouchMoveHandler(e) {
|
|
if (e.changedTouches.length === 2) {
|
|
return scrollerTouchMoveHandler(e)
|
|
}
|
|
|
|
const touch = e.changedTouches[0]
|
|
mousePosX = touch.pageX
|
|
mousePosY = touch.pageY
|
|
|
|
const newX = mousePosX - mouseInitPosX
|
|
const newY = mousePosY - mouseInitPosY
|
|
|
|
mouseInitPosX = mousePosX
|
|
mouseInitPosY = mousePosY
|
|
|
|
let msg = '{"type":"pointer","x": "' + newX + '","y": "' + newY + '"}'
|
|
|
|
ws.send(msg)
|
|
}
|
|
|
|
function capture(mode) {
|
|
}
|
|
|
|
function captureScreenshotClickHandler(e) {
|
|
const img = e.target.parentNode.querySelector('.capture-img img')
|
|
img.src = "/capture?type=screenshot&" + Math.random()
|
|
}
|
|
|
|
function captureLiveClickHandler(e) {
|
|
const img = e.target.parentNode.querySelector('.capture-img img')
|
|
|
|
if (img.src.indexOf("live") > -1) {
|
|
img.src = emptyImg
|
|
} else {
|
|
img.src = "/capture?type=live&" + Math.random()
|
|
}
|
|
}
|
|
|
|
function fullscreenHandler(e) {
|
|
const targetConf = e.target.getAttribute('data-target')
|
|
const isFullscreen = parseInt(e.target.getAttribute('data-fullscreen'))
|
|
const element = (targetConf === 'this')
|
|
? e.target
|
|
: document.querySelector(targetConf)
|
|
|
|
document.querySelector('body').classList.toggle('fullscreen', isFullscreen)
|
|
|
|
if (isFullscreen) {
|
|
e.target.setAttribute('data-fullscreen', '0')
|
|
|
|
if (document.exitFullscreen) {
|
|
document.exitFullscreen()
|
|
} else if (document.webkitExitFullscreen) {
|
|
document.webkitExitFullscreen()
|
|
} else if (document.mozCancelFullScreen) {
|
|
document.mozCancelFullScreen()
|
|
}
|
|
} else {
|
|
e.target.setAttribute('data-fullscreen', '1')
|
|
|
|
if (element.requestFullscreen) {
|
|
element.requestFullscreen()
|
|
} else if (element.webkitRequestFullscreen) {
|
|
element.webkitRequestFullscreen()
|
|
} else if (element.mozRequestFullScreen) {
|
|
element.mozRequestFullScreen()
|
|
}
|
|
}
|
|
}
|
|
|
|
function documentHashHandler() {
|
|
const hash = window.location.hash
|
|
|
|
if (hash) {
|
|
document.querySelector('a[href="' + hash + '"]').click()
|
|
} else {
|
|
document.querySelector('#nav > li:first-child a').click()
|
|
}
|
|
}
|
|
|
|
function addEventListenerOn(selector, eventName, listener) {
|
|
if (typeof selector === 'string') {
|
|
Array.from(document.querySelectorAll(selector)).forEach((element) => {
|
|
element.addEventListener(eventName, listener)
|
|
})
|
|
} else {
|
|
selector.addEventListener(eventName, listener)
|
|
}
|
|
}
|
|
|
|
function addListeners() {
|
|
addEventListenerOn('#nav a', 'click', navigationClickHandler)
|
|
addEventListenerOn('button[data-msg]', 'click', buttonClickHandler)
|
|
|
|
addEventListenerOn('#shortcut-clear', 'click', shortcutClearClickHandler)
|
|
addEventListenerOn('#shortcuts_special_keys input', 'change', shortcutsSpecialKeysOnChangeHandler)
|
|
addEventListenerOn('#shortcut-send', 'click', shortcutSendClickHandler)
|
|
|
|
addEventListenerOn('#text-clear', 'click', textClearClickHandler)
|
|
addEventListenerOn('#text-send', 'click', textSendClickHandler)
|
|
addEventListenerOn('#text', 'keyup', textKeyUpHandler)
|
|
|
|
Array.from(document.querySelectorAll('.live-text')).forEach((element) => {
|
|
element.setAttribute('data-composing', '0')
|
|
|
|
addEventListenerOn(element, 'compositionstart', (e) => {
|
|
element.setAttribute('data-composing', '1')
|
|
})
|
|
|
|
addEventListenerOn(element, 'compositionend', (e) => {
|
|
element.setAttribute('data-composing', '0')
|
|
})
|
|
|
|
addEventListenerOn(element, 'keyup', (e) => {
|
|
if (element.getAttribute('data-composing') === '1') {
|
|
return
|
|
}
|
|
|
|
liveTextKeyUpHandler(e)
|
|
})
|
|
})
|
|
|
|
addEventListenerOn(scroller, 'touchstart', scrollerTouchStartHandler)
|
|
addEventListenerOn(scroller, 'touchmove', scrollerTouchMoveHandler)
|
|
|
|
addEventListenerOn(pointer, 'click', pointerClickHandler)
|
|
addEventListenerOn(pointer, 'touchstart', pointerTouchStartHandler)
|
|
addEventListenerOn(pointer, 'touchmove', pointerTouchMoveHandler)
|
|
addEventListenerOn('#mouse-screenshot-live input', 'change', pointerLiveHandler)
|
|
|
|
addEventListenerOn('.capture-live', 'click', captureLiveClickHandler)
|
|
addEventListenerOn('.capture-screenshot', 'click', captureScreenshotClickHandler)
|
|
|
|
addEventListenerOn('.btn-fullscreen', 'click', fullscreenHandler)
|
|
}
|
|
|
|
function getVolume() {
|
|
if (document.querySelectorAll('.volume').length) {
|
|
try {
|
|
send('{"type":"volume","value":"value"}')
|
|
} catch (e) {
|
|
}
|
|
|
|
document.querySelectorAll('.volume input[type="range"]').forEach(function(input) {
|
|
if (input.getAttribute('data-event')) {
|
|
return
|
|
}
|
|
|
|
input.setAttribute('data-event', 'ok')
|
|
input.addEventListener('change', (e) => {
|
|
send(`{"type":"volume","value":"${e.target.value}"}`)
|
|
})
|
|
})
|
|
}
|
|
|
|
window.setTimeout(getVolume, 2000)
|
|
}
|
|
|
|
function setVolume(value) {
|
|
document.querySelectorAll('.volume').forEach(function(item) {
|
|
item.querySelector('input[type="range"]').value = value
|
|
})
|
|
}
|
|
|
|
function bootstrap() {
|
|
pointer = document.querySelector('#pointer')
|
|
scroller = document.querySelector('#scrollbar')
|
|
response = document.querySelector('#response')
|
|
screenshotImg = document.querySelector('#screenshot img')
|
|
|
|
shortcutsSpecialKeysOnChangeHandler()
|
|
createWebSocketConnection()
|
|
addListeners()
|
|
documentHashHandler()
|
|
getVolume()
|
|
|
|
if ('serviceWorker' in navigator) {
|
|
navigator.serviceWorker.register('/static/js/service_worker.js')
|
|
}
|
|
}
|
|
|
|
addEventListenerOn(window, 'DOMContentLoaded', bootstrap)
|