i would like to shuffle an array of images with jquery.The problem is that 'till now i did something which doesnt show images ...it shows only path for them.Where i was wrong?
Code here:
HTML:
<div id="array" class="thirdcanvas"></div>
<button class="array">Shuffle</button>
JS:
jQuery(function($){
$(document).ready( function()
{
$('#array').shuffle();
});
var arr = new Array("images/alfabet/a.png", "images/alfabet/b.png", "images/alfabet/c.png", "images/alfabet/e.png", "images/alfabet/f.png");
$('#array').text(arr.join(", "));
$('button.array').click(function(){
arr = $.shuffle(arr);
$('#array').text(arr.join(", "));
});
});
var image6 = new Image();
image6.src = "images/alfabet/a.png";
var image7 = new Image();
image7.src = "images/alfabet/b.png";
var image8 = new Image();
image8.src = "images/alfabet/c.png";
var image9 = new Image();
image9.src = "images/alfabet/e.png";
var image10 = new Image();
image10.src = "images/alfabet/f.png";
(function($){
$.fn.shuffle = function() {
return this.each(function(){
var items = $(this).children().clone(true);
return (items.length) ? $(this).html($.shuffle(items)) : this;
});
};
$.shuffle = function(arr) {
for(var j, x, i = arr.length; i; j = parseInt(Math.random() * i), x = arr[--i], arr[i] = arr[j], arr[j] = x);
return arr;
};
})(jQuery);
Try
jQuery(function ($) {
var arr = new Array("//placehold.it/32/ff0000.png", "//placehold.it/32/00ff00.png", "//placehold.it/32/0000ff.png", "//placehold.it/32/ff00ff.png", "//placehold.it/32/00ffff.png");
$.each($.shuffle(arr), function (_, src) {
$('<img />', {
src: src
}).appendTo('#array')
})
$('button.array').click(function () {
$('#array').shuffle()
});
});
(function ($) {
$.fn.shuffle = function () {
var _self = this,
children = $.shuffle(this.children().get());
$.each(children, function () {
_self.append(this)
})
return this;
};
$.shuffle = function (arr) {
for (var j, x, i = arr.length; i; j = parseInt(Math.random() * i), x = arr[--i], arr[i] = arr[j], arr[j] = x);
return arr;
};
})(jQuery);
Demo: Fiddle
This code goes in your click listener and creates images with the srcs from the array. You can then remove your new Image()s. This is not an efficient implementation, but it's fine for a small page. It involves the minimum changes to your original code.
$('button.array').click(function () {
arr = $.shuffle(arr);
$('#array').text(arr.join(", "));
// Added:
$(".thirdcanvas").html(""); // empties container
for (var i=0; i<arr.length ;i++){
// Add an image
$(".thirdcanvas").append($("<img src='" + arr[i] + "'>"));
}
});
It looks like you have all the parts you need there. We just need to take the image links and create <img> elements from them, then append them to the <div>. The shuffle function can then be called directly on the <div>, to shuffle the images in place, without having to use the original array again.
Something like:
$(document).ready( function() {
var arr = new Array("http://placehold.it/50x50&text=a", "ihttp://placehold.it/50x50&text=b", "http://placehold.it/50x50&text=c", "http://placehold.it/50x50&text=d", "http://placehold.it/50x50&text=e");
for(var i=0; i<arr.length; i++) {
var img = new Image();
img.src = arr[i];
$('#array').append(img);
}
$('button.array').click(function(){
$('#array').shuffle();
});
});
(function($){
$.fn.shuffle = function() {
return this.each(function(){
var items = $(this).children().clone(true);
return (items.length) ? $(this).html($.shuffle(items)) : this;
});
};
$.shuffle = function(arr) {
for(var j, x, i = arr.length; i; j = parseInt(Math.random() * i), x = arr[--i], arr[i] = arr[j], arr[j] = x);
return arr;
};
})(jQuery);
jsfiddle: http://jsfiddle.net/ygaw2/
This uses a for loop to iterate across the array of links, so the array can contain as many links as required.
You never create <img> elements, that's why you only see the URL.
Here's the code you should use:
// your bunch of pictures
var arr = new Array(
"http://placehold.it/100x100",
"http://placehold.it/120x100",
"http://placehold.it/140x100",
"http://placehold.it/160x100",
"http://placehold.it/180x100"
);
// Refresh pictures
function refreshPictures() {
// Create new DOM element
var pictures = $('<ul id="pictures"></ul>');
for(var i=0, n=arr.length; i<n; i++) {
pictures.append('<li><img src="'+arr[i]+'"/></li>');
}
// Replace current element by new one
$('#pictures').replaceWith(pictures);
}
// Add click listener on #randomize button
$('#randomize').on('click', function(){
arr = arr.shuffle();
refreshPictures();
});
// Initialize pictures
refreshPictures();
// Add shuffle() function to Array prototype
Array.prototype.shuffle = function() {
for(var j, x, i = this.length; i; j = parseInt(Math.random() * i), x = this[--i], this[i] = this[j], this[j] = x);
return this;
};
ul {
list-style: none;
padding: 0;
}
li {
float: left;
margin: 2px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.0.2/jquery.min.js"></script>
<ul id="pictures"></ul>
<button id="randomize">Shuffle</button>
Related
So I got multiple divs with different images embedded. Each one has its unique name attributes. I'm trying to apply the hover effect to each divs by changing the image source. I don't want to write multiple scripts, rather I'm trying to write a just one block of script that would effect every div.
<div id="div1" >
<img id="img1" name="img1" src="img1_up.jpg" />
</div>
<div id="div2">
<img id="img2" name="img2" src="img2_up.jpg" />
</div>...and so on
Now here is the script that I currently have for the rollover effects
<script>
var var1 = document.getElementById("div1");
var1.addEventListener("mouseover", changeImage1);
var1.addEventListener("mouseout", restoreImage1);
function changeImage1() {
document.getElementById("img1").src = "img1_ro.jpg";
}
function restoreImage1() {
document.getElementById("img1").src = "img1_up.jpg";
}
var var2 = document.getElementById("div2");
var2.addEventListener("mouseover", changeImage2);
var2.addEventListener("mouseout", restoreImage2);
function changeImage2() {
document.getElementById("img2").src = "img2_ro.jpg";
}
function restoreImage2() {
document.getElementById("img2").src = "img2_up.jpg";
}...and so on
</script>
I would like to use the name attributes from each images to create dynamic code to apply to all images. Here is what I have in mind but not sure the exact way to write it. PLEASE HELP
...
var dynamicVar = ????
dynamicVar.addEventListener("mouseover", changeImage();
dynamicVar.addEventListener("mouseout", restoreImage();
function changeImage() {
document.getElementById(dynamicVar).src = dynamicVar + "_ro.jpg";
}
function restoreImage() {
document.getElementById(dynamicVar).src = dynamicVar + "_up.jpg";
}
You can use loop to add event, don't need to specify id for each div:
var inputs = document.getElementsByTagName("div");
for(var i = 0; i < inputs.length; i++) {
if(inputs[i].id.indexOf('div') >= 0) {
inputs[i].addEventListener("mouseover", changeImage);
inputs[i].addEventListener("mouseout", restoreImage);
}
}
function changeImage(){
var tmpStr = this.id;
var divIndex = tmpStr.substring(3, tmpStr.length);
document.getElementById("img" + divIndex).src = divIndex + "_ro.jpg";
}
function restoreImage(){
var tmpStr = this.id;
var divIndex = tmpStr.substring(3, tmpStr.length);
document.getElementById("img" + divIndex).src = divIndex + "_up.jpg";
}
See on fiddle: Link
try this
var parent = document.getElementById("parent");
var childs = parent.getElementsByTagName('div');
for (var i = 0; i < childs.length; i++) {
(function () {
var e = childs[i];
e.addEventListener("mouseover", function () {
changeImage(e);
});
e.addEventListener("mouseout", function () {
restoreImage(e);
});
}());
}
function changeImage(element) {
var imgs = element.getElementsByTagName('img');
for (var i = 0; i < imgs.length; i++) {
alert(imgs[i].id);
}
}
function restoreImage(element) {
var imgs = element.getElementsByTagName('img');
for (var i = 0; i < imgs.length; i++) {
imgs[i].src = img_ro;
}
}
you can check this fiddle
I'm trying to shuffle som innerHTML, I've created some divisions were I add content from a list, now I want to shuffle this everytime I load the site. I've come up with this solution, and it shuffles the innerHTML, but It doesn't put it out in new HTML. Any ideas how to tweak it? Later I will create and shuffle a list of hrefs of image pictures. So basically it is going to be an 9-square image randomizer. I would really appriciate some help :)
<script>
var squareNumbers = ['1','2','3','4','5','6','7','8','9']; //need to create a new list to append image hrefs
for(var i = 0; i<=squareNumbers.length-1; i++){ //creates the chessboard
var div = document.createElement('div');
div.setAttribute('id', 'square'+squareNumbers[i]);
div.innerHTML = squareNumbers[i];
var checkHTML = document.getElementById('chessBoard').appendChild(div);
}
window.onload = function(){
var squareDivs = document.getElementById('chessBoard').getElementsByTagName('div');
var array = [];
for(var i = 0; i < squareDivs.length; i++){ //creates an array of the squares innerHTML
array.push(squareDivs[i].innerHTML);
}
var i = array.length, j, temp;
while(--i > 0){ //shuffles the array according to Fisher Yeates algorithm
j = Math.floor(Math.random() * (i+1));
temp = array[j];
array[j] = array[i];
array[i] = temp;
var squares = document.getElementById('chessBoard').getElementsByTagName('div').innerHTML = temp;
console.log(squares);
}
}
</script>
Update
This just updates them.
var squareNumbers = ['1','2','3','4','5','6','7','8','9'], j, temp;
for(var i = 0; i < squareNumbers.length; i++){ //creates the chessboard
var div = document.createElement('div');
div.setAttribute('id', 'square' + squareNumbers[i]);
div.innerHTML = squareNumbers[i];
document.getElementById('chessBoard').appendChild(div);
}
window.onload = function(){
for (i = squareNumbers.length - 1; i >= 0; i--) {
j = Math.floor(Math.random() * (i + 1));
temp = squareNumbers[j];
squareNumbers[j] = squareNumbers[i];
squareNumbers[i] = temp;
document.getElementById('chessBoard').getElementsByTagName('div')[i].innerHTML = temp;
}
}
Previous
Here, this does that:
window.onload = function(){
var squareNumbers = ['1','2','3','4','5','6','7','8','9'], j, temp;
for (i = squareNumbers.length - 1; i >= 0; i--) {
j = Math.floor(Math.random() * (i + 1));
temp = squareNumbers[j];
squareNumbers[j] = squareNumbers[i];
squareNumbers[i] = temp;
var div = document.createElement('div');
div.setAttribute('id', 'square'+squareNumbers[i]);
div.innerHTML = squareNumbers[i];
document.getElementById('chessBoard').appendChild(div);
}
}
Line 35, just before the alert, returns -1. I also tried $(this).index() with the same result. Here is what it should do: Clicking EN.gif should return 4, then grand_array_pics[4] should give me en_array_pics and load the .gifs in that array.
$(document).ready(function () {
var main_pics = ["AN.gif", "BN.gif", "CN.gif", "DN.gif", "EN.gif", "GN.gif"];
var starting_pics = ["AN.gif", "CN.gif", "EN.gif"];
var an_array_pics = ["BN.gif", "EN.gif", "GN.gif", "AN.gif","DN.gif"];
var bn_array_pics = ["CN.gif", "DN.gif", "GN.gif"];
var cn_array_pics = ["DN.gif", "GN.gif", "AN.gif", "CN.gif"];
var dn_array_pics = ["EN.gif", "AN.gif", "CN.gif"];
var en_array_pics = ["GN.gif", "AN.gif", "CN.gif", "EN.gif"];
var gn_array_pics = ["AN.gif", "CN.gif", "EN.gif", "GN.gif"];
var grand_array_pics = [
an_array_pics,
bn_array_pics,
cn_array_pics,
dn_array_pics,
en_array_pics,
gn_array_pics
];
var i = 0;
for (i = 0; i < starting_pics.length; i++) {
$("<img/>").attr("src", "images/" + starting_pics[i]).load(function () {
$(this).appendTo("#main");
$(this).addClass("pics");
});
}
$("#main").on("click", ".pics", function () {
var j = $.inArray(this, main_pics);
alert(j);
$("#sidebar .pics").remove();
$(this).clone().appendTo("#train");
$(this).clone().appendTo("#sidebar");
$("#main .pics").remove();
var chosen_pics_array = grand_array_pics[j];
var count = chosen_pics_array.length;
var k = 0;
for (k = 0; k < count; k++) {
$("<img/>").attr("src", "images/" + chosen_pics_array[k]).load(function () {
$(this).appendTo("#main");
$(this).addClass("pics");
});
}
});
}); //end ready
this is the DOM <img> element, while main_pics is an array of strings. It will never be found inside there. Use
var j = $.inArray(this.src.split("/").pop(), main_pics);
Give this a try. You need to get the name of the file and you're passing the element itself into $.inArray
var j = $.inArray(this.src.substring(this.src.lastIndexOf('/')+1), main_pics);
On page load, I am randomizing the order of the children divs with this Code:
function reorder() {
var grp = $("#team-posts").children();
var cnt = grp.length;
var temp, x;
for (var i = 0; i < cnt; i++) {
temp = grp[i];
x = Math.floor(Math.random() * cnt);
grp[i] = grp[x];
grp[x] = temp;
}
$(grp).remove();
$("#team-posts").append($(grp));
}
I cannot seem to figure out how to get the posts back in the original order. Here's the demo of my current code http://jsfiddle.net/JsJs2/
Keep original copy like following before calling reorder() function and use that for reorder later.
var orig = $("#team-posts").children();
$("#undo").click(function() {
orderPosts();
});
function orderPosts() {
$("#team-posts").html( orig ) ;
}
Working demo
Full Code
var orig = $("#team-posts").children(); ///caching original
reorder();
$("#undo").click(function(e) {
e.preventDefault();
orderPosts();
});
function reorder() {
var grp = $("#team-posts").children();
var cnt = grp.length;
var temp, x;
for (var i = 0; i < cnt; i++) {
temp = grp[i];
x = Math.floor(Math.random() * cnt);
grp[i] = grp[x];
grp[x] = temp;
}
$(grp).remove();
$("#team-posts").append($(grp));
}
function orderPosts() {
// set original order
$("#team-posts").html(orig);
}
How about an "undo" plugin, assuming it applies?
Just give each item a class with the corresponding order and then get the class name of each div and save it to a variable
$("#team-posts div").each(function() {
var parseIntedClassname = parseInt($(this).attr("class");
arrayName[parseIntedClassname] = $("#team-posts div." + parseIntedClassname).html()
});
You can reorder them from there by saving their html to an array in order
$("#team-posts").html();
for(var i=0;i<arrayName.length;i++){
$("#team-posts").append('<div class="'+i+'">'+arrayName[i]+'</div>');
}
The solution with saving away the original order is probably the best but if you have to dynamically sort it, you can use this:
http://www.w3schools.com/jsref/jsref_sort.asp
function orderPosts() {
var $grp = $("#team-posts"),
ordered = $grp.children().toArray().sort(function(a, b) {
return parseInt($(a).text()) > parseInt($(b).text());
});
$grp.empty().append(ordered);
}
I'm trying to draw a grid with random images assigned to each square. I'm having trouble with the draw sequence and potentially closure issues with the Javascript variables. Any help is appreciated.
var tileSize = 30;
var drawCanvasImage = function(ctx,tile,x,y) {
return function() {
ctx.drawImage(tile,x,y);
console.log("x = " + x + "/ y = " + y);
}
}
function textures(ctx) {
var grass = new Image();
var sea = new Image();
var woods = new Image();
for (var i=0; i<=10; i++) {
for (var j=0; j<=20; j++) {
rand = Math.floor(Math.random()*3 + 1);
x = i * tileSize;
y = j * tileSize;
if (rand == 1) {
grass.onload = drawCanvasImage(ctx,grass,x,y);
} else if (rand == 2) {
sea.onload = drawCanvasImage(ctx,sea,x,y);
} else {
woods.onload = drawCanvasImage(ctx,woods,x,y);
}
}
}
grass.src = "textures/grass.png";
sea.src = "textures/sea.png";
woods.src = "textures/woods.png";
}
//function called by the onload event in the html body tag
function draw() {
var ctx = document.getElementById("grid").getContext('2d');
grid(ctx); //a function to draw the background grid - works fine
textures(ctx);
}
The current result is three drawn tiles, all at the position of x = 300 (equivalent to the i loop of 10 * the tileSize of 30) and a random y position.
After following a lead and accounting for (maybe?) closure issues by creating the variable drawCanvasImage, I at least got those three tiles to draw.
----Edit----
Working Code - Revision 2:
function randomArray() {
for (var i=0; i<=(xValue/tileSize); i++) {
terrainArray[i] = [];
for (var j=0; j<=(yValue/tileSize); j++) {
rand = Math.floor(Math.random()*4 + 1);
if (rand == 1) {
terrainArray[i][j] = 3;
} else if (rand == 2) {
terrainArray[i][j] = 2;
} else if (rand == 3) {
terrainArray[i][j] = 1;
} else {
terrainArray[i][j] = 0;
}
}
}
}
var drawTerrain = function(ctx,tile,landUseValue) {
return function() {
for (var i=0; i<=(xValue/tileSize); i++) {
for (var j=0; j<=(yValue/tileSize); j++) {
if (terrainArray[i][j] == landUseValue) {
ctx.drawImage(tile,i*tileSize,j*tileSize);
}
}
}
}
}
function textures(ctx) {
var grass = new Image();
var sea = new Image();
var woods = new Image();
var desert = new Image();
grass.onload = drawTerrain(ctx,grass,3);
sea.onload = drawTerrain(ctx,sea,0);
woods.onload = drawTerrain(ctx,woods,2);
desert.onload = drawTerrain(ctx,desert,1);
grass.src = "textures/grass.png";
sea.src = "textures/sea.png";
woods.src = "textures/woods.png";
desert.src = "textures/desert.png";
}
You're rewriting the onloads of the three images in every iteratiom. So, it will only execute the last-added onload f or every image.
Suggestion: run your drawing method only after the thred are loaded(and them just call drawCanvasImage every iteration without an .onload=)
Even better:store the randoms in an array, have each image independantly walk through the array on load and add copies of only itself wherever applicable .
Improvement to rev 2
function randomArray() {
for (var i=0; i<=(xValue/tileSize); i++) {
terrainArray[i] = [];
for (var j=0; j<=(yValue/tileSize); j++) {
rand = Math.floor(Math.random()*4 + 1);
terrainArray[i][j] = 4-rand;
//OR: replace above two lines with terrainArray[i][j]=Math.floor(Math.random()*4 + 1);. There's no need to have them in exactly reverse order.
}
}
}
var drawTerrain = function(ctx,tile,landUseValue) {
return function() {
for (var i=0; i<=(xValue/tileSize); i++) {
for (var j=0; j<=(yValue/tileSize); j++) {
if (terrainArray[i][j] == landUseValue) {
ctx.drawImage(tile,i*tileSize,j*tileSize);
}
}
}
}
}
function textures(ctx) {
var grass = new Image();
var sea = new Image();
var woods = new Image();
var desert = new Image();
grass.onload = drawTerrain(ctx,grass,3);
sea.onload = drawTerrain(ctx,sea,0);
woods.onload = drawTerrain(ctx,woods,2);
desert.onload = drawTerrain(ctx,desert,1);
grass.src = "textures/grass.png";
sea.src = "textures/sea.png";
woods.src = "textures/woods.png";
desert.src = "textures/desert.png";
}
To make it even more flexible, you could use an array to store the images, and then use length. This way, if you want to add another image, all you have to do is modify the array.
var srcArray=["textures/grass.png","textures/sea.png","textures/woods.png","textures/desert.png"];
var imgArray=[];
var terrainArray=[];
function textures(ctx){
randomArray();
for(var i=0;i<srcArray.length;i++){
imgArray[i]=new Image();
imgArray[i].src=srcArray[i];
imgArray[i].onload=drawTerrain(ctx,i);
}
}
function randomArray() {
for (var i=0; i<=(xValue/tileSize); i++) {
terrainArray[i] = [];
for (var j=0; j<=(yValue/tileSize); j++) {
terrainArray[i][j]=Math.floor(Math.random()*srcArray.length);
}
}
}
var drawTerrain = function(ctx,index) {
return function() {
for (var i=0; i<=(xValue/tileSize); i++) {
for (var j=0; j<=(yValue/tileSize); j++) {
if (terrainArray[i][j] == index) {
ctx.drawImage(imgArray[index],i*tileSize,j*tileSize);
}
}
}
}
}
So now, all you have to do is call terrain(ctx) when you want to load all the images. And, whenever you want to add an image to the list of images, just add it to the array up top. You won't have to dig deeper and modify the random values and whatnot.
It's because every time you do a loop, you assign a new function to [image].onload, overwriting the previous one. That's how you end up with only three images.
This should work:
if (rand == 1) {
grass.addEventlistener('load', drawCanvasImage(ctx,grass,x,y), false);
} else if (rand == 2) {
sea.addEventlistener('load', drawCanvasImage(ctx,sea,x,y), false);
} else {
woods.addEventlistener('load', drawCanvasImage(ctx,woods,x,y), false);
}
Here you just add a new listener for every loop.