I am new to programming and I am working with a table on otree were 256 different buttons are displayed using Javascript. Each button unveils an icon which is recalled by a simple function.
In this function, I have installed a simple click counter that increases by one each time a button is clicked. The simple click counter works fine (that is not my issue) :)
The table:
for(var r = 0; r < rows;r++)
{
table += '<tr>';
for(var c= 0; c< cols;c++)
{
var random = Math.floor(Math.random() * nums.length);
table += '<td style="width:50px">' + '<button id="' + nums[random] + '" type="button" onclick="displayImage(this.id)">' + "show me" + '</button>' + '</td>';
nums.splice(random, 1);
}
table += '</tr>';
}
The function:
function displayImage(num){
document.canvas2.src = '{% static "bottone/'+ imagesArray[num]+ '.png" %}';
document.getElementById("YourImage2").style.visibility = "visible";
onClick();
}
The counter:
var clicks = 0;
function onClick() {
clicks += 1;
document.getElementById("clicks").innerHTML = clicks;
};
All good till here, there is a hidden HTML field and I manage to save the value of the counter when the user clicks the "next" button...
My problem is the following: this counter counts the amount of buttons clicked, however, I would like it to count only the number of times a button is clicked for the first time (could range from 0 to 256) while still enabling people to click the same button more times.
I´m sure it can be really simple but have no idea where to start...
You can track for each button whether it was clicked before, and if so not count the click.
Your onClick function would look like this (note you should pass it the id of the clicked button):
var clicks = 0;
function onClick(id) {
var clickedEl = document.getElementById(id);
if (clickedEl.dataset.wasClicked) {
return;
}
clickedEl.dataset.wasClicked = true;
clicks += 1;
document.getElementById("clicks").innerHTML = clicks;
}
Here is a simple JSFiddle example:
HTML:
<button onclick="buttonClicked(event)">
New 1
</button>
<button onclick="buttonClicked(event)">
New 2
</button>
<button onclick="buttonClicked(event)">
New 3
</button>
<div id="counter">0
</div>
JS:
var clickedList = [];
var counter = 0;
function buttonClicked(event){
if (clickedList.indexOf(event.currentTarget) === -1){
clickedList.push(event.currentTarget);
counter++;
document.getElementById("counter").innerHTML = counter;
console.log(counter);
}
}
Related
I'm new in javascript. i have a JS function that add and remove input fields. its working fine with my JS function. But I want when delete a field its Id looks like:
I have
no. 1
no. 2
no. 3
After Delete 2:
no. 1
no. 2
already i got this answer:
Reset JavaScript Counter after Deleting a field
But i want it with plain javascript. Can anyone help?
<script>
var count = 1;
function add_new(){
count++;
var div1 = document.createElement('div');
div1.id = count;
var delLink = '<button type="button" onclick="deleteLink('+count+')" class="btn btn-primary">Delete</button>';
div1.innerHTML = document.getElementById('add_link1').innerHTML+delLink;
document.getElementById('add_link').appendChild(div1);
document.getElementById("input_link1").id = count;
document.getElementById("input_link2").id = count;
document.getElementById("input_link3").id = count;
}
function deleteLink(eleId){
var ele = document.getElementById(eleId);
var par = document.getElementById('add_link');
par.removeChild(ele);
}
</script>
After deleting an element call the following function to reset Id of existing elements and also reduce the count.
function reset_counter(deletedCount) {
for (var impactedElementId = deletedCount + 1; impactedElementId < count; impactedElementId++) {
var currentElement = document.getElementById(impactedElementId);
currentElement.id = impactedElementId - 1;
var button = currentElement.firstChild;
button.innerHTML = 'Delete ' + currentElement.id;
button.setAttribute('onclick', 'deleteLink(' + currentElement.id + ')');
}
count--;
}
The full code is available here: AddDeleteElements Sample Code
HTML and JS....I need the array values to be displayed one by one on each click of the "create new button" button. Right now when I click it displays each button in the array???
<div class="container">
<button onClick="myPar()">Directions</button>
<button onClick="make()">Create New Button</button>
</div>
<script>
function myPar() {
var pgp = document.createElement("p");
var txt = document.createTextNode('Click on the "Create New Button" to reveal up to 10 links!!!');
pgp.appendChild(txt);
document.body.appendChild(pgp);
}
function make(){
sit = new Array("kilroerock.com","ultimateguitar.com","premierguitar.com","jhspedals.com","sweetwater.com","guitarcenter.com","musiciansfriend.com","patriots.com","bostonceltics.com")
for (i=0;i<=sit.length-1;i++){
var btn = document.createElement("input");
btn.setAttribute("value",sit[i]);
btn.setAttribute("type","button");
btn.setAttribute("style","background:#1B0D0D;color:white");
btn.setAttribute("onClick","document.location='http://www." + sit[i] + "'")
document.body.appendChild(btn);
}
}
</script>
Are you expecting something like this
Here s working example
https://plnkr.co/edit/juTx9sEZ4PhAoDrb2uHM?p=preview
function buttonClick(){
var length = sit.length;
if(i<length){
var btn = document.createElement("input");
btn.setAttribute("value",sit[i]);
btn.setAttribute("type","button");
btn.setAttribute("style","background:#1B0D0D;color:white");
btn.setAttribute("onClick","document.location='http://www." + sit[i] + "'")
document.body.appendChild(btn);
i++;}
}
You are iterating the whole array on every click. Instead of the for loop just hold a currentIndex variable outside of the function, then on each click get the sit[currentIndex], use it per your need and afterwards raise the currentIndex by 1.
var currentIndex = 0;
sit = new Array("kilroerock.com","ultimateguitar.com","premierguitar.com","jhspedals.com","sweetwater.com","guitarcenter.com","musiciansfriend.com","patriots.com","bostonceltics.com")
function make(){
if ( currentIndex < sit.length )
{
var btn = document.createElement("input");
btn.setAttribute("value",sit[currentIndex]);
btn.setAttribute("type","button");
btn.setAttribute("style","background:#1B0D0D;color:white");
btn.setAttribute("onClick","document.location='http://www." + sit[currentIndex] + "'")
document.body.appendChild(btn);
currentIndex++;
}
}
Here is a working example.
Simplest route based on your existing code is to implement a "counter".
// Initialize the counter outside of all functions, set to zero
var buttonIndex = 0;
function myPar() {
var pgp = document.createElement("p");
var txt = document.createTextNode('Click on the "Create New Button" to reveal up to 10 links!!!');
pgp.appendChild(txt);
document.body.appendChild(pgp);
}
function make() {
sit = new Array("kilroerock.com", "ultimateguitar.com", "premierguitar.com", "jhspedals.com", "sweetwater.com", "guitarcenter.com", "musiciansfriend.com", "patriots.com", "bostonceltics.com")
// Only add the button if within the array length
if (buttonIndex < sit.length) {
var btn = document.createElement("input");
// Modify this line to use buttonIndex, not i
btn.setAttribute("value", sit[buttonIndex]);
btn.setAttribute("type", "button");
btn.setAttribute("style", "background:#1B0D0D;color:white");
// Modify this line to use buttonIndex, not i
btn.setAttribute("onClick", "document.location='http://www." + sit[buttonIndex] + "'")
document.body.appendChild(btn);
// Increment the buttonIndex
buttonIndex++;
}
}
<div class="container">
<button onClick="myPar()">Directions</button>
<button onClick="make()">Create New Button</button>
</div>
I have the following code:
while ($row = $result->fetch_assoc()) {
echo "<div class='competitor' style='background: ".$row['Colour'].";'>";
echo "<div class='competitorname'>".$row['CompetitorName']."</div><br>";
echo "<div class='competitorscore' id='".$row['CompetitorID']."'>";
echo"<label id='".$row['CompetitorName']."'></label></div>";
echo "<input type='button' value='Increase' id='inc' onclick='incNumber()'/>";
echo "<input type='button' value='Decrease' id='dec' onclick='decNumber()'/>";
}
The code is linked to the following script:
var i = 0;
function incNumber() {
if (i < 10) {
i++;
} else if (i = 10) {
i = 0;
}
document.getElementById('display').innerHTML = i;
}
function decNumber() {
if (i > 0) {
--i;
} else if (i = 0) {
i = 10;
}
document.getElementById('display').innerHTML = i;
}
The code creates a scoreboard. It creates a div for each team with a score for that team.
The problem I'm having is that the "Increase" and "Decrease" buttons are increasing and decreasing the score on only one team (the first one). This is because the script is looking for the label with the id='display' and linking every button to that one.
My question is, how can I create a different ID for each team that works with the script so that each increase/decrease button is linked to a different team?
Use the CompetitorID as a parameter to the increment and decrement functions to tell it which row to affect. Your label:
<label id='display".$row['CompetitorID']."'></label>
Your button onclick event:
onclick='incNumber(".$row['CompetitorID'].")'
Then your JavaScript:
function incNumber(id) {
if (i < 10) {
i++;
} else if (i = 10) {
i = 0;
}
document.getElementById('display' + id).innerHTML = i;
}
Edit
For the issue in the comments, echo a hidden field which stores the value for each team:
<input type='hidden' id='score".$row['CompetitorID']."' value='0'/>
Then remove the global var i = 0; and modify your functions similar to this:
function incNumber(id) {
// Get the score input
var scoreField = document.getElementById('score' + id);
// Get the value
var i = parseInt(scoreField.value);
if (i < 10) {
i++;
} else if (i = 10) {
i = 0;
}
// Set the visual score
document.getElementById('display' + id).innerHTML = i;
// Set the score input to the new score
scoreField.value = i;
}
You have a $row['CompetitorID'] value which is, presumably, unique. Append that to the IDs you are using.
I have an age value which I'm using as a condition to enter an IF statement. The IF statement populates random values in to a field (this is a childs math game). After the fields are populated the user can enter their answers and then check them using a 'Check Answers' button. Once the 'Check Answers' block is run the IF statement gets ran again(!), which causes the math problems to change - new random values are created.
How can I prevent the IF statement from running after the page has already loaded; causing the values to change each time the 'Check Answers' button is clicked?
Here is is the relevant javascript:
$(document).ready(function () {
var getAge = localStorage.getItem('setAge');
var userResponse = new Array();
var answer = new Array();
if (getAge >= 1 && getAge <= 7) {
var operator = new Array('+', '-');
for (var counter = 0; counter <= 2; counter++) {
var index = Math.round(Math.random());
var1 = Math.floor((Math.random() * 5) + 1);
var2 = Math.floor((Math.random() * 10) + 1);
// these add the values to the mathQuestions.aspx
$('#a' + counter).text(var1);
$('#b' + counter).text(operator[index]);
$('#c' + counter).text(var2);
answer[counter] = eval(var1 + operator[index] + var2);
}
// this stores the users answers in userResponse[]
for (var counter = 0; counter <= 2; counter++) {
$('#d' + counter).change(function () {
for (var counter = 0; counter <= 2; counter++) {
userResponse[counter] = $('#d' + counter).val();
// window.alert("userResponse = " + userResponse[counter]);
}
});
}
// Button3 = 'Check Answers'
$('#Button3').click(function () {
for (var counter = 0; counter <= 2; counter++) {
window.alert('userResponse after checking the answers = ' + userResponse[counter]);
if (answer[counter] != userResponse[counter]) {
$('#span' + counter).val(answer[counter]);
}
}
});
});
I'm still learning all of this so I could have others errors that are contributing to my problem. To my knowledge the root problem is caused by the IF statement running again. Also, in case it's relevant I'm using Visual Studio Express 2012 for Web using some ASP controls (table, buttons, input, etc).
My guess is that the issue is not within the code you've posted, but within your HTML; Based on the code you've posted does contain a click-event, but this could never cause the 'randomize'-part to be ran again.
Could it be that your HTML looks like:
<form>
<button>Check answers</button>
</form>
or
<form>
<input type="submit" value="Check answers">
</form>
Having a button or submit inside a form-attribute results in a 'submit-action' when you hit the button. The result is that you first see the alert-message from the click-event. Next the page is reloaded and the whole document.ready() script will be executed again.
A simple solution could be:
$('#Button3').click(function (event) {
event.preventDefault()
/* ... */
}
This stops the form from submitting.
http://api.jquery.com/event.preventdefault/
I am using the setTimeout and clearTimeout functions to highlight words in a textarea element at certain specified intervals. The steps I am following are:
Get text from textarea element.
Split into words.
Output each word into a separate textarea element every 5 seconds.
The code is:
<html>
<head>
<script type="text/javascript">
/* this function does the folloeing:
* 1. takes all the words in the textarea.
* 2. Separates them into words.
* 3. Iterate through the list of words.
* 4. Search and highlight each word for 1 second.
*/
var highlightBtn = document.getElementById("start");
var continueHighlight = false;
var text;
var highlighter;
var words;
function startHighlight(val) {
continueHighlight = val;
console.log("Highlight = " + continueHighlight);
//1. get words within textarea.
var textarea = document.getElementById("inputText");
text = textarea.value;
console.log("text = " + text);
//2. split text into words.
var words = text.split(' ');
console.log("There are " + words.length + " words in the text.");
//highlight();
if(continueHighlight) {
//3. iterate through list of words.
var i = 0;
while(i < words.length) {
highlighter = setTimeout(searchAndHighlight, 5000, words[i]);
//console.log("Word highlighting = " + words[i]);
i = i + 1;
}
} else {
console.log("Stopping highlighting.");
clearTimeout(highlighter);
}
}
function highlight() {
if(continueHighlight) {
//3. iterate through list of words.
var i = 0;
while(i < words.length) {
highlighter = setTimeout(searchAndHighlight, 5000, words[i]);
//console.log("Word highlighting = " + words[i]);
i = i + 1;
}
} else {
console.log("Stopping highlighting.");
clearTimeout(highlighter);
}
}
function searchAndHighlight(word) {
console.log("Highlighting word = " + word);
var output = document.getElementById("output");
output.value = word;
}
</script>
</head>
<body>
<textarea id="inputText"></textarea>
<br/>
<button id="start" onclick="startHighlight('true')">Start!</button>
<br/>
<button id="stop" onclick="startHighlight('false')">Stop!</button>
<br/>
<textarea id="output"></textarea>
</body>
</html>
I expected every word to be displayed in the second textarea every 5 seconds. This is not happening. Instead, I get nothing for 5 seconds and then all words in quick succession. This happens even if I press the stop button. My questions:
Where am I going wrong in using the setTimeout function?
This piece of code:
var i = 0;
while(i < words.length) {
highlighter = setTimeout(searchAndHighlight, 5000, words[i]);
//console.log("Word highlighting = " + words[i]);
i = i + 1;
}
is rapidly calling setTimeout() a bunch of times in a row and setting them all for the same time. That will match your symptoms of waiting 5 seconds and then running them all at once.
You will either have to set each successive timeout for a longer period of time or change the structure of the code to not start the next timer until the first one fires.
Here's how you could solve it by only setting one setTimeout() at a time. This would also solve the stop button problem:
function highlight() {
if(continueHighlight) {
var i = 0;
function next() {
if (i < words.length) {
highlighter = setTimeout(function() {
searchAndHighlight(words[i]);
i++;
next();
}, 5000);
}
}
next();
} else {
console.log("Stopping highlighting.");
clearTimeout(highlighter);
}
}
When you want to stop the progressive highlighting, I don't understand why you're taking such a circuitous route. You should just call the clearTimeout(highlighter). There's no need to go through multiple functions like you're doing just to do that.
Or, the solution that sets successively longer timers could work like this:
var i = 0;
while(i < words.length) {
highlighter = setTimeout(searchAndHighlight, 5000 * (i+1), words[i]);
//console.log("Word highlighting = " + words[i]);
i = i + 1;
}
If you want to use this type of solution, then to fix the stop button problem, you will have to keep all the timer ids in an array and cancel all of them. Personally, I'd probably restructure the code and only have one setTimeout() in flight at a time and when each one fires you kick off the next one. Then, you only have one setTimeout() going at once so it's simpler to cancel.
Here is a solution that fixes the stop button problem. If you keep track of i, you could also have the highlight function resume where it left off.
<html>
<head>
<script type="text/javascript">
/* this function does the folloeing:
* 1. takes all the words in the textarea.
* 2. Separates them into words.
* 3. Iterate through the list of words.
* 4. Search and highlight each word for 1 second.
*/
var highlightBtn = document.getElementById("start");
var continueHighlight = false;
var text;
var highlighter;
var words;
function startHighlight(val) {
continueHighlight = val;
console.log("Highlight = " + continueHighlight);
//1. get words within textarea.
var textarea = document.getElementById("inputText");
text = textarea.value;
console.log("text = " + text);
//2. split text into words.
var words = text.split(' ');
console.log("There are " + words.length + " words in the text.");
//highlight();
//3. iterate through list of words.
var i = 0;
highlighter = setTimeout( function( ){
searchAndHighlight( words, 0 );
}, 5000);
function searchAndHighlight(words, i ) {
if(i >= words.length){
clearTimeout(highlighter);
}else{
console.log("Highlighting word = " + words[i]);
var output = document.getElementById("output");
output.value = words[i];
i++;
highlighter = setTimeout( function( ){
searchAndHighlight( words, i );
}, 5000);
}
}
}
function stopHighlight(){
console.log("Stopping highlighting.");
clearTimeout(highlighter);
}
</script>
</head>
<body>
<textarea id="inputText"></textarea>
<br/>
<button id="start" onclick="startHighlight()">Start!</button>
<br/>
<button id="stop" onclick="stopHighlight()">Stop!</button>
<br/>
<textarea id="output"></textarea>
</body>
</html>