HiveBrain v1.2.0
Get Started
← Back to all entries
patternjavascriptModerate

Console-like printing of message JavaScript

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
javascriptmessagelikeprintingconsole

Problem

I'm learning JavaScript and I've made a very simple little document-modifying script that prints a message as if it was someone typing into a console. It practices recursion and in my opinion, I feel a bit iffy about the number of if-cases in the code. My main concern is the JavaScript though I know there's still a lot I have to learn about CSS animations.



var text = document.getElementById('text');
var greeting = ['Hello. I am a console wannabe.',
'All systems are functioning.',
'I like pie.'];
text.innerHTML = '▮';

(function greet() {
if (greeting.length > 0 && greeting.length
body{
background-color: #000000;
color: #99ffcc;
font-family: Courier;
}

i{
font-style: unset;
font-size: 1em;
animation: blink 1100ms linear infinite;
}

@keyframes blink {
49% {
opacity: 1;
}
50% {
opacity: 0;
}
89% {
opacity: 0;
}
90% {
opacity: 1;
}
}
`



I would like as many opinions as you can have about my simple little script. Does it look like I have a small grasp of JavaScript?

Solution

Your code is really easy to understand, and there's not much wrong with it.

I promise I'll go easy on you.

  • Right on the first lines, something bothers me...



You have this:

var text = document.getElementById('text');
var greeting = ['Hello. I am a console wannabe.',
'All systems are functioning.',
'I like pie.'];
text.innerHTML = '▮';


What's wrong? The names!

text implies some actual text, but you have a `. greeting is alright, but it is actually text. And that is a prompt.

I propose the following rewrite:

var screen = document.getElementById('screen');
var text = ['Hello. I am a console wannabe.',
'All systems are functioning.',
'I like pie.'];
screen.innerHTML = '▮';


It all makes sense, except for the class, which I will explain later on.

And please, use the HTML entities, to avoid problems with file encodings.

Also, don't use
for this, since it will have problems when the animation is stopped.

The best would be to move the
prompt to the HTML and ignore that line.

  • Lets analyse the function greet().



You have the following code:

(function greet() {
if (greeting.length > 0 && greeting.length

Huh? The greet() function is preparing to type the text? And only works for this example? Well, let me re-write this for you.

function type(text, screen) {
//You have to check for lines and if the screen is an element
if(!text || !text.length || !(screen instanceof Element)) {
return;
}

//if it is not a string, you will want to make it into one
if('string' !== typeof text) {
text = text.join('\n');
}

//normalize newlines, and split it to have a nice array
text = text.replace(/\r\n?/g,'\n').split('');

//the prompt is always the last child
var prompt = screen.lastChild;
prompt.className = 'typing';

var typer = function(){
var character = text.shift();
screen.insertBefore(
//newlines must be written as a


character === '\n'
? document.createElement('br')
: document.createTextNode(character),
prompt
);

//only run this again if there are letters
if( text.length ) {
setTimeout(typer, 300);
} else {
prompt.className = 'idle';
}
};
setTimeout(typer, 300);
};


Wow, some fine German Overengeneering going on there!

You can pass it a string or an array of strings, and a 'screen', where the message will be added.

  • Now, enough of Javascript, lets talk about CSS!



It is a pretty straightforward CSS, without many complications.

But, remember that it suffered a rewrite.

Replace your i CSS with this:

#prompt{
font-style: unset;
font-size: 1em;
}
#prompt.idle {
animation: blink 1100ms linear infinite;
-webkit-animation: blink 1100ms linear infinite;
}


  • On your HTML, simply change the id.



Remember, we re-wrote it:

▮


Final result:

And now, all together:



function type(text, screen) {
//You have to check for lines and if the screen is an element
if(!text || !text.length || !(screen instanceof Element)) {
return;
}

//if it is not a string, you will want to make it into one
if('string' !== typeof text) {
text = text.join('\n');
}

//normalize newlines, and split it to have a nice array
text = text.replace(/\r\n?/g,'\n').split('');

//the prompt is always the last child
var prompt = screen.lastChild;
prompt.className = 'typing';

var typer = function(){
var character = text.shift();
screen.insertBefore(
//newlines must be written as a


character === '\n'
? document.createElement('br')
: document.createTextNode(character),
prompt
);

//only run this again if there are letters
if( text.length ) {
setTimeout(typer, 300);
} else {
prompt.className = 'idle';
}
};
setTimeout(typer, 300);
};

window.onload=function(){
var screen = document.getElementById('screen');
var text = [
'Hello. I am a better console wannabe.',
'All systems are functioning.',
'I like pie.'
];

type(text, screen);
};

body {
background-color: #000000;
color: #99ffcc;
font-family: Courier;
}
#prompt {
font-style: unset;
font-size: 1em;
}
#prompt.idle {
animation: blink 1100ms linear infinite;
-webkit-animation: blink 1100ms linear infinite;
}

@keyframes blink {
49% {opacity: 1;}
50% {opacity: 0;}
89% {opacity: 0;}
90% {opacity: 1;}
}
@-webkit-keyframes blink {
49% {opacity: 1;}
50% {opacity: 0;}
89% {opacity: 0;}
90% {opacity: 1;}
}

▮



To ressemble a little more a console, the animation is only applyed when there's no typing.

With minor changes, it is possible to make it work with keypresses on the keyboard. And with a write queue. But that's left as an exercise for the O.P.

Also, one cool thing you can try is to use a random timeout, to create a varying effect on the writ

Context

StackExchange Code Review Q#97106, answer score: 11

Revisions (0)

No revisions yet.