【问题标题】:Randomize a sequence of div elements with jQuery使用 jQuery 随机化 div 元素序列
【发布时间】:2010-12-04 18:29:09
【问题描述】:

我正在尝试使用 jQuery 完成我的第一步,但我在理解如何从 div 父元素中查找子元素列表时遇到了一些麻烦。我习惯于使用 ActionScript 2 和 ActionScript 3,所以我可能会误解一些概念,比如用 jQuery 随机化 div 元素序列的更好方法是什么!

我有这个简单的 HTML 代码部分:

<div class="band">
    <div class="member">
        <ul>
            <li>John</li>
            <li>Lennon</li>
        </ul>
    </div>
    <div class="member">
        <ul>
            <li>Paul</li>
            <li>McCartney</li>
        </ul>
    </div>
    <div class="member">
        <ul>
            <li>George</li>
            <li>Harrison</li>
        </ul>
    </div>
    <div class="member">
        <ul>
            <li>Ringo</li>
            <li>Starr</li>
        </ul>
    </div>
</div>

我尝试了一些方法来做到这一点,例如在一个数组中映射 .member div,然后更改排序顺序但没有成功。

function setArrayElements (element_parent) {
    var arr = [];
    //alert (element_parent[0].innerHTML);
    for (var i = 0; i < element_parent.children().length; i ++) {
        arr.push (element_parent[i].innerHTML);
    }
}
setArrayElements($(".band"));

当我试图提醒 element_parent[0] 时,我想得到我的 .member div 列表的第一个孩子,但事实并非如此。

如果我使用 element_parent[0].innerHTML 发出警报,我会看到:

<div class="member">
    <ul>
        <li>John</li>
        <li>Lennon</li>
    </ul>
</div>
<div class="member">
    <ul>
        <li>Paul</li>
        <li>McCartney</li>
    </ul>
</div>
<div class="member">
    <ul>
        <li>George</li>
        <li>Harrison</li>
    </ul>
</div>
<div class="member">
    <ul>
        <li>Ringo</li>
        <li>Starr</li>
    </ul>
</div>

为什么? 我该怎么做才能得到这样的成员之一?

<div class="member">
    <ul>
        <li>Paul</li>
        <li>McCartney</li>
    </ul>
</div>

