2

この質問の関数を使用して、jQuery を使用してテーブルの行をシャッフルしています。私が本当に望んでいるのは、次のように、最初の列のみをシャッフルし、残りはそのままにしておくことです。

a b c d
e f g h
i j

これに:

e b c d
i f g h
a j

Rob Wの答えの機能は次のとおりです。

(function($){
    //Shuffle all rows, while keeping the first column
    //Requires: Shuffle
 $.fn.shuffleRows = function(){
     return this.each(function(){
        var main = $(/table/i.test(this.tagName) ? this.tBodies[0] : this);
        var firstElem = [], counter=0;
        main.children().each(function(){
             firstElem.push(this.firstChild);
        });
        main.shuffle();
        main.children().each(function(){
           this.insertBefore(firstElem[counter++], this.firstChild);
        });
     });
   }
  /* Shuffle is required */
  $.fn.shuffle = function() {
    return this.each(function(){
      var items = $(this).children();
      return (items.length)
        ? $(this).html($.shuffle(items))
        : this;
    });
  }

  $.shuffle = function(arr) {
    for(
      var j, x, i = arr.length; i;
      j = parseInt(Math.random() * i),
      x = arr[--i], arr[i] = arr[j], arr[j] = x
    );
    return arr;
  }
})(jQuery)

しかし、これは私が望んでいたこととは反対のことをします。つまり、最初の列を除くすべての行をシャッフルします。最初の列のみをシャッフルするようにこれを変更するにはどうすればよいですか?

4

1 に答える 1

2

Here's what I came up with:

var $firstCells = $("#tableIdHere tr td:first-child"),
    $copies = $firstCells.clone(true);

[].sort.call($copies, function() { return Math.random() - 0.5; });

$copies.each(function(i){
    $firstCells.eq(i).replaceWith(this);
});

That is, select all the first cells using the :first-child selector, make a copy of them, and sort the copies randomly. Then loop through the (now randomised) copies and replace the originals with them.

Demo: http://jsfiddle.net/nnnnnn/ceTmL/

P.S. Note that this technique will randomly sort any collection of table cells or elements if you just change the selector that creates the $firstCells jQuery object, e.g., if you change the selector to "#tableIdHere tr" it will randomly sort the rows.

UPDATE:

"I cannot understand what the [] does?"

JavaScript arrays have a .sort() method that allows you to pass in a custom sort comparison function like the one I used above that returns a random number between -0.5 and +0.5 to sort in random order. But jQuery objects are not arrays so you can't just say $copies.sort(...) on the $copies jQuery object. However, jQuery objects are like arrays in that they have numerically indexed elements and a length property, and some array methods (including .sort()) can be called on array-like objects if you use the .call() or .apply() methods to call them. I could've said:

Array.prototype.sort.call($copies, ...

...but instead I went with the easier to type:

[].sort.call($copies, ...

...where [] is just an empty array that is there solely to provide access to the array .sort() method. The sort will be applied to the object that is the first parameter to .call, not to the empty array.

于 2012-09-04T06:55:28.650 に答える