如何在多个div元素中随机排序内容

7

我对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个回答

21

你是否可以使用像jQuery这样的JavaScript库?这是一个使用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') );

谢谢Owen,我认为这是迄今为止我看到的最好的答案。 - Chris
4
很遗憾,由于我的声望低于15,我无法给这个点赞。但是如果我可以的话,我会这样做。 - Chris

20
最近的一个问题被关闭,认为它是这个问题的重复,但我觉得我有一个比这里任何答案都更好的答案。 这种方法非常直接。 不必复制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);

3
好答案。如果Stackoverflow允许问题有多个“被采纳”的答案,我也会把这个标记为“被采纳”。 - Chris
这也适用于洗牌列表吗? - user962206
@gilly3 关于 "divs.splice(Math.floor(Math.random() * divs.length), 1)[0]" 的问题,[0] 的作用是什么? - user962206
是的,这就是重点。注意 while 循环... 我们会一直循环直到数组为空,而且所有的元素都已经被重新插入。 - gilly3
1
@user962206 - 我已经更新了我的答案,并详细解释了while循环内部发生的事情。希望这能为您澄清问题。 - gilly3
显示剩余5条评论

2
您可以获取每个 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

在 @gilly3 的 好回答 上进一步扩展,使用 jQuery,可以通过随机 sorting div 来避免循环中随机添加元素,然后一次性将它们全部 {{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
我会将这些div包裹在一个外部div中,然后将其id传递给shuffle_content()函数。
在函数中,你可以创建一个新的div,以随机顺序克隆包装div的节点来填充它,然后替换原始的包装div。

0

我会使用服务器端代码来实现这个。我知道这不是你问题的答案,但这是一种替代方案。

最好的问候,
弗兰克


0

针对您的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>

-1
我建议您随机化内容,而不是实际的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>

这并没有回答问题,只是解释了一种移动内容的不同方式。 - Joel Anair
我提供了一种快速移动内容的方法,这也是原作者的初衷。你认为问题在问什么? - Rob Allen

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接