Portfolio Widget: Typing Terminal

I spent the last few days developing a widget for my website redesign, and I want to share how I did it.

I made an ‘auto-typing’, terminal-styled widget that can display any text you want. It uses basic string and array methods to decompile a string and then, on a timer, it recompiles the text into the DOM to make it seem like it is being typed in.

What it looks like

In my example I use JavaScript object notation to add a little more style to it, but using your own ideas you can make it display anything you want. Check out my example here (please note that this version of my site is under-construction, I will be changing this link to my actual site once I finish the redesign).

What you will need:
 1) Basic knowledge of HTML, CSS, and JavaScript 
 2) Some experience using jQuery
 3) A text editor of your choice (I recommend Atom)

File set up:
Root Directory
| — index.html
| — main.css
| — script.js

I like to use Bootstrap, so if you want my exact set up follow the ‘Getting Started’ section in Bootstrap’s documentation.

I’m using the ‘Droid Sans Mono’ font, you can add it by copying-pasting the below code into the <head></head>

<link href=”https://fonts.googleapis.com/css?family=Droid+Sans+Mono" rel=”stylesheet”>

Now that you are all set up, lets get to coding!

Step 1. Set up your ‘terminal’ element:

<!-- Example with Bootstrap -->
<div class=”container-fluid”>
<div class=”row”>
<div class=”col-xs-12 col-sm-12 col-md-8">
<div class=”d-block terminal”>
<span id=”terminal-animated-text”></span>
</div>
</div>
</div>
</div>

In the above code I am using Bootstrap to add some structure to the page, but the only parts that are necessary are shown below:

<!-- Example without Bootstrap -->
<div class=”terminal”>
<span id=”terminal-animated-text”></span>
</div>

Step 2. Add some styling to your terminal element as well as the text.

.terminal {
font-family: “Droid Sans Mono”, monospace;
background-color: #000;
color: #0F0;
padding: 5px 8px 5px 8px;
margin-bottom: 15px;
height: 300px;
overflow-y: scroll;
}
.terminal span a {
color: #0F0;
}
.terminal::-webkit-scrollbar {
width: 5px;
}
.terminal::-webkit-scrollbar-track {
background-color: #000;
margin-right: 1px;
}
.terminal::-webkit-scrollbar-thumb {
background-color: #0F0;
}
.temrinal::-webkit-scrollbar-button {
background-color: #000;
}

Step 3. JavaScript time!

