Skip to content

Instantly share code, notes, and snippets.

@watzon
Created February 5, 2018 05:24
Show Gist options
  • Save watzon/bc13b34065fbedeb1346a750163246b6 to your computer and use it in GitHub Desktop.
Save watzon/bc13b34065fbedeb1346a750163246b6 to your computer and use it in GitHub Desktop.
Simple input buffer implementation
const KeyCodeMap = {
backspace: 8,
tab: 9,
return: 13,
left_arrow: 37,
up_arrow: 38,
right_arrow: 39,
down_arrow: 40,
insert: 45,
delete: 46
}
class InputBuffer {
constructor (element, startingValue) {
this.element = document.getElementById(element)
this.caret = 0
if (startingValue) {
} else {
if (this.element.value) {
this.buffer = this.element.value.split('')
} else {
this.buffer = []
}
}
this.element.value = this.buffer.join('')
this.element.onkeydown = this.keyDown.bind(this)
this.element.onpointerup = this.pointerUp.bind(this)
this.update()
}
pointerUp (event) {
this.caret = this.element.selectionStart
this.update()
}
// This is what you want to pass into the onkeydown event
keyDown (event) {
switch (event.keyCode) {
case KeyCodeMap.backspace: // Backspace
this.handleBackspace(event)
break
case KeyCodeMap.tab:
this.handleTab(event)
break
case KeyCodeMap.return:
this.handleReturn(event)
break
case KeyCodeMap.left_arrow:
this.handleArrow(event, 'left')
break
case KeyCodeMap.right_arrow:
this.handleArrow(event, 'right')
break
case KeyCodeMap.up_arrow:
this.handleArrow(event, 'up')
break
case KeyCodeMap.down_arrow:
this.handleArrow(event, 'down')
break
case KeyCodeMap.insert:
this.handleInsert(event)
break
case KeyCodeMap.delete:
this.handleDelete(event)
break
default:
this.handleCharacter(event)
break
}
this.update(event)
}
update () {
this.updateValue()
this._setCaretPosition(this.caret)
}
updateValue () {
this.element.value = this.buffer.join('')
}
handleBackspace (event) {
event.preventDefault()
if (this.caret === 0) return
this.buffer.splice(this.caret - 1, 1)
this.caret--
}
handleTab (event) {}
handleReturn (event) {}
handleArrow (event, direction) {
event.preventDefault()
switch (direction) {
case 'left':
if (this.caret !== 0)
this.caret--
break
case 'right':
if (this.caret !== this.buffer.length)
this.caret++
break
}
}
handleInsert (event) {}
handleDelete (event) {
event.preventDefault()
this.buffer.splice(this.caret, 1)
}
handleCharacter (event) {
event.preventDefault()
if (this._isCharacter(event)) {
this.buffer.splice(this.caret, 0, event.key)
this.caret++
}
}
// TODO: Make this ignore function keys
_isCharacter (event) {
const key = String.fromCharCode(event.keyCode || event.charCode)
return key.match(/[\w\s\d]/)
}
_setCaretPosition (position) {
const elem = this.element
if(elem.createTextRange) {
var range = elem.createTextRange();
range.move('character', position);
range.select();
}
else {
if(elem.selectionStart) {
elem.focus();
elem.setSelectionRange(position, position);
}
else
elem.focus();
}
}
}
class PasswordMask extends InputBuffer {
constructor (element, maskChar = '*') {
super(element, '')
this.maskChar = maskChar
}
updateValue () {
this.element.value = new Array(this.buffer.length).fill('*').join('')
}
}
// Create a PasswordMask for an element with the id of test
// <input type="text" id="test">
const mask = new PasswordMask('test')
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment