Okay so this is a bit hard to explain this, but I am trying to make where whenever a number is "spawned" or generated, it fades in instead of just popping up.
Here is the Fiddle that I am trying to do that with. I am using a input tag for the number and a for statement to generate the rest--
for (I = 0; I < $("#input:text").val(); I++) {
N.innerHTML += 1 + I + " "
}
I hope I explained that well enough so people understand!
Append span elements instead of text so that you can easily select elements using selector.
Use setTimeout to make it happen serially using index.
Try this:
var D = document,
In = D.getElementById("input"),
CC = D.getElementById("submit"),
N = D.getElementById("N"),
I;
$(In).keyup(function(Key) {
if (Key.keyCode == 13) {
for (var i = 0; i < $("#input:text").val().length; i++) {
var span = '<span style=\'display:none\'>' + (i + 1) + ' ' + $("#input:text").val()[i] + ' </span>'; //set display of `span` element as `none`
N.innerHTML += span;
}
}
$('#N span').each(function(i) {
setTimeout(function() {
$(this).hide().fadeIn(500);
}.bind(this), (i * 500)); // `.bind()` will pass the outer `this` context in`setTimeout` when handler is invoked
})
});
$(CC).click(function() {
N.innerHTML = "";
});
body {
cursor: default;
outline-width: 0px;
}
#main {
text-align: center;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
<body>
<div id="main">
<input type="text" id="input" maxlength="3" placeholder="Press submit to clear all" />
<input type="submit" id="submit" />
</div>
<h1 id="N"></h1>
</body>
Fiddle here
The jQuery fadeIn method would make this trivial. But if you want to do this with no libraries you can modify the opacity of the result div in a recursive loop. I modified your fiddle here and included it below. The key points are setting the result div to opacity:0 at start, then recursively calling the "fadeIn" function after your original code has ran. you can tweak the timeout delay and opacity increment to get the desired speed and smoothness of the fade effect.
HTML:
<body>
<div id="main">
<input type="text" id="input" maxlength="3" placeholder="Press submit to clear all" />
<input type="submit" id="clear" />
</div>
<h1 id="N"></h1>
</body>
CSS:
body {
cursor: default;
outline-width: 0px;
}
#main {
text-align: center;
}
#N {
opacity: 0;
}
JavaScript:
var D = document,
In = D.getElementById("input"),
CC = D.getElementById("clear"),
N = D.getElementById("N"),
I,
O = 0;
var fadeIn = function() {
O += 0.05
D.getElementById("N").style.opacity = O;
if (O < 1) {
setTimeout(fadeIn, 100)
}
}
$(In).keyup(function(Key) {
if (Key.keyCode == 13) {
for (I = 0; I < $("#input:text").val(); I++) {
N.innerHTML += 1 + I + " "
}
setTimeout(fadeIn, 100)
}
});
$(CC).click(function() {
N.innerHTML = "";
});
Related
I am very new to javaScript and I am currently trying to code a Lottery Game. The User is allowed to input 6 numbers between 1 and 49 and then Generate 6 random numbers and it will then tell you how many Numbers you got correct.
Everything seems to be working great so far but i can not figure out how to Code that you
Can not input the same number twice (This should result in an error code)
The Randomizer isnt allowed to draw the same number twice
My Code looks like this so far:
function validateBall(num) {
let ballValue = document.getElementById("ball" + num).value;
if (ballValue == "") {
alert("Ball " + num + " braucht eine Zahl");
return false;
}
if (isNaN(ballValue)) {
alert("Ball " + num + " ist keine Zahl");
return false;
}
let numberValue = parseInt(ballValue);
if (numberValue <= 0 || numberValue > 49) {
alert("Die Zahl des Balls muss zwischen 1-49 liegen");
return false;
}
return numberValue;
}
function containsDuplicates(ballValue) {
return array.length !== new Set(ballValue).size;
}
function output(str) {
let output = document.getElementById("output");
var tag = document.createElement("p");
var text = document.createTextNode(str);
tag.appendChild(text);
output.appendChild(tag);
}
function Jetzt_Spielen() {
let value1 = validateBall("1");
if (value1 == false)
return;
let value2 = validateBall("2");
if (value2 == false)
return;
let value3 = validateBall("3");
if (value3 == false)
return;
let value4 = validateBall("4");
if (value4 == false)
return;
let value5 = validateBall("5");
if (value5 == false)
return;
let value6 = validateBall("6");
if (value6 == false)
return;
let values = [value1, value2, value3, value4, value5, value6];
let outputDiv = document.getElementById("output");
outputDiv.innerHTML = "";
let matched = 0;
for (let i = 0; i < 6; i++) {
let randomNumber = Math.round(1 + Math.random() * 48);
output("Gezogene Zahl: " + randomNumber);
for (let j = 0; j < 6; j++) {
let myBallValue = values[j];
if (randomNumber == myBallValue) {
matched++;
break;
}
}
}
output("Du hast " + matched + " richtige Zahl(en)")
}
<div class="gelbe_box">
<h1>Lotto 6aus49</h1>
</div> <br>
<div class="position_middle">
<input id="ball1" class="LottoZahlen" />
<input id="ball2" class="LottoZahlen" />
<input id="ball3" class="LottoZahlen" />
<input id="ball4" class="LottoZahlen" />
<input id="ball5" class="LottoZahlen" />
<input id="ball6" class="LottoZahlen" />
<button id="submitBtn" value="button" onclick=" Jetzt_Spielen();">Jetzt Spielen</button>
<div id="output">
</div>
I dont really know how to continue with this. I either did something wrong already that I cant do it with this code or I just can not figure the code(s) out..
I'd really appreciate some help!!
Thank you in advance :)
Good UX and Restrictions
Plan the layout (HTML and essential CSS) first. To control how interaction with the user is done relies heavily on HTML and CSS, JavaScript is used to facilitate this interaction, gather user data, and process user's data and/or new data. In order to answer your question, I'm compelled to show you an approach to meet your objective and provide a solution that's foolproof for your particular problem.
HTML
If you require interaction from a user use a <form> and keep all of your relevant layout inside of it. Present only what the user needs to use, ideally a single form control like a button. Hide the rest of the HTML and restrict the user to go through phases. Instruct the user with simple messages and visual prompts. Don't use prompt() (it's aesthetically unappealing and popups feel "rude" IMO):
Figure I - The Layout
<form id='lottery'><!-- Wrap <form> around everything -->
<fieldset id='box'>
<!-- Always have simple clear directions -->
<legend>Click the button to begin</legend>
<!-- Offer the user only one or two choices at a time -->
<!-- ATM there are two empty <select> and a <button> that automatically
has focus (see Figure II). There's a <legend> prompting user to click
the <button>. There's also a hidden <button> and <output> ready for
the next phase.
-->
<select id='choices' multiple></select>
<!-- This button has focus as soon as the page is loaded because it's
assigned "tab-index='0'" and there's a line of JavaScript
(see Figure II)
-->
<button id='begin' tab-index='0'>Begin</button>
<button id='done' tab-index="0" type='button'>Done</button>
<select id='picked' multiple></select>
</fieldset>
<output id='note' class='hide'>
<small><sup>✳️</sup>To deselect a number, click the number in field on the right</small>
</output>
<!-- This hidden section is the final phase which displays the user's
numbers, the winning lottery numbers, and the numbers that matched.
-->
<fieldset id='results' class='hide'>
<label for='final'>Your Numbers: </label><output id='final' class='array'></output><br>
<label for='targets'>Winning Numbers: </label><output id='targets' class='array'></output><br>
<label for='hits'>Matching Numbers: </label><output id='hits' class='array'></output><br>
<button type='reset'>Replay</button>
</fieldset>
</form>
JavaScript
// This will hold the numbers the user picks
let numbers = [];
/*
This is an array of 49 empties "". It will be used as a counter and
then later repurposed to hold the winning numbers
*/
let A49 = [...Array(49)];
/*
Throughout this example the terse syntax of the HTMLFormsElement
interface will be used extensively. This references the <form>
*/
const lot = document.forms.lottery;
// 1st phase init(e) populates a <select> with 49 <option>s
lot.addEventListener('submit', init);
/*
2nd phase pick(e) allows the user to pick 6 numbers, no need to validate
user input there are 49 numbers and each number can only be picked once.
*/
lot.addEventListener('input', pick);
/*
Last phase draw(e) collects the users array of 6 numbers, then generates
a randomized array of 6 numbers, then displays both arrays with matches
highlighted.
*/
lot.elements.done.addEventListener('click', draw);
lot.onreset = function() {
window.location.reload();
};
lot.elements.begin.focus();
function init(e) {
e.preventDefault();
const IO = this.elements;
A49 = A49.map((_, index) => {
IO.choices.insertAdjacentHTML(
'beforeend',
`<option value="${index + 1}">${index + 1}</option>`
);
return index + 1;
});
//...
This answer is huge, apologies, I'll return later on to finish explaining the rest of this code. It's foolproof and meets if not exceeds all objectives of the OP, I hope this helps.
<!DOCTYPE html>
<html lang="en">
<head>
<title></title>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta
name="viewport"
content="width=device-width, initial-scale=1, shrink-to-fit=no"
/>
<style>
html {
font: 300 5vmin/1.25 'Segoe UI';
}
fieldset {
max-width: 15rem;
}
#box {
display: flex;
justify-content: center;
align-items: center;
}
input,
button,
output,
select,
label {
display: inline-block;
margin: 4px;
font: inherit;
}
button {
padding-bottom: 0.25rem;
border: 0;
border-radius: 2px;
outline: 0;
cursor: pointer;
}
label {
width: 4rem;
margin-right: 0;
}
mark {
padding: 1px;
background-color: #0047AB;
color: gold;
}
small {
font-size: 0.5rem;
}
legend b {
font-family: Consolas;
}
select {
width: 3rem;
height: 9rem;
border: 0.5 inset lightgrey;
border-radius: 2px;
outline: 0;
font-family: Consolas;
}
#choices {
overflow-y: scroll;
scrollbar-width: thin;
}
#choices::-webkit-scrollbar {
width: 0.25rem;
height: 9rem;
}
#picked {
overflow-y: hidden;
}
.array {
width: 7.5rem;
font-family: Consolas;
}
.hide {
visibility: hidden;
}
#done {
display: none;
}
#note {
margin-top: -4px;
}
[type='reset'] {
float: right;
}
select:focus,
button:focus {
color: #0047AB;
box-shadow: 0 0 0 2pt cornflowerblue;
}
</style>
</head>
<body>
<form id="lottery">
<fieldset id="box">
<legend>
Click the button to begin
</legend>
<select id="choices" multiple></select>
<button id="begin" tab-index="0">Begin</button>
<button id="done" tab-index="0" type="button">Done</button>
<select id="picked" multiple></select>
</fieldset>
<output id="note" class="hide">
<small>
<sup>✳️</sup>To deselect a number, click the number in field on the
right
</small>
</output>
<fieldset id="results" class="hide">
<label for="final">Your Numbers: </label>
<output id="final" class="array"></output><br />
<label for="targets">Winning Numbers: </label>
<output id="targets" class="array"></output><br />
<label for="hits">Matching Numbers: </label>
<output id="hits" class="array"></output><br />
<button id='replay' tab-index='0' type="reset">Replay</button>
</fieldset>
</form>
<script>
let numbers = [];
let A49 = [...Array(49)];
const lot = document.forms.lottery;
lot.addEventListener('submit', init);
lot.addEventListener('input', pick);
lot.elements.done.addEventListener('click', draw);
lot.onreset = function() {
window.location.reload();
};
lot.elements.begin.focus();
function init(e) {
e.preventDefault();
const IO = this.elements;
A49 = A49.map((_, index) => {
IO.choices.insertAdjacentHTML(
'beforeend',
`<option value="${index + 1}">${index + 1}</option>`
);
return index + 1;
});
IO.box.firstElementChild.innerHTML = `Pick <b>6</b> numbers -- 1 to 49<sup><small>✳️</small></sup>`;
IO.note.classList.remove('hide');
IO.begin.remove();
IO.done.style.display = 'inline-block';
IO.done.disabled = true;
IO.choices.focus();
}
function pick(e) {
const IO = this.elements;
const sel = e.target;
if (sel.id === 'choices') {
const copy = sel.options[sel.selectedIndex].cloneNode(true);
IO.picked.append(copy);
numbers.push(+sel.value);
sel.options[sel.selectedIndex].remove();
}
if (sel.id === 'picked') {
const copy = sel.options[sel.selectedIndex].cloneNode(true);
IO.choices.append(copy);
let nodeList = [...IO.choices.options];
let ordered = nodeList.sort((a, b) => +a.value - +b.value);
IO.choices.replaceChildren(...nodeList, ...ordered);
numbers = numbers.filter((number) => number !== +sel.value);
sel.options[sel.selectedIndex].remove();
}
if (numbers.length === 6) {
IO.choices.disabled = true;
IO.done.disabled = false;
IO.done.focus();
} else {
IO.choices.disabled = false;
IO.done.disabled = true;
}
IO.box.firstElementChild.innerHTML = `Pick <b>${
6 - numbers.length
}</b> numbers -- 1 to 49<sup><small>✳️</small></sup>`;
}
function draw(e) {
const IO = this.closest('form').elements;
IO.box.disabled = true;
IO.note.classList.add('hide');
IO.results.classList.remove('hide');
let drawn = shuffle(A49);
drawn.length = 6;
let match = drawn.filter((number) => numbers.includes(number));
IO.final.innerHTML = mark(numbers, match);
IO.targets.innerHTML = mark(drawn, match);
let outcome = match.length > 0 ? mark(match) : 'Goose Egg 🥚';
IO.hits.innerHTML = outcome;
IO.replay.focus();
}
function shuffle(array) {
let qty = array.length,
temp,
i;
while (qty) {
i = Math.floor(Math.random() * qty--);
temp = array[qty];
array[qty] = array[i];
array[i] = temp;
}
return array;
}
function mark(arrayA, arrayB = arrayA) {
arrayA.sort((a, b) => a - b);
return arrayA.map((n) =>
arrayB.includes(n) ? `<mark>${n}</mark>` : n
);
}
</script>
</body>
</html>
I am new to JavaScript and need some help.
I am creating a sudoku gameboard using multiple buttons. I want to draw/color the border of every third line and every third column, to evidentiate those 3x3 boxes. The problem is when I try to get each button's ID it says 'undefined' and I can't do what I intended.
What am I doing wrong? Or how should I color those lines that I am talking about?
function createButtons() {
var gameboard = document.getElementById("gameboard");
for (var i = 1; i <= 9; i++) {
for (var j = 1; j <= 9; j++) {
var button = document.createElement("button");
button.id = i + "." + j;
button.innerHTML = "cell " + i + "-" + j;
gameboard.appendChild(button);
}
}
}
function drawLines() {
var button = document.getElementsByName("button");
for (var i = 1; i <= 81; i++) {
if (button.id == 3 + "." + i || button.id == 6 + "." + i) {
button.style.border.bottom = "5px solid red"; //I don't know if this is correct
}
if (button.id == i + "." + 3 || button.id == i + "." + 6) {
button.style.border = "5px";
button.style.border.right = "solid yellow";
}
}
}
createButtons();
drawLines();
body {
background-color: #0f4c5c;
}
h1,
h5 {
color: white;
}
.sudoku #gameboard {
width: 40vmin;
height: 40vmin;
display: grid;
grid-template-columns: repeat(9, 1fr);
gap: 0;
}
.sudoku button {
width: 10vmin;
height: 10vmin;
background: white;
margin: 0;
}
<body>
<div class="container">
<div class="col">
<h1 class="row mx-auto my-3" id="title">
Sudoku
</h1>
<div class="row my-2 container sudoku">
<div class="gameboard" id="gameboard"></div>
</div>
</div>
</div>
</div>
</body>
Your drawLines() function is the root of the problem here.
As stated in my commend, getElementsByName will return undefined in this instance as there is no element on the DOM with a name attribute.
A different approach you could take would be to give every button a class name and target them all using getElementsByClassName, which you can then loop through, possibly using a map or forEach.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/forEach
In order to get every third element in the array, consider using the modulus operator (%).
Please have a look at https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Remainder for more information on usage of modulus.
I need to use class="side1" from the custList because that is the side of the cube I want to flash a different color everytime a certain time passes. The only way I found that it works is if I use a setInterval but I don't want it to just keep changing colors every so many seconds. If the cube as been sitting there for 5min it will go from green to yellow and if it's been there for 7min it will go to red and stay red until it's done and then disappears. What can I do to make it work?
<div id="loader"></div>
<div style="display: none;" id="myDiv" class="animate-bottom">
<%--The routing cube--%>
<div id="wrapD3Cube" class="normal"></div>
</div>
var custList = "";
var top = 0;
var left = 0;
for (var i = 0; i < Data.length; i++) {
custList += '<div class="D3Cube" id="D3Cube"' + i + '>';
custList += '<div class="side1" id="side1' + i + '"
style="position:absolute; opacity: 1.05; width: 112px; height: 112px;">
</div > ';.
var changeColor = 0
function colors() {
if (changeColor < 4000) {
document.getElementsByClassName("side1").style.backgroundColor
= '#91CB8A';
}
else if (changeColor >= 5000) {
document.getElementsByClassName("side1").style.backgroundColor
= '#F7B448';
}
else if (changeColor >= 6000) {
document.getElementsByClassName("side1").style.backgroundColor
= '#E84F60';
}
}
colors();
The function document.getElementsByClassName returns an HTMLCollection, so you have to choose an element:
document.getElementsByClassName("side1")[0].style.backgroundColor = "color";
This code intends to append numbers in a array to the string shown in a div after showing it in another div when one clicks a button. After clicking the button once, the number is shown correctly, but the button can not be clicked twice.
var index = 1;
var chartData = [103, 144, 142, 141]
function update_num(index, l){
console.log(l[index - 1])
document.getElementById('box1').innerHTML = l[index - 1] + ' MU';
setTimeout(function(){
document.getElementById('box1').innerHTML = ' ';
}, 1000);
setTimeout(function(){
document.getElementById('canvas').innerHTML = document.getElementById('canvas').innerHTML + ' ' + l[index - 1];
}, 1000);
}
function func_num() {
var index = 1;
/*Define what should happen after the button is clicked*/
document.getElementById("b").onclick = function(){
var buttonB = document.getElementById('b');
buttonB.disabled = true;
if(index <= 2 ){
update_num(index, chartData);
if(index == 1){
buttonB.innerHTML = 'Next Draw';
buttonB.style.left ='405px';
}
index++;
setTimeout(function(){
buttonB.disabled = false;
console.log('aaa ' + buttonB.disabled);
}, 1000);
} else if (index == 3){
while (index < chartData.length){
setTimeout(function(){update_num(index, chartData);}, 2000 * (index - manualClicks));
index ++;
}
setTimeout(function(){buttonB.disabled = false;}, 1000);
buttonB.innerHTML = 'To Task';
}else{
buttonB.style.visibility="hidden";
}
console.log('run6661' + buttonB.disabled);
if(index == 3 ){
setTimeout(function(){buttonB.innerHTML = 'Automatically Draw for {{ machine_cl }} times';}, forceToLookTime);
}
};
}
func_num();
<div id='canvas' style='position:relative;width:1305px;height:420px; margin: auto; margin-top: 20px;'>
<div>
<button id='b' type='button' style='visibility: visible; position: relative; left: 440px; top: 350px;'>Start</button>
<div id='box1' style='visibility: visible; position: relative; top: 300px; left: 40px; text-align: center;' >
</div>
From SPEC:
2.4.2. Boolean attributes
A number of attributes are boolean attributes. The presence of a
boolean attribute on an element represents the true value, and the
absence of the attribute represents the false value.
Also:
The values "true" and "false" are not allowed on boolean attributes.
To represent a false value, the attribute has to be omitted
altogether.
That said, you MUST remove explicitly the attribute, like this:
document.getElementById('my_button').removeAttribute("disabled");
Your Javascript code is totally fine, the problem is in the markup. You're opening the <div> tag, but not closing it properly, like </div>.
Change
<div id='canvas' style='position:relative;width:1305px;height:420px; margin:auto; margin-top: 20px;'>
<div>
to
<div id='canvas' style='position:relative;width:1305px;height:420px; margin:auto; margin-top: 20px;'>
</div>
How does citicards.com implement the login ID text box with special mask?
When you type "johndoe" and focus out the textbox becomes "jo***oe"
Is there a HTML5 mask with pattern?
Here is a sample implementation of the desired behaviour using pure javascript. This is just for a sample. You may need to do length check etc before actually using substr
document.querySelector("input#accountName").addEventListener("blur", function() {
var value = this.value;
document.querySelector("#maskedAccountName").textContent=this.value.substr(0,2)+this.value.substr(2,value.length-2).replace(/./g,"*")+this.value.substr(this.value.length-2, this.value.length);
this.style.display = "none";
document.querySelector("#maskedAccountName").style.display = "block";
}, false);
document.querySelector("#maskedAccountName").addEventListener("click", function() {
this.style.display = "none";
document.querySelector("input#accountName").style.display = "block";
document.querySelector("input#accountName").focus();
}, false);
div#maskedAccountName {
border: 1px solid rgba(231, 231, 231, 0.67);
padding: 2px;
display: none;
border-top-style: inset;
-webkit-appearance: textfield;
background-color: white;
width: 120px;
}
<input type="text" id="accountName">
<div id="maskedAccountName">
</div>
The reason why I'm not changing the existing input value is I may not be able to read the original value when accessed inside the form submit. So i've created a hidden div which is shown in place of the original input element. You can style the div to be same as the input element using CSS.
You have to use JS/jQuery. First count how mush letters from start and end you wish to take off, then replace everything else with * and append to fake input field.
You can see that in action here (replace opacity to 0 to completely hide input field, display: none will not work here, because you have to click on input itself):
$(document).ready(function() {
$("#hField").focusin(
function() {
$('#hFieldSp').text($(this).val());
});
$("#hField").focusout(function() {
var start = '';
var end = '';
var value = $(this).val();
var stars = '';
if (value.length < 3) {
return;
}
if (value.length > 6) {
start = value.substring(0, 2);
end = value.substring(value.length - 2);
stars = '*'.repeat(Math.max(1, value.length - 4));
} else {
start = value.substring(0, 1);
end = value.substring(value.length - 1);
stars = '*'.repeat(Math.max(1, value.length - 2));
}
$('#hFieldSp').text(start + stars + end);
});
$(document).on('input paste change', '#hField', function() {
$('#hFieldSp').text($(this).val());
});
});
String.prototype.repeat = function(num) {
return new Array(num + 1).join(this);
}
.wrapper {
float: left;
position: relative;
}
#hField,
#hFieldSp {
width: 100px;
height: 30px;
line-height: 30px;
border: 1px solid #ddd;
}
#hField {
opacity: .2;
position: absolute;
left: 0;
top: 0;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="wrapper">
<div id="hFieldSp"></div>
<input type="text" id="hField" />
</div>
I would use a dummy input for the display. Then on blur, transfer the value to a hidden input and alter the text in the dummy. You might also want the reverse in place in case the user wants to alter the value: on focus, copy the value from the hidden input to the dummy. Here's a sample, no jQuery required, and if there are less than 5 characters in the input, it will make all *s instead.
var start = 0;
var end = 4;
var dummy_user = document.getElementById("user");
var actual_user = document.getElementById("hidden_user");
dummy_user.addEventListener("blur", function() {
actual_user.value = dummy_user.value;
if (dummy_user.value.length > 4) {
start = 2;
end = dummy_user.value.length - 2;
}
var val = "";
for (var i = 0; i < start; i++) {
val += dummy_user.value[i];
}
for (i = start; i < end; i++) {
val += "*";
}
for (i = end; i < dummy_user.value.length; i++) {
val += dummy_user.value[i];
}
dummy_user.value = val;
});
dummy_user.addEventListener("focus", function() {
this.value = actual_user.value;
});
<form action="">
<input type="text" name="user" id="user">
<input type="hidden" name="hidden_user" id="hidden_user" value="">
<input type="password" name="password">
<input type="submit" value="Sign in">
</form>