var textToInput = ‘</> whoAmI() . . .’
+ ‘|{‘
+ ‘|?”name”: “Ethan Arrowood”,’
+ ‘|?”age”: 17,’
+ ‘|?”college”: “Wentworth Institute of Technology”,’
+ ‘|?”major”: “Computer Science”,’
+ ‘|?”hobbies”: [|??”Programming”, |??”Netflix”, |??”Ultimate Frisbee” |?],’
+ ‘|?”skills”: [|??”HTML/CSS”, |??”JavaScript”, |??”jQuery”, |??”React”, |??”WordPress”, |??”GitHub”|?],’
+ ‘|?”email”: “ethan.arrowood@gmail.com”’
+ ‘|};’;
var arr = textToInput.split(‘’);
$(document).ready(function() {
  var i = 0;
var w = window.setInterval(function() {
if (arr[i] === ‘|’) {
$(“#terminal-animated-text”).append(‘<br>’);
} else if (arr[i] === ‘?’) {
$(“#terminal-animated-text”).append(‘&nbsp;&nbsp;’);
} else {
$(“#terminal-animated-text”).append(arr[i]);
};
  $(“.terminal”).scrollTop($(“.terminal”)[0].scrollHeight);
i++;
  if ( i > arr.length ) {
window.clearInterval(w);
addLinks();
};
}, 50);
});
function addLinks() {
  var str;
var regexArr = [/(“ethan.arrowood@gmail.com”)/, /(“Wentworth Institute of Technology”)/];
var linkArr = [“<a href=’ethan.arrowood@gmail.com’>”, “<a href=’wit.edu’>”];
var m, mIndex, mLength, str1, str2, str3, linkText1;
var linkText2 = “</a>”;
var terminalSelector = $(“#terminal-animated-text”);
  regexArr.map(function(re){
str = $(“#terminal-animated-text”).html()
if((m = re.exec(str)) !== null) {
if (m.index === re.lastIndex) {
re.lastIndex++;
};
};
mIndex = m.index;
mLength = m[0].length;
str1 = str.substring(0,mIndex);
str2 = str.substring(mIndex, mIndex + mLength);
str3 = str.substring(mIndex + mLength);
linkText1 = linkArr[regexArr.indexOf(re)];
    terminalSelector.html(str1 + linkText1 + str2 + linkText2 + str3);
  });
};

Now lets break this down:

3.1 — The text you want to insert

var textToInput = ‘</> whoAmI() . . .’
+ ‘|{‘
+ ‘|?”name”: “Ethan Arrowood”,’
+ ‘|?”age”: 17,’
+ ‘|?”college”: “Wentworth Institute of Technology”,’
+ ‘|?”major”: “Computer Science”,’
+ ‘|?”hobbies”: [|??”Programming”, |??”Netflix”, |??”Ultimate Frisbee” |?],’
+ ‘|?”skills”: [|??”HTML/CSS”, |??”JavaScript”, |??”jQuery”, |??”React”, |??”WordPress”, |??”GitHub”|?],’
+ ‘|?”email”: “ethan.arrowood@gmail.com”’
+ ‘|};’;
var arr = textToInput.split(‘’);

We start by defining a string, in my case a multi-line string concatenated using ‘+’. I am using the ‘|’ symbol to denote a new-line to my compiler, and a ‘?’ to denote a tab. Then, I split the string into an array where each character is it’s own element in the array.

3.2 — The compiler

$(document).ready(function() {
  var i = 0;
var w = window.setInterval(function() {
    if (arr[i] === ‘|’) {
$(“#terminal-animated-text”).append(‘<br>’);
} else if (arr[i] === ‘?’) {
$(“#terminal-animated-text”).append(‘&nbsp;&nbsp;’);
} else {
$(“#terminal-animated-text”).append(arr[i]);
};
    $(“.terminal”).scrollTop($(“.terminal”)[0].scrollHeight);
    i++;
    if ( i > arr.length ) {
window.clearInterval(w);
addLinks();
};
}, 50);
});

We want our code to execute once the page finishes loading so we wrap our function in jQuery’s $(document).ready() method.

The core of this function is based around the window.setInterval() call that works almost like a while loop, but with a slight delay between the stack. My interval is set to 50 milliseconds, but you can change this to whatever you like. While I am developing I usually set the interval to 10 milliseconds.

The first if-else block parses the array and compiles according to the conditional statements. The fundamental statement here is we select our span element by its ID, and append the characters of our string one by one so it appears as if it is being typed in.

The next line involving calls to the .scrollTop() method creates the auto-scroll effect when the text overflows inside our terminal element.

And finally, the if() block at the bottom of the page will stop our Interval clock once we pass our entire array into the DOM, and then execute the addLinks() function (more on what this does next).

3.3 — Links! It’s important for SEO and user interaction to have links on our site so by using regular expressions we are able to dynamically add links after the text is magically typed into the terminal.

function addLinks() {
  var str;
var regexArr = [/(“ethan.arrowood@gmail.com”)/, /(“Wentworth Institute of Technology”)/];
var linkArr = [“<a href=’ethan.arrowood@gmail.com’>”, “<a href=’wit.edu’>”];
var m, mIndex, mLength, str1, str2, str3, linkText1;
var linkText2 = “</a>”;
var terminalSelector = $(“#terminal-animated-text”);
  regexArr.map(function(re){
str = $(“#terminal-animated-text”).html()
if((m = re.exec(str)) !== null) {
if (m.index === re.lastIndex) {
re.lastIndex++;
};
};
mIndex = m.index;
mLength = m[0].length;
str1 = str.substring(0,mIndex);
str2 = str.substring(mIndex, mIndex + mLength);
str3 = str.substring(mIndex + mLength);
linkText1 = linkArr[regexArr.indexOf(re)];
    terminalSelector.html(str1 + linkText1 + str2 + linkText2 + str3);
  });
};

The first lines of this function initialize all the necessary variables. We have the ‘str’ which will contain the contents of our <span> element. The next two are arrays we will be pulling regex expressions and the appropriate links from. The next two lines initializes an assortment of variables we will be using to insert our html links. And finally, the terminalSelector is just some jQuery to preselect our span tag.

Using the .map() function we loop over the regex array. The str variable is assigned the text of our <span> tag, and then we search for the starting index of our text using the compound if() statements.

After matching our regex to the text inside the span tag we begin to break down the str variable. At first we assign the the matched-text index, and determine its length. Then we create three substrings. The first is all text up to our intended link, the second is the text we want to link, and the third is all text following our intended link text.

After all of that we make one call to our <span> element and replace its contents with a modified version including our links!

And thats it!

Now you should have a fully functional auto-typing terminal for your website.

If you made it this far please give me some feedback as this is my first medium post!

Have a wonderful day and keep on coding!

-Ethan Arrowood

A single golf clap? Or a long standing ovation?

By clapping more or less, you can signal to us which stories really stand out.