Based on Insert a div in a random location in a list of divs -- I'm trying to randomly insert some cat photos into a div of non-cat photos:
http://jsfiddle.net/frank_o/QXdL3/21/
But is there a way to prevent the cats from appearing next to each other sequentially? They should be spread out.
JS:
var insertionTemplate = $('.template').find('.image').html(),
insertionTargetChildren = $('.main').find('.image'),
insertionFrequency = 3;
var random;
for (var i = 0; i < insertionFrequency; i++) {
random = Math.floor(Math.random() * insertionTargetChildren.length) + 0;
insertionTargetChildren.eq(random).append(insertionTemplate);
}
HTML:
<div class="template" style="display: none;">
<div class="image">
<img src="http://placekitten.com/75/150" />
</div>
</div>
<div class="main">
<div class="image">
<img src="http://lorempixel.com/75/150" />
</div>
<!-- ... -->
</div>
I've fixed the issues and made a check to see if the next or previous element is a cat.
var target = $('.main').find('.image'),
frequency = 3,
element = $();
for (var i = 0; i < frequency; i++) {
(function getElems() {
element = target.eq( Math.floor(Math.random() * target.length) );
var next = element.next(),
prev = element.prev(),
all = element.add(next, prev);
if (element.hasClass('cat') || next.hasClass('cat') || prev.hasClass('cat')) getElems();
}());
var template = $('.template div').clone(true);
element.before(template);
}
FIDDLE
Within your loop you could check to see whether the number generated is equal to the last number that was generated +-1
DEMO http://jsfiddle.net/QXdL3/22/
for (var i = 0; i < insertionFrequency; i++) {
random = Math.floor(Math.random() * insertionTargetChildren.length) + 0;
if (random != excludeNumA && random != excludeNumB) {
insertionTargetChildren.eq(random).append(insertionTemplate);
}
excludeNumA = random + 1;
excludeNumB = random - 1;
}
You can shotgun the list, like the above answers, but this is a bit more efficient since you only need to inspect the precise objects you are inserting against, rather than inspecting every image.
Add 2 steps. The first should shuffle the array of images so that they're in a different order every time. The second should create an array of insertion points into the other list. If you don't want cat images to be next to each other, then make sure your list of insertion points, is at least spaced by 2.
You should also use <script type="text/template">
tags for your templates.
http://jsfiddle.net/kf2zU/1/
HTML
<script id="cat-template" type="text/template">
<div class="image">
<img src="http://placekitten.com/75/150" />
</div>
</script>
<script id="img-template" type="text/template">
<div class="image">
<img src="http://lorempixel.com/75/150" />
</div>
</script>
<div class="main">
</div>
JS
var catTemplate = $("#cat-template").html();
var imgTemplate = $("#img-template").html();
//place images into .main
var $main = $(".main");
var numImages = 50;
for (var i = 0; i<numImages; i++){
$main.append($(imgTemplate));
}
//make a list of cat images for example
var numCatImages = 50;
var cats = [];
for (i = 0; i < numCatImages; i++){
cats.push($(catTemplate));
}
//shuffle the cat list so they appear in random order
cats = _.shuffle(cats);
//create a list of insertion points
var insertionPoints = [];
var insertionIndex = 0;
var minSpacing = 2;
var maxSpacing = 8;
var spacingRange = maxSpacing - minSpacing;
while(insertionIndex < numImages){
insertionIndex += Math.floor(Math.random() * spacingRange) + minSpacing;
insertionPoints.push(insertionIndex);
}
//place cat images at the insertion points
//it's important to start from the end and work your way forward so the previous insertions don't mess with subsequent insertion points
//so we reverse the array of insertion points
insertionPoints = insertionPoints.reverse();
var catIndex = 0;
_.each(insertionPoints, function(insertionIndex, i){
$main.children().eq(insertionIndex).after(cats[catIndex++]);
});