我确定这应该很容易,但我只是不知道怎么做 :(

请帮忙
谢谢
维托里奥


编辑:

感谢快速和各种获取选定孩子的方式,我会记下这些方式以备不时之需!
我尝试了这种方法,但似乎我无法获得整个 div(如果我弄错了什么,请告诉我,这可能太多了!!)。

我应该得到这个内容:

<div class="member">
    <ul>
        <li>Ringo</li>
        <li>Starr</li>
    </ul>
</div>

但是使用像 $("div.band div.member:eq(2)") 这样的方法之一或其他有用的方法,我得到了这个:

alert ($('div.band div.member')[0]);
/* result
<ul>
    <li>Ringo</li>
    <li>Starr</li>
</ul>
*/

那么有没有办法在我的节点中获取 .member div 容器?

【问题讨论】:

  • 你也会得到容器 div。如果使用 Firebug 和 console.log,则输出元素是第一个具有类成员的 div
  • 啊!谢谢,现在我知道我没有错!再见

标签: jquery html sorting html-manipulation


【解决方案1】:
$('div.band div.member');

将为您提供一个包含 &lt;div&gt; 的 jQuery 对象,该对象与选择器匹配,即带有类 member 的 div 是带有类 band 的 div 的后代。

jQuery 对象是一个类似数组的对象,其中每个匹配的元素都被分配了一个对象的数字属性(就像一个索引),并且还定义了一个 length 属性。得到一个元素是

// first element
$('div.band div.member')[0];

// first element
$('div.band div.member').get(0);

您可以指定根据 DOM 中的位置选择特定元素,而不是选择所有元素。例如

// get the first div with class member element
$("div.band div.member:eq(0)")

// get the first div with class member element
$("div.band div.member:nth-child(1)")

编辑:

这是我刚刚淘汰的一个插件

(function($) {

$.fn.randomize = function(childElem) {
  return this.each(function() {
      var $this = $(this);
      var elems = $this.children(childElem);

      elems.sort(function() { return (Math.round(Math.random())-0.5); });  

      $this.detach(childElem);  

      for(var i=0; i < elems.length; i++)
        $this.append(elems[i]);      

  });    
}
})(jQuery);

工作代码:

$('button').click(function() {
  $("div.band").randomize("table tr td", "div.member");
});

(function($) {

  $.fn.randomize = function(tree, childElem) {
    return this.each(function() {
      var $this = $(this);
      if (tree) $this = $(this).find(tree);
      var unsortedElems = $this.children(childElem);
      var elems = unsortedElems.clone();

      elems.sort(function() {
        return (Math.round(Math.random()) - 0.5);
      });

      for (var i = 0; i < elems.length; i++)
        unsortedElems.eq(i).replaceWith(elems[i]);
    });
  };

})(jQuery);
body {
  background-color: #000;
  font: 16px Helvetica, Arial;
  color: #fff;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

<div class="band">
  <table>
    <tr>
      <td>
        <div class="member">
          <ul>
            <li>John</li>
            <li>Lennon</li>
          </ul>
        </div>
      </td>
    </tr>
    <tr>
      <td>
        <div class="member">
          <ul>
            <li>Paul</li>
            <li>McCartney</li>
          </ul>
        </div>
      </td>
    </tr>
    <tr>
      <td>
        <div class="member">
          <ul>
            <li>George</li>
            <li>Harrison</li>
          </ul>
        </div>
      </td>
    </tr>
    <tr>
      <td>
        <div class="member">
          <ul>
            <li>Ringo</li>
            <li>Starr</li>
          </ul>
        </div>
      </td>
    </tr>
  </table>
</div>
<button>Randomize</button>

这是 Editable Working Demo。将 /edit 添加到 URL 以查看代码。如果您需要有关其工作原理的任何详细信息,请发表评论。它可能与处理某些情况(例如插件所连接的 jQuery 对象的其他子元素)变得更加健壮有关,但它会满足您的需求。

【讨论】:

  • 这个例子太棒了!我还没有看到这个jquery语法模式,但我会试试看!非常有用,看看我该怎么做!再次感谢
  • 我冒昧地做了一个modified version of your demo(我不知道其他19个编辑是什么)。希望这适用于更多情况。我的情况确实如此。
  • 我相信通过使用更好的随机播放功能可以改善这一点,请参阅stackoverflow.com/questions/2450954/…
  • @diachedelic 完全!
  • 我把这个概念更进一步,让它洗牌容器 div 的位置,因为这就是我要找的...jsfiddle.net/coolwebs/zLgsdno7/4
【解决方案2】:

我修改了 Russ Cam 的解决方案,使选择器是可选的,并且可以在多个容器元素上调用该函数,同时保留每个随机元素的父元素。

例如,如果我想随机化每个 '.member' div 中的所有 LI,我可以这样称呼它:

$('.member').randomize('li');

我也可以这样:

$('.member li').randomize();

所以这两种调用方式如下:

$(parent_selector).randomize(child_selector);

$(child_selector).randomize();

这是修改后的代码:

$.fn.randomize = function(selector){
    (selector ? this.find(selector) : this).parent().each(function(){
        $(this).children(selector).sort(function(){
            return Math.random() - 0.5;
        }).detach().appendTo(this);
    });

    return this;
};

缩小:

$.fn.randomize=function(a){(a?this.find(a):this).parent().each(function(){$(this).children(a).sort(function(){return Math.random()-0.5}).detach().appendTo(this)});return this};

【讨论】:

  • 我尝试使用它但得到错误:Uncaught TypeError: Object [object Object] has no method 'randomize'
  • @jlg,你必须在一个 JQuery 对象上调用它,像这样:$(selector).randomize(optional_selector)。你不能单独调用它,像这样:$.randomize(selector)
  • 这应该是公认的答案。Russ Cam 的解决方案在存在其他数学函数的情况下给出了一些回归结果。这工作得很好。
【解决方案3】:

使用排序的随机化并不总是随机化元素。最好使用像How can I shuffle an array? 那样的随机播放方法

这是我更新的代码

(function($) {
    $.fn.randomize = function(childElem) {
        function shuffle(o) {
            for(var j, x, i = o.length; i; j = Math.floor(Math.random() * i), x = o[--i], o[i] = o[j], o[j] = x);
            return o;
        };
        return this.each(function() {
            var $this = $(this);
            var elems = $this.children(childElem);

            shuffle(elems);

            $this.detach(childElem);  

            for(var i=0; i < elems.length; i++) {
                $this.append(elems[i]);      
            }
        });    
    }
})(jQuery);

【讨论】:

  • 我尝试了接受的解决方案,但我认为随机性不够好
【解决方案4】:

以防万一您可以在没有 jquery 的情况下执行此操作:

/** @param {HTMLElement} parent */
const shuffleChildren = (parent) => {
    const cards = [...parent.children];
    for (const child of cards) {
        const newPlace = Math.floor(Math.random() * cards.length);
        parent.insertBefore(child, cards[newPlace + 1] || null);
    }
};

(一个与 jquery 无关的答案作为这个答案的副本被关闭,所以在这里发布)

【讨论】:

    【解决方案5】:

    此解决方案受现有解决方案的启发,但使用Fisher-Yates algorithm 进行排序。

    这确保了元素被公平地随机化,这对于许多用例来说很重要。

    $.fn.randomizeChildrenOrder = function() {
        this.each(function(){
            let childrenArray = $(this).children().toArray();
            let shuffledChildrenArray = fisherYatesShuffle(childrenArray);
            $(shuffledChildrenArray).detach().appendTo(this);
        });
    
        return this;
        
        // https://stackoverflow.com/a/2450976/665825
        function fisherYatesShuffle(array){
            let currentIndex = array.length, temporaryValue, randomIndex;
            while (currentIndex !== 0) {
                randomIndex = Math.floor(Math.random() * currentIndex);
                currentIndex -= 1;
                temporaryValue = array[currentIndex];
                array[currentIndex] = array[randomIndex];
                array[randomIndex] = temporaryValue;
            }
            return array;
        }
    }
    

    用法:调用需要洗牌的元素的元素上的函数。如果元素与需要单独放置的元素共享父元素,请在它们周围添加一个额外的父元素,这样就不再是这种情况了。

    $('.member ul').randomizeChildrenOrder();
    

    广义的:

    $(parentSelector).randomizeChildrenOrder();
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2010-12-22
      • 2012-03-15
      • 2012-01-03
      • 1970-01-01
      • 1970-01-01
      • 2016-02-17
      • 1970-01-01
      相关资源
      最近更新 更多