I dedicated a few hours to creating a punk-inspired
terminal for a personal project.
An HTML/CSS/JS terminal is nothing new, there is a few of them out there, I can think of Jquery Terminal and ttty. I could of have just used them for this project, but I had a couple of issues when customizing them to my liking, and it was hard to get a custom caret working properly with them. So I decided to write one from scratch.
<input>
CARET ISSUE!HTML and CSS don't let you customize the caret (the blinking line) in text inputs or content-editable elements. The default caret is pretty plain, and it doesn't let you do much with styling. Life would be so much easier if we could change the shape, color, add animations, etc... But no. HTML refuses to help us there.
Here's how I tackled it:
<input>
and <textarea>
tags. Instead, I opted for a <div>
element with the contenteditable="true"
attribute. This allowed me to create a text field without the usual constraints.<span>
element and customized its appearance using CSS. This gave me full control over its look, including color, size, and blinking speed.<div>
whenever there was user input, making sure it stays in the right spot. caret
.clear_console()
:
This function clears the console by removing all content within the #MainTerm element. It also calls kill_drop() and attach_bash() to reset the terminal.
clear_cmd_history()
:
Clears the command history by resetting the commandHistory array and displays a message indicating that the terminal history has been cleared.
attach_bash()
:
Creates and appends a new terminal line to the #MainTerm element. This line includes a custom bash prompt and an editable <div>
element for user input. It also sets up event listeners for keyup and keydown events.
rebind_bash()
:
Sets up event listeners for keyup and keydown events on the input element with the ID core_input. It's responsible for handling user input and updating the caret position.
addToHistory(command)
:
Adds a user-entered command to the command history stored in the commandHistory array.
getPreviousCommand()
:
Retrieves the previous command from the command history based on the current index, allowing users to cycle through their command history using the arrow keys.
getNextCommand()
:
Retrieves the next command from the command history, allowing users to cycle through their command history in reverse order.
updateCaretPosition()
:
Updates the position of the custom caret (#caret) within the input element. It also checks if the caret has reached the terminal's width and triggers a command submission if necessary.
submit_cmd()
:
Handles the submission of a user-entered command. It appends the user's input to the terminal and adds the command to the command history. The input element is then cleared for the next command.
getCaretPosition(element)
:
Calculates and returns the current caret position within an editable element.
term_echo(term_str)
:
Appends a line to the terminal with a custom prompt and the provided term_str.
term_echo_okay(term_str)
:
Similar to term_echo, this function appends a line to the terminal but uses a different prompt style for positive messages.
HELP_PRINT()
:
Displays a list of available commands and their descriptions in the terminal.
PARSE_CMD(CMD)
:
Parses user-entered commands, identifies the command type, and triggers the corresponding action or displays an error message for unknown commands.
This project is a work in progress, created mostly for fun. It serves as an experimental foundation for a potential library, it does lack adherence to naming conventions and such... It is far from away from meeting the complex but intricate demands of the enterprise
and it has never meant to. But it can serve as an example on how to overcome HTML limitations to achieve groundbreaking functionality.
Now, seriously HTML. No custom carets? Rly? -.- !
I hope you enjoyed it, you can check the demo Here.