Valid XHTML     Valid CSS2    

Listing du fichier sorttable.js

 

00001     /*
00002      SortTable
00003      version 2
00004      7th April 2007
00005      Stuart Langridge, http://www.kryogenix.org/code/browser/sorttable/
00006     
00007      Instructions:
00008      Download this file
00009      Add <script src="sorttable.js"></script> to your HTML
00010      Add class="sortable" to any table you'd like to make sortable
00011      Click on the headers to sort
00012     
00013      Thanks to many, many people for contributions and suggestions.
00014      Licenced as X11: http://www.kryogenix.org/code/browser/licence.html
00015      This basically means: do what you want with it.
00016     */
00017     
00018     
00019     var stIsIE = /*@cc_on!@*/false;
00020     
00021     sorttable = {
00022      init: function() {
00023      // quit if this function has already been called
00024      if (arguments.callee.done) return;
00025      // flag this function so we don't do the same thing twice
00026      arguments.callee.done = true;
00027      // kill the timer
00028      if (_timer) clearInterval(_timer);
00029     
00030      if (!document.createElement || !document.getElementsByTagName) return;
00031     
00032      sorttable.DATE_RE = /^(\d\d?)[\/\.-](\d\d?)[\/\.-]((\d\d)?\d\d)$/;
00033     
00034      forEach(document.getElementsByTagName('table'), function(table) {
00035      if (table.className.search(/\bsortable\b/) != -1) {
00036      sorttable.makeSortable(table);
00037      }
00038      });
00039     
00040      },
00041     
00042      makeSortable: function(table) {
00043      if (table.getElementsByTagName('thead').length == 0) {
00044      // table doesn't have a tHead. Since it should have, create one and
00045      // put the first table row in it.
00046      the = document.createElement('thead');
00047      the.appendChild(table.rows[0]);
00048      table.insertBefore(the,table.firstChild);
00049      }
00050      // Safari doesn't support table.tHead, sigh
00051      if (table.tHead == null) table.tHead = table.getElementsByTagName('thead')[0];
00052     
00053      if (table.tHead.rows.length != 1) return; // can't cope with two header rows
00054     
00055      // Sorttable v1 put rows with a class of "sortbottom" at the bottom (as
00056      // "total" rows, for example). This is B&R, since what you're supposed
00057      // to do is put them in a tfoot. So, if there are sortbottom rows,
00058      // for backwards compatibility, move them to tfoot (creating it if needed).
00059      sortbottomrows = [];
00060      for (var i=0; i<table.rows.length; i++) {
00061      if (table.rows[i].className.search(/\bsortbottom\b/) != -1) {
00062      sortbottomrows[sortbottomrows.length] = table.rows[i];
00063      }
00064      }
00065      if (sortbottomrows) {
00066      if (table.tFoot == null) {
00067      // table doesn't have a tfoot. Create one.
00068      tfo = document.createElement('tfoot');
00069      table.appendChild(tfo);
00070      }
00071      for (var i=0; i<sortbottomrows.length; i++) {
00072      tfo.appendChild(sortbottomrows[i]);
00073      }
00074      delete sortbottomrows;
00075      }
00076     
00077      // work through each column and calculate its type
00078      headrow = table.tHead.rows[0].cells;
00079      for (var i=0; i<headrow.length; i++) {
00080      // manually override the type with a sorttable_type attribute
00081      if (!headrow[i].className.match(/\bsorttable_nosort\b/)) { // skip this col
00082      mtch = headrow[i].className.match(/\bsorttable_([a-z0-9]+)\b/);
00083      if (mtch) { override = mtch[1]; }
00084      if (mtch && typeof sorttable["sort_"+override] == 'function') {
00085      headrow[i].sorttable_sortfunction = sorttable["sort_"+override];
00086      } else {
00087      headrow[i].sorttable_sortfunction = sorttable.guessType(table,i);
00088      }
00089      // make it clickable to sort
00090      headrow[i].sorttable_columnindex = i;
00091      headrow[i].sorttable_tbody = table.tBodies[0];
00092      dean_addEvent(headrow[i],"click", function(e) {
00093     
00094      if (this.className.search(/\bsorttable_sorted\b/) != -1) {
00095      // if we're already sorted by this column, just
00096      // reverse the table, which is quicker
00097      sorttable.reverse(this.sorttable_tbody);
00098      this.className = this.className.replace('sorttable_sorted',
00099      'sorttable_sorted_reverse');
00100      this.removeChild(document.getElementById('sorttable_sortfwdind'));
00101      sortrevind = document.createElement('span');
00102      sortrevind.id = "sorttable_sortrevind";
00103      sortrevind.innerHTML = stIsIE ? '&nbsp<font face="webdings">5</font>' : '&nbsp;&#x25B4;';
00104      this.appendChild(sortrevind);
00105      return;
00106      }
00107      if (this.className.search(/\bsorttable_sorted_reverse\b/) != -1) {
00108      // if we're already sorted by this column in reverse, just
00109      // re-reverse the table, which is quicker
00110      sorttable.reverse(this.sorttable_tbody);
00111      this.className = this.className.replace('sorttable_sorted_reverse',
00112      'sorttable_sorted');
00113      this.removeChild(document.getElementById('sorttable_sortrevind'));
00114      sortfwdind = document.createElement('span');
00115      sortfwdind.id = "sorttable_sortfwdind";
00116      sortfwdind.innerHTML = stIsIE ? '&nbsp<font face="webdings">6</font>' : '&nbsp;&#x25BE;';
00117      this.appendChild(sortfwdind);
00118      return;
00119      }
00120     
00121      // remove sorttable_sorted classes
00122      theadrow = this.parentNode;
00123      forEach(theadrow.childNodes, function(cell) {
00124      if (cell.nodeType == 1) { // an element
00125      cell.className = cell.className.replace('sorttable_sorted_reverse','');
00126      cell.className = cell.className.replace('sorttable_sorted','');
00127      }
00128      });
00129      sortfwdind = document.getElementById('sorttable_sortfwdind');
00130      if (sortfwdind) { sortfwdind.parentNode.removeChild(sortfwdind); }
00131      sortrevind = document.getElementById('sorttable_sortrevind');
00132      if (sortrevind) { sortrevind.parentNode.removeChild(sortrevind); }
00133     
00134      this.className += ' sorttable_sorted';
00135      sortfwdind = document.createElement('span');
00136      sortfwdind.id = "sorttable_sortfwdind";
00137      sortfwdind.innerHTML = stIsIE ? '&nbsp<font face="webdings">6</font>' : '&nbsp;&#x25BE;';
00138      this.appendChild(sortfwdind);
00139     
00140      // build an array to sort. This is a Schwartzian transform thing,
00141      // i.e., we "decorate" each row with the actual sort key,
00142      // sort based on the sort keys, and then put the rows back in order
00143      // which is a lot faster because you only do getInnerText once per row
00144      row_array = [];
00145      col = this.sorttable_columnindex;
00146      rows = this.sorttable_tbody.rows;
00147      for (var j=0; j<rows.length; j++) {
00148      row_array[row_array.length] = [sorttable.getInnerText(rows[j].cells[col]), rows[j]];
00149      }
00150      /* If you want a stable sort, uncomment the following line */
00151      //sorttable.shaker_sort(row_array, this.sorttable_sortfunction);
00152      /* and comment out this one */
00153      row_array.sort(this.sorttable_sortfunction);
00154     
00155      tb = this.sorttable_tbody;
00156      for (var j=0; j<row_array.length; j++) {
00157      tb.appendChild(row_array[j][1]);
00158      }
00159     
00160      delete row_array;
00161      });
00162      }
00163      }
00164      },
00165     
00166      guessType: function(table, column) {
00167      // guess the type of a column based on its first non-blank row
00168      sortfn = sorttable.sort_alpha;
00169      for (var i=0; i<table.tBodies[0].rows.length; i++) {
00170      text = sorttable.getInnerText(table.tBodies[0].rows[i].cells[column]);
00171      if (text != '') {
00172      if (text.match(/^-?[£$¤]?[\d,.]+%?$/)) {
00173      return sorttable.sort_numeric;
00174      }
00175      // check for a date: dd/mm/yyyy or dd/mm/yy
00176      // can have / or . or - as separator
00177      // can be mm/dd as well
00178      possdate = text.match(sorttable.DATE_RE)
00179      if (possdate) {
00180      // looks like a date
00181      first = parseInt(possdate[1]);
00182      second = parseInt(possdate[2]);
00183      if (first > 12) {
00184      // definitely dd/mm
00185      return sorttable.sort_ddmm;
00186      } else if (second > 12) {
00187      return sorttable.sort_mmdd;
00188      } else {
00189      // looks like a date, but we can't tell which, so assume
00190      // that it's dd/mm (English imperialism!) and keep looking
00191      sortfn = sorttable.sort_ddmm;
00192      }
00193      }
00194      }
00195      }
00196      return sortfn;
00197      },
00198     
00199      getInnerText: function(node) {
00200      // gets the text we want to use for sorting for a cell.
00201      // strips leading and trailing whitespace.
00202      // this is *not* a generic getInnerText function; it's special to sorttable.
00203      // for example, you can override the cell text with a customkey attribute.
00204      // it also gets .value for <input> fields.
00205     
00206      hasInputs = (typeof node.getElementsByTagName == 'function') &&
00207      node.getElementsByTagName('input').length;
00208     
00209      if (node.getAttribute("sorttable_customkey") != null) {
00210      return node.getAttribute("sorttable_customkey");
00211      }
00212      else if (typeof node.textContent != 'undefined' && !hasInputs) {
00213      return node.textContent.replace(/^\s+|\s+$/g, '');
00214      }
00215      else if (typeof node.innerText != 'undefined' && !hasInputs) {
00216      return node.innerText.replace(/^\s+|\s+$/g, '');
00217      }
00218      else if (typeof node.text != 'undefined' && !hasInputs) {
00219      return node.text.replace(/^\s+|\s+$/g, '');
00220      }
00221      else {
00222      switch (node.nodeType) {
00223      case 3:
00224      if (node.nodeName.toLowerCase() == 'input') {
00225      return node.value.replace(/^\s+|\s+$/g, '');
00226      }
00227      case 4:
00228      return node.nodeValue.replace(/^\s+|\s+$/g, '');
00229      break;
00230      case 1:
00231      case 11:
00232      var innerText = '';
00233      for (var i = 0; i < node.childNodes.length; i++) {
00234      innerText += sorttable.getInnerText(node.childNodes[i]);
00235      }
00236      return innerText.replace(/^\s+|\s+$/g, '');
00237      break;
00238      default:
00239      return '';
00240      }
00241      }
00242      },
00243     
00244      reverse: function(tbody) {
00245      // reverse the rows in a tbody
00246      newrows = [];
00247      for (var i=0; i<tbody.rows.length; i++) {
00248      newrows[newrows.length] = tbody.rows[i];
00249      }
00250      for (var i=newrows.length-1; i>=0; i--) {
00251      tbody.appendChild(newrows[i]);
00252      }
00253      delete newrows;
00254      },
00255     
00256      /* sort functions
00257      each sort function takes two parameters, a and b
00258      you are comparing a[0] and b[0] */
00259      sort_numeric: function(a,b) {
00260      aa = parseFloat(a[0].replace(/[^0-9.-]/g,''));
00261      if (isNaN(aa)) aa = 0;
00262      bb = parseFloat(b[0].replace(/[^0-9.-]/g,''));
00263      if (isNaN(bb)) bb = 0;
00264      return aa-bb;
00265      },
00266      sort_alpha: function(a,b) {
00267      if (a[0]==b[0]) return 0;
00268      if (a[0]<b[0]) return -1;
00269      return 1;
00270      },
00271      sort_ddmm: function(a,b) {
00272      mtch = a[0].match(sorttable.DATE_RE);
00273      y = mtch[3]; m = mtch[2]; d = mtch[1];
00274      if (m.length == 1) m = '0'+m;
00275      if (d.length == 1) d = '0'+d;
00276      dt1 = y+m+d;
00277      mtch = b[0].match(sorttable.DATE_RE);
00278      y = mtch[3]; m = mtch[2]; d = mtch[1];
00279      if (m.length == 1) m = '0'+m;
00280      if (d.length == 1) d = '0'+d;
00281      dt2 = y+m+d;
00282      if (dt1==dt2) return 0;
00283      if (dt1<dt2) return -1;
00284      return 1;
00285      },
00286      sort_mmdd: function(a,b) {
00287      mtch = a[0].match(sorttable.DATE_RE);
00288      y = mtch[3]; d = mtch[2]; m = mtch[1];
00289      if (m.length == 1) m = '0'+m;
00290      if (d.length == 1) d = '0'+d;
00291      dt1 = y+m+d;
00292      mtch = b[0].match(sorttable.DATE_RE);
00293      y = mtch[3]; d = mtch[2]; m = mtch[1];
00294      if (m.length == 1) m = '0'+m;
00295      if (d.length == 1) d = '0'+d;
00296      dt2 = y+m+d;
00297      if (dt1==dt2) return 0;
00298      if (dt1<dt2) return -1;
00299      return 1;
00300      },
00301     
00302      shaker_sort: function(list, comp_func) {
00303      // A stable sort function to allow multi-level sorting of data
00304      // see: http://en.wikipedia.org/wiki/Cocktail_sort
00305      // thanks to Joseph Nahmias
00306      var b = 0;
00307      var t = list.length - 1;
00308      var swap = true;
00309     
00310      while(swap) {
00311      swap = false;
00312      for(var i = b; i < t; ++i) {
00313      if ( comp_func(list[i], list[i+1]) > 0 ) {
00314      var q = list[i]; list[i] = list[i+1]; list[i+1] = q;
00315      swap = true;
00316      }
00317      } // for
00318      t--;
00319     
00320      if (!swap) break;
00321     
00322      for(var i = t; i > b; --i) {
00323      if ( comp_func(list[i], list[i-1]) < 0 ) {
00324      var q = list[i]; list[i] = list[i-1]; list[i-1] = q;
00325      swap = true;
00326      }
00327      } // for
00328      b++;
00329     
00330      } // while(swap)
00331      }
00332     }
00333     
00334     /* ******************************************************************
00335      Supporting functions: bundled here to avoid depending on a library
00336      ****************************************************************** */
00337     
00338     // Dean Edwards/Matthias Miller/John Resig
00339     
00340     /* for Mozilla/Opera9 */
00341     if (document.addEventListener) {
00342      document.addEventListener("DOMContentLoaded", sorttable.init, false);
00343     }
00344     
00345     /* for Internet Explorer */
00346     /*@cc_on @*/
00347     /*@if (@_win32)
00348      document.write("<script id=__ie_onload defer src=javascript:void(0)><\/script>");
00349      var script = document.getElementById("__ie_onload");
00350      script.onreadystatechange = function() {
00351      if (this.readyState == "complete") {
00352      sorttable.init(); // call the onload handler
00353      }
00354      };
00355     /*@end @*/
00356     
00357     /* for Safari */
00358     if (/WebKit/i.test(navigator.userAgent)) { // sniff
00359      var _timer = setInterval(function() {
00360      if (/loaded|complete/.test(document.readyState)) {
00361      sorttable.init(); // call the onload handler
00362      }
00363      }, 10);
00364     }
00365     
00366     /* for other browsers */
00367     window.onload = sorttable.init;
00368     
00369     // written by Dean Edwards, 2005
00370     // with input from Tino Zijdel, Matthias Miller, Diego Perini
00371     
00372     // http://dean.edwards.name/weblog/2005/10/add-event/
00373     
00374     function dean_addEvent(element, type, handler) {
00375      if (element.addEventListener) {
00376      element.addEventListener(type, handler, false);
00377      } else {
00378      // assign each event handler a unique ID
00379      if (!handler.$$guid) handler.$$guid = dean_addEvent.guid++;
00380      // create a hash table of event types for the element
00381      if (!element.events) element.events = {};
00382      // create a hash table of event handlers for each element/event pair
00383      var handlers = element.events[type];
00384      if (!handlers) {
00385      handlers = element.events[type] = {};
00386      // store the existing event handler (if there is one)
00387      if (element["on" + type]) {
00388      handlers[0] = element["on" + type];
00389      }
00390      }
00391      // store the event handler in the hash table
00392      handlers[handler.$$guid] = handler;
00393      // assign a global event handler to do all the work
00394      element["on" + type] = handleEvent;
00395      }
00396     };
00397     // a counter used to create unique IDs
00398     dean_addEvent.guid = 1;
00399     
00400     function removeEvent(element, type, handler) {
00401      if (element.removeEventListener) {
00402      element.removeEventListener(type, handler, false);
00403      } else {
00404      // delete the event handler from the hash table
00405      if (element.events && element.events[type]) {
00406      delete element.events[type][handler.$$guid];
00407      }
00408      }
00409     };
00410     
00411     function handleEvent(event) {
00412      var returnValue = true;
00413      // grab the event object (IE uses a global event object)
00414      event = event || fixEvent(((this.ownerDocument || this.document || this).parentWindow || window).event);
00415      // get a reference to the hash table of event handlers
00416      var handlers = this.events[event.type];
00417      // execute each event handler
00418      for (var i in handlers) {
00419      this.$$handleEvent = handlers[i];
00420      if (this.$$handleEvent(event) === false) {
00421      returnValue = false;
00422      }
00423      }
00424      return returnValue;
00425     };
00426     
00427     function fixEvent(event) {
00428      // add W3C standard event methods
00429      event.preventDefault = fixEvent.preventDefault;
00430      event.stopPropagation = fixEvent.stopPropagation;
00431      return event;
00432     };
00433     fixEvent.preventDefault = function() {
00434      this.returnValue = false;
00435     };
00436     fixEvent.stopPropagation = function() {
00437      this.cancelBubble = true;
00438     }
00439     
00440     // Dean's forEach: http://dean.edwards.name/base/forEach.js
00441     /*
00442      forEach, version 1.0
00443      Copyright 2006, Dean Edwards
00444      License: http://www.opensource.org/licenses/mit-license.php
00445     */
00446     
00447     // array-like enumeration
00448     if (!Array.forEach) { // mozilla already supports this
00449      Array.forEach = function(array, block, context) {
00450      for (var i = 0; i < array.length; i++) {
00451      block.call(context, array[i], i, array);
00452      }
00453      };
00454     }
00455     
00456     // generic enumeration
00457     Function.prototype.forEach = function(object, block, context) {
00458      for (var key in object) {
00459      if (typeof this.prototype[key] == "undefined") {
00460      block.call(context, object[key], key, object);
00461      }
00462      }
00463     };
00464     
00465     // character enumeration
00466     String.forEach = function(string, block, context) {
00467      Array.forEach(string.split(""), function(chr, index) {
00468      block.call(context, chr, index, string);
00469      });
00470     };
00471     
00472     // globally resolve forEach enumeration
00473     var forEach = function(object, block, context) {
00474      if (object) {
00475      var resolve = Object; // default
00476      if (object instanceof Function) {
00477      // functions have a "length" property
00478      resolve = Function;
00479      } else if (object.forEach instanceof Function) {
00480      // the object implements a custom forEach method so use that
00481      object.forEach(block, context);
00482      return;
00483      } else if (typeof object == "string") {
00484      // the object is a string
00485      resolve = String;
00486      } else if (typeof object.length == "number") {
00487      // the object is array-like
00488      resolve = Array;
00489      }
00490      resolve.forEach(object, block, context);
00491      }
00492     };
00493     

Pour ne pas voir les numéros de ligne, ajoutez &nl=non à la suite du nom du fichier.

 

 

retour gH    Retour à la page principale de   (gH)