Любой способ перемешать содержимое в нескольких элементах div - PullRequest
5 голосов
/ 24 ноября 2008

Я относительно новичок в Javascript и мне было интересно, есть ли быстрый способ перемешать контент, содержащийся в нескольких тегах <div>. Например

<div id='d1'>
  <span>alpha</span>
  <img src='alpha.jpg'>
</div>
<div id='d2'>
  <span>beta</span>
  <img src='beta.jpg'>
</div>
<div id='d3'>
  <span>gamma</span>
  <img src='gamma.jpg'>
</div>

<button onclick='shuffle_content();'>Shuffle</button>

После нажатия на кнопку, я бы хотел, чтобы содержимое в d1, d2, d3 менялось местами (например, возможно, сначала будет d3, затем d1, затем d2).

Быстрый способ переместить вещи - скопировать первый элемент div (d1), затем поместить его в самый конец (после d3), а затем удалить исходный d1. Но это на самом деле не случайным образом. Это просто заставляет вещи идти в цикле (что может быть хорошо).

Любые предложения будут оценены. Спасибо.

Ответы [ 8 ]

19 голосов
/ 24 ноября 2008

Вы в порядке с использованием библиотеки JavaScript, как jQuery ? Вот быстрый пример jQuery, чтобы выполнить то, что вам нужно. единственная модификация вашего HTML - это добавление элемента контейнера, как было предложено:

<div id="shuffle">
    <div id='d1'>...</div>
    <div id='d2'>...</div>
    <div id='d3'>...</div>
</div>

и JavaScript:

function shuffle(e) {               // pass the divs 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 our set
       replace.append(temp);        // add the selected div to our new set
       e = e.not(temp); // remove our selected div from the main set
       size--;
    }
    $('#shuffle').html(replace.html() );     // update our container div with the
                                             // new, randomized divs
}

shuffle( $('#shuffle div') );
14 голосов
/ 10 марта 2012

Недавний вопрос был просто закрыт как дубликат этого, но я чувствую, что у меня есть лучший ответ, чем любой здесь. Этот метод очень прямой. Нет копирования с копированием HTML, поэтому сохраняются изменения в DOM, стилях, обработчиках событий и т. Д.

Чтобы перетасовать все дочерние элементы некоторого родительского элемента, выберите случайный дочерний элемент и добавляйте его обратно к родительскому элементу за раз, пока все дочерние элементы не будут повторно добавлены.

Использование jQuery:

var parent = $("#shuffle");
var divs = parent.children();
while (divs.length) {
    parent.append(divs.splice(Math.floor(Math.random() * divs.length), 1)[0]);
}

Демо: http://jsfiddle.net/C6LPY/2

Без jQuery это похоже и просто:

var parent = document.getElementById("shuffle");
var divs = parent.children;
var frag = document.createDocumentFragment();
while (divs.length) {
    frag.appendChild(divs[Math.floor(Math.random() * divs.length)]);
}
parent.appendChild(frag);

Демо: http://jsfiddle.net/C6LPY/5/



Редактировать: Ниже приведен код:

// Create a document fragment to hold the shuffled elements
var frag = document.createDocumentFragment();

// Loop until every element is moved out of the parent and into the document fragment
while (divs.length) {

    // select one random child element and move it into the document fragment
    frag.appendChild(divs[Math.floor(Math.random() * divs.length)]);
}

// appending the document fragment appends all the elements, in the shuffled order
parent.appendChild(frag);
2 голосов
/ 24 ноября 2008

Вы можете получить содержимое каждого div

c1 = document.getElementById('div1').innerHTML
c2 = document.getElementById('div2').innerHTML
c3 = document.getElementById('div3').innerHTML

Затем определите новый порядок для них случайным образом .. и затем поместите каждый контент в новое место назначения

скажем, например, случайность дала:

c1_div = 'div2'
c2_div = 'div1'
c3_div = 'div3'

тогда вы просто:

document.getElementById(c1_div).innerHTML = c1
document.getElementById(c2_div).innerHTML = c2
document.getElementById(c3_div).innerHTML = c3
1 голос
/ 07 мая 2019

Расширение на хороший ответ с помощью @ gilly3, используя jQuery, можно фактически избежать добавления случайно выбранных элементов divs в цикле, случайным образом sort ing * Вместо 1007 * и append сразу все:

$(function() {
  var parent = $("#shuffle");
  var divs = parent.children();
  divs.sort(function(a, b) {
    return 0.5 - Math.random();
  });
  parent.append(divs);
});

Демо : http://jsfiddle.net/ey70Lxhk/

Обратите внимание, что этот метод не является точным с точки зрения случайности и основан на sort, который не масштабируется линейно с количеством элементов.

0 голосов
/ 25 ноября 2008

Для вашего HTML короткий ответ на ваш вопрос:

