I have set up a simple image array and want to ensure that each image from the array is used only once. I am new to javascript and am not sure how to implement the splice element.
A link to the full site: http://p3.katecooperuk.com
Here is my javascript array:
var calendarImg = [
"url(/images/tree.jpg)",
"url(/images/santa.jpg)",
"url(/images/stockings.jpg)",
"url(/images/snoopy.jpg)",
"url(/images/stockings2.jpg)",
"url(/images/bear.jpg)",
"url(/images/penguins.jpg)",
"url(/images/baubles.jpg)",
"url(/images/polarbear.jpg)",
"url(/images/village.jpg)",
"url(/images/village2.jpg)",
"url(/images/nativity.jpg)",
"url(/images/santa2.jpg)",
"url(/images/snowman.jpg)",
"url(/images/snow.jpg)",
]
function imgRandom(imgArr) {
return imgArr[Math.floor(Math.random() * imgArr.length)];
}
$('.doors').click(function(){
// Select Random Image
var doorImage = imgRandom(calendarImg);
// Change background image of door that was clicked
$(this).css('background-image', doorImage);
});
if you want to know more about splice, visit this MDN documentation.
function getRandomImage(arr) {
if (arr.length > 0) {
random = Math.floor(Math.random()*arr.length)
return arr.splice(random, 1)[0];
}
}
This function would return you an element from the array and delete that element from the array. So, every time you call the function, you get back an unique element until the array is empty.
If the array is empty, the function returns undefined.
If there is anything more regarding the implementation, ask away.
Your logic is almost correct. Please try:
$('.doors').bind('click',function(){
// Select Random Image
var doorImage = imgRandom(calendarImg);
// Change background image of door that was clicked
$(this).css('background-image', doorImage);
}
Also improve your random function:
function imgRandom(imgArr) {
var return_item = imgArr[Math.floor(Math.random() * imgArr.length)];
if (imgArr.length > 0) {
calendarImg = [];
var random = Math.floor(Math.random()*imgArr.length);
calendarImg = imgArr.splice(random, 1);
}
return return_item;
}
Related
I've been trying to write a go back function. What this function will do is it'll store last two ID number that has been generated and append when there is a new one, delete the first one.
I have this function which creates the IDs and plays the video with that ID.
function newVideo(){
let rando = Math.floor((Math.random() * 3970) + 1);
document.getElementById("vsrc").src = "https://raw.githubusercontent.com/ondersumer07/vinematik-videos/master/vid/" + rando + ".mp4";
document.getElementById("videoEl").load();
return rando;
}
I am returning the rando to use it outside this function, and I can access it outside the function, the problem is, the variable outside the function is not updating everytime newVideo() run.
The code for that goes like this:
let rando = newVideo();
let vidids = [];
if (vidids.length < 2) {
vidids.push(rando)
console.log("added")
} else {
vidids.shift()
console.log("deleted")
};
Basically what this does is to get the returned rando value and push it to the vidids array, delete the first one if there is more than two but it won't, it does not update the let vidids = []; array for some reason. I need it to update everytime the newVideo() function ran.
Also, I want the if to add if there is less then two items in that array and delete from the start of the array if there is more than two items in it. Not really sure if that'll work too.
I can't seem to figure out how to do this, am I doing this whole thing wrong or is there still hope for this function? How am I supposed to write that function?
Edit: I've changed the vidids.length part yet the problem still occur because let rando = newVideo(); doesn't update.
In order to keep the last two Items of an array, you can use something like this.
let vidids = [];
function addToArray(item, array){
array.unshift(item);
return array.slice(0,1);
}
//test
vidids = addToArray(newVideo(), vidids);
vidids =addToArray(newVideo(), vidids);
vidids =addToArray(newVideo(), vidids);
vidids =addToArray(newVideo(), vidids);
vidids =addToArray(newVideo(), vidids);
console.log('Done');
You've made a small mistake that caused your code to not work properly.
The IF condition is intended to check the length of the 'vidids' array,
What actually happens is that it compares the array referance instead of it's length
To fix the issue, add .length after 'vidids' inside of the IF condition.
....
if (vidids.length < 2) {
.....
I figured it out. Basically what I did is storing every number the algorithm creates and then taking one before the last.
Which goes like this:
The algorithm for creating random numbers:
function randomNum() {
let rando = Math.floor((Math.random() * 3970) + 1);
return rando;
};
Then I put this function in a variable:
let videoid = randomNum()
I had another variable called videoids which is above and outside of the randomNum function and is an array:
let videoids = []
After that I stored every number I created with videoid inside videoids by pushing it(This push needs to be inside your function):
videoids.push(videoid);
Okay so I stored all the numbers this way. Now I should take one before the last so I can go to previous video. So I needed to create a function, I used this function which was created by Tadeck, in this thread.
if (!Array.prototype.last) {
Array.prototype.last = function() {
return this[this.length - 2];
};
};
Now I can put that inside of my prevVideo function which looks like this:
function prevVideo() {
document.getElementById("vsrc").src = srcRaw + videoids.last() + ".mp4";
document.getElementById("videoEl").load();
videoids.push(videoids.last());
}
Note: Don't forget to push videoids.last inside your videoids otherwise you can only go to your previous number for once.
I need to remove an element from an array used the splice method, but I don't know the index of the object that I wish to remove. I've tried adding an ID that mimicks the index to remove the item but this doesn't appear to be working.
RandomiseNextQuestion: function(player1qs) {
// Pick a random question
this.Questions = player1qs;
var rand = Math.floor(Math.random() * player1qs.length);
function findQ(q) {
return q.qId === rand;
}
this.CurrentQuestion = player1qs.find(findQ);
if(this.CurrentQuestion) {
// Process question
}
// Remove that question so it can't be used again
this.Questions.splice(this.CurrentQuestion.qId, 1);
}
I've also tried using the 'rand' value to remove the item but that doesn't work either.
You can map to find the index of your element
var yourArray = ['bla','bloe','blie'];
var elementPos = yourArray.indexOf('bloe');
console.log(elementPos); // this will show the index of the element you want
yourArray.splice(elementPos,1); // this wil remove the element
console.log(yourArray);
you can do it like this I suppose
getRandomQuestion: function(playerQuestions) {
// Pick a random question and return question and index of question
this.questions = playerQuestions;
var rand = Math.floor(Math.random() * playerQuestions.length);
return this.questions[rand];
}
removeQuestion: function(question, playerQuestions){
playerQuestions.splice(playerQuestions.indexOf(question), 1);
return playerQuestions; // removes question and gives back the remaining questions
}
processQuestion: function(question){
//do something with the question
}
// you would call it like this
var questionsPlayer1 = ["the meaning of life", "the answer to everything"]
var question = getRandomQuestion(questionsPlayer1);
processQuestion(question);
removeQuestion(question, questionsPlayer1);
All you can do with a single command is a filter
arr.filter((value) => value !== removeValue)
Otherwise, if you want to keep using your array (aka mutable), you will have to use something like:
const i = arr.indexOf('value')
arr.splice(i, 1)
This fiddle demonstrates my problem: https://jsfiddle.net/petebere/fhg84je2/
I would like to make sure that every time a user clicks a button a random element from the array will be displayed. The problem is that sometimes when the new shuffle is carried out, the first element in the newly shuffled array is the same as the last element in the previously shuffled array. On these occasions when the user clicks the button the same element is displayed. The user has to then click the button again (or more times) to display a different element. I would like to avoid this.
I've tried introducing the if statement to shuffle again if the first element is equal to the last element but this does not seem to work.
Your help would be greatly appreciated.
The HTML code:
<div id="container">
<button id="clickHere">Click here to pick a random element from the array</button>
<div id="resultDiv"></div>
</div><!-- container -->
The JavaScript code:
/* define the array with a list of elements */
var arrayList = [
"1st element in array</br>",
"2nd element in array</br>",
"3rd element in array</br>",
];
/* define the function to shuffle the array */
function shuffleArray() {
for (var i = arrayList.length - 1; i > 0; i--) {
var j = Math.floor(Math.random() * (i + 1));
var temp = arrayList[i];
arrayList[i] = arrayList[j];
arrayList[j] = temp;
}
}
/* execute the shuffleArray function */
shuffleArray();
/* button event initiating the randomiser function */
document.getElementById('clickHere').onclick = function () {
randomiser ();
}
/* populate the resultDiv for the first time */
document.getElementById('resultDiv').innerHTML = arrayList[0];
/* define the array index value for the first click */
var arrayIndex = 1;
/* define the main function */
function randomiser () {
document.getElementById('resultDiv').innerHTML = arrayList[arrayIndex];
arrayIndex = (arrayIndex+1);
if (arrayIndex>arrayList.length-1) {
arrayIndex = 0;
var lastArrayElement = arrayList[arrayList.length-1]
shuffleArray();
var firstArrayElement = arrayList[0];
if (firstArrayElement == lastArrayElement) {
shuffleArray();
}
}
}
EDIT 1:
The two different solutions suggested by 1) SpiderPig and 2) Jonas-Äppelgran have solved my problem.
This is an updated fiddle with the first solution which uses a combination of push and shift methods: https://jsfiddle.net/petebere/axatv0wg/
This is an updated fiddle with the second solution which uses a while loop instead of an if statement: https://jsfiddle.net/fhg84je2/2/
Both solutions work perfectly, however my preferred solution is the second one as I find it easier to understand.
Perform a while instead of the if check when looking if the randomly generated string will be the same as last time.
Psuedocode: while (old == new) { randomize(); } This won't stop looping/randomizing until old is not new.
See updated jsfiddle
You just need to do a small change to your code.
Instead of
if (firstArrayElement == lastArrayElement) {
shuffleArray();
}
try this
if (firstArrayElement == lastArrayElement) {
arrayList.push(arrayList.shift());
}
I am using the Colorbox Lightbox script to call a hidden div on a page. It works great but there is a catch. I have 15 hidden divs. When a link is clicked I would like a new lightbox to show each time without repeating until all have been shown. I do not know how to do this.
Here is my code to call the lightbox:
$(".colorbox").colorbox({
inline:true
});
Here is the HTML of the hidden divs
<div class="hide">
<div id="lightbox1">
<!-- Content -->
</div>
<div id="lightbox2">
<!-- Content -->
</div>
<!-- etc -->
</div>
How would I call each div at random until all have been shown then start over?
Also is there a way that once divs 1 - 15 have been shown to then show one last div (id="last-div") before restarting?
Note: All divs would be called on a click and I am using jQuery 1.8.2.
I do not know where to start, I have seen scripts using Math.random() but I do not understand enough to make that work.
UPDATE
I have tried Ian's answer but the lightbox is not showing (but I can see in the console log that the script is working)
Originally he has this in his script:
$(selector).show();
which I changed to this:
$(selector).colorbox({inline:true });
What do I need to do to call the lightbox?
Note: No errors are thrown.
So my idea was similar to Eric's, but I wanted to make it work "completely". So instead of storing references to all the divs in an array, I just decided to store an array of ints representing each div. The way I eventually select them with jQuery is "#lightbox + i", so if you don't have this exact structure (where the divs have an id like "lightbox" and an int - from 1 to the last count), then you can use .eq() or nth-child. It won't be the exact same results, but it will have the same random effect, just done in a different way. I found a function that "randomizes" an array - I'm guessing like what Eric's Shuffle does. But here's where I got it from - How to randomize (shuffle) a JavaScript array? . I had to modify it to return a new array instead of modify the one passed to the function. Also, I kept everything in the document.ready scope, instead of the global scope, so things are passed/returned a lot. It worked fine before when I had all and randomed declared globally and didn't pass them around, I just thought this would be "better" since they weren't global.
Here's the fiddle:
http://jsfiddle.net/6qYCL/1/
And here's the Javascript:
$(document).ready(function () {
var all,
randomed;
all = generateAll();
randomed = generateRandomed(all);
$("#generator").on("click", function (evt) {
evt.preventDefault();
randomed = doNext(all, randomed);
});
});
function generateAll() {
// Generates the array of "all" divs to work on
var a = [];
var divs = $(".hide > div.lightbox");
for (var i = 1; i <= divs.length; i++) {
a.push(i);
}
console.log("List of divs available to toggle: " + a);
return a;
}
function generateRandomed(all) {
// Randomizes the original array
randomed = fisherYates(all);
console.log("Setting randomized array: " + randomed);
return randomed;
}
function doNext(all, randomed) {
$(".lightbox, #last-div").hide();
if (randomed.length < 1) {
console.log("All lightboxes toggled, showing last, then starting over");
$("#last-div").show();
randomed = generateRandomed(all);
} else {
var next = randomed.shift();
var selector = "#lightbox" + next;
console.log("Showing " + selector);
$(selector).show();
console.log("What's left: " + randomed);
}
return randomed;
}
// Randomizes an array and returns the new one (doesn't modify original)
function fisherYates ( myArray ) {
var return_arr = myArray.slice(0);
var i = return_arr.length;
if ( i == 0 ) return false;
while ( --i ) {
var j = Math.floor( Math.random() * ( i + 1 ) );
var tempi = return_arr[i];
var tempj = return_arr[j];
return_arr[i] = tempj;
return_arr[j] = tempi;
}
return return_arr;
}
It accounts for getting to the end of the list and display #new-div like you mentioned, then starting the process over. If you look in your browser's console, you can "watch" what's happening during initialization and when clicking the link.
I think this is close to what you were looking for. I'm not sure which is a better solution - storing references to the elements or just an array of ints to loop through and eventually find. I know there are many variations on how to do this - when/how to store the counting stuff, when/how to randomize the array or retrieve a random value (and how to keep track of which has been used), where to store all references, and plenty more. I hope this at least helps!
Create an array of all of them, then shuffle that array, then pull the next one each time you get a click. When you run out, you can repopulate the array if necessary.
Something like this (using the Shuffle method from this source):
Fiddle
var array = $(".hide div").toArray(); // Add all divs within the hide div to an array
var randomArray = Shuffle(array); // Shuffle the array
$("a").click(function() {
if (randomArray.length > 0)
alert(randomArray.shift().innerHTML); // Show contents of div, as an example
else
alert("None left!");
return false;
});
The solution below works by passing an array of elements to a function. As each div is displayed it is taken out of the array. Then from the divs left in the array the next one is picked at random.
// call this function on page load
function begin( ) {
var arr = $(".hide div").toArray();
// further elements can be added to arr i.e. last-div
showDivs( arr.length, arr );
}
// begin displaying divs
function showDivs( numberOfDivs, divArray ) {
var i, lastDiv;
function nextDiv( ) {
// depending on number of slides left get random number
i = randomInt( numberOfDivs );
if( lastDiv ) { $(lastDiv).hide() };
$( divArray[ i ] ).fadeIn( 3000 );
// now that this div has been displayed
// remove from array and cache
lastDiv = divArray.splice( i, 1 );
numberOfDivs--;
// no more divs to display
if( numberOfDivs == 0 ) { return };
setTimeout( nextDiv, 4000);
}
setTimeout( nextDiv, 1000);
}
// calculate next random index
function randomInt( divsLeft ) {
var i = Math.random() * divsLeft;
return Math.round( i );
}
Fiddle here
I am using a onclick function and adding a value to by paasing a value to it. If the value already exists den i remove that value from the list.
function send_value(str)
{
//alert(str);
var sub_id = document.getElementById('selected_sub_id').value;
//alert(sub_id.indexOf(str));
if(sub_id.indexOf(str)==-1)
{
if(sub_id=="")
{
sub_id+=str;
}
else
{
sub_id+=',';
sub_id+=str;
}
}
else
{
sub_id = sub_id.replace(str+",", "");
sub_id = sub_id.replace(","+str, "");
sub_id = sub_id.replace(str, "");
}
//alert(sub_id);
document.getElementById('selected_sub_id').value=sub_id;
}
This is the function. Suppose i have the values 1,2,3,4 in the selected_sub_id and i am passing 5 to it, it will be stored as 1,2,3,4,5
now i am passing 24 it will be stored as 1,2,3,4,5,24
No suppose i want to remove 2, so when i send 2 to the function it removes all the occurrences of 2 so i am left with only 1,3,4,54...
kindly help me with this thanks in advance..
You most probably want an array for this. It makes things much easier.
Create one first:
var arr = [];
Adding goes with .push:
arr.push(24);
Removing goes with .splice and .indexOf (the 1 means 'removing 1 element'):
arr.splice(arr.indexOf(24), 1);
Converting to a string goes with .join:
arr.join(); // 1,2,3,24 or something similar depending on elements
For example: http://jsfiddle.net/ScBNQ/.
var arr = [];
// adding
arr.push(1);
arr.push(2);
arr.push(3);
arr.push(24);
// removing
arr.splice(arr.indexOf(2), 1);
// joining
arr.join(); // 1,3,24