Chaining button clicks with jQuery - javascript
I'm trying to build a simple website that let's you click 6 different buttons. Each click of the button is supposed to trigger the display of specific content (as an img file). Clicking each of the six buttons should lead to different content. I have managed to achieve this part via Javascript getElementById.
However, to add a bit more complexity, I want to implement sequential decision making. Meaning that clicking Button "1" and THEN clicking Button "2" (or 3-6 for that matter) should each lead to the display of other specific content. Likewise clicking Button "1", then "2" and then "1" again should also display specific content. My sequential decision making is supposed to be limited to only two buttons interacting until the end of the decision is reached. So essentially, something like 1 -> 2 -> 3 can not happen, but 3 -> 6 -> 3 can happen. I hope it's not too complicated what I'm trying to do.
Anyway, here's some code I wrote trying to achieve this, but I'm fairly sure that my toggle function is not the correct way to go about it as I'm essentially simply placing pictures above each other and there is no sequency to any of the decisions made. I think to achieve this, I would need to chain the clicks, but I'm completely lost as to how to achieve that. Any help is greatly appreciated.
a:link {
color: white;
text-decoration: none;
}
a:visited {
color: white;
text-decoration: none;
}
a:hover {
color: white;
text-decoration: none;
}
a:active {
color: white;
text-decoration: none;
}
a.pos:link {
color: black;
text-decoration: none;
}
a.pos:visited {
color: black;
text-decoration: none;
}
a.pos:hover {
color: white;
text-decoration: none;
}
a.pos:active {
color: black;
text-decoration: none;
}
a.button:link, a.button:visited {
margin: auto;
position: absolute;
top: 0px;
left: 0px;
background-color: yellowgreen;
width: 345px;
line-height: 20px;
height: 185px;
border: 2px solid;
border-color: white;
text-align: center;
border-radius: 100px;
font-family: open sans;
font-size: 9px;
color: black;
font-weight: 650;
color: white;
padding: 14px 25px;
text-align: center;
text-decoration: none;
display: inline-block;
}
a.button:hover, a.button:active {
background-color: yellowgreen;
}
body {margin:0;}
ul {
list-style-type: none;
margin: 0;
padding: 0;
overflow: hidden;
background-color: #333;
position: fixed;
top: 0;
width: 100%;
}
li {
float: left;
}
li a {
display: block;
color: white;
text-align: center;
padding: 20px 30px;
font-family: open sans;
text-decoration: none;
}
li a:hover:not(.active) {
background-color: #111;
}
.active {
background-color: #4CAF50;
}
h1 {
color: whitesmoke;
font-family: open sans;
font-size: 300%;
}
.table {
margin: auto;
position: relative;
width: 450px;
top: -1350px;
border: 6px solid #333333;
border-radius: 250px;
background: #737373;
padding-top: 150px;
padding-right: 50px;
padding-left: 50px;
padding-bottom: 150px;
}
#quattro {
margin: auto;
position: absolute;
bottom: -25px;
right: 250px;
background-color: gold;
width: 50px;
line-height: 50px;
height: 50px;
border: 1px solid black;
text-align: center;
border-radius: 50px;
font-family: open sans;
font-size: 20px;
font-weight: 650;
}
#uno {
margin: auto;
position: absolute;
top: -25px;
right: 250px;
background-color: gold;
width: 50px;
line-height: 50px;
height: 50px;
border: 1px solid black;
text-align: center;
border-radius: 50px;
font-family: open sans;
font-size: 20px;
font-weight: 650;
}
#duo {
margin: auto;
position: absolute;
top: 25px;
right: 10px;
background-color: gold;
width: 50px;
line-height: 50px;
height: 50px;
border: 1px solid black;
text-align: center;
border-radius: 50px;
font-family: open sans;
font-size: 20px;
font-weight: 650;
}
#tres {
margin: auto;
position: absolute;
bottom: 25px;
right: 10px;
background-color: gold;
width: 50px;
line-height: 50px;
height: 50px;
border: 1px solid black;
text-align: center;
border-radius: 50px;
font-family: open sans;
font-size: 20px;
font-weight: 650;
}
#cinqo {
margin: auto;
position: absolute;
bottom: 25px;
left: 10px;
background-color: gold;
width: 50px;
line-height: 50px;
height: 50px;
border: 1px solid black;
text-align: center;
border-radius: 50px;
font-family: open sans;
font-size: 20px;
font-weight: 650;
}
#seis {
margin: auto;
position: absolute;
top: 25px;
left: 10px;
background-color: gold;
width: 50px;
line-height: 50px;
height: 50px;
border: 1px solid black;
text-align: center;
border-radius: 50px;
font-family: open sans;
font-size: 20px;
font-weight: 650;
}
.imgrange1 {
text-align: center;
color: white;
position: absolute;
top: 400px;
left: -400px;
}
.imgrange2 {
text-align: center;
color: white;
position: absolute;
top: 400px;
left: 320px;
}
.centered {
font-family: open sans;
font-size: 150%;
position: absolute;
top: -3%;
left: 50%;
transform: translate(-50%, -50%);
}
<!DOCTYPE html>
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<link rel="stylesheet" href="css/style.css">
<style>
.myimgdivtoggle1 {
display: none;
}
.myimgdivtoggle2 {
display: none;
}
.myimgdivtoggle3 {
display: none;
}
.myimgdivtoggle4 {
display: none;
}
.myimgdivtoggle5 {
display: none;
}
</style>
<script>
$(document).ready(function(){
$('.togglebtn1').click(function(){
$('.myimgdivtoggle1').toggle();
});
});
$(document).ready(function(){
$('.togglebtn2').click(function(){
$('.myimgdivtoggle2').toggle();
});
});
$(document).ready(function(){
$('.togglebtn3').click(function(){
$('.myimgdivtoggle3').toggle();
});
});
$(document).ready(function(){
$('.togglebtn4').click(function(){
$('.myimgdivtoggle4').toggle();
});
});
$(document).ready(function(){
$('.togglebtn5').click(function(){
$('.myimgdivtoggle5').toggle();
});
});
$(document).ready(function(){
$('.togglebtn6').click(function(){
$('.myimgdivtoggle6').toggle();
});
});
</script>
</head>
<body>
<ul>
<li><a class="active" href="index.html">Main</a></li>
<li>News</li>
<li>Contact</li>
<li>About</li>
</ul>
<div style="padding:20px;margin-top:30px;background-color:cadetblue;height:1500px;">
<h1><center>TEST</center></h1>
</div>
<div class="table">
<button type="button" class="togglebtn1" id="uno">1</button>
<div class="myimgdivtoggle1">
<img src="1.JPG" class="imgrange1"/>
</div>
<button type="button" class="togglebtn2" id="duo">2</button>
<div class="myimgdivtoggle2">
<img src="2.JPG" class="imgrange1"/>
</div>
<button type="button" class="togglebtn3" id="tres">3</button>
<div class="myimgdivtoggle3">
<img src="3.JPG" class="imgrange1"/>
</div>
<button type="button" class="togglebtn4" id="quattro">4</button>
<div class="myimgdivtoggle4">
<img src="4.JPG" class="imgrange1"/>
</div>
<button type="button" class="togglebtn5" id="cinqo">5</button>
<div class="myimgdivtoggle5">
<img src="5.JPG" class="imgrange1"/>
</div>
<button type="button" class="togglebtn6" id="seis">6</button>
<div class="myimgdivtoggle6">
<img src="6.JPG" class="imgrange1"/>
</div>
</body>
</html>
Though I can not provide you with a firm solution, I can however offer a small example which illustrates how to incorporate an array which tracks the buttons that have been clicked, as well as a way to get certain content from combinations of buttons.
Run the example and try the combinations 363, 254, 521 and 165 to get some results showing up. I've tried my best to show what the produced output is.
I'd suggest that you take a look at it and ask any questions if you have them. I'll check in to see if you do.
$(document).ready(function() {
/**
* Select the buttons.
* The $display and $clickedButtons are just to output
* the values that are stored.
*/
const $buttons = $('.button');
const $display = $('#display');
const $clickedButtons = $('#clicked-buttons');
const $removeButton = $('#remove-button');
/**
* Array which tracks your clicked buttons.
* If a button is clicked, the value of that button should be added to this array.
* The combination of the values will then later represent the key.
*/
const values = [];
/**
* This is where any know combinations are stored.
* The values in the values array will later be transformed into a single string to
* see if it matches any key in the combinations object below.
* If it does, it will give you a value, otherwise undefined.
*/
const combinations = {
"363": "https://www.fillmurray.com/200/200",
"254": "https://www.fillmurray.com/220/220",
"521": "https://www.fillmurray.com/240/240",
"165": "https://www.fillmurray.com/300/300"
};
/**
* Combines the values to form a single key and check if that key matches a combination.
* If there is a match the content should be anything other than undefined.
*/
function tryCombination() {
// This will output the current values from the array.
$clickedButtons.text(values);
// Transform the array into a single string.
// This will be the key to select content.
// ["1", "2", "3"] becomes "123".
const key = values.join('');
// Check if key has a match in the combinations object.
const url = combinations[key];
if (url !== undefined) {
// It does, show the content.
$display.attr('src', url);
$display.removeClass('hidden');
} else {
// It doesn't, empty the content.
$display.removeAttr('src');
$display.addClass('hidden');
}
}
/**
* Listen for the click event on all the buttons.
* When clicked, get the value of that clicked button and add that to the values array.
* It then calls the tryCombination function to evaluate if the values in the values
* array make a valid combination.
*/
$buttons.on('click', function() {
// This is the currently clicked button.
const $button = $(this);
// Get the value of the button.
const value = $button.val();
// If there already are 3 previously clicked buttons,
// then empty the array, so we can start a new combination.
if (values.length === 3) {
values.length = 0;
}
// Now add the newly clicked value.
values.push(value);
// Render and try the combination.
tryCombination();
});
/**
* Remove the last item in the values array.
* Then retry to create a valid combination.
*/
$removeButton.on('click', function() {
// Remove the last item from the values array
values.pop();
// Render and try the new combination.
tryCombination();
})
});
.container {
display: grid;
grid-template-rows: auto auto;
grid-template-columns: 200px 1fr;
grid-gap: 1em;
border: 1px solid #d0d0d0;
background-color: #f7f7f7;
padding: 1em;
border-radius: 5px;
}
.buttons {
grid-area: 1 / 1 / 2 / 3;
}
#display {
grid-area: 2 / 1 / 3 / 2;
width: 200px;
height: 200px;
background-color: #d0d0d0;
border-radius: 5px;
}
#clicked-buttons {
grid-area: 2 / 2 / 3 / 3;
display: block;
background-color: #d0d0d0;
border-radius: 5px;
padding: 1em;
margin: 0;
}
#remove-button {
grid-area: 1 / 2 / 2 / 3;
}
.hidden {
opacity: 0;
visibility: hidden;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="container">
<div class="buttons">
<button class="button" id="1" value="1" >1</button>
<button class="button" id="2" value="2" >2</button>
<button class="button" id="3" value="3" >3</button>
<button class="button" id="4" value="4" >4</button>
<button class="button" id="5" value="5" >5</button>
<button class="button" id="6" value="6" >6</button>
</div>
<img id="display" class="hidden">
<button id="remove-button">Remove last input</button>
<code id="clicked-buttons"></code>
</div>
Edit
In the spirit of showing is better than telling; your last comment was about having a loose combination of numbers. This adds another layer of complexity.
Objects can only have keys that are strings (or Symbols) to get and set values. But in your case you'll want an array of numbers which represent the keys in any order, so plain objects are not suitable anymore.
The solution for this is the Map object. This object can have any type of key and value. So we can make a link between a combination of numbers and the images they represent (hence the name "map").
The example below uses this method. I've written a function that checks if an array of numbers is a match with any combination in the map. And if it does it return an array of images, referring to your previous comment.
Check it out. I believe this one to be more complex, so once more feel free to ask questions.
/**
* Create a Map instance.
*/
const combinations = new Map();
/**
* Values and keys are added with the set() method.
* This could still be improved with a loop setting each
* combination / images pair.
*/
combinations.set([3, 3, 6], ['https://www.fillmurray.com/200/200', 'https://www.fillmurray.com/200/200']);
combinations.set([2, 4, 5], ['https://www.fillmurray.com/220/220', 'https://www.fillmurray.com/220/220']);
combinations.set([1, 2, 5], ['https://www.fillmurray.com/240/240']);
combinations.set([1, 5, 6], ['https://www.fillmurray.com/300/300', 'https://www.fillmurray.com/300/300', 'https://www.fillmurray.com/300/300']);
const tryCombination = (key, combinations) => {
/**
* Loop over every combination.
* [combination, images] exposes the key-value pair,
* it's just a syntax to write fewer lines
*/
for (const [combination, images] of combinations) {
/**
* Create an array for the matches. If a number of the
* combination is in the given key, then that number
* will be pushed to the matches list. In the end,
* if everything matches, we should have just as many
* matches as numbers in the combination. That way
* we know if a key is correct.
*/
const matches = [];
/**
* We'll do some manipulation on the combination array,
* so to keep it intact we make a copy and manipulate that instead.
*/
const combinationCopy = Array.from(combination);
/**
* Count backwards through the combination array.
* Backwards counting is necessary when you remove items
* from the array while looping. I'd suggest you look
* into that subject.
*/
for (let i = combinationCopy.length - 1; i >= 0; i--) {
/**
* Get the current number we're looping over.
*/
const number = combinationCopy[i];
/**
* If that number is in the key array..
*/
if (key.includes(number)) {
/**
* ..then push that number to the matches array..
*/
matches.push(number);
/**
* ..and remove it from the copied combination array.
* We do this to prevent duplicate hits for cases
* where you have multiple occurrences of the same number,
* like [3, 3, 6]. When the first 3 hits, it will be removed.
* Then we have [3, 6] and we know we only need one more
* 3 and a 6.
*/
combinationCopy.splice(i, 1);
}
}
/**
* Now if every number has been matched correctly, then
* the amount of matches should be the same as the length
* of the combination. If that is the case, return the
* images. Otherwise, do nothing.
*/
if (matches.length === combination.length) {
return images;
}
}
/**
* If there are no matches, just return false, notifying the
* user that the combination is incorrect.
*/
return false;
};
console.log(tryCombination([5, 4, 2], combinations)); // Hit!
console.log(tryCombination([5, 1, 6], combinations)); // Hit!
console.log(tryCombination([2], combinations)); // Fail!
console.log(tryCombination([5, 4, 4], combinations)); // Fail!
console.log(tryCombination([3, 6, 3], combinations)); // Hit!
Related
Is there a way to change the value of any one button in a set of buttons at a time when one of them is clicked?
im looking for a way to change the backgroundColor of only the button which is clicked in a set of 4 buttons in react. Example:- default color is white, if the 2nd button is clicked its background color becomes blue, if the 4th button is clicked its bg color becomes blue but all others become white. I could do it with getElementBy classes/id or queryselector but the thing is it is present in 4 columns so it messes with the same button number in the other rows. If you dont get what I mean, see the image. export default function Quiz() { const [quiz, setQuiz] = React.useState([]); function getQuiz() { fetch("my api key") .then((res) => res.json()) .then((data) => setQuiz(data["results"])); } //the api gives 5 questions with 4 options each React.useEffect(() => { getQuiz(); }, []); const renderQuiz = quiz.map((val) => { // im using decodeURIComponent since its a "url base" or something type array. let question = decodeURIComponent(val["question"]); let correctAnswer = decodeURIComponent(val["correct_answer"]); let wrongOptions = val["incorrect_answers"]; let allOptions = []; wrongOptions.map((elem) => allOptions.push(decodeURIComponent(elem))); allOptions.push(correctAnswer); allOptions = shuffle(allOptions); //suffle is a function in another file which shuffles the contents of an array. function RenderOptions() { return allOptions.map((val) => { return ( <> <button className="opt-btn">{val}</button> {" "} </> ); }); } return ( <div className="container"> <div className="question">{question}</div> <div className="options"> <RenderOptions /> </div> <hr className="dash" /> </div> ); }); return <div className="quiz">{renderQuiz}</div>; } CSS #import url("https://fonts.googleapis.com/css2?family=Karla&display=swap"); #import url("https://fonts.googleapis.com/css2?family=Inter&display=swap"); body { background-color: #f5f7fb; height: 100%; overflow: hidden; } .quiz { display: block; margin: auto; text-align: center; margin-top: 30px; width: 800px; } .question { font-family: "Karla"; font-style: normal; font-weight: bold; font-size: 16px; line-height: 19px; color: #293264; padding-top: 10px; padding-bottom: 15px; text-align: justify; } .options{ text-align: left; max-width: 700px; } .opt-btn { border: 0.794239px solid #4d5b9e; width: -moz-fit-content; width: fit-content; box-sizing: border-box; border-radius: 7.94239px; padding-left: 15px; padding-right: 15px; padding-top: 5px; padding-bottom: 5px; background: #f5f7fb; font-family: Inter; font-style: normal; font-weight: 600; font-size: 11px; line-height: 12px; text-align: justify; color: #293264; } .dash { width: 630px; height: 0px; border: 0.794239px solid #dbdef0; transform: rotate(-0.05deg); margin-left: 0; } Will give more info if needed.
Changing a span field to an input field for updating information
I am creating a way to edit dynamic content. I found a question on here that got me started in terms of changing text (spans in my case) into input fields. Currently, I can't figure out the following issue. When you click "Edit" (on the right side) the input fields replace the span (this is what I want), but when when you click outside of the input the input fields add new span fields instead of replacing the input fields. I am wanting the styling and the fields to constantly stay in their original place. Does anyone see what I am doing wrong? var projID = ''; //Obtaining ID and Editing the projects $(document.body).on('click', '.recEdit', '[data-editable]', function() { projID = $(this).parent().data('recid'); console.log('Project ID is..... ' + projID); var $el = $(this).parent().children().find('span'); var $input = $('<input/>').val( $el.text() ); $el.replaceWith( $input ); var save = function(){ var $p = $('<span data-editable class="recBaseFormat" />').text( $input.val() ); $input.replaceWith( $p ); }; /** We're defining the callback with `one`, because we know that the element will be gone just after that, and we don't want any callbacks leftovers take memory. Next time `p` turns into `input` this single callback will be applied again. */ $input.one('blur', save).focus(); }); .recentProjectCont { width: 98%; height: 85px; border-bottom: 1px solid #ccc; padding: 10px 0; margin: 0 10px; display: block; position: relative; } .recentProjectImg { width: 100px; height: 85px; display: inline-block; vertical-align: top; } .recentProjectImg img { width: 100%; height: 100%; object-fit: cover; } .recProjInfoCont { display: inline-block; vertical-align: top; width: 80%; height: 100%; margin-left: 20px; } .recInfoCont1, .recInfoCont2 { height: 100%; display: inline-block; vertical-align: top; } .recInfoCont1 { width: 40%; } .recInfoCont2 { width: 52%; text-align: right; } .recBaseFormat, .projectViews { letter-spacing: .1rem; line-height: 1.4em; color: #2f2f2f; display: block; margin-bottom: 5px; } .recProjName { font-size: 1.1rem; font-family: 'Muli', sans-serif; } .recInfoStat, .projectViews { font-size: .7rem; font-family: 'Nunito', sans-serif; } .recEdit { position: absolute; top: 20%; left: 97%; cursor: pointer; } <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script> <div class="recentProjectCont"> <div class="recProjInfoCont"> <div class="recInfoCont1"> <span class="recProjName recBaseFormat" data-editable>Name</span> <span class="recInfoStat recBaseFormat recAlt" data-editable>Alt</span> <span class="recInfoStat recBaseFormat recCat" data-editable>Category</span> </div> <div class="recInfoCont2"> <span class="recInfoStat recBaseFormat" data-editable>Status</span> <span class="recInfoStat recBaseFormat" data-editable>Creator</span> </div> </div> <div class="recEdit">Edit</div> </div>
This code could definitely be optimized, but it should get you going in the right direction. There were a few issues with your code. The issue I mentioned above, which is that your selector was only targeting the last span element within the parent element. We can solve that by using the each method to loop over every span within the parent. Another issue is that you were losing the classes for your spans when you were replacing them with inputs. I've solved that by saving a list of classes for each span before replacing them with an input so that they can be reapplied when they are converted back to spans. Finally, you were firing the save function for all inputs on blur of any input, meaning that the user would only be able to edit one span and then when they clicked out, all inputs would have been converted back. Instead, now it will only convert back when you unfocus each specific input. var projID = ''; //Obtaining ID and Editing the projects $(document.body).on('click', '.recEdit', '[data-editable]', function() { projID = $(this).parent().data('recid'); console.log('Project ID is..... ' + projID); $(this).parent().children().find('span').each(function() { var classList = $(this).attr('class'); $input = $('<input/>').val($(this).text()); $(this).replaceWith($input); $input.on('blur',function() { $(this).replaceWith('<span data-editable class="' + classList + '">' + $(this).val() + '</span>'); }); }); }); .recentProjectCont { width: 98%; height: 85px; border-bottom: 1px solid #ccc; padding: 10px 0; margin: 0 10px; display: block; position: relative; } .recentProjectImg { width: 100px; height: 85px; display: inline-block; vertical-align: top; } .recentProjectImg img { width: 100%; height: 100%; object-fit: cover; } .recProjInfoCont { display: inline-block; vertical-align: top; width: 80%; height: 100%; margin-left: 20px; } .recInfoCont1, .recInfoCont2 { height: 100%; display: inline-block; vertical-align: top; } .recInfoCont1 { width: 40%; } .recInfoCont2 { width: 52%; text-align: right; } .recBaseFormat, .projectViews { letter-spacing: .1rem; line-height: 1.4em; color: #2f2f2f; display: block; margin-bottom: 5px; } .recProjName { font-size: 1.1rem; font-family: 'Muli', sans-serif; } .recInfoStat, .projectViews { font-size: .7rem; font-family: 'Nunito', sans-serif; } .recEdit { position: absolute; top: 20%; left: 97%; cursor: pointer; } <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script> <div class="recentProjectCont"> <div class="recProjInfoCont"> <div class="recInfoCont1"> <span class="recProjName recBaseFormat" data-editable>Name</span> <span class="recInfoStat recBaseFormat recAlt" data-editable>Alt</span> <span class="recInfoStat recBaseFormat recCat" data-editable>Category</span> </div> <div class="recInfoCont2"> <span class="recInfoStat recBaseFormat" data-editable>Status</span> <span class="recInfoStat recBaseFormat" data-editable>Creator</span> </div> </div> <div class="recEdit">Edit</div> </div> Finally, as others have mentioned, another option would be to use the contenteditable attribute on your spans. This is an HTML solution for editing HTML elements that are not editable by default. It essentially does the same thing you're trying to do with Javascript, but it's much cleaner. It also has very good browser support. One drawback to this solution would be that it will not be immediately clear to the user that the element is editable like it would be with an actual button that says "Edit." But there are some solutions for that as well. <span contenteditable="true">You can edit me</span>
You could use juste the contenteditable attribute toggle each click !
Random sort array
I am trying to shuffle the original deck of cards, then subtract 2 cards from the shuffled deck, being player one's cards. Then before I move to player 2, I would like to shuffle the cards again, whose length should be at 50(52-2). The second player I will repeat the process(50-2). Notice the order of the third console log array before uncommenting the fourth console log and freshDeck__01 in the JavaScript. The order is good before uncommenting. I want that order, and then to shuffle. let playerone = document.querySelector(".dealItP1"); let playertwo = document.querySelector(".dealItP2"); let playerthree = document.querySelector(".dealItP3"); let playerfour = document.querySelector(".dealItP4"); let deck = ["2 Club","2 Spade","2 Diamond","2 Heart","3 Club","3 Spade","3 Diamond","3 Heart","4 Club","4 Spade","4 Diamond","4 Heart","5 Club","5 Spade","5 Diamond","5 Heart","6 Club","6 Spade","6 Diamond","6 Heart","7 Club","7 Spade","7 Diamond","7 Heart","8 Club","8 Spade","8 Diamond","8 Heart","9 Club","9 Spade","9 Diamond","9 Heart","10 Club","10 Spade","10 Diamond","10 Heart","Jack Club","Jack Spade","Jack Diamond","Jack Heart","Queen Club","Queen Spade","Queen Diamond","Queen Heart","King Club","King Spade","King Diamond","King Heart","Ace Club","Ace Spade","Ace Diamond","Ace Heart"]; let originaldeck = [...deck]; function dealIt(){ function shuffle(deck) { var currentIndex = deck.length, temporaryValue, randomIndex; while (0 !== currentIndex) { randomIndex = Math.floor(Math.random() * currentIndex); currentIndex -= 1; temporaryValue = deck[currentIndex]; deck[currentIndex] = deck[randomIndex]; deck[randomIndex] = temporaryValue; } return deck; } var arr = deck; let freshDeck_00 = shuffle(arr); //length = 52 *Working* shuffled// let p1Deal = freshDeck_00.filter(function(value, index, arr){return index < 2;}); //length=2 *Working* PlayerOne delt cards// let loadedDeck_00 = freshDeck_00.filter(x => !p1Deal.includes(x)).concat(p1Deal.filter(x => !freshDeck_00.includes(x))); //length = 50 *Working* Symmetrical Difference between p1Deal and freshdeck_00 set to loadedDeck_00 ready to be shuffled again// playerone.innerHTML= p1Deal; // let freshDeck_01 = shuffle(loadedDeck_00);// //*IMPORTANT* WORKING UP TO THIS POINT WITH THE THRE CONSOLE LOGS, BUT WHEN UNCOMMENTING FRESHDECK_01 AND FORTH CONSOLE LOG, NOTICE THE DIFFERENCE IN ORDER OF LOADEDDECK__00(THIRD CONSOLE LOG)// console.log(freshDeck_00); console.log(p1Deal); console.log(loadedDeck_00); //console.log(freshDeck_01);// } .main{ box-sizing: border-box; border: 3px solid green; height: 1000px; width: 1000px; position: absolute; background-color: black; } .title{ box-sizing: border-box; border: 3px green solid; height: 100px; width: 200px; position: absolute; top: 10%; left: 50%; background-color: green; opacity: .2; font-family: coniferous, sans-serif; font-style: normal; font-weight: 300; } .P1{ box-sizing: border-box; border: 3px green solid; height: 100px; width: 100px; position: absolute; top: 30%; left: 45%; background-color: green; opacity: .5; font-family: coniferous, sans-serif; font-style: normal; font-weight: 300; color: red; } .P2{ box-sizing: border-box; border: 3px green solid; height: 100px; width: 100px; position: absolute; top: 45%; left: 10%; background-color: green; opacity: .5; font-family: coniferous, sans-serif; font-style: normal; font-weight: 300; color: red; } .P3{ box-sizing: border-box; border: 3px green solid; height: 100px; width: 100px; position: absolute; top: 60%; left: 45%; background-color: green; opacity: .5; font-family: coniferous, sans-serif; font-style: normal; font-weight: 300; color: red; } .P4{ box-sizing: border-box; border: 3px green solid; height: 100px; width: 100px; position: absolute; top: 45%; left: 80%; background-color: green; opacity: .5; font-family: coniferous, sans-serif; font-style: normal; font-weight: 300; color: red; } <!doctype html> <html> <head> <meta charset="UTF-8"> <title>Untitled Document</title> <link href="pokerTryOne.css" rel="stylesheet" type="text/css"> </head> <body> <div class="main"> <header><h1 class="title"><button onClick="dealIt()">Click Button to Deal</button></h1></header> <div class="P1"><p>Pot:</p><div class="dealItP1"></div></div> <div class="P2"><p>Pot:</p><div class="dealItP2"></div></div> <div class="P3"><p>Pot:</p><div class="dealItP3"></div></div> <div class="P4"><p>Pot:</p><div class="dealItP4"></div></div> <div class="dealBet"></div> <div class="flopIt"></div> <div class="flopBet"></div> <div class="turnIt"></div> <div class="turnBet"></div> <div class="riverIt"></div> <div class="riverBet"></div> </div> <script type="text/javascript" src="pokerTryOne.js"></script> </body> </html>
when I wanted to reassign freshdeck_01 by randomizing it again I receive the same array as before. No you do not receive an array that is ordered the same way as before. The issue here is that Array.prototype.sort() sorts the array in-place. This means that you are shuffling your original array freshdeck_01 and then assigning a reference to that very same (now shuffled) array to another variable freshdeck_01_fresh. If you actually inspect your array before running your shuffling function, you will see that the order gets changed: let deck = [1,2,3,4,5,6,7,8] console.log(deck); deck.sort(function(a, b){return 0.5 - Math.random()}); console.log(deck); If you need to keep a copy of your unshuffled array, you can use a decomposing assignment [...x] to do that. Simple assignment would not work, as it would only create a reference to the same array. let deck = [1,2,3,4,5,6,7,8] let copyOfOrigDeck = [...deck]; let notASeparateCopy = deck; console.log(deck); deck.sort(function(a, b){return 0.5 - Math.random()}); console.log('unshuffled: ' + copyOfOrigDeck); console.log('shuffled: ' + deck); console.log('notASeparateCopy: ' + notASeparateCopy); All that being said, there are probably better ways to shuffle array elements than your approach. I am no expert in that field, so I will leave that research up to you.
Sort() isn't the correct function for this, shuffle has been covered extensively check it out here this and many other places on the net.
const numbers = [1,2,3,4,5,6,7,8,9,10] // Returns a random value from a list. const sampleFromList = list => list[Math.floor(Math.random() * list.length)] const shuffle = ( list, // Creates an array with every index of the original list. availableIndexes = [...list].map((n, i) => i), shuffledList = [], ) => { // Asks for a random index from the whitelist of available indexes. const availableIndex = sampleFromList(availableIndexes) // Adds the value of what's in the original list in the random whitelisted index. shuffledList = [...shuffledList, list[availableIndex]] // Filters out the used index, so is not used again. availableIndexes = availableIndexes.filter(n => n !== availableIndex) return ( // If there are available indexes, use a recursive function to continue shuffling. Otherwise return the shuffled list. availableIndexes.length ? shuffle(list, availableIndexes, shuffledList) : shuffledList ) } console.log(shuffle(numbers))
Assign a value to input field
let slider = document.getElementById("slider"); let rightBtn = document.getElementById("rightbutton"); let leftBtn = document.getElementById("leftbutton"); let element = document.getElementById("elementtype").innerHTML; let celciusBoiling = document.getElementById("celciusboiling").value; let chlorine = ["Chlorine", 100, 200]; function moveSliderRight() { if (rightBtn.onclick) { slider.value++; } } function moveSliderLeft() { if (leftBtn.onclick) { slider.value--; } } function main() { moveSliderRight(); moveSliderLeft(); if (slider.value == parseInt(2)) { element = chlorine[0]; celciusBoiling = chlorine[1]; } } main(); * { margin: 0; padding: 0; box-sizing: border-box; background-color: peachpuff; } header { width: 90%; margin: 10px auto 0px; } header h1 { text-align: center; border: 1px solid black; padding: 15px 0px; } .navbar { width: 75%; margin: 50px auto 50px; padding: 10px 0px; display: flex; justify-content: space-around; border: 1px solid black; } .navlinks { border-right: 1px solid black; width: 50%; text-align: center; display: block; } #nav3 { border: none; } #intro { margin: 0px auto 50px; width: 40%; text-align: center; } #slider { -webkit-appearance: none; background-color: grey; width: 90%; display: block; margin: auto; } #slider::-webkit-slider-thumb { cursor: pointer; } #slider::-moz-range-thumb { cursor: pointer; } #valuetag { text-align: center; margin-top:25px; } h2 { text-align: center; font-size: 45px; text-decoration: underline; } #display { width: 90%; margin-left: 50px; margin-bottom: 50px; font-size: 40px; } #display div { display: inline-block; width: 45%; text-align: center; } span { font-size: 15px; } .boiling { margin-left: 6%; } .boilingpointslider { text-align: center; } button { margin: 20px 20px 20px 0px; width: 75px; } <header> <h1>Periodic Table Gases - Interative Slider</h1> <nav> <div class="navbar"> <div class="navlinks">Boiling Point</div> <div class="navlinks" id="nav3">Melting Point</div> </div> </nav> </header> <div id="intro"> <p>Interact with the slider buttons to view the displayed properties held by gases, within the periodic table of elements.</p> </div> <h2 id="elementtype">Hydrogen</h2> <div id="display"> <div class="boiling"> <h2>Boiling Point</h2> <input id="celciusboiling" type="number" value="0"><span>℃</span> <input id="fahrenboiling" type="number"><span>℉</span> <input id="kelvinboiling" type="number"><span>K</span> </div> <div class="melting"> <h2>Melting Point</h2> <input id="celciusmelting" type="number"><span>℃</span> <input id="fahrenmelting" type="number"><span>℉</span> <input id="kelvinmelting" type="number"><span>K</span> </div> </div> <input type="range" min="0" max="9" value="0" id="slider"> <div class="boilingpointslider"> <button id="leftbutton" onclick="moveSliderLeft()">Left</button> <button id="rightbutton" onclick="moveSliderRight()">Right</button> </div> I am having issues transferring a value to an input field. Within the snippet linked their is a heading with the value hydrogen and to the bottom left their is a boiling point heading with a input field for celcius. I'm trying to achieve a scenario whereby you move the slider along using the buttons and at each value the heading changes to a different element and the input value for just the celcius boiling point changes. I can't get this to work though. The buttons are working to make the slider move left and right, but for whatever reason i cant get the value to appear within the input field or change the heading. I've displayed the code i have already to get the buttons to move the slider and a snippet of what i thought would allow the changes i want to take place when the slider value changes to 2. I cant get it to to work though Thanks.
You don't show your HTML, but I presume that slider is an input (text or hidden). The value attribute is a string, even if you assign it a number, so you need to first convert it to a integer if you want to increment or decrement it, like so: slider.value = parseInt(slider.value)++ // or -- Note that also you are trying to parseInt(2) down in your main(), which makes no sense as 2 is already an integer.
how to run javascript function 'live' without refresh?
im trying to make a average grade calculator, now thats is going fine but now i want to calculate the average immediately when a number gets inputted in one of the fields. I've been trying this with "on(), live(), onkeyup()" but can't get it to work. The result of the average now displays beneath the inputfields 'onclick' on the button. I want the average displayed there but then as soon as you input numbers in one of the fields it should show there as it now does after the onclick. What i've tryed with the 'on(), live(), onkeyup()' is to connect them to the input fields and connect them to the calculator() function. Is there a easy way to do this or a other certain way? greetings. function calculator() { var weight = 0; var mark = 0; var weights = document.querySelectorAll('[id^=weight-]'); var grades = document.querySelectorAll('[id^=mark-]'); var trs = document.getElementsByTagName('tr'); var tBody = document.getElementsByTagName('tbody')[0]; var totalWeight = 0; var totalGrade = 0; for (var i = 0; i < weights.length; i++) { totalWeight += +weights[i].value; } for (var i = 0; i < grades.length; i++) { totalGrade += +grades[i].value; } var finalGrade=totalGrade/totalWeight; var display = document.getElementById('output-div'); var newTr = document.createElement('TR'); newTr.innerHTML = `<td><input id="weight-${trs.length + 1}" type="text" size=2 value=""></td><td><input id="mark-${trs.length + 1}" type="text" size=2 value=""></td>`; tBody.appendChild(newTr); display.innerHTML='Je gemiddelde is: ' +finalGrade.toFixed(2); } html { background-color: ; } header { background-color: ; } h2 { text-align: center; } h3 { text-align: center; } body { font-family: 'Roboto', sans-serif; } table { margin: auto; } tr { background-color: ; } td { background-color: ; } #table-title { font-size: 20px; font-style: italic; text-align: center; position: relative; } input { text-align: center; } [id^="mark"] { width: 100px; } [id^="weight"] { width: 100px; } #calc-btn-div { position: relative; width: 150px; margin: auto; } #calc-btn { position: relative; padding: 5px; margin-top: 20px; } #calc-btn:hover { border-color: black; box-shadow: 8px 8px 8px 0 rgba(0,0,0,0.24), 0 17px 50px 0 rgba(0,0,0,0.19); } /* #add-input-div { height: 50px; text-align: center; width: 300px; margin: auto; margin-top: 20px; } #add-input-btn { position: relative; padding: 5px; margin-top: 20px; } #add-input-btn:hover { border-color: black; box-shadow: 8px 8px 8px 0 rgba(0,0,0,0.24), 0 17px 50px 0 rgba(0,0,0,0.19); } */ #output-div { background-color: ; height: 50px; text-align: center; width: 300px; margin: auto; margin-top: 20px; } /* The Modal (background) */ .modal { display: none; /* Hidden by default */ position: fixed; /* Stay in place */ z-index: 1; /* Sit on top */ left: 0; top: 0; width: 100%; /* Full width */ height: 100%; /* Full height */ overflow: auto; /* Enable scroll if needed */ background-color: rgb(0,0,0); /* Fallback color */ background-color: rgba(0,0,0,0.4); /* Black w/ opacity */ } /* Modal Content/Box */ .modal-content { background-color: #fefefe; margin: 15% auto; /* 15% from the top and centered */ padding: 20px; border: 1px solid #888; width: 80%; /* Could be more or less, depending on screen size */ } /* The Close Button */ .close { color: #aaa; float: right; font-size: 28px; font-weight: bold; } .close:hover, .close:focus { color: black; text-decoration: none; cursor: pointer; } <html> <head> <link href="https://fonts.googleapis.com/css?family=Roboto" rel="stylesheet"> </head> <header> <h2>Gemiddelde cijfer</h2> <h3>Voer hieronder je cijfers in</h3> </header> <body> <table id="table"> <tr id="table-title"> <td>Weging</td> <td>Cijfer</td> </tr> <tr> <td><input id="weight-1" type="text" size=2 value=""></td> <td><input id="mark-1" type="text" size=2 value=""></td> </tr> </table> <div id="calc-btn-div"> <input id="calc-btn" type="button" value="Berekenen je gemiddelde" onclick="calculator()"> </div> <!-- <div id="add-input-div"> <input id="add-input-btn" type="button" value="Voeg cijfer toe" onclick="addInput()"> </div> --> <div id="output-div"></div> </body> </html>
Using vanilla JavaScript I would attach an eventListener to the inputfields like this document.getElementById('weight-1').addEventListener('change',function(){ calculator(); }); document.getElementById('mark-1').addEventListener('change',function(){ calculator(); }); These addEventListener functions adds listeners to the "input" field's predefined 'change'-events, and fires the calculator(); function from your code. Seeing that you are using some sort of dynamic generation of the inputfields, you could add the listeners to your inputfields using the same querySelector that you use to target them during calculation. It would mean replacing getElementById('weight-1') in my example above with querySelectorAll('[id^=weight-]') for the weight-fields. Also, doing work with values, IO, and calculation between html and JavaScript, I would suggest using a library like jQuery. jQuery simplifies these processes a lot. This is the documentation for the jQuery alternative onClick function: https://api.jquery.com/change/
I think you could do that with an angularJS module. Take a look at this tutorial : https://www.w3schools.com/angular/angular_modules.asp maybe it will help.