Attachment 'common.js.patch'

Download

   1 diff -r dc854677e9bd wiki/htdocs/common/js/common.js
   2 --- a/wiki/htdocs/common/js/common.js	Wed Jan 07 01:41:18 2009 +0100
   3 +++ b/wiki/htdocs/common/js/common.js	Thu Jan 08 12:31:58 2009 +0100
   4 @@ -389,3 +389,497 @@
   5      return getElementsByClassName(className, tag, elm);
   6  };
   7  
   8 +/*
   9 +  SortTable
  10 +  version 2
  11 +  7th April 2007
  12 +  Stuart Langridge, http://www.kryogenix.org/code/browser/sorttable/
  13 +  
  14 +  Instructions:
  15 +  Download this file
  16 +  Add <script src="sorttable.js"></script> to your HTML
  17 +  Add class="sortable" to any table you'd like to make sortable
  18 +  Click on the headers to sort
  19 +  
  20 +  Thanks to many, many people for contributions and suggestions.
  21 +  Licenced as X11: http://www.kryogenix.org/code/browser/licence.html
  22 +  This basically means: do what you want with it.
  23 +*/
  24 +
  25 + 
  26 +var stIsIE = /*@cc_on!@*/false;
  27 +
  28 +sorttable = {
  29 +  init: function() {
  30 +    // quit if this function has already been called
  31 +    if (arguments.callee.done) return;
  32 +    // flag this function so we don't do the same thing twice
  33 +    arguments.callee.done = true;
  34 +    // kill the timer
  35 +    if (_timer) clearInterval(_timer);
  36 +    
  37 +    if (!document.createElement || !document.getElementsByTagName) return;
  38 +    
  39 +    sorttable.DATE_RE = /^(\d\d?)[\/\.-](\d\d?)[\/\.-]((\d\d)?\d\d)$/;
  40 +    
  41 +    forEach(document.getElementsByTagName('table'), function(table) {
  42 +      if (table.className.search(/\bsortable\b/) != -1) {
  43 +        sorttable.makeSortable(table);
  44 +      }
  45 +    });
  46 +    
  47 +  },
  48 +  
  49 +  makeSortable: function(table) {
  50 +    if (table.getElementsByTagName('thead').length == 0) {
  51 +      // table doesn't have a tHead. Since it should have, create one and
  52 +      // put the first table row in it.
  53 +      the = document.createElement('thead');
  54 +      the.appendChild(table.rows[0]);
  55 +      table.insertBefore(the,table.firstChild);
  56 +    }
  57 +    // Safari doesn't support table.tHead, sigh
  58 +    if (table.tHead == null) table.tHead = table.getElementsByTagName('thead')[0];
  59 +    
  60 +    if (table.tHead.rows.length != 1) return; // can't cope with two header rows
  61 +    
  62 +    // Sorttable v1 put rows with a class of "sortbottom" at the bottom (as
  63 +    // "total" rows, for example). This is B&R, since what you're supposed
  64 +    // to do is put them in a tfoot. So, if there are sortbottom rows,
  65 +    // for backwards compatibility, move them to tfoot (creating it if needed).
  66 +    sortbottomrows = [];
  67 +    for (var i=0; i<table.rows.length; i++) {
  68 +      if (table.rows[i].className.search(/\bsortbottom\b/) != -1) {
  69 +        sortbottomrows[sortbottomrows.length] = table.rows[i];
  70 +      }
  71 +    }
  72 +    if (sortbottomrows) {
  73 +      if (table.tFoot == null) {
  74 +        // table doesn't have a tfoot. Create one.
  75 +        tfo = document.createElement('tfoot');
  76 +        table.appendChild(tfo);
  77 +      }
  78 +      for (var i=0; i<sortbottomrows.length; i++) {
  79 +        tfo.appendChild(sortbottomrows[i]);
  80 +      }
  81 +      delete sortbottomrows;
  82 +    }
  83 +    
  84 +    // work through each column and calculate its type
  85 +    headrow = table.tHead.rows[0].cells;
  86 +    for (var i=0; i<headrow.length; i++) {
  87 +      // manually override the type with a sorttable_type attribute
  88 +      if (!headrow[i].className.match(/\bsorttable_nosort\b/)) { // skip this col
  89 +        mtch = headrow[i].className.match(/\bsorttable_([a-z0-9]+)\b/);
  90 +        if (mtch) { override = mtch[1]; }
  91 +              if (mtch && typeof sorttable["sort_"+override] == 'function') {
  92 +                headrow[i].sorttable_sortfunction = sorttable["sort_"+override];
  93 +              } else {
  94 +                headrow[i].sorttable_sortfunction = sorttable.guessType(table,i);
  95 +              }
  96 +              // make it clickable to sort
  97 +              headrow[i].sorttable_columnindex = i;
  98 +              headrow[i].sorttable_tbody = table.tBodies[0];
  99 +              dean_addEvent(headrow[i],"click", function(e) {
 100 +
 101 +          if (this.className.search(/\bsorttable_sorted\b/) != -1) {
 102 +            // if we're already sorted by this column, just 
 103 +            // reverse the table, which is quicker
 104 +            sorttable.reverse(this.sorttable_tbody);
 105 +            this.className = this.className.replace('sorttable_sorted',
 106 +                                                    'sorttable_sorted_reverse');
 107 +            this.removeChild(document.getElementById('sorttable_sortfwdind'));
 108 +            sortrevind = document.createElement('span');
 109 +            sortrevind.id = "sorttable_sortrevind";
 110 +            sortrevind.innerHTML = stIsIE ? '&nbsp<font face="webdings">5</font>' : '&nbsp;&#x25B4;';
 111 +            this.appendChild(sortrevind);
 112 +            return;
 113 +          }
 114 +          if (this.className.search(/\bsorttable_sorted_reverse\b/) != -1) {
 115 +            // if we're already sorted by this column in reverse, just 
 116 +            // re-reverse the table, which is quicker
 117 +            sorttable.reverse(this.sorttable_tbody);
 118 +            this.className = this.className.replace('sorttable_sorted_reverse',
 119 +                                                    'sorttable_sorted');
 120 +            this.removeChild(document.getElementById('sorttable_sortrevind'));
 121 +            sortfwdind = document.createElement('span');
 122 +            sortfwdind.id = "sorttable_sortfwdind";
 123 +            sortfwdind.innerHTML = stIsIE ? '&nbsp<font face="webdings">6</font>' : '&nbsp;&#x25BE;';
 124 +            this.appendChild(sortfwdind);
 125 +            return;
 126 +          }
 127 +          
 128 +          // remove sorttable_sorted classes
 129 +          theadrow = this.parentNode;
 130 +          forEach(theadrow.childNodes, function(cell) {
 131 +            if (cell.nodeType == 1) { // an element
 132 +              cell.className = cell.className.replace('sorttable_sorted_reverse','');
 133 +              cell.className = cell.className.replace('sorttable_sorted','');
 134 +            }
 135 +          });
 136 +          sortfwdind = document.getElementById('sorttable_sortfwdind');
 137 +          if (sortfwdind) { sortfwdind.parentNode.removeChild(sortfwdind); }
 138 +          sortrevind = document.getElementById('sorttable_sortrevind');
 139 +          if (sortrevind) { sortrevind.parentNode.removeChild(sortrevind); }
 140 +          
 141 +          this.className += ' sorttable_sorted';
 142 +          sortfwdind = document.createElement('span');
 143 +          sortfwdind.id = "sorttable_sortfwdind";
 144 +          sortfwdind.innerHTML = stIsIE ? '&nbsp<font face="webdings">6</font>' : '&nbsp;&#x25BE;';
 145 +          this.appendChild(sortfwdind);
 146 +
 147 +                // build an array to sort. This is a Schwartzian transform thing,
 148 +                // i.e., we "decorate" each row with the actual sort key,
 149 +                // sort based on the sort keys, and then put the rows back in order
 150 +                // which is a lot faster because you only do getInnerText once per row
 151 +                row_array = [];
 152 +                col = this.sorttable_columnindex;
 153 +                rows = this.sorttable_tbody.rows;
 154 +                for (var j=0; j<rows.length; j++) {
 155 +                  row_array[row_array.length] = [sorttable.getInnerText(rows[j].cells[col]), rows[j]];
 156 +                }
 157 +                /* If you want a stable sort, uncomment the following line */
 158 +                //sorttable.shaker_sort(row_array, this.sorttable_sortfunction);
 159 +                /* and comment out this one */
 160 +                row_array.sort(this.sorttable_sortfunction);
 161 +                
 162 +                tb = this.sorttable_tbody;
 163 +                for (var j=0; j<row_array.length; j++) {
 164 +                  tb.appendChild(row_array[j][1]);
 165 +                }
 166 +                
 167 +                delete row_array;
 168 +              });
 169 +            }
 170 +    }
 171 +  },
 172 +  
 173 +  guessType: function(table, column) {
 174 +    // guess the type of a column based on its first non-blank row
 175 +    sortfn = sorttable.sort_alpha;
 176 +    for (var i=0; i<table.tBodies[0].rows.length; i++) {
 177 +      text = sorttable.getInnerText(table.tBodies[0].rows[i].cells[column]);
 178 +      if (text != '') {
 179 +        if (text.match(/^-?[£$?]?[\d,.]+%?$/)) {
 180 +          return sorttable.sort_numeric;
 181 +        }
 182 +        // check for a date: dd/mm/yyyy or dd/mm/yy 
 183 +        // can have / or . or - as separator
 184 +        // can be mm/dd as well
 185 +        possdate = text.match(sorttable.DATE_RE)
 186 +        if (possdate) {
 187 +          // looks like a date
 188 +          first = parseInt(possdate[1]);
 189 +          second = parseInt(possdate[2]);
 190 +          if (first > 12) {
 191 +            // definitely dd/mm
 192 +            return sorttable.sort_ddmm;
 193 +          } else if (second > 12) {
 194 +            return sorttable.sort_mmdd;
 195 +          } else {
 196 +            // looks like a date, but we can't tell which, so assume
 197 +            // that it's dd/mm (English imperialism!) and keep looking
 198 +            sortfn = sorttable.sort_ddmm;
 199 +          }
 200 +        }
 201 +      }
 202 +    }
 203 +    return sortfn;
 204 +  },
 205 +  
 206 +  getInnerText: function(node) {
 207 +    // gets the text we want to use for sorting for a cell.
 208 +    // strips leading and trailing whitespace.
 209 +    // this is *not* a generic getInnerText function; it's special to sorttable.
 210 +    // for example, you can override the cell text with a customkey attribute.
 211 +    // it also gets .value for <input> fields.
 212 +    
 213 +    hasInputs = (typeof node.getElementsByTagName == 'function') &&
 214 +                 node.getElementsByTagName('input').length;
 215 +    
 216 +    if (node.getAttribute("sorttable_customkey") != null) {
 217 +      return node.getAttribute("sorttable_customkey");
 218 +    }
 219 +    else if (typeof node.textContent != 'undefined' && !hasInputs) {
 220 +      return node.textContent.replace(/^\s+|\s+$/g, '');
 221 +    }
 222 +    else if (typeof node.innerText != 'undefined' && !hasInputs) {
 223 +      return node.innerText.replace(/^\s+|\s+$/g, '');
 224 +    }
 225 +    else if (typeof node.text != 'undefined' && !hasInputs) {
 226 +      return node.text.replace(/^\s+|\s+$/g, '');
 227 +    }
 228 +    else {
 229 +      switch (node.nodeType) {
 230 +        case 3:
 231 +          if (node.nodeName.toLowerCase() == 'input') {
 232 +            return node.value.replace(/^\s+|\s+$/g, '');
 233 +          }
 234 +        case 4:
 235 +          return node.nodeValue.replace(/^\s+|\s+$/g, '');
 236 +          break;
 237 +        case 1:
 238 +        case 11:
 239 +          var innerText = '';
 240 +          for (var i = 0; i < node.childNodes.length; i++) {
 241 +            innerText += sorttable.getInnerText(node.childNodes[i]);
 242 +          }
 243 +          return innerText.replace(/^\s+|\s+$/g, '');
 244 +          break;
 245 +        default:
 246 +          return '';
 247 +      }
 248 +    }
 249 +  },
 250 +  
 251 +  reverse: function(tbody) {
 252 +    // reverse the rows in a tbody
 253 +    newrows = [];
 254 +    for (var i=0; i<tbody.rows.length; i++) {
 255 +      newrows[newrows.length] = tbody.rows[i];
 256 +    }
 257 +    for (var i=newrows.length-1; i>=0; i--) {
 258 +       tbody.appendChild(newrows[i]);
 259 +    }
 260 +    delete newrows;
 261 +  },
 262 +  
 263 +  /* sort functions
 264 +     each sort function takes two parameters, a and b
 265 +     you are comparing a[0] and b[0] */
 266 +  sort_numeric: function(a,b) {
 267 +    aa = parseFloat(a[0].replace(/[^0-9.-]/g,''));
 268 +    if (isNaN(aa)) aa = 0;
 269 +    bb = parseFloat(b[0].replace(/[^0-9.-]/g,'')); 
 270 +    if (isNaN(bb)) bb = 0;
 271 +    return aa-bb;
 272 +  },
 273 +  sort_alpha: function(a,b) {
 274 +    if (a[0]==b[0]) return 0;
 275 +    if (a[0]<b[0]) return -1;
 276 +    return 1;
 277 +  },
 278 +  sort_ddmm: function(a,b) {
 279 +    mtch = a[0].match(sorttable.DATE_RE);
 280 +    y = mtch[3]; m = mtch[2]; d = mtch[1];
 281 +    if (m.length == 1) m = '0'+m;
 282 +    if (d.length == 1) d = '0'+d;
 283 +    dt1 = y+m+d;
 284 +    mtch = b[0].match(sorttable.DATE_RE);
 285 +    y = mtch[3]; m = mtch[2]; d = mtch[1];
 286 +    if (m.length == 1) m = '0'+m;
 287 +    if (d.length == 1) d = '0'+d;
 288 +    dt2 = y+m+d;
 289 +    if (dt1==dt2) return 0;
 290 +    if (dt1<dt2) return -1;
 291 +    return 1;
 292 +  },
 293 +  sort_mmdd: function(a,b) {
 294 +    mtch = a[0].match(sorttable.DATE_RE);
 295 +    y = mtch[3]; d = mtch[2]; m = mtch[1];
 296 +    if (m.length == 1) m = '0'+m;
 297 +    if (d.length == 1) d = '0'+d;
 298 +    dt1 = y+m+d;
 299 +    mtch = b[0].match(sorttable.DATE_RE);
 300 +    y = mtch[3]; d = mtch[2]; m = mtch[1];
 301 +    if (m.length == 1) m = '0'+m;
 302 +    if (d.length == 1) d = '0'+d;
 303 +    dt2 = y+m+d;
 304 +    if (dt1==dt2) return 0;
 305 +    if (dt1<dt2) return -1;
 306 +    return 1;
 307 +  },
 308 +  
 309 +  shaker_sort: function(list, comp_func) {
 310 +    // A stable sort function to allow multi-level sorting of data
 311 +    // see: http://en.wikipedia.org/wiki/Cocktail_sort
 312 +    // thanks to Joseph Nahmias
 313 +    var b = 0;
 314 +    var t = list.length - 1;
 315 +    var swap = true;
 316 +
 317 +    while(swap) {
 318 +        swap = false;
 319 +        for(var i = b; i < t; ++i) {
 320 +            if ( comp_func(list[i], list[i+1]) > 0 ) {
 321 +                var q = list[i]; list[i] = list[i+1]; list[i+1] = q;
 322 +                swap = true;
 323 +            }
 324 +        } // for
 325 +        t--;
 326 +
 327 +        if (!swap) break;
 328 +
 329 +        for(var i = t; i > b; --i) {
 330 +            if ( comp_func(list[i], list[i-1]) < 0 ) {
 331 +                var q = list[i]; list[i] = list[i-1]; list[i-1] = q;
 332 +                swap = true;
 333 +            }
 334 +        } // for
 335 +        b++;
 336 +
 337 +    } // while(swap)
 338 +  }  
 339 +}
 340 +
 341 +/* ******************************************************************
 342 +   Supporting functions: bundled here to avoid depending on a library
 343 +   ****************************************************************** */
 344 +
 345 +// Dean Edwards/Matthias Miller/John Resig
 346 +
 347 +/* for Mozilla/Opera9 */
 348 +if (document.addEventListener) {
 349 +    document.addEventListener("DOMContentLoaded", sorttable.init, false);
 350 +}
 351 +
 352 +/* for Internet Explorer */
 353 +/*@cc_on @*/
 354 +/*@if (@_win32)
 355 +    document.write("<script id=__ie_onload defer src=javascript:void(0)><\/script>");
 356 +    var script = document.getElementById("__ie_onload");
 357 +    script.onreadystatechange = function() {
 358 +        if (this.readyState == "complete") {
 359 +            sorttable.init(); // call the onload handler
 360 +        }
 361 +    };
 362 +/*@end @*/
 363 +
 364 +/* for Safari */
 365 +if (/WebKit/i.test(navigator.userAgent)) { // sniff
 366 +    var _timer = setInterval(function() {
 367 +        if (/loaded|complete/.test(document.readyState)) {
 368 +            sorttable.init(); // call the onload handler
 369 +        }
 370 +    }, 10);
 371 +}
 372 +
 373 +/* for other browsers */
 374 +//window.onload = sorttable.init;
 375 +
 376 +// written by Dean Edwards, 2005
 377 +// with input from Tino Zijdel, Matthias Miller, Diego Perini
 378 +
 379 +// http://dean.edwards.name/weblog/2005/10/add-event/
 380 +
 381 +function dean_addEvent(element, type, handler) {
 382 +        if (element.addEventListener) {
 383 +                element.addEventListener(type, handler, false);
 384 +        } else {
 385 +                // assign each event handler a unique ID
 386 +                if (!handler.$$guid) handler.$$guid = dean_addEvent.guid++;
 387 +                // create a hash table of event types for the element
 388 +                if (!element.events) element.events = {};
 389 +                // create a hash table of event handlers for each element/event pair
 390 +                var handlers = element.events[type];
 391 +                if (!handlers) {
 392 +                        handlers = element.events[type] = {};
 393 +                        // store the existing event handler (if there is one)
 394 +                        if (element["on" + type]) {
 395 +                                handlers[0] = element["on" + type];
 396 +                        }
 397 +                }
 398 +                // store the event handler in the hash table
 399 +                handlers[handler.$$guid] = handler;
 400 +                // assign a global event handler to do all the work
 401 +                element["on" + type] = handleEvent;
 402 +        }
 403 +};
 404 +// a counter used to create unique IDs
 405 +dean_addEvent.guid = 1;
 406 +
 407 +function removeEvent(element, type, handler) {
 408 +        if (element.removeEventListener) {
 409 +                element.removeEventListener(type, handler, false);
 410 +        } else {
 411 +                // delete the event handler from the hash table
 412 +                if (element.events && element.events[type]) {
 413 +                        delete element.events[type][handler.$$guid];
 414 +                }
 415 +        }
 416 +};
 417 +
 418 +function handleEvent(event) {
 419 +        var returnValue = true;
 420 +        // grab the event object (IE uses a global event object)
 421 +        event = event || fixEvent(((this.ownerDocument || this.document || this).parentWindow || window).event);
 422 +        // get a reference to the hash table of event handlers
 423 +        var handlers = this.events[event.type];
 424 +        // execute each event handler
 425 +        for (var i in handlers) {
 426 +                this.$$handleEvent = handlers[i];
 427 +                if (this.$$handleEvent(event) === false) {
 428 +                        returnValue = false;
 429 +                }
 430 +        }
 431 +        return returnValue;
 432 +};
 433 +
 434 +function fixEvent(event) {
 435 +        // add W3C standard event methods
 436 +        event.preventDefault = fixEvent.preventDefault;
 437 +        event.stopPropagation = fixEvent.stopPropagation;
 438 +        return event;
 439 +};
 440 +fixEvent.preventDefault = function() {
 441 +        this.returnValue = false;
 442 +};
 443 +fixEvent.stopPropagation = function() {
 444 +  this.cancelBubble = true;
 445 +}
 446 +
 447 +// Dean's forEach: http://dean.edwards.name/base/forEach.js
 448 +/*
 449 +        forEach, version 1.0
 450 +        Copyright 2006, Dean Edwards
 451 +        License: http://www.opensource.org/licenses/mit-license.php
 452 +*/
 453 +
 454 +// array-like enumeration
 455 +if (!Array.forEach) { // mozilla already supports this
 456 +        Array.forEach = function(array, block, context) {
 457 +                for (var i = 0; i < array.length; i++) {
 458 +                        block.call(context, array[i], i, array);
 459 +                }
 460 +        };
 461 +}
 462 +
 463 +// generic enumeration
 464 +Function.prototype.forEach = function(object, block, context) {
 465 +        for (var key in object) {
 466 +                if (typeof this.prototype[key] == "undefined") {
 467 +                        block.call(context, object[key], key, object);
 468 +                }
 469 +        }
 470 +};
 471 +
 472 +// character enumeration
 473 +String.forEach = function(string, block, context) {
 474 +        Array.forEach(string.split(""), function(chr, index) {
 475 +                block.call(context, chr, index, string);
 476 +        });
 477 +};
 478 +
 479 +// globally resolve forEach enumeration
 480 +var forEach = function(object, block, context) {
 481 +        if (object) {
 482 +                var resolve = Object; // default
 483 +                if (object instanceof Function) {
 484 +                        // functions have a "length" property
 485 +                        resolve = Function;
 486 +                } else if (object.forEach instanceof Function) {
 487 +                        // the object implements a custom forEach method so use that
 488 +                        object.forEach(block, context);
 489 +                        return;
 490 +                } else if (typeof object == "string") {
 491 +                        // the object is a string
 492 +                        resolve = String;
 493 +                } else if (typeof object.length == "number") {
 494 +                        // the object is array-like
 495 +                        resolve = Array;
 496 +                }
 497 +                resolve.forEach(object, block, context);
 498 +        }
 499 +};
 500 +
 501 +
 502 

Attached Files

To refer to attachments on a page, use attachment:filename, as shown below in the list of files. Do NOT use the URL of the [get] link, since this is subject to change and can break easily.
  • [get | view] (2013-02-05 20:15:05, 0.1 KB) [[attachment:arrow-down.gif]]
  • [get | view] (2009-02-04 14:03:52, 18.5 KB) [[attachment:common.js.patch]]
  • [get | view] (2008-07-06 17:34:01, 22.0 KB) [[attachment:hg-export-1.diff]]
  • [get | view] (2010-09-07 22:04:53, 8.2 KB) [[attachment:sortable.zip]]
 All files | Selected Files: delete move to page copy to page

You are not allowed to attach a file to this page.