What do I need to add to the following code, so that a different variable is chosen each time and not the same letter occurs after itself.
goal is a situation like this:
after pressing run: change = a
after pressing run second time: change = b
after pressing run third time: change = a
after pressing run for the fourth time: change = c
after pressing run for the fifth time: change = b
...
var ch = ['a', 'b', 'c']
change = document.getElementById("1").innerHTML = ch[Math.floor(Math.random() * ch.length)];
<label id="1"> </label>
You'll need to add a system where you remove the character from the list after it has been selected. This way, when you call the random select function again you won't be able to select the same value twice in a row.
However you do need to save the item you've selected somewhere in a variable so that you're able to add it back to the list once a new character has been chosen.
The snippet below demonstrates this principle. Try it out and follow the annotations to figure out the logic. It even works when you add more options. No chances of the same consecutive results.
const output = document.getElementById('output');
const button = document.getElementById('select');
// Available options.
const options = ['a', 'b', 'c'];
// Previously selected option.
let selectedOption = null;
// Function which selects a random item from
// the options array.
const selectRandomOption = () => {
// Get a random index and select the option.
const index = Math.floor(Math.random() * options.length);
const option = options[index];
// If there is a previous selected option..
if (selectedOption !== null) {
// ..then add it back to the list.
options.push(selectedOption);
}
// Store the newly selected option..
selectedOption = option;
// ..and remove it from the list so it cannot
// be selected again until the next time
// selectRandomOption is called.
options.splice(index, 1);
// Return the selected option.
return option;
};
// Trigger the selectRandomOption when clicking
// on the button and show the result in the output.
button.addEventListener('click', () => {
const option = selectRandomOption();
output.value = option;
});
<output id="output"> </output>
<button id="select">Select random but not the same</button>
If I understand you correctly, what you want is called a "toggle" functionality.
You can achieve that with the following code:
var span = document.getElementById("value");
span.innerHTML = 'on';
function toggle(){
span.innerHTML = (span.innerHTML == 'on' ? 'off' : 'on');
}
<p>
value: <span id="value"></span>
</p>
<button onClick="toggle()"> click me </button>
You should remove the value from index once its been used
rand = Math.floor(Math.random()*ch.length);
change = document.getElementById("1").innerHTML = ch[rand];
ch.splice(rand,1)
I'm reading this as a toggle between a and b. Code below does that.
let displayDiv = document.getElementById("result");
let [a,b] = ['a','b'];
//one-liner swap & display
toggle = () => {
displayDiv.innerText = ([a,b] = [b,a])[0];
}
<button onclick="toggle()">Run</button>
<div id="result">a</div>
To cycle through a list of options, you can use Array.shift() and re-insert the previous content of the output-element back into the array.
let options = ["B", "C", "D", "E"];
document.querySelector("button").addEventListener("click", () => {
let output = document.querySelector("#output");
options.push(output.innerHTML);
output.innerHTML = options.shift();
});
<span id="output">A</span>
<button>New value</button>
To select a random value of a list, randomize the selection using Math.random(), and save the content of the HTML-element back inside the array. Then, remove that array-element and set the HTML-element's content to that value.
let options = ["B", "C", "D", "E"];
let output = document.querySelector("#output");
document.querySelector("button").addEventListener("click", () => {
options.push(output.innerHTML);
let newValue = options[Math.floor(Math.random() * options.length)];
output.innerHTML = newValue;
options.splice(options.indexOf(newValue), 1);
});
<span id="output">A</span>
<button>New value</button>
Related
Still new to JS
I'm trying to handle a submission of a form with input elements of type radio in a way that it will trigger appending a new element to "main" element, using the value set by what the user chooses. That's the main functionality I'm looking for with this.
My code consists of 4 main js functions: three that assist creation and appendage of new elements; one that creates p elements (prGenerator), one that creates the input radio (createOption) and one that creates the form (createRadioInput), and one called foo that calls createRadioInput to which a (fifth) function is passed that has a switch used to select what new p element to append next based on input set at the point where submission handling is defined for the form when the submit button is hit.
The problem is that the switch always defaults to default, regardless of the value passed, and I don't understand why.
Here's my code, the important bits are the foo function, specially when it calls createRadioInput, and inside createRadioInput when the event listener is defined for the created form:
<body>
<div id="main">
</div>
<script>
function foo() {
const options = [];
const groupName = "group1";
prGenerator("Choose and option to render the next:");
options.push(createOption("option1", groupName, 0, "Render option 1"));
options.push(createOption("option2", groupName, 1, "Render option 2"));
const lambExec = (input) => {
console.log("pased input to lambExec: " + input);
const storyOption1 = "Option 1 selected: The quick brown fox jumps over the lazy dogs";
const storyOption2 = "Option 2 selected: A B C D E F G H I J K L M O P Q R S T U V X Y Z";
switch (input) {
case 0: //branches out to check zach story
prGenerator(storyOption1);
break;
case 1: //branches out to return to study room
prGenerator(storyOption2);
break;
default: //switch will always default to this... why?
prGenerator("...No option given.");
break;
}
};
createRadioInput("form1", groupName, options, lambExec);
}
/**#param formName unique name for the group of input radio elements
* #param groupName the name of the relevant radio input elements
* #param options list of option object (see createOptions function) that will be used to append to the main HTML element
* #param exec passed lambda to rexecute after sumition
* #desc given a name and an list of options, it will create and append the input radio elments into the main HTML element**/
function createRadioInput(formName, groupName, options, exec) {
let input = -1;
const main = document.getElementById("main"); //getting parent HTML element to append
let newForm = document.createElement("form"); //creating form
newForm.action = "#"; //form's data stays on the page
newForm.name = formName;
//this function to execute after form detects subition event
const handleSubmition = (event) => {
const group = document.getElementsByName(groupName); //get relevant group of options
for (let i = 0; i < group.length; ++i) {
if (group[i].checked) {
input = group[i].value;
console.log("submited: " + input);
}
group[i].disabled = true;
}
console.log("input before passing to exec() inside handleSubmition inside createRadioInput: " + input);
//FIXME: Why is input not working?
exec(input); //part of the story to execute after submition
event.preventDefault(); //to avoid reloading after sumition
};
newForm.addEventListener("submit", handleSubmition); //add a new event listener
options[0].input.checked = "checked"; //FIXME: maybe we don't want this... make the first option the default
//innerinner function as a lambda to apply to each element in otpions
const lambForEach = (current) => {
newForm.appendChild(current.input);
newForm.appendChild(current.label);
const br = document.createElement("br");
newForm.appendChild(br);
};
options.forEach(lambForEach); //append option
//appending the submit element
const submit = document.createElement("input");
submit.name = groupName;
submit.type = "submit";
submit.value = "Continue";
newForm.appendChild(submit);
main.appendChild(newForm);
}
/**#param id the ID for the input
* #param name name for the radio input
* #param value the value to be returned if slected
* #param text the inner text for the label of input
* #desc helper function to create user input of type radio*/
function createOption(id, name, value, text) {
//creating the input radio element
let newInput = document.createElement("input");
newInput.type = "radio";
newInput.id = id;
newInput.name = name;
newInput.value = value;
//creating the lable
let newLabel = document.createElement("label");
newLabel.for = id;
newLabel.innerHTML = text;
return {
input: newInput,
label: newLabel
};
}
/**#param str string to display on the website
* #desc automatizes the creation of pr elements*/
function prGenerator(str) {
const main = document.getElementById("main");
const pr = document.createElement("p");
pr.innerHTML = str;
main.appendChild(pr);
}
</script>
<script>
foo()
</script>
</body>
<footer>
this is a footer
</footer>
Also, if anybody has any suggestions in how to better achieve the previously described functionality, like maybe using promises and handling them(?).
Just as #Jon P explained in the comment to my question, a form returns String values, and the switch was using ints. So switch should be case "0":... case "1":, etc.
Next time, a debugger should be used instead of just printing to the console
I have a button that creates two input fields on click. I want to add a unique id for each couple of inputs that is created so that I can delete them later. Currently when I add the inputs they all have the same id 0 and the index does not increment, why and how can I make it increment? Here is my code:
createNewPricedRoundShareholder() {
const mainParent = document.getElementById('main-parent');
var index = 0;
const newPlatformNameInput1 = document.createElement("input");
newPlatformNameInput1.id = index + '_first';
newPlatformNameInput1.value = index;
const newPlatformNameInput2 = document.createElement("input");
newPlatformNameInput2.id = index + '_second';
newPlatformNameInput2.value = index;
const deleteButton = document.createElement("button");
deleteButton.innerText = 'delete';
const wrapperParent = document.createElement('div');
wrapperParent.id = index + '_parent';
wrapperParent.appendChild(newPlatformNameInput1);
wrapperParent.appendChild(newPlatformNameInput2);
wrapperParent.appendChild(deleteButton); mainParent.appendChild(wrapperParent);
index++;
}
and my html:
<div id="main-parent"></div>
I know you said you want an ID so you can use it to delete your row later, but you don't actually need it. If you add this code to your function, you can delete the entire row without the need of using an ID. This code will allow you to target the specific button, then the parent of that button and remove it.
deleteButton.addEventListener("click",function(e){
e.preventDefault();
e.target.parentNode.remove();
});
I think that is because you increase the index at the end of your function but you should increase it after creating the first input and before creating the second one
[...]
const newPlatformNameInput1 = document.createElement("input");
newPlatformNameInput1.id = index + '_first';
newPlatformNameInput1.value = index;
index++;
const newPlatformNameInput2 = document.createElement("input");
newPlatformNameInput2.id = index + '_second';
[...]
I have a list will a list but it only has one item I need to be able to replace that with a new one. But there should one be one.
Because there is a condition involve I need to be able to create an variable if something there or not but I found the list to be easier so how can I replace an item in a list with a new one
let subject_reply = [];
if (email.subject.startsWith("Re:") == true) {
subject_reply.push(email.subject);
}else{
subject_reply.push(`Re: ${email.subject}`);
}
Maybe this helps you, to replace an item of an array you can use splice method, this code says: replace item at index 1, delete that item and insert 'Boxer'.
var dogs = ['Bulldog', 'Beagle', 'Labrador'];
dogs.splice(1, 1, 'Boxer');
console.log(dogs);
I'm not sure if that is what you asked for, it's an array that holds one item only, by clearing the array when we click on the button and it takes the value of the input and then pushing it to the array by making it the only value.
If the `value` starts with *Re:*{
Push as it is.
} else {
Push: "Re: value"
}
var myInput = document.getElementById('myInput');
var myBtn = document.getElementById('myBtn');
let subject_reply = [];
myBtn.addEventListener('click', () => {
subject_reply = [];
var textValue = myInput.value;
if (textValue.startsWith("Re:") == true) {
subject_reply.push(textValue);
} else{
subject_reply.push(`Re: ${textValue}`);
}
console.log(subject_reply);
});
<input type='text' id='myInput'>
<button id='myBtn'>Click</button>
It's difficult to answer a poorly-worded question. As I understand it, one of these is the answer you seek:
subject_reply.push("Re: " + email.subject.replace(/^Re:\s?/, ""));
OR
subject_reply[0] = "Re: " + email.subject.replace(/^Re:\s?/, "");
I understand you want to replace a string value in an array.
For this, Function "Replace()" will help. In this problem specific to you, "EmailREAdder()" will help you adding "RE:" at the start of a string which does not contain "RE:".
/* Function for replacing an item */
const Replace = (arr,oldValue, newValue) => arr.splice(arr.indexOf(oldValue), 1, newValue);
/* Setting all without "RE:" to RE*/
const EmailREAdder = arr => {
arr.map(item => {
if(!item.match(/RE:/)){
Replace(arr, item, `RE: ${item}`);
}
});
}
/* code */
let users = [
"RE: Farman Ali",
"Usman",
"Fraz"
];
console.log(users);
EmailREAdder(users);
console.log(users);
I push strings to an array and display the elements in a textarea. The array populates as expected when onchange is triggered, and then I need to get the number of elements in the array, but the IDarr.length stays fixed on 2. Can anybody advise me on the error? Here’s my code:
Script:
function UpdBttn(ct){
var array = document.getElementById('array').innerHTML;
var IDarr = [array];
IDarr.push(ct);
document.getElementById('array').innerHTML = IDarr;
alert(IDarr.length);
}
Receiving textarea:
<textarea id="array"></textarea><br>
Input text (from databaseloop) to populate IDarr onchange:
<input Type="text" id="event<%=ct%>" value="<%=events(dates)%>" onchange="UpdBttn(this, '<%=ct%>')">
I'm not exactly sure what you're trying to achieve, but you might do something like this:
function UpdBttn(ct){
var array = document.getElementById('array').innerHTML;
var IDarr = array.split(',');
IDarr.push(ct);
document.getElementById('array').innerHTML = IDarr.join(',');
alert(IDarr.length);
}
You need to define your variable outside of the function to prevent it from initializing each time you call the function try this:
var IDarr = [];
function UpdBttn(ct){
var array = document.getElementById('array').innerHTML;
IDarr.push(ct);
document.getElementById('array').innerHTML = IDarr;
alert(IDarr.length);
}
innerHTML returns a string. So when you retrieve array using var array = document.getElementById('array').innerHTML; it is single string. So you have one element that is string in your array and after pushing another element it become two.
const button = document.querySelector('button');
button.addEventListener('click', function() {
const divContent = document.querySelector('#array').innerHTML
const idArr = [divContent];
console.log(idArr);
idArr.push('lorem');
document.getElementById('array').innerHTML = idArr;
// The length will be same
console.log(idArr.length);
});
<div id="array">Item1, Item2</div>
<button>Click Me</button>
I am not really sure about how your innerHTML (Note - If you need only the contents between tag, better use textContent) looks. But you need to convert your textContent from string to array.
const button = document.querySelector('button');
button.addEventListener('click', function() {
const divContent = document.querySelector('#array').innerHTML
const idArr = [...divContent.split(',')];
console.log(idArr);
idArr.push('lorem');
document.getElementById('array').innerHTML = idArr;
console.log(idArr.length);
});
<div id="array">Item1,Item2</div>
<button>Click Me</button>
This implementation is wrong. when use create var IDarr = [array];
you always create a new array with one element. So when you push output array is same 2 for all the time. If you trying to implement the char counter functionality. Please user string, not an array.
Wrong:
var arr = ['s']
console.log(arr.length) // 1
console.log(arr) //s
arr.push('e')
console.log(arr.length) // 2
console.log(arr) //se
//next time
var arr = ['se']
console.log(arr.length) // 1
console.log(arr) //se
arr.push('e')
console.log(arr.length) // 2
console.log(arr) //se,e
Correct Way:
var text = 's'
console.log(text.length) // 1
console.log(text) //s
text = text + 'e'
console.log(text.length) // 2
console.log(text) //se
//next time
var text = 'se'
console.log(text.length) // 2
console.log(text) //se
text = text + 'ee'
console.log(text.length) // 3
console.log(text) //see
I'm really sorry for I am aware similar questions have already been asked, but whenever I try to do it myself, none seem to apply or work. Basically when a user clicks on one of the elements, I am trying to get the following variables:
the id of the selected element
an array with all of the values prior to selected + selected one
an array with all of the values post-selected (selected not included)
the id of the element directly following the selected one
Thanks to your help in different posts, I have so far managed to complete the first two ones (in italic), but am unable to achieve the other two.
Would anyone know how to do so please? Thank you all in advance for your help!!
jQuery:
var days = ['#monday','#tuesday','#wednesday','#thursday','#friday','#saturday','#sunday'];
$('.days').on('click', function() {
var day = '#'+this.id;
var index = days.indexOf(day)+1;
var prev = days.slice(0, index);
var next = days.slice(index);
var above = days[index];
});
Should look more like this (though I really don't understand your code logic):
var dayIds = ['monday','tuesday','wednesday','thursday','friday','saturday','sunday'];
$('.days').on('click', function() {
//get selected element id
var dayId = this.id;
//find selected position in array and delete all values after
var dayPos = dayIds.indexOf(dayId);
var daysBelow = dayIds.slice(0, dayPos + 1;
//find position of item directly after selected and get value
var dayAfterPos = dayIds.indexOf(dayId) + 1;
var dayAfter = dayIds[dayAfterPos]; //(not working)
//only keep values following selected one
...
console.log(floorsBelow, floorId);
});
This is how you need to slicing the array. I'm not sure all the requirements you have so I have just taken out a snippet to demonstrate how you can get your values.
var dayIds = new Array('#monday','#tuesday','#wednesday','#thursday','#friday','#saturday','#sunday');
const current = '#thursday';
const currentIndex = dayIds.indexOf(current)+1;
const prev = dayIds.slice(0, currentIndex);
const next = dayIds.slice(currentIndex);
console.log(current); //#thursday
console.log(prev); //[ '#monday', '#tuesday', '#wednesday', '#thursday' ]
console.log(next); // [ '#friday', '#saturday', '#sunday' ]
EDIT:
Added newVar to contain next value
var dayIds = new Array('#monday','#tuesday','#wednesday','#thursday','#friday','#saturday','#sunday');
const current = '#thursday';
const currentIndex = dayIds.indexOf(current)+1;
const prev = dayIds.slice(0, currentIndex);
const next = dayIds.slice(currentIndex);
const newVar = dayIds[currentIndex];
console.log(current); //#thursday
console.log(prev); //[ '#monday', '#tuesday', '#wednesday', '#thursday' ]
console.log(next); // [ '#friday', '#saturday', '#sunday' ]
console.log(newVar); // #friday