Yik Jin Yik Jin - 6 months ago 18
CSS Question

<span> cursor not working as expected

I'm trying to create a "web-based terminal" in HTML, CSS and JS, but I'm having some issues with the thick white cursor that I had created using

<span>
. Basically, I'm trying to make the cursor stop flashing after the user clicks outside of the terminal and make it flash again once the user clicks inside the terminal. However, the problem comes when the user clicks on the terminal. The
setTimeout()
in Javascript seemed as if it stopped working and the cursor only flashes once when you click on the terminal. Below is my code:



// Javascript

'use strict';

class Cursor {
constructor() {
this.page = document.querySelector(".js-body");
this.cmd = document.querySelector(".js-console");
this.cursor = document.querySelector(".js-cursor");

this.flashCursor = this.flashCursor.bind(this);
this.showCursor = this.showCursor.bind(this);
this.hideCursor = this.hideCursor.bind(this);

this.cursorVisible = false;
this.cursorFocus = true;

this.flashCursor();
this.addEventListeners();
}

addEventListeners() {
this.page.addEventListener('click', this.hideCursor);
this.cmd.addEventListener('click', this.showCursor);
}

flashCursor() {
if (this.cursorVisible) {
this.cursor.classList.remove('cursor--visible');
this.cursorVisible = false;
} else {
this.cursor.classList.add('cursor--visible');
this.cursorVisible = true;
}

this.cursorTimeout = setTimeout(this.flashCursor, 500);
}

showCursor() {
if (this.cursorFocus)
return;
this.cursorFocus = true;
this.flashCursor();
}

hideCursor() {
if (!this.cursorFocus)
return;
this.cursorFocus = false;
clearTimeout(this.cursorTimeout);
}
}

new Cursor();

/**
* CSS
*/

body {
background-color: #1A237E;
background: #1A237E url("https://yikjin.ml/cmd/img/main-bg.jpg") center no-repeat;
background-size: cover;
-webkit-background-size: cover;
color: #E0E0E0;
font-family: monospace;
font-size: 15px;
height: 100vh;
position: relative;
}
.console {
background-color: rgba(0, 43, 54, 0.75);
padding: 25px;
width: 750px;
max-width: 100%;
height: 90%;
position: absolute;
margin: auto;
top: 0;
bottom: 0;
left: 0;
right: 0;
overflow-x: auto;
}
.console p {
width: 100%;
min-height: 20px;
line-height: 20px;
margin: 0;
}
/**
* Prevent selection in .console__cmd
*/

.console__cmd {
-webkit-touch-callout: none;
-webkit-user-select: none;
-khtml-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
-webkit-tap-highlight-color: transparent;
}
/**
* Cursor visibility
*/

.cursor {
display: inline-block;
background-color: transparent;
width: 10px;
}
.cursor--visible {
background-color: #E0E0E0;
}
/**
* Highlight colors
*/

*::selection {
background-color: #E0E0E0;
color: #000;
}
*::-moz-selection {
background-color: #E0E0E0;
color: #000;
}

/**
* Text colors
*/

span.text-version {
color: #2196F3;
}
span.text-ip {
color: #E91E63;
font-weight: bold;
}
span.text-location {
color: #7E57C2;
font-weight: bold;
}

<!-- HTML -->

<body class="js-body">
<div class="js-console console">
<p>Command Prompt
<span class="text-version">[Version 1.0]</span>
</p>
<p>(c) 2016 Yik Jin. All rights reserved.</p>
<p></p>
<p>Type in a command to begin.</p>
<p></p>

<div class="console__cmd">
<span>
<span class="text-ip">me</span>@<span class="text-location">localhost</span>
~$
</span>
<span class="text"></span>
<span class="js-cursor cursor">&nbsp;</span>
</div>
</div>
</body>





You might need to view the result full page. Here's the JSFiddle link. Any help would be appreciated!

Answer

It looks like both your click handlers are getting fired since the click event is allowed to propagate. This immediately stops the blinking after it's started. Add a console.log() message on each method to see what's happening.

Try:

showCursor(e) {
   e.stopPropagation();
   ...
}

hideCursor(e) {
   e.stopPropagation();
   ...
}

I also recommend using setInterval() and clearInterval() which are builtins designed to call events at a specified interval, so you don't have to re-schedule a timeout on each call.