268 lines
9.1 KiB
TypeScript
268 lines
9.1 KiB
TypeScript
type KeyboardRowName = `row${number}${"" | "_"}${string}`;
|
|
type KeyboardRow = Partial<Record<KeyboardRowName, string[]>>
|
|
interface VirtualKeyboard {
|
|
[layoutName: string]: KeyboardRow;
|
|
}
|
|
|
|
let showVirtualNumpad = (heading: string, maxlength = 4, isPassword: boolean, allowDecimals = true, allowClose = true, submitFunction: Function) => {
|
|
let numpad = $('#virtualNumpad');
|
|
let inputBox = $('#virtualNumpadInput')
|
|
let closeKeyboardButton = $('.closeKeyboards')
|
|
|
|
numpad.css('display', 'flex')
|
|
|
|
let showCloseButton = allowClose ? 'flex' : 'none'
|
|
closeKeyboardButton.css('display', showCloseButton)
|
|
$('#virtualNumpadHeading').html(heading)
|
|
|
|
/*
|
|
The numpad always submits to a function.
|
|
If a function isn't specified, it will submit
|
|
to the same function that called it
|
|
*/
|
|
|
|
numpad.data('value', '');
|
|
inputBox.text('');
|
|
|
|
numpad.data('maxlength', maxlength)
|
|
numpad.data('submitfunction', submitFunction)
|
|
numpad.data('password', isPassword);
|
|
numpad.data('allowdecimals', allowDecimals);
|
|
|
|
$(document).off('keyup');
|
|
$(document).on('keyup', e => {
|
|
let key = e.key;
|
|
switch (key) {
|
|
case 'Backspace':
|
|
case 'Delete':
|
|
key = 'clear'
|
|
break;
|
|
case 'Enter':
|
|
key = 'submit'
|
|
break;
|
|
}
|
|
|
|
virtualNumpadInput(key)
|
|
});
|
|
}
|
|
|
|
|
|
let hideVirtualKeyboard = () => {
|
|
let keyboard = $('#virtualKeyboard');
|
|
keyboard.hide()
|
|
$('#virtualKeyboardHeading').html('');
|
|
$(document).unbind('keyup');
|
|
}
|
|
|
|
let hideVirtualNumpad = () => {
|
|
let numpad = $('#virtualNumpad')
|
|
numpad.css('display', 'none')
|
|
$('#virtualNumpadHeading').html('')
|
|
$(document).unbind('keyup')
|
|
}
|
|
|
|
let virtualNumpadInput = (input: string) => {
|
|
let inputBox = $('#virtualNumpadInput')
|
|
let numpad = $('#virtualNumpad')
|
|
let maxlength = numpad.data('maxlength')
|
|
let allowDecimals = numpad.data('allowdecimals')
|
|
let submitFunction = numpad.data('submitfunction')
|
|
let allowedValues = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'submit', 'clear']
|
|
let currentValue = numpad.data('value').toString()
|
|
|
|
if (allowDecimals)
|
|
allowedValues.push('.', ',')
|
|
|
|
let validInput = allowedValues.includes(input);
|
|
//If the input is a valid number, decimal point or command.
|
|
if (validInput) {
|
|
switch (input) {
|
|
case 'submit':
|
|
hideVirtualNumpad()
|
|
let numpadValue: string = numpad.data('value').length > 0 ? numpad.data('value') : "0"
|
|
submitFunction(numpadValue)
|
|
break;
|
|
case 'clear':
|
|
clearNumpadInput()
|
|
break;
|
|
default:
|
|
let newText = currentValue + input
|
|
let isPassword = numpad.data('password')
|
|
let length = input.length + inputBox.text().length
|
|
|
|
if (length <= maxlength) {
|
|
inputBox.append(isPassword ? '*' : input)
|
|
numpad.data('value', newText)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
let clearNumpadInput = () => {
|
|
$('#virtualNumpadInput').text("")
|
|
$('#virtualNumpad').data('value', '')
|
|
}
|
|
|
|
let setupVirtualNumpad = () => {
|
|
$(document).on('click', '.virtualNumpadButton', e => {
|
|
virtualNumpadInput($(e.target).data('value').toString())
|
|
})
|
|
|
|
$('.closeKeyboards').on('click', () => {
|
|
hideVirtualKeyboard();
|
|
hideVirtualNumpad()
|
|
});
|
|
}
|
|
|
|
let setupVirtualKeyboard = (keyboardLayouts: VirtualKeyboard) => {
|
|
Application.keyboard = {
|
|
capsLock: false,
|
|
shift: false,
|
|
layouts: keyboardLayouts,
|
|
currentLayout: 'default',
|
|
}
|
|
|
|
$(document).on('click', '.virtualKeyboardButton', e => {
|
|
virtualKeyboardInput($(e.target).data('value'));
|
|
})
|
|
|
|
$(document).on('click', '.forceFocus', (e) => {
|
|
$('#virtualKeyboardInput').trigger('focus')
|
|
})
|
|
setKeyboardLayout('default')
|
|
}
|
|
|
|
let showVirtualKeyboard = (heading: string, maxlength = 32, isPassword = false, submitFunction :Function = () => {hideVirtualKeyboard()}) => {
|
|
let keyboard = $('#virtualKeyboard')
|
|
let inputBox = $('#virtualKeyboardInput')
|
|
|
|
keyboard.css('display', 'flex')
|
|
$('#virtualKeyboardHeading').html(heading)
|
|
$('.forceFocus').trigger('click')
|
|
|
|
keyboard.data('value', '')
|
|
inputBox.val('')
|
|
keyboard.data('maxlength', maxlength)
|
|
keyboard.data('password', isPassword)
|
|
keyboard.data('submitfunction', submitFunction)
|
|
inputBox.attr('autofocus', 'autofocus');
|
|
inputBox.trigger('focus')
|
|
inputBox.trigger('click')
|
|
inputBox.trigger('select')
|
|
$(document).on('keyup', e => {
|
|
let key = e.key
|
|
if (key == 'Enter' && inputBox.val().toString().length > 0) {
|
|
key = 'submit'
|
|
virtualKeyboardInput(key)
|
|
}
|
|
})
|
|
}
|
|
|
|
let virtualKeyboardInput = (input: string) => {
|
|
let inputBox = $('#virtualKeyboardInput')
|
|
let keyboard = $('#virtualKeyboard');
|
|
|
|
let maxlength = keyboard.data('maxlength');
|
|
let isPassword = keyboard.data('password');
|
|
let length = input.length + inputBox.text().length
|
|
|
|
switch (input.toLowerCase()) {
|
|
case 'backspace':
|
|
case 'delete':
|
|
let newText = inputBox.text().slice(0, -1);
|
|
inputBox.val(newText)
|
|
keyboard.data('value', newText);
|
|
break;
|
|
case 'submit':
|
|
hideVirtualKeyboard();
|
|
let submitFunction = keyboard.data('submitfunction')
|
|
submitFunction(inputBox.val());
|
|
break;
|
|
case 'shift':
|
|
if (Application.keyboard.capsLock) break;
|
|
Application.keyboard.shift = !Application.keyboard.shift
|
|
Application.keyboard.capsLock = false
|
|
setKeyboardLayout('default', Application.keyboard.shift ? 'shift' : '')
|
|
break;
|
|
case 'capslock':
|
|
Application.keyboard.shift = false
|
|
Application.keyboard.capsLock = !Application.keyboard.capsLock
|
|
let capsLockButton = $('[data-value="capslock"]')
|
|
capsLockButton.toggleClass('active')
|
|
setKeyboardLayout('default', Application.keyboard.capsLock ? 'shift' : '')
|
|
break;
|
|
case 'space':
|
|
input = ' ';
|
|
break;
|
|
}
|
|
|
|
//Stops keys such as F5 being pressed.
|
|
if (input.length == 1) {
|
|
if (Application.keyboard.shift || Application.keyboard.capsLock) {
|
|
input = input.toUpperCase()
|
|
|
|
//If shift, reload lowercase
|
|
if (Application.keyboard.shift) {
|
|
Application.keyboard.shift = false
|
|
setKeyboardLayout('default');
|
|
}
|
|
}
|
|
|
|
let newText = inputBox.val() + input;
|
|
keyboard.data('value', newText);
|
|
inputBox.val(newText)
|
|
}
|
|
|
|
}
|
|
|
|
let setKeyboardLayout = (layout: string, modifier = '') => {
|
|
if (modifier != '') modifier = `_${modifier}`
|
|
Application.keyboard.currentLayout = layout
|
|
let layoutToLoad = Application.keyboard.layouts[layout]
|
|
|
|
$('.virtualKeyboardRow').each((index, row) => {
|
|
/*
|
|
We start at 1 instead of 0. Makes it easier for non-programmers
|
|
and translators making their own language packs
|
|
*/
|
|
index = index + 1
|
|
|
|
let currentRow : string[] = layoutToLoad[`row${index}${modifier}`]
|
|
$(row).children('a').each((keyIndex, button) => {
|
|
let key = $(button);
|
|
let keyValue: string = currentRow[keyIndex];
|
|
|
|
/*
|
|
KeyText is the text that appears
|
|
in the button. KeyData is the value
|
|
submitted when the button is pressed.
|
|
*/
|
|
let keyText = keyValue;
|
|
let keyData = keyValue;
|
|
|
|
key.addClass('posButton');
|
|
key.addClass('virtualKeyboardButton');
|
|
|
|
let pattern = new RegExp(/\[([^)]+)\]/);
|
|
let matches = keyValue.match(pattern);
|
|
|
|
if (matches) {
|
|
keyText = keyValue.replace(pattern, '');
|
|
keyData = matches[1];
|
|
}
|
|
|
|
key.html(keyText)
|
|
|
|
//Use attr() as some keys have CSS dependent on data-value
|
|
key.attr('data-value', keyData)
|
|
key.data('value', keyData)
|
|
|
|
})
|
|
})
|
|
}
|
|
|
|
$(() => {
|
|
setupVirtualNumpad()
|
|
ajax('/ajax/getKeyboardLayout/english', null, 'get',setupVirtualKeyboard, null, null)
|
|
})
|