JSFiddle - React, Tailwind, and code Playground
HTML
<table>
<tr>
<td>
<textarea class='comment-box' rows="4" cols="60"></textarea>
</td>
<td valign="top">
<button class='add-comment'>Add Comment</button>
</td>
</tr>
<tr>
<td colspan="2">
<div class="comment-status"></div>
</td>
</tr>
<tr class="popup-container">
<td colspan="2">
<div class="popup"><h1>a</h1><div class="close">Click this box to close the message.</div></div>
</td>
</tr>
</table>
<div id="comments">
</div>
CSS
body {
font-family: Helvetica, Arial;
font-size: 13px;
}
button {
font-size: 0.9em;
margin: 0 10px;
padding: 5px;
background-color: #CCC;
border: 1px solid #AAA;
}
.comment-status {
margin: 3px 0;
color: #999;
}
.mild {
color: #999;
color: #9B764F;
}
.spicy {
color: #CF7721;
}
.hot {
color: #FE7A15
}
.sizzling {
color: red;
}
.popup {
color: white;
padding: 5px;
background-color: #FE7A15;
}
.popup h1 {
font-size: 1.3em;
}
.popup div.close {
margin: 3px 0;
font-size: 0.9em;
}
.popup-container {
cursor: pointer;
display: none;
}
.comment {
color: #666;
margin: 10px 0;
}
JavaScript
/**
* Stores the timestamp when the last comment was submitted
*/
var lastCommentTimestamp = null;
/**
* Handle comment change.
* Update character count.
* Indicate progress
*/
function handleCommentUpdate(comment) {
var status = $('.comment-status');
status.text(getStatusText(comment));
status.removeClass('mild spicy hot sizzling');
status.addClass(getStatusClass(comment));
}
/**
* Is the comment valid for submission
*/
function commentSubmittable(comment) {
var notTooSoon = !isTooSoon();
var notEmpty = !isEmpty(comment);
var hasEnoughCharacters = !isTooShort(comment);
return notTooSoon && notEmpty && hasEnoughCharacters;
}
/**
* Was last comment submitted less than 15 seconds ago?
*/
function isTooSoon() {
if(lastCommentTimestamp == null) {
return false;
}
var minDelay = 15 * 1000; // milliseconds
return (Date.now() - lastCommentTimestamp) < minDelay;
}
/**
* Seriously? Comment for this?
*/
function isEmpty(comment) {
return comment == '';
}
/**
* Shouldn't be less than 15 characters
*/
function isTooShort(comment) {
return comment.replace(/\s+/g, " ").length < 15;
}
/**
* Map comment size to class names
*/
function getStatusClass(comment) {
var max = 600;
var remaining = max - comment.length;
if(remaining < 0) return 'sizzling';
if(remaining < 120) return 'hot';
if(remaining < 250) return 'spicy';
if(remaining < 350) return 'mild';
return '';
}
/**
* Comment progress message
*/
function getStatusText(comment) {
if(comment == '') {
return 'enter at least 15 characters';
}
if(comment.length < 15) {
var remaining = 15 - comment.length;
return remaining + ' more to go..';
}
var remaining = 585 - comment.length;
return remaining + ' characters left';
}
function popup(message) {
$('.popup-container').fadeIn();
$('.popup h1').text(message);
}
// update comment progress...