http://www.pseliger.de/jsExtendedApi/jsApi.Array.shuffle.js
    http://www.pseliger.de/jsExtendedApi/jsApi.Array.shuffle.dev.js


    uses the libraries:
    - jsApi.Math.randomize.js
    - jsApi.Array.contains.js


    source code:

//  -----   feel free to use this stuff   ---   play with it   ---   copy as You  like   -----
//  -----   but leave this authors 2 lines untouched:  pseliger@gmx.net [january 2004]   -----
//
//  extended javascript-api-methods       :
//  * jsApi-extension-name / file-name    : "jsApi.Array.shuffle.dev.js"
//  * original download-location          : "http://www.pseliger.de/jsExtendedApi/jsApi.Array.shuffle.dev.js"
//
//                                        - takes advantage of method "Math.randomize" as well as of method "Array.contains";
//                                        - make sure that the libraries "jsApi.Math.randomize.js" and "jsApi.Array.contains.js" are included into your document;
//
//  first review        : january 31-2004 - code review and new method "Array.getShuffled" that will return a shuffled copy of the still unchanged remaining operand array;
//  first public release:    july 05-2003 - shuffles objects within their arrays;
//

  Array.prototype.shuffle = function() { // durchmischt objekte innerhalb ihrer arrays; // shuffles objects within their arrays;
    var randomIndex = 0;
    var randomRow = [];
    var arr = [];
    var i;
    while (randomRow.length < this.length) { // erzeugt eine liste von zufallszahlen, deren werte zwischen "0" und der um 1 verminderten anzahl von eintraegen im array liegen; // creates a vector (row) of random indeces whose values will range from "0" to the amount of array entries less 1;
      randomIndex = Math.randomize(this.length-1);
      if (!randomRow.contains(randomIndex)) {
        randomRow[randomRow.length] = randomIndex;
      }
    }
    for (i=0; i<randomRow.length; i++) {
      randomIndex = randomRow[i];
      arr = arr.concat(this.slice(randomIndex,randomIndex+1)); // fuegt die werte des arrays entsprechend ihrer zufaellig gewaehlten idizes einem rueckgabe-array hinzu; // puts the values of the array according to their randomly generated indices into a special "return array";
    }
  //return arr;                     // bis hier verhaelt sich die methode wie "getShuffled" aber nicht wie "shuffle"; // till here the method rather is a "getShuffled" than a real "shuffle" one;

    for (i=0; i<arr.length; i++) {  // schreibt die werte zurueck in den eigentlichen operanden; // writes values back into the realy ment operand array;
      this[i] = arr[i];
    }
  };

  Array.prototype.getShuffled = function() { // laesst den operanden unveraendert, gibt aber ein neues durchmischtes array zurueck; // keeps the operand untouched but returns a new shuffled array instead;
    var randomIndex = 0;
    var randomRow = [];
    var arr = [];
    var i;
    while (randomRow.length < this.length) { // erzeugt eine liste von zufallszahlen, deren werte zwischen "0" und der um 1 verminderten anzahl von eintraegen im array liegen; // creates a vector (row) of random indeces whose values will range from "0" to the amount of array entries less 1;
      randomIndex = Math.randomize(this.length-1);
      if (!randomRow.contains(randomIndex)) {
        randomRow[randomRow.length] = randomIndex;
      }
    }
    for (i=0; i<randomRow.length; i++) {
      randomIndex = randomRow[i];
      arr = arr.concat(this.slice(randomIndex,randomIndex+1)); // fuegt die werte des arrays entsprechend ihrer zufaellig gewaehlten idizes einem rueckgabe-array hinzu; // puts the values of the array according to their randomly generated indices into a special "return array";
    }
    return arr;
  };