PageSourceSearch

https://www.electoralgeography.com/new/en/wp-content/plugins/wp-table/tablesort.js

js electoralgeography.com collected 2026-10-02 10:28:02 UTC 23,748 bytes, 523 lines download raw bytes

1/*
2        TableSort revisited v2.9 by frequency-decoder.com
3
4        Released under a creative commons Attribution-ShareAlike 2.5 license (http://creativecommons.org/licenses/by-sa/2.5/)
5
6        Please credit frequency decoder in any derivative work - thanks
7        
8        You are free:
9
10        * to copy, distribute, display, and perform the work
11        * to make derivative works
12        * to make commercial use of the work
13
14        Under the following conditions:
15
16                by Attribution.
17                --------------
18                You must attribute the work in the manner specified by the author or licensor.
19
20                sa
21                --
22                Share Alike. If you alter, transform, or build upon this work, you may distribute the resulting work only under a license identical to this one.
23
24        * For any reuse or distribution, you must make clear to others the license terms of this work.
25        * Any of these conditions can be waived if you get permission from the copyright holder.
26*/
27
28var fdTableSort = {
29
30        regExp_Currency:        /^[£$€¥¤]/,
31        regExp_Number:          /^(\-)?[0-9]+(\.[0-9]*)?$/,
32        pos:                    -1,
33        uniqueHash:             1,
34        thNode:                 null,
35        tableCache:             {},
36        tableId:                null,
37
38        addEvent: function(obj, type, fn) {
39                if( obj.attachEvent ) {
40                        obj["e"+type+fn] = fn;
41                        obj[type+fn] = function(){obj["e"+type+fn]( window.event );}
42                        obj.attachEvent( "on"+type, obj[type+fn] );
43                } else
44                        obj.addEventListener( type, fn, false );
45        },
46
47        stopEvent: function(e) {
48                e = e || window.event;
49
50                if(e.stopPropagation) {
51                        e.stopPropagation();
52                        e.preventDefault();
53                }
54                /*@cc_on@*/
55                /*@if(@_win32)
56                e.cancelBubble = true;
57                e.returnValue = false;
58                /*@end@*/
59                return false;
60        },
61
62        init: function() {
63                if (!document.getElementsByTagName) return;
64
65                var tables = document.getElementsByTagName('table');
66                var sortable, headers, thtext, aclone, a, span, columnNum, noArrow, reverseSortOnInit;
67
68                a               = document.createElement("a");
69                a.href          = "#";
70                a.onkeypress    = fdTableSort.keyWrapper;
71
72                span            = document.createElement("span");
73
74                for(var t = 0, tbl; tbl = tables[t]; t++) {
75                
76                        headers = fdTableSort.getTableHeaders(tbl);
77                        
78                        sortable  = false;
79                        columnNum = tbl.className.search(/sortable-onload-([0-9]+)/) != -1 ? parseInt(tbl.className.match(/sortable-onload-([0-9]+)/)[1]) - 1 : -1;
80                        showArrow = tbl.className.search(/no-arrow/) == -1;
81                        reverse   = tbl.className.search(/sortable-onload-([0-9]+)-reverse/) != -1;
82                        
83                        // Remove any old dataObj for this table (tables created from an ajax callback require this)
84                        if(tbl.id && tbl.id in fdTableSort.tableCache) delete fdTableSort.tableCache[tbl.id];
85
86                        var colCnt = -1;
87                        
88                        for (var z=0, th; th = headers[z]; z++) {
89                        
90                                colCnt += th.getAttribute("colspan") ? Number(th.getAttribute("colspan")) : 1;
91                                
92                                if(th.className && th.className.match('sortable') && (!th.getAttribute("colspan") || th.getAttribute("colspan") == 1)) {
93
94                                        // Remove previously applied classes for the ajaxers also
95                                        th.className = th.className.replace(/forwardSort|reverseSort/, "");
96
97                                        if(colCnt == columnNum) sortable = th;
98                                        thtext = fdTableSort.getInnerText(th);
99
100                                        while(th.firstChild) th.removeChild(th.firstChild);
101
102                                        // Create the link
103                                        aclone = a.cloneNode(true);
104                                        aclone.appendChild(document.createTextNode(thtext));
105                                        aclone.title = "Sort on " + thtext;
106                                        a.onclick = th.onclick = fdTableSort.clickWrapper;
107                                        th.appendChild(aclone);
108
109                                        // Add the span if needs be
110                                        if(showArrow) th.appendChild(span.cloneNode(false));
111
112                                        var cn = "fd-column-" + colCnt;
113                                        th.className = th.className.replace(/fd-identical|fd-not-identical/, "").replace(/fd-column-([0-9]+)/, "") + " " + cn;
114                                        fdTableSort.disableSelection(th);
115                                };
116                        };
117
118                        if(sortable) {
119                                fdTableSort.thNode = sortable;
120                                fdTableSort.initSort();
121                                if(reverse) {
122                                        fdTableSort.thNode = sortable;
123                                        fdTableSort.initSort();
124                                };
125                        };
126                };
127        },
128        
129        disableSelection: function(element) {
130                element.onselectstart = function() {
131                        return false;
132                };
133                element.unselectable = "on";
134                element.style.MozUserSelect = "none";
135        },
136        
137        getTableHeaders: function(tbl) {
138                var headers;
139                var thead = tbl.getElementsByTagName('thead');
140
141                if(thead && thead.length) {
142                        thead = thead[0];
143                        headers = thead.getElementsByTagName('tr');
144                        headers = headers[headers.length - 1].getElementsByTagName('th');
145                } else {
146                        headers = tbl.getElementsByTagName('th');
147                }
148                return headers;
149        },
150        
151        countColumns: function(thList) {
152                var colCnt = 0;
153                for(var i = 0, th; th = thList[i]; i++) {
154                        colCnt += th.getAttribute("colspan") ? Number(th.getAttribute("colspan")) : 1;
155                };
156
157                return colCnt;
158        },
159        
160        getTH: function(thList, pos) {
161                var thList = fdTableSort.thNode.parentNode.getElementsByTagName("th");
162
163                for(var i = 0, th; th = thList[i]; i++) {
164                        var re = new RegExp( "(fd-column-" + pos + ")([^0-9]+)" );
165                        if(th.className.search(re) != -1) return th;
166                };
167        },
168        
169        clickWrapper: function(e) {
170                e = e || window.event;
171                if(fdTableSort.thNode == null) {
172                        fdTableSort.thNode = this;
173                        fdTableSort.addSortActiveClass();
174                        setTimeout("fdTableSort.initSort()",5);
175
176                };
177                return fdTableSort.stopEvent(e);
178        },
179
180        keyWrapper: function(e) {
181                e = e || window.event;
182                var kc = e.keyCode != null ? e.keyCode : e.charCode;
183                if(kc == 13) {
184                        var targ = this;
185                        while(targ.tagName.toLowerCase() != "th") targ = targ.parentNode;
186
187                        fdTableSort.thNode = targ;
188                        fdTableSort.addSortActiveClass();
189                        setTimeout("fdTableSort.initSort()",5);
190
191                        return fdTableSort.stopEvent(e);
192                };
193                return true;
194        },
195
196        jsWrapper: function(tableid, colNum) {
197                var table = document.getElementById(tableid);
198                fdTableSort.thNode = fdTableSort.getTH(table.getElementsByTagName('th'), colnum);
199                if(!fdTableSort.thNode || fdTableSort.thNode.className.search(/fd-column/) == -1) return false;
200                fdTableSort.addSortActiveClass();
201                fdTableSort.initSort();
202        },
203
204        addSortActiveClass: function() {
205                if(fdTableSort.thNode == null) return;
206                fdTableSort.addClass(fdTableSort.thNode, "sort-active");
207                fdTableSort.addClass(document.getElementsByTagName('body')[0], "sort-active");
208                if("sortInitiatedCallback" in window) {
209                        var tableElem   = fdTableSort.thNode;
210                        while(tableElem.tagName.toLowerCase() != 'table' && tableElem.parentNode) {
211                                tableElem = tableElem.parentNode;
212                        };
213                        sortInitiatedCallback(tableElem.id);
214                };
215        },
216
217        removeSortActiveClass: function() {
218                fdTableSort.removeClass(fdTableSort.thNode, "sort-active");
219                fdTableSort.removeClass(document.getElementsByTagName('body')[0], "sort-active");
220                if("sortCompleteCallback" in window) {
221                        var tableElem   = fdTableSort.thNode;
222                        while(tableElem.tagName.toLowerCase() != 'table' && tableElem.parentNode) {
223                                tableElem = tableElem.parentNode;
224                        };
225                        sortCompleteCallback(tableElem.id);
226                };
227        },
228
229        addClass: function(e,c) {
230                if(new RegExp("(^|\\s)" + c + "(\\s|$)").test(e.className)) return;
231                e.className += ( e.className ? " " : "" ) + c;
232        },
233
234        removeClass: function(e,c) {
235                e.className = !c ? "" : e.className.replace(new RegExp("(^|\\s*\\b[^-])"+c+"($|\\b(?=[^-]))", "g"), "");
236        },
237
238        prepareTableData: function(table) {
239                // Create a table id if needs be
240                if(!table.id) table.id = "fd-table-" + fdTableSort.uniqueHash++;
241
242                var data = [];
243
244                var start = table.getElementsByTagName('tbody');
245                start = start.length ? start[0] : table;
246
247                var trs = start.getElementsByTagName('tr');
248                var ths = fdTableSort.getTableHeaders(table);
249
250                var numberOfRows = trs.length;
251                var numberOfCols = fdTableSort.countColumns(ths);
252
253                var data = [];
254                var identical = new Array(numberOfCols);
255                var identVal  = new Array(numberOfCols);
256
257                var tr, td, th, txt, tds, col, row;
258
259                var rowCnt = 0;
260
261                // Start to create the 2D matrix of data
262                for(row = 0; row < numberOfRows; row++) {
263
264                        tr              = trs[row];
265
266                        // Have we any th tags or are we in a tfoot ?
267                        if(tr.getElementsByTagName('th').length > 0 || (tr.parentNode && tr.parentNode.tagName.toLowerCase() == "tfoot")) continue;
268
269                        data[rowCnt]    = [];
270                        tds             = tr.getElementsByTagName('td');
271                        col             = -1;
272
273                        for(var tmp = 0, th; th = ths[tmp]; tmp++) {
274
275                                col += th.getAttribute("colspan") ? Number(th.getAttribute("colspan")) : 1;
276
277                                if(th.className.search(/sortable/) == -1 || (th.getAttribute("colspan") && Number(th.getAttribute("colspan")) > 1)) continue;
278
279                                td  = tds[col];
280
281                                txt = fdTableSort.getInnerText(td) + " ";
282
283                                txt = txt.replace(/^\s+/,'').replace(/\s+$/,'');
284
285                                if(th.className.search(/sortable-date/) != -1) {
286                                        txt = fdTableSort.dateFormat(txt, th.className.search(/sortable-date-dmy/) != -1);
287                                } else if(th.className.search(/sortable-numeric|sortable-currency/) != -1) {
288                                        txt = parseFloat(txt.replace(/[^0-9\.\-]/g,''));
289                                        if(isNaN(txt)) txt = "";
290                                } else if(th.className.search(/sortable-text/) != -1) {
291                                        txt = txt.toLowerCase();
292                                } else if(th.className.search(/sortable-([a-zA-Z\_]+)/) != -1) {
293                                        if((th.className.match(/sortable-([a-zA-Z\_]+)/)[1] + "PrepareData") in window) {
294                                                txt = window[th.className.match(/sortable-([a-zA-Z\_]+)/)[1] + "PrepareData"](td, txt);
295                                        };
296                                } else {
297                                        if(txt != "") {
298                                                fdTableSort.removeClass(th, "sortable");
299                                                if(fdTableSort.dateFormat(txt) != 0) {
300                                                        fdTableSort.addClass(th, "sortable-date");
301                                                        txt = fdTableSort.dateFormat(txt);
302                                                } else if(txt.search(fdTableSort.regExp_Number) != -1 || txt.search(fdTableSort.regExp_Currency) != -1) {
303                                                        fdTableSort.addClass(th, "sortable-numeric");
304                                                        txt = parseFloat(txt.replace(/[^0-9\.\-]/g,''));
305                                                        if(isNaN(txt)) txt = "";
306                                                } else {
307                                                        fdTableSort.addClass(th, "sortable-text");
308                                                        txt = txt.toLowerCase();
309                                                };
310                                        };
311                                };
312
313                                if(rowCnt > 0 && identVal[col] != txt) {
314                                        identical[col] = false;
315                                };
316
317                                identVal[col]     = txt;
318                                data[rowCnt][col] = txt;
319                        };
320
321                        // Add the tr for this row
322                        data[rowCnt][numberOfCols] = tr;
323
324                        // Increment the row count
325                        rowCnt++;
326                }
327
328                // Get the row and column styles
329                var colStyle = table.className.search(/colstyle-([\S]+)/) != -1 ? table.className.match(/colstyle-([\S]+)/)[1] : false;
330                var rowStyle = table.className.search(/rowstyle-([\S]+)/) != -1 ? table.className.match(/rowstyle-([\S]+)/)[1] : false;
331
332                // Cache the data object for this table
333                fdTableSort.tableCache[table.id] = { data:data, pos:-1, identical:identical, colStyle:colStyle, rowStyle:rowStyle, noArrow:table.className.search(/no-arrow/) != -1 };
334        },
335
336        initSort: function() {
337
338                var span;
339                var thNode      = fdTableSort.thNode;
340
341                // Get the table
342                var tableElem   = fdTableSort.thNode;
343                while(tableElem.tagName.toLowerCase() != 'table' && tableElem.parentNode) {
344                        tableElem = tableElem.parentNode;
345                };
346
347                // If this is the first time that this table has been sorted, create the data object
348                if(!tableElem.id || !(tableElem.id in fdTableSort.tableCache)) {
349                        fdTableSort.prepareTableData(tableElem);
350                };
351
352                // Cache the table id
353                fdTableSort.tableId = tableElem.id;
354
355                // Get the column position using the className added earlier
356                fdTableSort.pos = thNode.className.match(/fd-column-([0-9]+)/)[1];
357
358                // Grab the data object for this table
359                var dataObj     = fdTableSort.tableCache[tableElem.id];
360
361                // Get the position of the last column that was sorted
362                var lastPos     = dataObj.pos;
363
364                // Get the stored data object for this table
365                var data        = dataObj.data;
366                var colStyle    = dataObj.colStyle;
367                var rowStyle    = dataObj.rowStyle;
368                var len1        = data.length;
369                var len2        = data[0].length - 1;
370                var identical   = dataObj.identical[fdTableSort.pos] == false ? false : true;
371                var noArrow     = dataObj.noArrow;
372
373                if(lastPos != fdTableSort.pos && lastPos != -1) {
374                        var th = fdTableSort.getTH(thNode.parentNode.getElementsByTagName('th'), lastPos);
375
376                        fdTableSort.removeClass(th, "forwardSort");
377                        fdTableSort.removeClass(th, "reverseSort");
378                        if(!noArrow) {
379                                // Remove arrow
380                                span = th.getElementsByTagName('span')[0];
381                                while(span.firstChild) span.removeChild(span.firstChild);
382                        };
383                };
384
385                // If the same column is being sorted then just reverse the data object contents.
386                var classToAdd = "forwardSort";
387
388                if(lastPos == fdTableSort.pos && !identical) {
389                        data.reverse();
390                        classToAdd = thNode.className.search(/reverseSort/) != -1 ? "forwardSort" : "reverseSort";
391                } else {
392                        fdTableSort.tableCache[tableElem.id].pos = fdTableSort.pos;
393                        if(!identical) {
394                                if(thNode.className.match(/sortable-numeric|sortable-currency|sortable-date/)) {
395                                        data.sort(fdTableSort.sortNumeric);
396                                } else if(thNode.className.match('sortable-text')) {
397                                        data.sort(fdTableSort.sortText);
398                                } else if(thNode.className.search(/sortable-([a-zA-Z\_]+)/) != -1 && thNode.className.match(/sortable-([a-zA-Z\_]+)/)[1] in window) {
399                                        data.sort(window[thNode.className.match(/sortable-([a-zA-Z\_]+)/)[1]]);
400                                };
401                        };
402                };
403
404                fdTableSort.removeClass(thNode, "forwardSort");
405                fdTableSort.removeClass(thNode, "reverseSort");
406                fdTableSort.addClass(thNode, classToAdd);
407
408                if(!noArrow) {
409                        var arrow = thNode.className.search(/forwardSort/) != -1 ? " \u2193" : " \u2191";
410                        span = thNode.getElementsByTagName('span')[0];
411                        while(span.firstChild) span.removeChild(span.firstChild);
412                        span.appendChild(document.createTextNode(arrow));
413                };
414
415                if(!rowStyle && !colStyle && identical) {
416                        fdTableSort.removeSortActiveClass();
417                        fdTableSort.thNode = null;
418                        return;
419                }
420
421                var hook = tableElem.getElementsByTagName('tbody');
422                hook = hook.length ? hook[0] : tableElem;
423
424                var td, tr;
425
426                for(var i = 0; i < len1; i++) {
427                        tr = data[i][len2];
428                        if(colStyle) {
429                                if(lastPos != -1) {
430                                        fdTableSort.removeClass(tr.getElementsByTagName('td')[lastPos], colStyle);
431                                }
432                                fdTableSort.addClass(tr.getElementsByTagName('td')[fdTableSort.pos], colStyle);
433                        };
434                        if(!identical) {
435
436                                if(rowStyle) {
437                                        if(i % 2) fdTableSort.addClass(tr, rowStyle);
438                                        else fdTableSort.removeClass(tr, rowStyle);
439                                };
440
441                                hook.removeChild(tr); /* Netscape 8.1.2 requires the removeChild call */
442                                hook.appendChild(tr);
443                        };
444                };
445                fdTableSort.removeSortActiveClass();
446                fdTableSort.thNode = null;
447        },
448
449        getInnerText: function(el) {
450                if (typeof el == "string" || typeof el == "undefined") return el;
451                if(el.innerText) return el.innerText;
452
453                var txt = '', i;
454                for (i = el.firstChild; i; i = i.nextSibling) {
455                        if (i.nodeType == 3)            txt += i.nodeValue;
456                        else if (i.nodeType == 1)       txt += fdTableSort.getInnerText(i);
457                };
458
459                return txt;
460        },
461        
462        dateFormat: function(dateIn, favourDMY) {
463                var dateTest = [
464                        { regExp:/^(0[1-9]|1[012])([- \/.])(0[1-9]|[12][0-9]|3[01])([- \/.])(\d\d?\d\d)$/, d:3, m:1, y:5 },  // mdy
465                        { regExp:/^(0[1-9]|[12][0-9]|3[01])([- \/.])(0[1-9]|1[012])([- \/.])(\d\d?\d\d)$/, d:1, m:3, y:5 },  // dmy
466                        { regExp:/^(\d\d?\d\d)([- \/.])(0[1-9]|1[012])([- \/.])(0[1-9]|[12][0-9]|3[01])$/, d:5, m:3, y:1 }   // ymd
467                        ];
468
469                var start;
470                var cnt = 0;
471
472                while(cnt < 3) {
473                        start = (cnt + (favourDMY ? 4 : 3)) % 3;
474
475                        if(dateIn.match(dateTest[start].regExp)) {
476                                res = dateIn.match(dateTest[start].regExp);
477                                y = res[dateTest[start].y];
478                                m = res[dateTest[start].m];
479                                d = res[dateTest[start].d];
480                                if(m.length == 1) m = "0" + m;
481                                if(d.length == 1) d = "0" + d;
482                                if(y.length != 4) y = (parseInt(y) < 50) ? '20' + y : '19' + y;
483
484                                return y+m+d;
485                        }
486
487                        cnt++;
488                }
489
490                return 0;
491        },
492
493        sortDate: function(a,b) {
494                var aa = a[fdTableSort.pos];
495                var bb = b[fdTableSort.pos];
496
497                return aa - bb;
498        },
499
500        sortNumeric:function (a,b) {
501                var aa = a[fdTableSort.pos];
502                var bb = b[fdTableSort.pos];
503
504                if(aa === "" && !isNaN(bb)) return -1;
505                else if(bb === "" && !isNaN(aa)) return 1;
506                else if(aa == bb) return 0;
507
508                return aa - bb;
509        },
510
511        sortText:function (a,b) {
512                var aa = a[fdTableSort.pos];
513                var bb = b[fdTableSort.pos];
514
515                if(aa == bb) return 0;
516                if(aa < bb)  return -1;
517
518                return 1;
519        }
520};
521
522fdTableSort.addEvent(window, "load", fdTableSort.init);
523

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.