I have 4 div elements in a row (they are cards). I need to mix these divs on every page reflesh. How can I mix them?
I did this:
var random = Math.floor(Math.random() * $(".card").length);
$(".card")
.hide()
.eq(random)
.show();
But it gives just 1 random div. I need 4 random divs.
Here is the divs:
<div className="card clubs" ref="card1">
<img className="img" src={a} alt="a" />
</div>
<div className="card diamonds" ref="card2">
<img className="img" src={b} alt="b" />
</div>
<div className="card hearts" ref="card3">
<img className="img" src={c} alt="c" />
</div>
<div className="card spades" ref="card4">
<img className="img" src={d} alt="d" />
</div>
You can use something like this:
var parent = $("#cards"); // Parent container containing '.card' objects
var cards = parent.children();
while (cards.length) {
parent.append(cards.splice(Math.floor(Math.random() * cards.length), 1)[0]);
}
assuming your cards are wrapped in:
<div id='cards'>
<div className="card clubs" ref="card1">
<img className="img" src={a} alt="a" />
</div>
<div className="card diamonds" ref="card2">
<img className="img" src={b} alt="b" />
</div>
<div className="card hearts" ref="card3">
<img className="img" src={c} alt="c" />
</div>
<div className="card spades" ref="card4">
<img className="img" src={d} alt="d" />
</div>
</div>
What your code does, is choosing the card that will be displayed ("randomly"). If you want to display all the four cards and just shuffle their position, you will have to reposition them randomly.
https://css-tricks.com/snippets/jquery/shuffle-children/
$.fn.shuffleChildren = function() {
$.each(this.get(), function(index, el) {
var $el = $(el);
var $find = $el.children();
$find.sort(function() {
return 0.5 - Math.random();
});
$el.empty();
$find.appendTo($el);
});
};
randojs.com can handle jQuery elements, so it makes this kinda simple.
//grab shuffled array of jQuery card elements
var shuffledCards = randoSequence($(".card"));
//store their shuffled htmls
var shuffledCardHTMLs = [];
for(var i = 0; i < shuffledCards.length; i++){
shuffledCardHTMLs[i] = shuffledCards[i].value[0].outerHTML;
}
//replace cards on page with those shuffled htmls
for(var i = 0; i < shuffledCardHTMLs.length; i++){
$(".card").eq(i)[0].outerHTML = shuffledCardHTMLs[i];
}
This solution does NOT care where on the page the card elements are located; it will handle anything. We store the htmls before we start replacing card elements on the page because we don't want to end up trying to access the html of an element that we've already overwritten. If you want to use this code, just toss this in the head tag of your HTML document first:
<script src="https://randojs.com/1.0.0.js"></script>
Related
I have 2 grid divs, one with images and the other with a list of names. Each element within each of the divs corresponds to another within the other div (eg. .image-1 corresponds with .name-1).
When you hover over one of the elements, I want that element AND the corresponding element in the other div to both disappear.
For example, when you hover over "Name 1", I want that and the corresponding image to both disappear. Here's my general html setup:
<body>
<div class="wrapper">
<div class="picture-grid grid">
<div class="grid-box image-1">
<img src="images/image1.png" />
</div>
<div class="grid-box image-2">
<img src="images/image2.png" />
</div>
<div class="grid-box image-3">
<img src="images/image3.png" />
</div>
<div class="grid-box image-4">
<img src="images/image4.png" />
</div>
<div class="grid-box image-5">
<img src="images/image5.png" />
</div>
</div>
<div class="names-grid grid">
<div class="grid-box name-1">Name 1</div>
<div class="grid-box name-2">Name 2</div>
<div class="grid-box name-3">Name 3</div>
<div class="grid-box name-4">Name 4</div>
<div class="grid-box name-5">Name 5</div>
</div>
</div>
</body>
I'm sorry, I've been stuck on this for hours and would love some help! Here's a fiddle:
https://jsfiddle.net/8egpf1j3/
One solution using JQuery is to add data-* attributes to the HTML markup. In this approach we going to add a data-target attribute that will hold the class of the related element that should be hidden (with opacity: 0) when the current element is hovered. You can use JQuery.data() to work with data-* attributes. Check the next simplified example, from where I hope you can understand the underlying idea.
$(".grid-box").hover(
// Handler for hover-in.
function()
{
$(this).css("opacity", 0);
$($(this).data("target")).css("opacity", 0);
},
// Handler for hover-out.
function()
{
$(this).css("opacity", 1);
$($(this).data("target")).css("opacity", 1);
}
);
.grid-box {
width: 100px;
background-color: skyblue;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="wrapper">
<div class="picture-grid grid">
<div class="grid-box image-1" data-target=".name-1">
IMAGE 1
</div>
<div class="grid-box image-2" data-target=".name-2">
IMAGE 2
</div>
<div class="grid-box image-3" data-target=".name-3">
IMAGE 3
</div>
<div class="grid-box image-4" data-target=".name-4">
IMAGE 4
</div>
</div>
<hr>
<div class="names-grid grid">
<div class="grid-box name-1" data-target=".image-1">
Name 1
</div>
<div class="grid-box name-2" data-target=".image-2">
Name 2
</div>
<div class="grid-box name-3" data-target=".image-3">
Name 3
</div>
<div class="grid-box name-4" data-target=".image-4">
Name 4
</div>
</div>
</div>
You can do it this way, I suppose number of images and names is the same, and they are in the same order. Means image number one is first in its div, and name number one is first in its div.
//getting all pictures by <a> tag
var pictures = document.querySelector(".picture-grid").querySelectorAll("a");
//getting all names by <a> tag
var names = document.querySelector(".names-grid").querySelectorAll("a");
//attach reaction to "hover" event to all pictures and names
for (var i = 0; i < pictures.length; i++){
pictures[i].addEventListener("mouseenter", hide.bind(i));
names[i].addEventListener("mouseenter", hide.bind(i));
}
//run function on "hover" event, i = index of chosen image/name
function hide (){
var i = this;
pictures[i].style.opacity = 0;
names[i].style.opacity = 0;
}
So i am creating a carousel generator framework and I want to make the implementation as simple as possible for the user. The developer is supposed to add
images without caring about design/responsiveness. The framework must take every image and insert it in a div with the classname of "slide". In this case from this code:
<div id="album" class="album">
<img src="./assets/img1.jpeg" alt="img1">
<img src="./assets/img2.jpeg" alt="img2">
<img src="./assets/img3.jpeg" alt="img3">
<img src="./assets/img4.jpeg" alt="img4">
<img src="./assets/img5.jpeg" alt="img5">
<img src="./assets/img6.jpeg" alt="img6">
</div>
the framework should generate this:
<div class="slide">
<img src="./assets/img1.jpeg" alt="img1">
</div>
<div class="slide">
<img src="./assets/img2.jpeg" alt="img2">
</div>
<div class="slide">
<img src="./assets/img3.jpeg" alt="img3">
</div>
<div class="slide">
<img src="./assets/img4.jpeg" alt="img4">
</div>
<div class="slide">
<img src="./assets/img5.jpeg" alt="img5">
</div>
<div class="slide">
<img src="./assets/img6.jpeg" alt="img6">
</div>
But the following code generates only 3 of the 6 images:
let album = document.getElementById("album");
let nextButton = document.getElementById('nextButton');
nextButton.addEventListener('', () => {
album.scrollBy(window.innerWidth, 0);
})
Object.keys(album.children).forEach(key => {
if (album.children[key].tagName === 'IMG') {
let newDiv = document.createElement('div');
newDiv.className = "slide";
newDiv.append(album.children[key]);
album.replaceChild(newDiv, album.children[key]);
}
})
and has an error:
Uncaught TypeError: Cannot read property 'tagName' of undefined
at Object.keys.forEach.key (index.js:9)
at Array.forEach (<anonymous>)
at index.js:8
and the generated carousel is:
Ideas? Thanks in advance.
This happens because .children creates a live collection of nodes so the iteration changes while you insert new children div inside the forEach
you could instead create a static collection like
let nodes = document.querySelectorAll('#album > img');
and iterate over that collection of nodes
let album = document.getElementById('album');
let nodes = document.querySelectorAll('#album > img');
Object.keys(nodes).forEach(i => {
let slide = document.createElement('div');
slide.className = 'slide';
slide.appendChild(nodes[i]);
album.appendChild(slide)
});
Codepen demo
The generated source is
In the Index file I have these divs which I note by IDs, let's say there are 3 of these:
<div class="col-sm-6 col-md-4 col-lg-3 grid-item" id="one">
<div class="well">
<a href="http://" target="_blank">
<img class="class" src="img/pic.jpg" alt=""/>
</a>
<p></p>
<nav>
<div class="anim-icons">
<ul>
<li>
<a href="#">
<img src="" alt="">
</a>
</li>
</ul>
</div>
</nav>
</div>
</div>
And this is part of the JS file:
var one = document.querySelector("#one");
var two = document.querySelector("#two");
var three= document.querySelector("#three");
const randomButton= document.querySelector("#randomButton");
function Randomizer() {
var array = [one, two, three];
var result = array[Math.floor(Math.random() * array.length)];
console.log(result);
var node = document.createElement("DIV");
node.innerHTML(result);
node.appendChild(result);
document.getElementById("#placeofresult").appendChild(node);
}
randomButton.addEventListener("click", Randomizer, false);
This if where I want that above div to be displayed:
<div>
<button class="btn btn-light" id="randomButton">
press!
</button>
<br>
<div id="placeofresult"> </div>
</div>
If I press the button, I want one of the divs from the Index file displayed in the div on the page where this JS belongs, but I don't know how to append a whole div by an id.
Thank you for your insights in advance!
appendChild will work fine if you need to insert div into another one.
Suppose, there is <div id="one">One</div> which you want to append inside <div id="placeofresult"></div>; you need to do the following
document.getElementById("placeofresult").appendChild(document.getElementById("one"));
or if you want to clone the div with id="one" and insert it, do the following:
const newOne = document.getElementById("one").cloneNode(true);
document.getElementById("placeofresult").appendChild(newOne);
Hope it helps. Revert for any doubts.
A solution for your problem could be to write the three divs you want to display entirely into js like this:
const divs = [
"
<div id="one">
...
</div>
",
"<div id="two">
...
</div>
",
"<div id="three">
...
</div>
"
]
Using your randomButton
randomButton.addEventListener("click", Randomizer, false);
You just have to set the innerHTML of your result div to the corresponding div of the divs array:
function Randomizer() {
var resultHTML = divs[Math.floor(Math.random() * array.length)];
document.getElementById("#placeofresult").innerHTML(resultHTML);
}
Another solution is to set the style of your divs to display none and display only the randomly chosen div after the button click:
Your html:
<div id="placeofresult">
<div id="one" style="display:none">
...
</div>
<div id="two" style="display:none">
...
</div>
<div id="three" style="display:none">
...
</div>
</div>
Your Randomizer:
function Randomizer() {
var array = [one, two, three];
// Set all divs to hidden
array.forEach(function(id){
document.getElementById(id).style.display = "none";
})
var result = array[Math.floor(Math.random() * array.length)];
document.getElementById(result).style.display = "block";
}
I have a single page site which shows/hides section on click within the viewport.
This is an example of one of the sections:
<section id="question1">
<div class="container-fluid">
<div class="row">
<div class="question-container">
<div class="question-box">
<p>What is the answer to this question?</p>
</div>
</div>
<a href="#">
<div id="cheetah" class="col-xs-12 col-lg-6">
<img src="images/cheetah.jpg" class="img-responsive" />
</div>
</a>
<a href="#">
<div id="hedgehog" class="col-xs-12 col-lg-6">
<img src="images/hedgehog.jpg" class="img-responsive" />
</div>
</a>
</div>
</div>
</section>
The problem I am having is that I don't want section ID's to be the same as the a tag href within it. If that makes sense? This is the jQuery I have already:
$(document).ready(function(){
//ID array
var questionArray = ['#question1', '#question2', '#question3', '#question4', '#question5', '#question6', '#question7', '#question8', '#question9', '#question10'];
//collect sections and place in array
var sectionArray = [];
$('section').each(function(){
sectionArray.push(this);
})
//randomise id array
questionArray.sort(function() {
return 0.5 - Math.random()
});
//Target a elements - attach ID to next question
for(var i = 0; i < sectionArray.length; i++) {
var aEl = $(sectionArray[i]).find('a');
$(aEl).each(function(){
$(this).attr('href', questionArray[i]);
})
}
}
Any help?
EDIT:
Link to codepen: https://codepen.io/samrbrown/full/aLdgYK/
I am using a script called swipeview to put multiple instances of a gallery on a page. It generates the structure like this:
<div id="slider-1">
<div id="swipeview-slider">
<div id="swipeview-masterpage">
<img src="images/01.jpg" id="one"/>
</div>
<div id="swipeview-masterpage" class="swipeview-active">
<img src="images/02.jpg" id="two"/>
</div>
</div>
</div>
<div id="slider-2">
<div id="swipeview-slider">
<div id="swipeview-masterpage">
<img src="images/01.jpg" id="one"/>
</div>
<div id="swipeview-masterpage" class="swipeview-active">
<img src="images/02.jpg" id="two"/>
</div>
</div>
</div>
The only thing that is unique to each image is the top-level div ID (slider-1, slider-2).
Without using jQuery, how can I get the ID of each separate image within the 'swipeview-active' class?
With jQuery I would select them with something along these lines:
$('#slider-1 > .swipeview-slider > .swipeview-masterpage .swipeview-active > img ').attr('id');
How can I do achieve this in regular js?
First of all: IDs must not start with a digit.
The dot-selector selects elements by class name. Use class=.. instead of id=....
Corrected code, using document.querySelectorAll (demo: http://jsfiddle.net/rGAkm/3/).
var images = document.querySelectorAll('#slider-1 > .swipeview-slider > .swipeview-masterpage .swipeview-active > img[id]');
var len = images.length;
var output = document.getElementById('output');
for (var i=0; i<len; i++) {
var image = images[i];
output.appendChild(image);
}
Replace #slider-1 with [id^="slider-"] if you want to select all images in this structure, which is a child of id="slider-1", id="slider-2", ...
Probably not the most elegant solution, but it works. I replaced the img tags with span tags for demonstration. I also gave the last 2 span tags a different id, and added one extra, to show it working on both root slider divs for any number of spans (images). Hope it helps.
http://jsfiddle.net/vNqhd/3/
html:
<div id="slider-1">
<div id="swipeview-slider">
<div id="swipeview-masterpage">
<span id="one">img1</span>
</div>
<div id="swipeview-masterpage" class="swipeview-active">
<span id="two">img2</span>
</div>
</div>
</div>
<div id="slider-2">
<div id="swipeview-slider">
<div id="swipeview-masterpage">
<span id="three">img3</span>
</div>
<div id="swipeview-masterpage" class="swipeview-active">
<span id="four">img4</span>
</div>
<div id="swipeview-masterpage" class="swipeview-active">
<span id="five">img5</span>
</div>
</div>
</div>
<button onclick="myfunc('slider-1');">button</button>
<button onclick="myfunc('slider-2');">button</button>
<div id="msg"></div>
js:
function myfunc(divID){
var myVar = document.getElementById(divID);
var imgIDs = [];
var counter = 0;
var str = "";
//walk the DOM from a root div and look for img/span tags
//and store their IDs
while(true){
if(myVar === undefined){ break; }
if(myVar.getElementsByTagName('div').length > 0){
myVar = myVar.getElementsByTagName('div')[0];
continue;
} else if(myVar.getElementsByTagName('span').length > 0){
imgIDs.push(myVar.getElementsByTagName('span')[0].id);
counter++;
myVar = myVar.parentNode.getElementsByTagName('div')[counter];
} else { break; }
}
//display results
for(var i = 0; i < imgIDs.length; i++){
str += imgIDs[i] + "<br/>";
}
document.getElementById('msg').innerHTML = str;
}