function shuffle_content() {
 var divA = new Array(3);
 for(var i=0; i < 3; i++) {
  divA[i] = document.getElementById('d'+(i+1));
  document.body.removeChild(divA[i]);
 }
 while (divA.length > 0)
  document.body.appendChild(divA.splice(Math.floor(Math.random() * divA.length),1)[0]);
}

Чтобы туда попасть, я написал следующее, что, я думаю, работает лучше:

<html>
<div id="cards">
<div id="card0">Card0</div><div id="card1">Card1</div>
<div id="card2">Card2</div><div id="card3">Card3</div>
<div id="card4">Card4</div><div id="card5">Card5</div>
<div id="card6">Card6</div><div id="card7">Card7</div>
<div id="card8">Card8</div><div id="card9">Card9</div>
</div>
<button id="shuffle">Shuffle</button>
<script language="javascript">
<!--
document.getElementById('shuffle').onclick = function () {
var divCards = document.getElementById('cards');
var divCardsArray = new Array(
    document.getElementById('card0'),
    document.getElementById('card1'),
    document.getElementById('card2'),
    document.getElementById('card3'),
    document.getElementById('card4'),
    document.getElementById('card5'),
    document.getElementById('card6'),
    document.getElementById('card7'),
    document.getElementById('card8'),
    document.getElementById('card9')
    );
return function() {
    var mDivCardsArray=divCardsArray.slice();
    while (divCards.childNodes.length > 0) {
        divCards.removeChild(divCards.firstChild);
    }
    while (mDivCardsArray.length > 0) {
        var i = Math.floor(Math.random() * mDivCardsArray.length);
        divCards.appendChild(mDivCardsArray[i]);
        mDivCardsArray.splice(i,1);
    }
    return false;
}
}()
//-->
</script>
</html>

Я пытался упаковать этот последний оператор while в:

    while (mDivCardsArray.length > 0) {
        divCards.appendChild(
            mDivCardsArray.splice(
                Math.floor(Math.random() * mDivCardsArray.length)
                ,1)[0]
        );
    }

но это довольно сложно прочитать и подвержено ошибкам.

Используя jQuery или Prototype, вы можете следовать той же базовой структуре и получить желаемый результат.

Лично я думаю, что это выглядит даже лучше, если вы добавите еще 2 div в стек cards, развернете divCardsArray, вставите следующий блок стилей и добавите этот код сразу после определения divCardsArray.

<html>
...
<style>
html,body{height:100%;width:100%;text-align:center;font-family:sans-serif;}
#cards,#cards div{padding:5px;margin:5px auto 5px auto;width:100px;}
</style>
...
<div id="cardA">CardA</div><div id="cardB">CardB</div>
...
var colorCardsArray = new Array(
    '#f00', '#f80', '#ff0', '#8f0', '#0f0', '#0f8',
    '#0ff', '#08f', '#00f', '#80f', '#f0f', '#f08' );
for(var i=0;i<divCardsArray.length;i++)
    divCardsArray[i].style.backgroundColor=colorCardsArray[i];
...
</html>
0 голосов
/ 24 ноября 2008

Я бы использовал серверный код для достижения этой цели. Я знаю, что на самом деле это не ответ на ваш вопрос, но - альтернативная реализация.

С наилучшими пожеланиями,
Фрэнк

0 голосов
/ 24 ноября 2008

Я бы предложил вам рандомизировать контент, а не самих Div. Вы можете сделать это, поместив контент на отдельные html-страницы - без заголовка или тела, а только с контентом.

Затем используйте функцию при загрузке страницы, чтобы случайным образом назначить, какой div получает какой контент, и используйте это для изменения содержимого DIV:

<script type="text/javascript">
    function ajaxManager(){
        var args = ajaxManager.arguments;

        if (document.getElementById) {
            var x = (window.ActiveXObject) ? new ActiveXObject("Microsoft.XMLHTTP") : new XMLHttpRequest();
        }
        if (x){         
            switch (args[0]){
                case "load_page":
                    if (x)
                    {
                        x.onreadystatechange = function()
                        {
                            if (x.readyState == 4 && x.status == 200){
                                el = document.getElementById(args[2]);
                                el.innerHTML = x.responseText;
                            }
                        }
                        x.open("GET", args[1], true);
                        x.send(null);
                    }
                    break;

                case "random_content":
                    ajaxManager('load_page', args[1], args[2]); /* args[1] is the content page, args[2] is the id of the div you want to populate with it. */       
                    break;
            } //END SWITCH
        } //END if(x)
    } //END AjaxManager

</script>
0 голосов
/ 24 ноября 2008

Я бы обернул div в внешний div, а затем передал бы его идентификатор shuffle_content ().

Там вы можете создать новый div, клонировать узлы div обертки в случайном порядке, чтобы заполнить его, затем заменить div обертки новым div.

...