Last active
November 1, 2023 09:50
-
-
Save itsmikita/41d1b8f7c70cf9008726 to your computer and use it in GitHub Desktop.
Enables simple "coding" features (tabbing and auto-closing tags) to a textarea
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* Simplify your <textarea> life! | |
* | |
* This script enables tabbing (2 spaces) on textareas with class '.code'. | |
* It also auto-closes basic HTML tags. | |
* | |
* Enjoy your coffee! | |
* | |
* @author Mikita Stankiewicz <[email protected]> | |
* | |
* NEU: Removed jQuery and refactored the code to TypeScript. | |
* WARNING! Not tested, use at your own risk! | |
*/ | |
class Code_Edit { | |
private textarea: HTMLTextAreaElement; | |
private autoClosingTags: string[]; | |
constructor(textarea: HTMLTextAreaElement) { | |
this.textarea = textarea; | |
// Tabbing | |
this.enableTabbing(); | |
// Auto-close tags | |
// Add more auto-closing tags here | |
this.autoClosingTags = [ | |
'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'p', 'a', 'em', 'strong', | |
'ul', 'ol', 'li', | |
'table', 'thead', 'tfoot', 'tr', 'td', | |
'div', 'span', 'section', 'article', 'header', 'footer', 'aside', | |
'button', 'textarea', 'select', 'option' | |
]; | |
this.enableAutoCloseTags(); | |
} | |
/** | |
* Enable tabbing | |
*/ | |
enableTabbing() { | |
this.textarea.addEventListener('keydown', (event) => { | |
const keyCode = event.keyCode || event.which; | |
// Tab is '9', ok | |
if (9 === keyCode) { | |
event.preventDefault(); | |
const position = this.textarea.selectionStart, | |
before = this.textarea.value.substr(0, position), | |
after = this.textarea.value.substr(this.textarea.selectionEnd, this.textarea.value.length); | |
const tab = " "; | |
this.textarea.value = before + tab + after; | |
this.textarea.selectionStart = | |
this.textarea.selectionEnd = position + tab.length; | |
this.textarea.focus(); | |
} | |
// Enter is '13' | |
if (13 === keyCode) { | |
const position = this.textarea.selectionStart, | |
before = this.textarea.value.substr(0, position), | |
after = this.textarea.value.substr(this.textarea.selectionEnd, this.textarea.value.length); | |
const lines = before.split("\n"), | |
lastLine = lines[lines.length - 1], | |
indent = lastLine.match(/[\s]{4,}/); | |
if (!indent) | |
return; | |
// Cancel that new line, we add it manually | |
event.preventDefault(); | |
this.textarea.value = before + "\n" + indent[0] + after; | |
this.textarea.selectionStart = | |
this.textarea.selectionEnd = position + indent[0].length + 1; | |
this.textarea.focus(); | |
} | |
}); | |
} | |
/** | |
* Auto-close tags | |
*/ | |
enableAutoCloseTags() { | |
this.textarea.addEventListener('keydown', (event) => { | |
const keyCode = event.keyCode || event.which; | |
// Close tag '>' | |
if (190 === keyCode) { | |
const position = this.textarea.selectionStart, | |
before = this.textarea.value.substr(0, position), | |
after = this.textarea.value.substr(this.textarea.selectionEnd, this.textarea.value.length), | |
tagName = before.match(/<([^>]+)$/)[1].match(/^([a-z1-6]+)/)[1]; | |
// Not an auto-closing tag | |
if (-1 === this.autoClosingTags.indexOf(tagName)) | |
return; | |
const closeTag = '</' + tagName + '>'; | |
this.textarea.value = before + closeTag + after; | |
this.textarea.selectionStart = | |
this.textarea.selectionEnd = position; | |
this.textarea.focus(); | |
} | |
// Mustache '{' | |
if (219 === keyCode) { | |
const position = this.textarea.selectionStart, | |
before = this.textarea.value.substr(0, position), | |
after = this.textarea.value.substr(this.textarea.selectionEnd, this.textarea.value.length); | |
this.textarea.value = before + '}' + after; | |
this.textarea.selectionStart = | |
this.textarea.selectionEnd = position; | |
this.textarea.focus(); | |
} | |
}); | |
} | |
} | |
/** | |
* Onload | |
*/ | |
window.addEventListener('DOMContentLoaded', () => { | |
const textareas = document.querySelectorAll('textarea.code'); | |
textareas.forEach((textarea) => { | |
new Code_Edit(textarea as HTMLTextAreaElement); | |
}); | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Psst: Duplicate code here and there, look into
enableAutoCloseTags()
if you need to add more closing tags, I am too lazy for now..