I'm very new to Javascript and jQuery. I'm trying to create a film list that will randomly pick an item from the list, post the result, and remove the item from the original list. It uses text input, .push and .append to keep track of the list and update an array of matching text. My thinking was that I would use an array that matches the ul to generate a random index number from its length and then use the number to remove the li from the ul by index. The basic idea is working. My issue is that every time it selects an item from the list, the item it removes from the array is different than the item it posts and removes from the ul. The parts seem to work fine separately until I run them in a function together tied to a button.
Here is the code I'm using. The watchList array is populated with a .push whenever text is accepted to update the ul. I've checked and the index for both match up.
function randomShow(){
var r = Math.floor(Math.random() * watchList.length);
for(var i = 0; i < watchList.length; i++){
if(i === r) {
alert(watchList[i]);
watchList.splice(watchList.indexOf[i],1);
$("li").eq(i).remove();
}
}
}
I think you don’t need a loop. Try this;
function randomShow(){
var r = Math.floor(Math.random() *watchList.length);
$("li").eq(r).remove();
}
Related
In my program, when the user clicks a button, an item (a string) from an array gets randomly selected, and is then outputted to the user.
My goal is to introduce some kind of "remove this item from the array after displaying to the user" functionality, to prevent repeat outputs. That way, each time they're viewing a fresh item, and not seeing the same ones over and over again.
Here is my v1 version of coding this:
Array1 = [] // the full array of all items is contained in here.
Array2 = [] // this is the post-display holding bay for items the user has seen already.
After outputting an item to the user from Array 1? That item will be added to Array 2. BEFORE displaying any array items to a user? It will cross-reference the randomly selected item against the full list of items in Array2, basically using IF/ELSE IF logic. Something like this:
for (let i = 0; i < NumberOfArray2Items; i++) {
if (Array1ItemToDisplay === Array2[i]) {
NumberOfMatches = j++ // basically, increment a numerical variable, so that any value
// greater than 0 indicates, yes, it's been outputted to the user before
}
}
if (NumberOfMatches === 0) {
DisplayCurrentArrayItem();
} else if (NumberOfMatches > 0) {
SelectAnotherArrayItemToDisplay();
}
That's a rough version of what I have in mind, and frankly it sounds like a terrible solution because it requires two very lengthy programmatic steps:
Looping over every single item in Array2 for cross-referencing
Potentially running that dozens, maybe hundreds of times, if it continues to find matches each time it runs that block of code.
Is there some simpler, faster method of cross-refencing an item against an entire array? Or perhaps cross-referencing both arrays against each other, to only leave the remaining items that don't match, and then select from that intermediate list of items that hasn't yet been displayed?
These arrays will contain tens of thousands of items, so my concern is, as presently written, this code will take forever to execute. Is there some simpler, faster, more efficient solution I'm not seeing?
Here you go, each time the button is clicked a random element from the array is shown. That element is then removed - so no duplicates are shown.
const data = ['foo', 'bar', 'bat', 'baz'];
document.getElementById('btn').addEventListener("click", e => {
if(!data.length) return;
const idx = Math.floor(Math.random() * data.length);
console.log(data[idx]);
data.splice(idx, 1);
});
<button id=btn>click</button>
I also added a check to make sure that when there are no unique items left nothing happens, not sure if this is what you wanted or not. If not - remove the line if(!data.length) return;
I have this piece of code:
for (var i = 0, row; row = document.getElementById("myTbl").rows[i]; i++) {
row.cells[headCatg.cellIndex].classList.remove("red");
row.deleteCell(headCatg.cellIndex);
}
I need to remove the class "red" from each cell of the table column and then delete that column. The reason I need to remove class first, because it has been added to DOM by another cript and if I remove the column the class just appears in the next column.
When I run each of these commands (remove() and deleteCell()) individually in the loop, everything seem to work fine, but when I put them together, the column is removed but the class shifts to another column.
What am I missing?
You have to convert the HTMLcollection to an array
The reason why your code wasn't working properly it's because HTMLcollection returns a live NodeList which means when you use remove on each element in the collection the other elements gets rearranged and the length of the list get's smaller causing you to skip some of them so you should convert your html collection to an array using Array.from
row = document.getElementByClassName("myTbl")
rowarr=Array.from(row)
for (var i = 0, rowarr.length; i++) {
row[i].cells[headCatg.cellIndex].classList.remove("red");
row[i].deleteCell(headCatg.cellIndex);
}
I am trying to figure out how to build a forEach loop with an unknown number of elements. Randomly pick one, do XYZ to it. Make it visible. Remove that element from consideration. Repeat picking a random number from remaining elements.
My thoughts so far are to make an array of the elements id's. Use the array.forEach() to loop over them. Select an element at random from the array. Execute XYZ then remove selected id from array then repeat till forEach expires.
So first of all if you can think of a better way I'm open to any and all ideas.
I didn't get far before I hit my first roadblock and that is dynamically generating the array of id's.
I get the number of elements (they will always be children of the parent so no worries there.
//get count of all elements and loop till all are visible
var elementCount = $('#PartialsContainer').children().size();
Next I goto generate my array but it results in one element in the array holding the value of elementCount.
//create array of quantity
var elementArray = $.makeArray( elementCount );
So I could do a loop through elements getting their id like this but surely there is a better way?
for (var i = 0; i < elementCount; i++)
{
elementArray.push( $element[i] //its pseudo code I know it won't work );
}
Thank you for any ideas / tips on improving this design / approach.
Try something like
var $els = $('#PartialsContainer').children();
while($els.length){
var $el = $els.eq(Math.floor(Math.random() * $els.length));
//do something with $el
$els = $els.not($el);
}
Demo: Fiddle
Following a prior post on how to update the order of an array. I followed the suggestion of Michael Best and used splice() to modify the ordering of my array on button click
self.moveup = function (itemIndex) {
var i = self.itemList.indexOf(itemIndex);
if(i >= 1){
var array = self.itemList();
self.itemList.splice(i-1, 2, array[i], array[i-1]);
}
Where I am having trouble is in incrementing the items in the array. From reading the usage of Array Splice The first param indicates where the change should occur for moving up I would think that would be i+1 , the value 2 indicates how many items in the array would change so no change there and then the range I thought would be the selected item array[i] and the end would be [i+1] as I am increasing the position.
self.itemList.splice(i+1, 2, array[i], array[i+1]);
In the attached fiddler you can see the values increase but the items do not actually change order they are only replicating when you hit the down button. I expected the result to be the same as when calling moveUp.
I'd appreciate any pointers on what I am missing here. http://jsfiddle.net/rlcrews/SCWmk/5/
-cheers
Almost there. Here's how I did it.
When moving an item up, you need to swap it with the previous item. Thus, you need to replace the elements at indices i-1 and i with array[i] and array[i-1], respectively. Your moveup method does exactly that, so all is good.
Now, when moving an item down, you need to swap it with the next item. Thus, you replace the elements at indices i and i+1 with array[i+1] and array[i], respectively. Your code however changes the elements i+1 and i+2, which is no good. Instead, you should be doing:
self.itemList.splice(i, 2, array[i+1], array[i]);
You start splicing at i (as you're removing the elements at i and i+1) and you replace them (insert at that index) with array[i+1] and array[i].
On another note, your check for whether you can move the item down is incorrect. The only item you should not move down is the last item, i.e. the element at index self.itemList().length-1. Thus, the check should look like if (i < array.length - 1) { ... } (see the fiddle).
I have a long array of strings that will have a varying length because I'm pulling the strings from a database table that will be filled dynamically by user submission, however, that long array will be comprised of a repeating set of 6 variables. So I want to slice it at every 6th index, turning what I've sliced into an array, and then printing the list of those sub arrays to the page.
This is what I have so far:
//I'm using Parse as my database and the find() method is one way you query it.
var search = [];
query.find({
success: function(results) {
//loop through results to get the key-value pair of each row
for (i = 0; i < results.length; i++){
activity = results[i].get("activity");
scene = results[i].get("location");
neighborhood = results[i].get("neighborhood");
date = results[i].get("date");
details = results[i].get("details");
time = results[i].get("time");
//Here I'm pushing the row of the six variables into an array, but since there will be multiple rows on the table from multiple submissions, the array will contain however many rows there are.
search.push(activity, scene, neighborhood, date, details, time);
//my second array
var search2 = [];
//This is that part I'm unsure of. I want to loop through the search array slicing it at every 6th index creating multiple sub arrays. I then want to write the list of those sub arrays to the page
for(i=0; i < search.length; i+=6){
search2 = search.slice(0,6);
}
//this is the div I want to write the arrays to.
$("#mainDiv").text(search2);
};// closes success function
Instead of pushing each individual field onto the search array and then slicing each set out at the end, why don't you just add each record's set of data as an array to your search array?
search.push([activity, scene, neighborhood, date, details, time]);
That way, when you loop through the search array to print out each record's values you don't have to do any slicing or incrementing by 6. For each loop you already have the array slice you want:
for (i = 0; i < search.length; i++) {
$('#mainDiv').append(search[i]);
}
Maybe I've misread your question, but it looks like you want to add all the records to your #mainDiv. If you use the jQuery text() method for each iteration of your loop, you'll just overwrite the text for each iteration, making the result the final value of your loop instead of all of the values of all of the items. To add each record to your #mainDiv, you want to use the append() method.
You might also want to add some spaces between the values, assuming you are using my approach to storing sets of arrays instead of individual field array items:
for (i = 0; i < search.length; i++) {
$('#mainDiv').append(search[i].join(' '));
}