What I need done is:
Original State:
<div class="shuffledv">
<div id="1"></div>
<div id="2"></div>
<div id="3"></div>
</div>
<div class="shuffledv">
<div id="4"></div>
<div id="5"></div>
<div id="6"></div>
</div>
After Shuffle:
<div class="shuffledv">
<div id="2"></div>
<div id="3"></div>
<div id="1"></div>
</div>
<div class="shuffledv">
<div id="5"></div>
<div id="4"></div>
<div id="6"></div>
</div>
The Divs within the first div stay there but get shuffled, and the same happens for the second div with the same class.
To shuffle divs inside a specific div I use something like this:
function shuffle(e) { // pass divs inside #parent to the function
var replace = $('<div>');
var size = e.size();
while (size >= 1) {
var rand = Math.floor(Math.random() * size);
var temp = e.get(rand); // grab a random div from #parent
replace.append(temp); // add the selected div to new container
e = e.not(temp); // remove our selected div from #parent
size--;
}
$('#parent').html(replace.html()); // add shuffled divs to #parent
}
Called lie this: shuffle('#parent .divclass')
Where all Divs with class divclass are inside #parent
I think it should start out something like
function shuffle() {
$(".shuffledv").each(function() {
and then do some form of the original function, but I've just gotten completely lost at this point. I have no idea how to go forward from here. Please let me know if you need anymore info.
Take a look at this jsfiddle. Essentially what we do is for each of the container shuffledv divs we find all children divs and store them in a list, then we remove them from the DOM, e.g.:
$(".shuffledv").each(function(){
var divs = $(this).find('div');
for(var i = 0; i < divs.length; i++) $(divs[i]).remove();
Then I grabbed the Fisher-Yates shuffling algorithm from here to randomise the list of our divs, and finally we append them back to the parent container, like this:
for(var i = 0; i < divs.length; i++) $(divs[i]).appendTo(this);
Hope this helps!
Gave this an initial run through:
(function () {
"use strict";
// Cycle over each .shuffledv HTMLElement
$(".shuffledv").each(function () {
// Remove all divs within, store in $d
var $d = $(this).find("div").remove();
// Sort $d randomnly
$d.sort(function () { return Math.floor(Math.random() * $d.length); });
// Append divs within $d to .shuffledv again
$d.appendTo(this);
});
}());
Demo: http://jsfiddle.net/uYyAH/2/
Related
I would like to shuffle specific DIVs (based on class) around on each page load.
Note i'm using a Wordpress Theme and as such, do not have full control over HTML structure without changing base themes (which i'm not willing to do)
jfiddle is here.
$(function() {
$(".shuffle").each(function() {
var parent = $(this),
divs = parent.children().remove();
while (divs.length) {
parent.append(divs.splice(Math.floor(Math.random() * divs.length), 1)[0]);
}
});
});
Parent DIV class = "shuffle"
Child DIVs class = "shuffle-child"
What am I doing wrong? Apologies for lack of JS experience!!
For your particular scenario you can use the following, adapted for jQuery from https://stackoverflow.com/a/11972692/2413733 #AlexeyLebedev's answer using the Fischer-Yates Shuffle.
var shuffleKids = $('.shuffle-kids'), // the elements to shuffle
shuffle = shuffleKids.parent(); // the container div
for (var i = shuffleKids.length; i >= 0; i--) {
shuffle.append(shuffle.children()[Math.random() * i | 0]);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class='shuffle'>
<div class='shuffle-kids'>milk</div>
<div class='shuffle-kids'>butter</div>
<div class='shuffle-kids'>eggs</div>
<div class='shuffle-kids'>orange juice</div>
<div class='shuffle-kids'>bananas</div>
</div>
I would like to rebuild an html tag structure to a new one on resizing the browser window. Have anyone an idea how can I get from the first structure to the second structure. I need this for an responsive personal project. Maybe with an JavaScript resize Event, I don't know...
<div class="wrapper">
<div class="slide">
<div class="item"></div>
<div class="item"></div>
</div>
<div class="slide">
<div class="item"></div>
<div class="item"></div>
</div>
</div>
<div class="wrapper">
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
</div>
You could listen to the resize event on the window and then restructure your HTML when the window is below a certain size. Moving elements from the first structure to the second isn't a big problem, however the challenge lies in reverting that again. How will you know which of the .item's belonged to which .slide?
One way to do this is to keep track of the parent for each .item in a separate data- attribute when you make the list:
function makeList() {
var $slides = $('.slide'),
$items = $();
// For each slide set a data-attribute on all its child .item's
$slides.each(function(i) {
var $item = $(this).children('.item');
$item.attr('data-slide', i+1);
$items = $items.add($item);
});
// Append all items directly to the wrapper
$('.wrapper').html($items).attr('data-structure', 'list');
}
I set a data attribute to the .wrapper so we know that it's already converted to a list. Otherwise on every resize this would be fired, you only want it once (until it resizes back to where you want the slides).
When you want the slide again, loop through all the .items and keep a list of slide number's. For each new data-slide number you encounter make a new slide and add that to the total list;
function makeSlides() {
var $slides = $(),
slideNumbers = [],
$currentSlide = $();
$('.item[data-slide]').each(function() {
var $item = $(this),
slideNumber = $item.attr('data-slide');
// if the slide number wasn't in the array yet push the current slide into $slides and create a new one
if(slideNumbers.indexOf(slideNumber) < 0) {
$slides = $slides.add($currentSlide);
$currentSlide = $('<div class="slide" />');
slideNumbers.push(slideNumber);
}
$currentSlide.append($item);
});
// add the last currentSlide
$slides = $slides.add($currentSlide);
// place all slides in the wrapper
$('.wrapper').html($slides).attr('data-structure', 'slides');
}
Then finally you bind the resize event and fire these functions when needed:
$(window).resize(function(e) {
var currentStructure = $('.wrapper').attr('data-structure');
if(window.innerWidth < 600) {
if( currentStructure !== 'list') {
makeList();
}
} else {
if( currentStructure !== 'slides') {
makeSlides();
}
}
});
jsFiddle demo: http://jsfiddle.net/gktLnw31/3/
I do think this could be a bit more efficient, but this is just a proof of concept. Hopefully it'll give you some insights.
I would better take a look at foundation since it already includes the responsive design by default instead of trying to change it dynamically by code
I have a parent div and it has 9 same div's am trying to swap two div's index. Following is my code:
HTML:
<div id="cont" class="container">
<div class="no">1</div>
<div class="no">2</div>
<div class="no">3</div>
<div class="blank"></div>
<div class="no">4</div>
<div class="no">5</div>
<div class="no">6</div>
<div class="no">7</div>
<div class="no">8</div>
</div>
now I want to swap say 5th and 6th indexed elements. I have no clue how to do that in JavaScript. I know there is function called .index() but how to do that in pure JS.
Here's one implementation: http://jsfiddle.net/x8hWj/2/
function swap(idx1, idx2) {
var container = document.getElementById('cont');
// ditch text nodes and the like
var children = Array.prototype.filter.call(
container.childNodes,
function(node) {
return node.nodeType === 1;
}
);
// get references to the relevant children
var el1 = children[idx1];
var el2 = children[idx2];
var el2next = children[idx2 + 1];
// put the second element before the first
container.insertBefore(el2, el1);
// now put the first element where the second used to be
if (el2next) container.insertBefore(el1, el2next);
else container.appendChild(el1);
}
This starts by getting a list of all element child nodes, then uses insertBefore to rearrange them.
The JS below works exactly like it should, my JS knowledge is 0%. Only thing is i need the code below to target multiple divs but same id or different id's does not matter. It also needs to be infinite. so every 50 seconds it needs to repeat. The goal of the js below is to reset CSS3 animations i have running. Project files can be found here: www.dreamsynk.com/img/slider.
// retrieve the element
element = document.getElementById("ani");
setTimeout(function() {
// -> removing the class
element.classList.remove("one");
// -> triggering reflow /* The actual magic */
// without this it wouldn't work. Try uncommenting the line and the transition won't be retriggered.
element.offsetWidth = element.offsetWidth;
// -> and re-adding the class
element.classList.add("one");
}, (50*1000)); //40 seconds
UPDATES:
<div class="slider">
<div class="inner">
<div id="ani" class="one"></div>
<div id="ani" class="two"></div>
<div id="ani" class="three"></div>
<div id="ani" class="four"></div>
<div id="ani" class="five"></div>
<div id="ani" class="six"></div>
</div>
</div>
// retrieve an array-like object with elements
var elements = document.querySelectorAll("ani");
setTimeout(function() {
for (var i=0; i<elements.length; i++) {
var element = elements[i];
element.classList.remove("one two three four five six");
element.offsetWidth = element.offsetWidth;
element.classList.add("one two three four five six");
}
}, (50*1000)); //50 seconds
I am doing something wrong?
You should use document.getElementsByClassName if you want to have an array of elements. document.getElementById normally only gives you the first element of that ID.
The difference between an ID and a class is that an ID can be used to identify one element, whereas a class can be used to identify more than one.
You can also use document.getElementsByName(),
document.getElementsByTagName(),
document.getElementsByTagNameNS() and document.querySelectorAll() of course.
The elements you get from document.getElementsByClassName is known as a HTMLCollection, which is just an array. So if you want to add elements into the collection you can use array.push.
var array = document.getElementsByClassName("classname");
var element = document.getElementById("ani");
array.push(element);
setTimeout(function() {
var i = array.length;
while(i--) {
array[i].classList.remove("one");
array[i].offsetWidth = element.offsetWidth;
array[i].classList.add("one");
}
}, (99999));
Updates:
.classList.remove() can only do 1 class at a time. The same goes
to .classList.add().
What you can do is to create a prototype for DOMTokenList
like this:
DOMTokenList.prototype.addMany = function(classes) {
var array = classes.split(' ');
for (var i = 0, length = array.length; i < length; i++) {
this.add(array[i]);
}
}
and remove/add the classes this way:
element.classList.addMany("one two three four five six");
By the way for .querySelectorAll(selector), you are not using
a proper CSS selector.
You can read more about the syntax of CSS selector here.
And as I have mentioned before, you can't have duplicate ids.
Ids are supposed to be unique.
You can use querySelectorAll to get elements with any css path and then every 50 seconds iterate between them and do the same steps you did for your single element.
Code fixed for your use case:
HTML:
<div class="slider">
<div class="inner">
<div class="ani" id="one"></div>
<div class="ani" id="two"></div>
<div class="ani" id="three"></div>
<div class="ani" id="four"></div>
<div class="ani" id="five"></div>
<div class="ani" id="six"></div>
</div>
</div>
JavaScript:
var container = document.querySelector('slider');
var elements = Array.prototype.slice.call(container.querySelectorAll(".ani"));
setTimeout(function() {
elements.forEach(function(el) { el.classList.remove('ani'); });
container.offsetWidth = container.offsetWidth;
elements.forEach(function(el) { el.classList.add('ani'); });
}, (50*1000)); //50 seconds
// retrieve the elements
var elements = document.querySelectorAll("div");
setInterval(function() {
for(var i = 0; i < elements.length; i++){
// -> removing the class
elements[i].classList.remove("one");
// -> triggering reflow /* The actual magic */
// without this it wouldn't work. Try uncommenting the line and the transition won't be retriggered.
elements[i].offsetWidth = element.offsetWidth;
// -> and re-adding the class
elements[i].classList.add("one");
}
}, (50*1000)); //50 seconds
I have a page that looks like so:
<div id="container">
<div class="item">...</div>
<div class="item">...</div>
<div class="item">...</div>
<div class="item">...</div>
</div>
I was wondering if there is a way that I could insert a div randomly between any of the "item" divs, so when the page is loaded, it would look like:
<div id="container">
<div class="item">...</div>
<div class="item">...</div>
<div class="rondomDiv">...</div>
<div class="item">...</div>
<div class="item">...</div>
</div>
All the divs with the "item" class are dynamically generated, and cannot be modified. Any ideas?
Thanks in advance!
Try something like below,
var $items = $('#container').find('.item');
var pos = Math.floor(Math.random() * $items.length)
$('.randomDiv').insertAfter($items.eq(pos));
I'd suggest, pending further information:
$('.item').eq(
/* I'm using the eq() method to select a specific element,
and creating the random number (in the range from 0-(number-of-elements))
within the method to avoid creating unnecessary variables. */
Math.floor(Math.random() * $('.item').length)
/* after() creates an element from the html string, and inserts it after
the element selected earlier with the eq() method */
).after('<div class="random"></div>');
JS Fiddle demo.
A slightly altered, though more verbose, alternative to the above:
$('<div />', {
'class': 'random',
'text': '...'
}).insertAfter($('.item').eq(Math.floor(Math.random() * $('.item').length)));
JS Fiddle demo.
References:
after().
eq().
insertAfter().
Math.floor().
Math.random().
Code:
HTML:
<div id="container">
</div>
JS:
$(document).ready(function(){
for(var i =1; i<10; i++) {
$("#container").append("<div class='item' id='"+i+"'>Item</div>"); /*adding item divs dynamically */
}
/*the real magic is below */
var rand_id = Math.floor((Math.random()*10)+1); /*generating an item divs ID randomly */
$("#"+rand_id).after("<div class='randomDiv'>Random DIv</div>"); /*adding the random div after that div of the rand_id */
});
Fiddle: http://jsfiddle.net/mareebsiddiqui/ULcTc/
Explanation:
This is simple. First I add the item divs dynamically by giving them ID's respectively with starting from 1 and ending on 10. Then I generate a random ID using Math.floor() and Math.random() JavaScript functions. Then I fetch(using a simple technique) the div with that random ID and then after that div I add a random div.
I will not provide code if you tried nothing.
But if you don't know where to start and need a workflow :
Coun't the number of div in container Create a random number between 0 and the number of div.
Append your div after the div with the random number index.
This will work:
function randomDiv() {
var divCount = $(".item").length;
var randomnumber=Math.floor(Math.random()*divCount);
$("div.item:eq(" + randomnumber + ")").after("<div class='randomDiv'>hey im random</div>");
}
Demo: http://jsfiddle.net/meaFv/
This is a case where the non-jQuery answer is equivalent to the jQuery answer, in terms of lines of code:
// Assuming you already have a reference to the random div at "randomDiv"
var container = document.getElementById('container');
var position = Math.floor(Math.random() * container.childNodes.length);
container.insertBefore(randomDiv, childNodes[position]);
Example here: http://jsfiddle.net/qbqfR/ Press RUN a bunch of times to see it in action.
var x=Math.floor(Math.random()*$('#container').children().length);
$('#container div').eq(x).append('<div class="rondomDiv">YAY</div>');
itemLength = $('#container .item').length; //quantity of .items
randomPlace = Math.floor((Math.random()*itemLength)); //some random from 0 to .item length
randomDiv = $('<div />',{
'class':'randomDiv',
text: randomPlace
}); //.randomDiv
$('#container .item').eq(randomPlace).after(randomDiv); //place it after the .item of position 'randomPlace'
http://jsfiddle.net/RaphaelDDL/4tpCy/
Try this -
var $items = $('#container .item');
$items.eq(Math.floor(Math.random() * $items.length ))
.after("<div class='rondomDiv'></div>");