Get same image randomly two times only - javascript

I am creating images flip game in jquery. I am having trouble with images. In image flip game we have only two images of the same type. I have 44 img tags and 22 images. I am taking images randomly.
Q1. How to take two images only of the same type?
Q2. If one image is clicked it should be displayed as it is working now but when any other image is clicked then if the sources (src) of both the images are same, both should be hidden forever. If not both should turn over again.
Here is my code of the script.
<script>
var imgSources = new Array();
var twoImagesOnly = [];
for(var c = 1; c < 22; c++){
imgSources.push(c + ".png");
}
$('#add').click(function(){
addElements(44);
$('#add').attr('disabled', 'true');
});
function addElements(times){
var main = $('#main');
for(j = 1; j <= times; j++){
var div = $("<div>");
var img = $("<img>");
img.attr('src', getImage());
img.attr('width', '100');
img.attr('height', '100');
img.click(function(event){
$(this).slideUp();
event.stopPropagation();
});
div.click(function(){
$(this).children('img').slideDown();
});
div.addClass('div');
div.append(img);
img.addClass('myimg');
main.append(div);
img.slideUp('fast');
}
}
var counter;
function getImage(){
var rand = Math.floor(Math.random() * 22) + 1;
var str = '';
if($.inArray(rand, twoImagesOnly) == -1){
str = rand + '.png';
twoImagesOnly[counter] = rand;
counter++;
}else{
getImage();
}
return str;
}
</script>
and here JSFiddle

Seems someone beat me to the punch with half of my solution while I was editing the fiddle, but I'll post this just because the second half should help you a bit with ensuring that only 2 of each card are posted.
First off, to initialize the array, use the following:
for(var c = 1; c < 23; c++){
imgSources.push(c + ".png");
imgSources.push(c + ".png");
}
This will iterate 22 times, adding files 1.png through 22.png twice each.
Then, to ensure only two of each image are used:
function getImage(){
var rand = Math.floor(Math.random() * imgSources.length);
var str = imgSources[rand];
imgSources.splice(rand,1);
return str;
}
What this will do is remove each array item as they are used, sort of like drawing cards from a deck, ensuring that only two of each image are used and avoiding the "keep trying until it works" approach you had.
Fiddle

