Countdown using astrisk - html

Currently it shows smallest to biggest. I want it start from biggest to smallest, can't figure it out.
Current output of code
Sample run:
Input to text box: 3
Output in div:
[*]
[**]
[***]
And that’s all folks!
Desired output of code
Sample Run:
Input to text box: 3
Output in div:
[***]
[**
[*]
And that’s all folks!
<!doctype html>
<!—This code will produce a triangle of stars -->
<!-- ================================== -->
<html>
<head>
<title> Countdown </title>
<script type="text/javascript">
function Countdown() {
var count, astrisk;
i=1;
//j=0;
count = parseFloat(document.getElementById('countBox').value);
document.getElementById('outputDiv').innerHTML = '';
astrisk = '*'
while (i<count) {
j=0;
while (j<i) {
document.getElementById('outputDiv').innerHTML =
document.getElementById('outputDiv').innerHTML + astrisk ;
j=j+1;
}
document.getElementById('outputDiv').innerHTML =
document.getElementById('outputDiv').innerHTML + '<br>';
i=i+1;
}
document.getElementById('outputDiv').innerHTML =
document.getElementById('outputDiv').innerHTML + 'And that\'s all folks!' + '<br>';
}
</script>
</head>
<body>
<p>
Start of the countdown:
<input type="text" id="countBox" size=4 value=10>
</p>
<input type="button" value="Begin Countdown" onclick="Countdown();">
<hr>
<div id="outputDiv"></div>
</body>
</html>
I tried flipping some variables, couldn't exactly get it to do what I want. Most of my attempts have led to my computer crashing, I feel like answer is there, but I can't exactly see it. code isn't properly formatted, spent 2 hours trying to indent correctly, and eventually I gave up.

Get the input, button and p (output)
Add click event to the button
When the button is clicked, get input.value plus 1 since it's automatically decreased at the beginning of the function
Print to the DOM the asterisk repeated by the value (that is decreased every 1 second).
When the value reaches 0, clear the function.
let btn = document.querySelector('button');
let input = document.querySelector('input');
let output = document.querySelector('p');
// Button onclick
btn.addEventListener('click', () => {
// Save the run time (input value + 1) since it's automatically decreased at run-time
let timesRun = Number(input.value) + 1;
// Disable the button when it's counting
btn.disabled = true;
// Repeated function every 1 second
let interval = setInterval(function(){
// Decrease the run time
timesRun -= 1;
// If reaches 0, clear the function
if(timesRun === 0){
btn.disabled = false;
clearInterval(interval);
output.innerHTML = 'TIMEOUT';
// Else? print the * repeated by times remain
} else {
output.innerHTML = '*'.repeat(timesRun);
}
}, 1000);
});
<input type="number" placeholder="Countdown" />
<button>Start</button>
<div>
<p></p>
</div>
Updated with the following conditions:
Check that the input is a valid number and not empty
Accept a number between 1 and 10 (including)
let btn = document.querySelector('button');
let input = document.querySelector('input');
let output = document.querySelector('p');
// Button onclick
btn.addEventListener('click', () => {
// Check it's a valid nubmer and not empty
if(input.value.length === 0 || isNaN(Number(input.value))) {
output.innerHTML = 'Please type a valid number.';
// Check if the number is between 1 and 10
} else if (Number(input.value) <= 0 || Number(input.value) > 10) {
output.innerHTML = 'Please type a number between 1-10';
} else {
// Save the run time (input value + 1) since it's automatically decreased at run-time
let timesRun = Number(input.value) + 1;
// Disable the button when it's counting
btn.disabled = true;
// Repeated function every 1 second
let interval = setInterval(function(){
// Decrease the run time
timesRun -= 1;
// If reaches 0, clear the function
if(timesRun === 0){
btn.disabled = false;
clearInterval(interval);
output.innerHTML = 'TIMEOUT';
// Else? print the * repeated by times remain
} else {
output.innerHTML = '*'.repeat(timesRun);
}
}, 1000);
}
});
<input type="number" placeholder="Countdown" />
<button>Start</button>
<div>
<p></p>
</div>

Related

How to "hide" a password in html text input

I am currently building a form, where I have a password.
Is a way to maintain the input type as text while the password remains "hidden".
So basically instead of this being displayed in the text field:
mypassword
I want it to say:
*********
or something close to that. So basically just making the text that the user inputs not to be visible.
I know that changing the type to password will be a solution but I need to maintain the type as text.
One reason why this could be useful is temporarily show last entered character as on mobile devices:
function passwordInput(el)
{
//already initialized?
if (el.actualValue !== undefined)
return el;
let timer = null;
el.actualValue = el.value;
el.addEventListener("input", e =>
{
clearTimeout(timer);
const val = el.value,
start = el.selectionStart,
end = el.selectionEnd,
len = val.length - el.actualValue.length,
//find none-hidden characters
diff = (val.substring(0, start).match(/[^●]+/g)||[""])[0],
//this will be shown for nn seconds
last = diff === "" ? "" : diff[diff.length - 1],
//replace all characters with hidden character
vis = "".padStart(val.length, "●");
//record new value
el.actualValue = el.actualValue.substring(0, start - diff.length) + diff + el.actualValue.substring(start - len);
//replace visible value with hidden characters, except for the last "new" character
el.value = vis.substring(0, start - last.length) + last + vis.substring(start);
//set cursor back to it's original position
el.selectionStart = start;
el.selectionEnd = end;
//hide entire visible value after nn seconds
timer = setTimeout(() =>
{
const start = el.selectionStart,
end = el.selectionEnd;
el.value = vis;
el.selectionStart = start;
el.selectionEnd = end;
}, 1000); // 1 second delay
});
if (el.value !== "")
el.dispatchEvent(new Event("input"))
return el;
}
passwordInput(document.getElementById("myInput")).addEventListener("input", e =>
{
//display real value
output.textContent = e.target.actualValue;
});
<input type="text" id="myInput" autocomplete="off">
<div>Actual value: <span id="output"></span><div>
Basically, what it does, is store actual value in inputElement.actualValue property and replaces value with "●" character. There is one kink I didn't bother to look at, is selection getting reset when last character become hidden.

Google Chrome and Safari on MacOS grabs the character preceding the selected text when you drag'n'drop it into <textarea>

Clean textarea code (as in sandbox) without any side factors (like scripts and specific styles) its work via drag'n'drop in the Chrome browser is followed by a strange phenomenon.
<textarea cols="80" rows="10">
row1w1 row1w2 row1w3 row1w4 row1w5
row2w1 row2w2 row2w3 row2w4 row2w5
row3w1 row3w2 row3w3 row3w4 row3w5
row4w1 row4w2 row4w3 row4w4 row4w5
row5w1 row5w2 row5w3 row5w4 row5w5
row6w1 row6w2 row6w3 row6w4 row6w5
row7w1 row7w2 row7w3 row7w4 row7w5
</textarea>
For example, I drag the first word from any line somewhere like in the GIF image.
Along with the word, for some reason the drag-n-drop event grabs the character before the word (in this case, it's a line break character), even though that character was not selected. It is "compensated", if I may say so, by a space put before the word inserted in the new place. In some cases, this space can stand before the word, after the word and even turn into two spaces on both sides of the word, and sometimes does not appear at all.
The actual question is. Is there a way to make Chrome behave like a text editor or like Firefox? Is there a standard somewhere, or at least some description of how the phenomenon works, when it puts a space and when it doesn't?
I tried to solve this problem with a script. But the code works very crudely. For example, I can not track the difference between moving the selected text one character forward or backward. I think there is a better solution.
// If Google Chrome used
if (/Chrome/.test(window.navigator.userAgent)) {
// This variable handles source drag info
let dragging = null;
// This flag indicates whether the browser has captured a character before the word
let captureFlag = null;
// DragStart event handler
textarea.ondragstart = (e) => {
// First of all, аt this point we can read the initial state before dragging
const {
value,
selectionStart,
selectionEnd
} = textarea;
// Selected text
const selectionData = value.substring(selectionStart, selectionEnd);
// And keep the symbol before of the selected word
const selectionBefore = selectionStart ? value[selectionStart - 1] : '';
dragging = {
selectionStart,
selectionEnd,
selectionData,
selectionBefore
};
}
// Input event handler
textarea.oninput = (e) => {
// When dragging, this event is triggered twice
if (e.inputType == 'deleteByDrag') {
// At this point the highlighted word has already been deleted.
const {
selectionStart
} = textarea;
// If the cursor moved one character backward,
// the browser has definitely captured this character
captureFlag = dragging && selectionStart == (dragging.selectionStart - 1);
} else if (e.inputType == 'insertFromDrop') {
// At this point, the selected word is already inserted in its new location.
if (dragging) {
// Chrome browser leaves the word selected.
const {
value,
selectionStart,
selectionEnd
} = textarea;
// First we cut out what is inserted from the value
let newValue = value.substr(0, selectionStart) + value.substr(selectionEnd);
// If the browser does grab a character before selecting
if (captureFlag && dragging.selectionStart > 0) {
// Let's calculate his position
const insertPos = dragging.selectionStart - 1;
// Put the missing symbol back in place
newValue = newValue.substr(0, insertPos) +
dragging.selectionBefore +
newValue.substr(insertPos);
}
// Next, we have to determine the offset.
// If the pasted text was inserted somewhere after the deletion,
// we need to add to the offset one character that we just inserted
const offset = (captureFlag && (selectionStart > dragging.selectionStart)) ? 1 : 0;
// Now let's count the positions where we insert the originally selected text
const newSelectionStart = selectionStart + offset;
const newSelectionEnd = dragging.selectionEnd - dragging.selectionStart +
selectionStart + offset;
// Insert text that was originally selected (still in the dragstart event)
newValue = newValue.substr(0, newSelectionStart) +
dragging.selectionData +
newValue.substr(newSelectionStart);
// Apply the new value
textarea.value = newValue;
// And let's select this area of text like the browser
textarea.setSelectionRange(newSelectionStart, newSelectionEnd, "none");
}
}
}
// Reset the variables when the drag is finished
textarea.ondragend = () => {
dragging = null;
captureFlag = null
};
}
<textarea id="textarea" cols="80" rows="10">
row1w1 row1w2 row1w3 row1w4 row1w5
row2w1 row2w2 row2w3 row2w4 row2w5
row3w1 row3w2 row3w3 row3w4 row3w5
row4w1 row4w2 row4w3 row4w4 row4w5
row5w1 row5w2 row5w3 row5w4 row5w5
row6w1 row6w2 row6w3 row6w4 row6w5
row7w1 row7w2 row7w3 row7w4 row7w5
</textarea>
UPDATE
I was fixed to track the dragging of the word one character backward or forward.
// If Google Chrome used
if (/Chrome/.test(window.navigator.userAgent)) {
// This variable handles source drag info
let dragging = null;
// This flag indicates whether the browser has captured a character before the word
let captureFlag = null;
// DragStart event handler
textarea.ondragstart = (e) => {
// First of all, аt this point we can read the initial state before dragging
const {
value,
selectionStart,
selectionEnd
} = textarea;
// Selected text
const selectionData = value.substring(selectionStart, selectionEnd);
// And keep the symbol before of the selected word
const selectionBefore = selectionStart ? value[selectionStart - 1] : '';
// Save drag position
dragging = {
selectionStart,
selectionEnd,
selectionData,
selectionBefore,
dragLayerX: e.layerX,
dragLayerY: e.layerY,
dropLayerX: -1,
dropLayerY: -1,
};
}
// drop event handler
textarea.ondrop = (e) => {
// Save drop position
dragging.dropLayerX = e.layerX;
dragging.dropLayerY = e.layerY;
}
// Input event handler
textarea.oninput = (e) => {
// When dragging, this event is triggered twice
if (e.inputType == 'deleteByDrag') {
// At this point the highlighted word has already been deleted.
const {
selectionStart
} = textarea;
// If the cursor moved one character backward,
// the browser has definitely captured this character
captureFlag = dragging && selectionStart == (dragging.selectionStart - 1);
} else if (e.inputType == 'insertFromDrop') {
// At this point, the selected word is already inserted in its new location.
if (dragging) {
// Chrome browser leaves the word selected.
const {
value,
selectionStart,
selectionEnd
} = textarea;
// First we cut out what is inserted from the value
let newValue = value.substr(0, selectionStart) + value.substr(selectionEnd);
// If the browser does grab a character before selecting
if (captureFlag && dragging.selectionStart > 0) {
// Let's calculate his position
const insertPos = dragging.selectionStart - 1;
// Put the missing symbol back in place
newValue = newValue.substr(0, insertPos) +
dragging.selectionBefore +
newValue.substr(insertPos);
}
// Next, we have to determine the offset.
let offset;
// If text was dragged from end of row and dropped to start of next row
if(selectionStart == dragging.selectionStart){
offset = 1;
}
// If text was dragging on one char backward or forward
// It was need to be calculated
else if(selectionStart - dragging.selectionStart == -1){
// First of all, lets calculate one text line height
let ctx = document.createElement('canvas').getContext('2d');
ctx.font = getComputedStyle(textarea).font;
const measure = ctx.measureText(textarea.value);
const lineHeight = measure.fontBoundingBoxAscent + measure.fontBoundingBoxDescent;
// Then set offset 0 if text moved backward or 2 if forward
if(Math.abs(dragging.dragLayerY - dragging.dropLayerY) > 0.6 * lineHeight){
offset = dragging.dragLayerY < dragging.dropLayerY ? 2 : 0;
}
else {
offset = dragging.dragLayerX < dragging.dropLayerX ? 2 : 0;
}
}
else {
// If the pasted text was inserted somewhere after the deletion,
// we need to add to the offset one character that we just inserted
offset = (captureFlag && (selectionStart > dragging.selectionStart)) ? 1 : 0;
}
// Now let's count the positions where we insert the originally selected text
const newSelectionStart = selectionStart + offset;
const newSelectionEnd = dragging.selectionEnd - dragging.selectionStart +
selectionStart + offset;
// Insert text that was originally selected (still in the dragstart event)
newValue = newValue.substr(0, newSelectionStart) +
dragging.selectionData +
newValue.substr(newSelectionStart);
// Apply the new value
textarea.value = newValue;
// And let's select this area of text like the browser
textarea.setSelectionRange(newSelectionStart, newSelectionEnd, "none");
}
}
}
// Reset the variables when the drag is finished
textarea.ondragend = () => {
dragging = null;
captureFlag = null
};
}
<textarea id="textarea" cols="80" rows="10">
row1w1 row1w2 row1w3 row1w4 row1w5
row2w1 row2w2 row2w3 row2w4 row2w5
row3w1 row3w2 row3w3 row3w4 row3w5
row4w1 row4w2 row4w3 row4w4 row4w5
row5w1 row5w2 row5w3 row5w4 row5w5
row6w1 row6w2 row6w3 row6w4 row6w5
row7w1 row7w2 row7w3 row7w4 row7w5
</textarea>

Why does this Javascript function rewrite the innerHTML of one div but not the other?

I'm using NodeJS to query a MySQL database for a single entry of a journal, but the results aren't going to both of the assigned divs. I have an iFrame in my center column, dedicated to two divs (one hidden at any given time). One div is a read-only page for the journal entry, and the other one contains a TinyMCE rich-text editor. I have buttons in left column to switch between the views.
The rich-text editor loads properly on initial load of page, but doesn't update as I navigate with the calendar; the read-only innerHTML does update properly as I navigate.
calDt[] is an array that holds dates. calDt[0] is the active date, while calDt[1] holds a dummy date used for navigating the calendar without changing the entry.
app.js:
app.get('/getdata/:dateday', (req, res) => {
let sql = `SELECT entry FROM main where dateID ='${req.params.dateday}'`
let query = db.query(sql, (err, results) => {
if(err) {
throw err
}
res.send(JSON.stringify(results));
})
})
middle-left.ejs
<button style= "height:22px"; type="button" onclick="readDivHere()">Lock</button>
<button style= "height:22px"; type="button" onclick="editDivHere()">Edit</button></div>
<script> // the Lock button brings us back to the completed entry in the middle stuff
function readDivHere() {
document.getElementById('frame1').contentWindow.readDivHere();
document.getElementById('frame1').scrolling = "yes";
}
</script>
<script> // the Edit button will bring tinymce rich-text editor to the middle stuff
function editDivHere() {
document.getElementById('frame1').contentWindow.editDivHere();
document.getElementById('frame1').scrolling = "no";
}
</script>
middle-center.ejs
<iframe id="frame1" class="entryon" src="" frameborder="0px"></iframe>
<script>
document.getElementById("frame1").src = "iframe";
</script>
iframe.ejs
<div id="readDiv" class="here" style="display: block; background: white; padding-top: 0px; padding-left: 10px; padding-right: 8px; min-height: 810px; width: 967px;"><%- include ('entry'); %></div>
<div id="editDiv" class="here" style="display: none; padding: 0px;" ><%- include ('editPage'); %></div>
<script> //function that switches from rich-text editor back to real entry
function readDivHere() { // here we run a function to update text of read-only entry
document.getElementById("readDiv").style.display="block";
document.getElementById("editDiv").style.display="none";
}
</script>
<script> //function that switches from read-only entry to rich-text editor
function editDivHere() {
document.getElementById("readDiv").style.display="none";
document.getElementById("editDiv").style.display="block";
}
</script>
entry.ejs
<div id="readOnlyEntry"></div>
<script>
// load the active entry into the middle column for proper reading
function loadEntry(p) {
var x = parent.calDt[1].getFullYear();
var y = parent.calDt[1].getMonth();
y = y + 1;
if (y < 10) {
y = "0" + y;
};
if (p < 10) {
p = "0" + p;
}
var newDate = x + "" + y + "" + p; // p is a date formatted like 20210808
            var xhttp = new XMLHttpRequest();
            xhttp.onreadystatechange = function() {
                const text = this.responseText;
                const obj = JSON.parse(text);
document.getElementById("readOnlyEntry").innerHTML = obj[0].entry;
document.getElementById("richTextEd").innerHTML = obj[0].entry; // doesn't work!
            }
xhttp.open("GET", "../getdata/" + newDate, true);
        xhttp.send();
}
</script>
<script>
// rich-text editor populates correctly on load
loadEntry(parent.calDt[0].getDate());
</script>
editPage.ejs
<%- include ('tinymce'); %>
<form method="POST" action="../result" enctype="multipart/form-data">
<textarea name="content" id="richTextEd">Here's the default text.</textarea>
</form>
calendar-clicker.ejs
var p = x.innerHTML; // get the value of the calendar cell text (i.e. day of the month)
p = p.match(/\>(.*)\</)[1];
var d = calDt[1].getFullYear(); // what year is the calendar referencing?
var q = calDt[1].getMonth(); // what month is the calendar referencing?
q = q + 1; // compensate for javascript's weird month offset
calDt[0] = new Date(q + "/" + p + "/" + d); // assign a new global date variable
calDt[1] = calDt[0]; // temporarily reset navigation date to active date
document.getElementById('frame1').contentWindow.loadEntry(p);
Does the failure have to do with assigning the innerHTML to a different .ejs? If I put the form into the same div as the read-only entry, the form still fails to update as I navigate.
Solved it.
In entry.ejs, I replaced...
document.getElementById("richTextEd").innerHTML = obj[0].entry;
with
tinymce.get("richTextEd").setContent(obj[0].entry);
https://www.tiny.cloud/blog/how-to-get-content-and-set-content-in-tinymce/

how to change the div value with a counter

I don't understand why this function does not change the value of num every time I press the button. basically i wanted to make a counter that adds one to the div every time i press the button.
<div class="elements" id="txtthrow">0</div>
<button class="button1" id="buttonNewHand" onclick="newFaceTot()">new<br>number</button>
//------------------------------------------------------------------------
refthrow = document.getElementById("txtthrow");
function newFaceTot(){
numberChanged();
}
function numberChanged(){
var num = parseInt(refthrow.value, 10);
refthrow.innerHTML = changeNumber(num);
}
function changeNumber(num){
num = num + 1;
return num;
}
Only form (e.g. input/select/textarea) elements have a value. For other elements use innerHTML or innerText to get the content.
const refthrow = document.getElementById("txtthrow");
function newFaceTot() {
numberChanged();
}
function numberChanged() {
var num = parseInt(refthrow.innerText, 10);
refthrow.innerHTML = changeNumber(num);
}
function changeNumber(num) {
num = num + 1;
return num;
}
<div class="elements" id="txtthrow">0</div>
<button class="button1" id="buttonNewHand" onclick="newFaceTot()">new<br>number</button>
Therefore the value attribute was undefined. And parseInt(undefined) is NaN (not a number).

html type="number" : Show always 2 digits after dot?

in a type="number" input, i would like to show 2 digits after dot like "2.50"
if a try
<input name="price" type="number" step="0.01" value="2.5">
this show me "2.5" and not "2.50"
Have you a method to do this ? HTML5 pure or with javascript ?
you need to use Jquery or JavaScript for that what ever you want but this solution in Jquery
You Can't go for more than 2 number
//Use keyup to capture user input & mouse up to catch when user is changing the value with the arrows
$('.trailing-decimal-input').on('keyup mouseup', function (e) {
// on keyup check for backspace & delete, to allow user to clear the input as required
var key = e.keyCode || e.charCode;
if (key == 8 || key == 46) {
return false;
};
// get the current input value
let correctValue = $(this).val().toString();
//if there is no decimal places add trailing zeros
if (correctValue.indexOf('.') === -1) {
correctValue += '.00';
}
else {
//if there is only one number after the decimal add a trailing zero
if (correctValue.toString().split(".")[1].length === 1) {
correctValue += '0'
}
//if there is more than 2 decimal places round backdown to 2
if (correctValue.toString().split(".")[1].length > 2) {
correctValue = parseFloat($(this).val()).toFixed(2).toString();
}
}
//update the value of the input with our conditions
$(this).val(correctValue);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input id="my-number-input" class="form-control trailing-decimal-input" type="number" min="0.01" step="0.01" value="2.50" />
you can preview or edit code Here on JSFiddle
You can solve by script Like :
<script type="text/javascript">
$(document).ready(function() {
var num = 2.5;
var n = num.toFixed(2);
alert(n);
});
</script>
<script type="text/javascript">
$(document).ready(function() {
var num = 2.500;
var n = num.toFixed(1);
alert(n);
});
</script>