Q1. A quick solution to be sure that exactly two images are present, could be to push twice to your array:
for(var c = 1; c < 22; c++){
imgSources.push(c + ".png");
imgSources.push(c + ".png");
}
And then randomize it (see https://stackoverflow.com/a/2450976/3207406 for function example)
And then fetch the image in order with a function like
getImage(i)
Q2. Regarding the "two clicks",
you could use one global variable:
first_image
Which will be null if no image was previously shown.
Otherwise, it will contain the details of the currently show image (like source and id). If the sources don't match, then you can turn back the two pictures after some time.

Related

shuffling a nodelist and traversing dom properly in javascript

this has been kind of a hard question to explain so i'll do my best..
basically, i have a raffle app (of sorts). i have a grid of images that are assigned names(captions) and are created dynamically using javascript. the end goal of it is to have each picture on a different spot on the grid with a different name every time a button is clicked. the names are captured from a textarea and stored into an array. for the most part, i have it working. my only issue is that when the button is clicked, the images and names do not random independent of each other. in other words, the images will move on the grid, but the names stay the same for each picture.
i merely just want to shuffle the p tags around. i know it's because my img and p tags are part of the same div, but i'm lost on how to do these separately while still keeping the grid form, otherwise things start going out of place. the grid uses bootstrap.
now this line in particular did sort of work for me:
tDisplay.getElementsByTagName("p") [Math.random() * tDisplay.children.length | 0].textContent = names[Math.random() * tDisplay.children.length | 0];
i know it's long and ugly, just rough draft, but my problem with this is that i do not want names appearing any different than they appear in the names array. so if i have a names array:
["jon", "tim", "tim", "bob", "sally"]
these 5 names should appear on the grid, with "tim" showing 2 times and the other names appearing once. the random line shown above was breaking this rule. as an example when i tested it, "bob" would show up multiple times when it is only in the array once, and "jon" would be left out. i would just like to shuffle.
here is my code for my button logic. there are 3 buttons and a text area. if the baseball or football button is clicked, it will display teams of the respective sport, and then theres the actual random button at the bottom. the img and the p tags are appending to a div (newDiv), which is then appended to the display div tDisplay. i've commented out lines that do not work.
//button logic
bGroup.addEventListener("click", function images(e) {
if (e.target.id !== "random") {
tDisplay.innerHTML = "";
for (var i = 0; i < names.length; i++) {
var newDiv = document.createElement("div");
var newImg = document.createElement("img");
var userName = document.createElement("p");
newDiv.className = "col-sm-3 col-md-3 col-lg-2"
newDiv.appendChild(newImg);
newDiv.appendChild(userName);
userName.textContent = names[i];
if (e.target.id === "baseball") {
newImg.src = "images/baseball/team" + i + ".jpg";
} else if (e.target.id === "football") {
newImg.src = "images/football/team" + i + ".gif";
}
tDisplay.appendChild(newDiv);
};
} else {
for (var i = 0; i <= tDisplay.children.length; i++) {
tDisplay.appendChild(tDisplay.children[Math.random() * tDisplay.children.length | 0] );
// tDisplay.appendChild(tDisplay.children[Math.random() * tDisplay.children.length | 0].lastChild.innerHTML = p[Math.random() * tDisplay.children.length | 0]);
// tDisplay.getElementsByTagName("p") [Math.random() * tDisplay.children.length | 0].textContent = names[Math.random() * tDisplay.children.length | 0];
// names[Math.random() * tDisplay.children.length | 0];
}
}
});
I think its easier to just redraw the whole thing instead of shuffling it. For that we need to shuffle the names array, then take a random image and prevent duplicates:
//a shuffle function taken from https://stackoverflow.com/questions/6274339/how-can-i-shuffle-an-array
function shuffle(a) {
for (let i = a.length; i; i--) {
let j = Math.floor(Math.random() * i);
[a[i - 1], a[j]] = [a[j], a[i - 1]];
}
}
//a names array
var names = ["john","jack"];
//a number array
var numbers = Array.from({length:names.length}).map((_,i)=>i);
function update(){
//shuffle
shuffle(names);
shuffle(numbers);
tDisplay.innerHTML = "";
names.forEach(( name,i) => {
var newDiv = document.createElement("div");
var newImg = document.createElement("img");
var userName = document.createElement("p");
newDiv.className = "col-sm-3 col-md-3 col-lg-2"
newDiv.appendChild(newImg);
newDiv.appendChild(userName);
userName.textContent = name;
if (e.target.id === "baseball") {
newImg.src = "images/baseball/team" + numbers[ i ] + ".jpg";
} else if (e.target.id === "football") {
newImg.src = "images/football/team" + numbers[ i ] + ".gif";
}
tDisplay.appendChild(newDiv);
});
}

Randomize gallery array

I'm trying to randomize a gallery of images. The HTML contains only the images, the idea is to then get the array, shuffle it and add them to divs acting as thumbnails. I took the shuffling code from here (the Durstenfeld version): How to randomize (shuffle) a JavaScript array?
My code:
var pics = document.getElementsByTagName("img");
//the Durstenfeld shuffle
for (m = pics.length - 1; m > 0; m--) {
var k = Math.floor(Math.random() * (m + 1));
var temp = pics[m];
pics[m] = pics[k];
pics[k] = temp;
}
//giving ID to each image and adding them to a thumbnail div
for (e = 0; e < pics.length; e++) {
pics[e].id = e;
var photo = document.getElementById(e);
var parent_section = photo.parentNode;
var new_div = document.createElement("div");
new_div.classList.add("thumbnail");
new_div.appendChild(photo);
parent_section.appendChild(new_div);
}
The thing is, this works perfectly fine in IE, but in all of the other browsers I tried, the images are simply placed in the default order (the order in which they are written in the HTML). The shuffling itself should be correct so I'm sure there's something wrong with my implementation of it, but I can't figure it out.
Your Array isnt an Array. Do this:
var pics = Array.from(document.getElementsByTagName("img"));

Why is my code causing (EDIT:) my page to crash?

I'm trying to randomly load some images to the page's html divs and my code is sometimes working, like on the first page load, but on maybe the second or third it causes the page to blank out and buffer and crashes the tab.
Here's a link to the full file (Excluding image srcs):
Here's the full js file: (be careful because it will crash the tab if you reload it several times)
https://repl.it/GBvG/2
var topnum = 7; //will later be used to represent current index
var rando; //will later be used as a swap index
var temporary; //will later be used as a temporary holder so we can swap rando and topnum
var myCard = document.getElementsByClassName('card');
var myArray = [
'Images/aceheart.png',
'Images/aceheart.png',
'Images/kingheart.png',
'Images/kingheart.png',
'Images/queenheart.png',
'Images/queenheart.png',
'Images/tenheart.png',
'Images/tenheart.png'
];
function create(){
while(topnum > 0){ //loops over all 8 elements
rando = Math.floor((Math.random() * topnum) + 0);
//will swap elements as long as the random index we got is not the same as the current index
if(myArray[rando] !== myArray[topnum]){
temporary = myArray[topnum];
myArray[topnum] = myArray[rando]; //randomizes topindex value
myArray[rando] = temporary;
topnum--;
}; // end of if
}; //end of while
for(var i = 0; i <= 8;i++){
var imgElement = "<img src='" + myArray[i] + "' alt='test' width='200px' height='275px'/>";
myCard[i].innerHTML = imgElement;
}; //end of for loop
}; // end of create
I'm almost positive the problem is with this snippet, though I don't know why:
for(var i = 0; i <= 8;i++){
var imgElement = "<img src='" + myArray[i] + "' alt='test' width='200px' height='275px'/>";
myCard[i].innerHTML = imgElement;
}; //end of for loop
You have 8 cards but your loop runs 9 iterations.
Change
for(var i = 0; i <= 8;i++)
To
for(var i = 0; i < 8;i++) // use `<` instead of `<=`
Also, as Gerardo Furtado mentioned in the comments, you should put topnum-- outside the if in the while loop. Otherwise you'll have an infinite loop.
while(topnum > 0) {
rando = Math.floor((Math.random() * topnum) + 0);
if(myArray[rando] !== myArray[topnum]){
// ...
}
topnum--; // <-- move the decrement here
}

Javascript to double size of all images in all divs of a particular class

So I wrote this javascript to double the images size of all images within all divs of a particular class. Here's what I came up with it.
var lmnts = document.getElementsByTagName('*'), i;
for (i in lmnts) {
if((' ' + lmnts[i].className + ' ').indexOf(' ' + 'ClassName' + ' ') > -1) {
var images = document.lmnts[i].getElementsByTagName('img');
for(var j=0; j<images.length; j++)
{
images[j].height *= 2;
images[j].width *= 2;
}
}
}
However I can't get it to work :(
EDIT: It's a user script. So it doesn't work means, it didn't do what it was supposed to do.
There are no errors in js console.
On debugging, i find that it enters the first loop just once and then fails after the line
var images = document.lmnts[i].getElementsByTagName('img');
EDIT2: It's a userscript to double the image size of all images of class fileThumb in 4chan.org boards.
A major problem would be the var images = document.lmnts[i].getElementsByTagName('img'); line.
the lmnts is a variable and not a property of the document.
It should read var images = lmnts[i].getElementsByTagName('img');
Also, instead of manually looping over all the elements in the DOM and manually testing if the className contains the class you want you could use the document.getElementsByClassName('ClassName') or the more modern document.querySelectorAll('.ClassName'). Using the second method you could also select all images in one go with document.querySelectorAll('.ClassName img').
So all your code could be simplified to
var images = document.querySelectorAll('.ClassName img');
for (var j = 0; j < images.length; j++){
images[j].height *= 2;
images[j].width *= 2;
}
Update (based on comment)
The images on 4chan have a style attribute applied to them that sets the dimensions while the images[j].height sets the attribute height of the image. Unfortunately the style attribute takes precentence and show the values set from the script are not in effect.
You should alter the style attribute like this
var images = document.querySelectorAll('.fileThumb img');
for (var j = 0; j < images.length; j++){
var image = images[j],
initialWidth = parseInt(image.style.width, 10),
initialHeight = parseInt(image.style.height, 10);
image.style.width = (initialWidth * 2) + 'px';
image.style.height= (initialHeight * 2) + 'px';
}

Making individual letters in a string different colours

I'm trying to make the colour different for certain letters (if found) in a string eg. the letter i. The search count is working I just can't figure out the changing html colour of the individual letter.
I know if it was a whole word then I could just use split strings, but can't figure out how to do it for a single letter. I've found some examples, one that I have tried is at the bottom that is not working either.
//getMsg is another function, which passes in a user inputted string
function searchMsg(getMsg) {
alert (getMsg);
var msgBoxObject = document.getElementById('msgBox');
var pos = getMsg.indexOf('i')
var txtToFind = (document.getElementById('txtToFind').value);
var count = 0;
while (pos !== -1){
count++;
pos = getMsg.indexOf('i', pos + 1);
document.writeln (+count);
msgBoxObject.innerHTML = (count);
}
getMsg = getMsg.replace('/i/g<span class="red">i</span>');
document.writeln (getMsg);
}
Edit; I've added in this, but can't get the loop to work correctly so it displays all instances of the letter found instead of just one: /*while (pos !== -1){
count++;
pos = getMsg.indexOf('i', pos + 1);
document.writeln (+count);
msgBoxObject.innerHTML = (count);
}
*/
var count = 0; // Count of target value
var i = 0; // Iterative counter
// Examine each element.
for(i=0; i<arr.length; i++)
{ if(arr[i] == targetValue)
count++;
}
return count;
}
searchIndex = txtMsg.indexOf(txtToFind);
if (searchIndex >=0 ) {
// Copy text from phrase up till the match.
matchPhrase = txtMsg.slice(0, searchIndex);
matchPhrase += '<font color="red">' + txtToFind + '</font>';
matchPhrase += txtMsg.slice(searchIndex + txtToFind.length);
} else {
matchPhrase = "No matches"
}
displayProcessedMsg(matchPhrase);
document.writeln(matchPhrase);
You either need to add the corresponding css for that class or change the tag like #john_Smith specified
Adding the CSS
span.red {
color: red;
}
Changing the tag
On your code replace this
getMsg = getMsg.replace('/i/g<span class="red">i</span>');
for
getMsg = getMsg.replace('/i/g<span style:"color:red">i</span>');
Some example of inline css
Some advice on color palettes
Try looking into d3 color scales(https://github.com/mbostock/d3/wiki/Ordinal-Scales#categorical-colors) or apply a principle similar to incrementing an RGB value instead of using names of colors.
Hope this helps.

Categories

Resources