From a38905569c783b6aefa15e89ceeaa54efa5ee0de Mon Sep 17 00:00:00 2001 From: "Kasper D. Fischer" Date: Tue, 6 May 2014 11:26:47 +0000 Subject: [PATCH] Moving map2014 to trunk. --- .gitattributes | 17 + .gitignore | 3 + scripts/mkGeolocationTable.py | 61 ++ www/TileLayer.Grayscale.js | 51 ++ www/events.js | 239 +++++++ www/first.png | Bin 0 -> 720 bytes www/index.html.de | 140 +++++ www/jquery.localtime-0.9.1.min.js | 4 + www/jquery.tablesorter.min.js | 5 + www/jquery.tablesorter.pager.css | 42 ++ www/jquery.tablesorter.pager.min.js | 2 + www/jquery.tablesorter.widgets.min.js | 17 + www/last.png | Bin 0 -> 737 bytes www/leaflet.css | 478 ++++++++++++++ www/leaflet.js | 9 + www/logo_RUB_155x30.png | Bin 0 -> 9436 bytes www/main.css | 67 ++ www/map.js | 192 ++++++ www/misc.js | 85 +++ www/next.png | Bin 0 -> 736 bytes www/prev.png | Bin 0 -> 745 bytes www/sprintf.min.js | 1 + www/stations.js | 118 ++++ www/theme.blue.css | 221 +++++++ www/widget-pager.js | 863 ++++++++++++++++++++++++++ 25 files changed, 2615 insertions(+) create mode 100644 .gitattributes create mode 100644 .gitignore create mode 100755 scripts/mkGeolocationTable.py create mode 100644 www/TileLayer.Grayscale.js create mode 100644 www/events.js create mode 100644 www/first.png create mode 100644 www/index.html.de create mode 100644 www/jquery.localtime-0.9.1.min.js create mode 100644 www/jquery.tablesorter.min.js create mode 100644 www/jquery.tablesorter.pager.css create mode 100644 www/jquery.tablesorter.pager.min.js create mode 100644 www/jquery.tablesorter.widgets.min.js create mode 100644 www/last.png create mode 100644 www/leaflet.css create mode 100644 www/leaflet.js create mode 100644 www/logo_RUB_155x30.png create mode 100644 www/main.css create mode 100644 www/map.js create mode 100644 www/misc.js create mode 100644 www/next.png create mode 100644 www/prev.png create mode 100644 www/sprintf.min.js create mode 100644 www/stations.js create mode 100644 www/theme.blue.css create mode 100644 www/widget-pager.js diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..bb9254b --- /dev/null +++ b/.gitattributes @@ -0,0 +1,17 @@ +* text=auto !eol +www/TileLayer.Grayscale.js -text +www/first.png -text +www/jquery.localtime-0.9.1.min.js -text +www/jquery.tablesorter.min.js -text +www/jquery.tablesorter.pager.css -text +www/jquery.tablesorter.pager.min.js -text +www/jquery.tablesorter.widgets.min.js -text +www/last.png -text +www/leaflet.css -text +www/leaflet.js -text +www/logo_RUB_155x30.png -text +www/next.png -text +www/prev.png -text +www/sprintf.min.js -text +www/theme.blue.css -text +www/widget-pager.js -text diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..f47c021 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +www/event.xml +www/geolocation.js +www/stations.xml diff --git a/scripts/mkGeolocationTable.py b/scripts/mkGeolocationTable.py new file mode 100755 index 0000000..c1fc070 --- /dev/null +++ b/scripts/mkGeolocationTable.py @@ -0,0 +1,61 @@ +#! /usr/bin/env python +# -*- coding: utf-8 -*- +# $Id$ + +''' +Script to lookup city names of events with Nominatim service + +The input should be an valid quakeML file passed to stdin. +The output will will be a javascript structure to be included in the +SeisObs map service. + +the script should be updated regulary keep the total number of all +AJAX calls to the Nominatim service small +''' + +# imports +try: + import xml.etree.cElementTree as ET +except ImportError: + import xml.etree.ElementTree as ET +from sys import stdin +import urllib2 as URL +import json as JSON + +# constants +namespaces = {'sc3': 'http://geofon.gfz-potsdam.de/ns/seiscomp3-schema/0.7', + 'qml': 'http://quakeml.org/xmlns/bed/1.2'} + +# initialise variables +geolocationTable = {}; + +# parse event.xml +DOM = ET.parse(stdin).getroot() +#DOM = ET.parse('../www/event.xml').getroot() + +# iterate over all events +for event in DOM.iterfind('qml:eventParameters/qml:event', namespaces): + publicID = event.attrib['publicID'].split('/')[2] + lat = event.find('./qml:origin/qml:latitude/qml:value', namespaces).text + lng = event.find('./qml:origin/qml:longitude/qml:value', namespaces).text + url = 'https://open.mapquestapi.com/nominatim/v1/reverse.php?lat={0}&lon={1}&zoom=10&format=json'.format(lat, lng) + # send and evaluate nominatim request + response = URL.urlopen(url) + if ( response.msg == 'OK' ): + data = JSON.loads(response.read()) + try: + city = data['address']['city'] + country = data['address']['country'] + countryCode = data['address']['country_code'].upper() + value = city + if ( countryCode != 'DE' ): + value = '{0} ({1})'.format(value, countryCode) + geolocationTable[publicID] = value + except: + print 'Could not etract city for event {0}'.format(publicID) + else: + print 'Request {0} failed'.format(url) +# dump json +print 'var geolocationTable = '+JSON.dumps(geolocationTable) + + diff --git a/www/TileLayer.Grayscale.js b/www/TileLayer.Grayscale.js new file mode 100644 index 0000000..7d9e934 --- /dev/null +++ b/www/TileLayer.Grayscale.js @@ -0,0 +1,51 @@ +/* + * L.TileLayer.Grayscale is a regular tilelayer with grayscale makeover. + */ + +L.TileLayer.Grayscale = L.TileLayer.extend({ + options: { + enableCanvas: true + }, + + initialize: function (url, options) { + var canvasEl = document.createElement('canvas'); + if( !(canvasEl.getContext && canvasEl.getContext('2d')) ) { + options.enableCanvas = false; + } + + L.TileLayer.prototype.initialize.call(this, url, options); + }, + + _loadTile: function (tile, tilePoint) { + tile.setAttribute('crossorigin', 'anonymous'); + L.TileLayer.prototype._loadTile.call(this, tile, tilePoint); + }, + + _tileOnLoad: function () { + if (this._layer.options.enableCanvas && !this.canvasContext) { + var canvas = document.createElement("canvas"); + canvas.width = canvas.height = this._layer.options.tileSize; + this.canvasContext = canvas.getContext("2d"); + } + var ctx = this.canvasContext; + + if (ctx) { + this.onload = null; // to prevent an infinite loop + ctx.drawImage(this, 0, 0); + var imgd = ctx.getImageData(0, 0, this._layer.options.tileSize, this._layer.options.tileSize); + var pix = imgd.data; + for (var i = 0, n = pix.length; i < n; i += 4) { + pix[i] = pix[i + 1] = pix[i + 2] = (3 * pix[i] + 4 * pix[i + 1] + pix[i + 2]) / 8; + } + ctx.putImageData(imgd, 0, 0); + this.removeAttribute("crossorigin"); + this.src = ctx.canvas.toDataURL(); + } + + L.TileLayer.prototype._tileOnLoad.call(this); + } +}); + +L.tileLayer.grayscale = function (url, options) { + return new L.TileLayer.Grayscale(url, options); +}; diff --git a/www/events.js b/www/events.js new file mode 100644 index 0000000..6891b1d --- /dev/null +++ b/www/events.js @@ -0,0 +1,239 @@ +/* do reverse geolocation lookup */ +function getGeolocation(id, lat, lng) { + if ( !geolocationTable[id] ) { + // $.getJSON( "//nominatim.openstreetmap.org/reverse", { lat: lat, lon: lng, zoom: 10, format: "json" } ) + $.getJSON( "//open.mapquestapi.com/nominatim/v1/reverse.php", { lat: lat, lon: lng, zoom: 10, format: "json" } ) + .done(function( json ) { + var city = json.address["city"]; + var country = json.address["country"]; + var countryCode = json.address["country_code"].toUpperCase(); + geolocationTable[id] = city; + ( country != "Deutschland" ) ? geolocationTable[id] = geolocationTable[id] + " ("+countryCode+")" : null; + if ( city ) { + $("#eventstable a.toggle[eventid="+id+"]").text(geolocationTable[id]); + var sort = [[0,1],[1,1],[2,1]]; + $("#eventstable").trigger("update", [true]); + $("#eventstable").trigger("updateCache"); + $("#eventstable").trigger("sorton", [sort]); + } else { + console.log("Nominatim did not provide a city tag for "+lat+" / "+lng); + }; + }) + .fail(function( jqxhr, textStatus, error ) { + var err = textStatus + ", " + error; + console.log( "Request Failed: " + err ); + }); + }; +}; + +/* Load events using ajax */ +function ajaxLoadEvents(stime, etime) { + var mapBounds = map.getBounds(); + var N = mapBounds.getNorth(); + var E = mapBounds.getEast(); + var S = mapBounds.getSouth(); + var W = mapBounds.getWest(); + var d = 0.1; + if ( !stime ) { + var stime = new Date(); + stime.setDate(stime.getDate()-180); + }; + if ( !etime ) { + var etime = new Date(); + etime.setDate(etime.getDate()+1); + }; + var url = "https://ariadne.geophysik.ruhr-uni-bochum.de/fdsnws/event/1/query" + var request_data = { + starttime: sprintf("%d-%02d-%02d", stime.getFullYear(), stime.getMonth()+1, stime.getDate()), + endtime: sprintf("%d-%02d-%02d", etime.getFullYear(), etime.getMonth()+1, etime.getDate()), + minlat: S-d, + maxlat: N+d, + minlon: W-d, + maxlon: E+d, + minmag: minMag-0.1, + }; + $.ajax({ + type: "GET", + url: url, + data: request_data, + dataType: "xml", + success: function (xml) { + $(xml).find('event').each(function () { + var id = $(this).attr('publicID').split('/')[2]; + var mag = $(this).find('magnitude > mag > value').text(); + var otime = $(this).find('origin > time > value').text(); + var lng = $(this).find('origin > longitude > value').text(); + var lat = $(this).find('origin > latitude > value').text(); + var mag = $(this).find('magnitude > mag > value').text(); + var evaluationMode = $(this).find('evaluationMode').text(); + var evaluationStatus = $(this).find('evaluationStatus').text(); + var type = $(this).find('type').last().text(); + var location = getLocation(Number(lat), Number(lng))[0]; + ( location ) ? null : location = $(this).find('description > text').text(); + // create table row: Date, Time, Mag, Location + if ( !eventTable[id] && ( type == 'earthquake' || type == 'induced or triggered event' || type == 'outside of network interest') && evaluationMode != 'automatic' && evaluationStatus != 'preliminary' && Number(mag)+0.05 >= minMag ) { + var row = '' + + ''+otime.split('.')[0]+'Z' + + ''+otime.split('.')[0]+'Z' + + sprintf('%.1f', Number(mag)) + + ''+location+'Karte' + + ''; + row += '' + + 'not implemented'; + var added = $('#eventstable tbody').append(row); + added.find('.tablesorter-childRow td').hide(); + $('#eventstable').find('td.utctime-date').each(function() { + $.localtime.formatObject($(this), "dd.MM.yyyy"); + $(this).removeClass('utctime-date'); + $(this).addClass('localtime-date'); + }); + $('#eventstable').find('td.utctime-time').each(function() { + $.localtime.formatObject($(this), "HH:mm"); + $(this).removeClass('utctime-time'); + $(this).addClass('localtime-time'); + }); + // create marker + var marker = addEventMarker(id, Number(lat), Number(lng), Number(mag)); + var text = sprintf('

%s

', id, location) + + sprintf('

Ereignis: %s
', id) + + sprintf('Ort: %.4f °N, %.4f °O
', Number(lat), Number(lng)) + + sprintf('Zeit: %sZ

', otime.split('.')[0], otime.split('.')[0]); + marker.bindPopup(text); + // try to get better location with reverse geolocation lookup (nominatim), check cache first + ( geolocationTable[id] ) ? $("#eventstable a.toggle[eventid="+id+"]").text(geolocationTable[id]) : getGeolocation(id, lat, lng); + }; + }); + }, + complete: function () { + initStationTable(); + var sort = [[0,1],[1,1],[2,1]]; + $("#eventstable").trigger("update", [true]); + $("#eventstable").trigger("updateCache"); + $("#eventstable").trigger("sorton", [sort]); + initMapLink(); + }, + error: function( jqxhr, textStatus, error ) { + var err = textStatus + ", " + error; + console.log( "Request Failed: " + err ); + } + }); +}; + +// add row to table +function addEventRow(id, props) { + $('#eventstable').tablesorter({ + sortList: "[[0,0], [1,1]], [2,1]", + resort: true, + showProcessing: true, + pager_size: 35 + }); + var html = '' + + ''+props.date+'T'+props.time.split('.')[0]+'Z' + + ''+props.date+'T'+props.time.split('.')[0]+'Z' + + ''+props.mag+'' + + ''+props.location+'Karte' + + '' + + '' + + '' + + "
ID                     "+id+"\n\n"
+		+ "Origin\n"
+		+ "Date                   "+props.date+"\n"
+		+ "Time                   "+props.time+"\n"
+		+ "Latitude                "+props.lat+" deg  +/-    "+props.lat_err+" km\n"
+		+ "Longitude                "+props.lon+" deg  +/-    "+props.lon_err+" km\n"
+		+ "Depth                       "+props.depth+" km   +/-    "+props.depth_err+" km\n"
+		+ "Residual RMS             "+props.rms+" s\n"
+		+ "Azimuthal gap             "+props.gap+" deg\n\n"
+		+ props.no_phases + " Phase arrivals:\n"
+		+ "sta  net   dist azi  phase   time         res     wt  sta\n";
+	for ( i = 0 ; i < props.no_phases ; i++ ) {
+		html +=  props.phases[i];
+		( i < props.no_phases -1 ) ? html += "\n" : null ;
+	};
+	html += "
\n"; + var added = $('#eventstable tbody').append(html); + added.find('.tablesorter-childRow td').hide(); + $('#eventstable').find('td.utctime-date').each(function() { + $.localtime.formatObject($(this), "dd. MM. yyyy"); + $(this).removeClass('utctime-date'); + $(this).addClass('localtime-date'); + }); + $('#eventstable').find('td.utctime-time').each(function() { + $.localtime.formatObject($(this), "HH:mm"); + $(this).removeClass('utctime-time'); + $(this).addClass('localtime-time'); + }); + // force resorting + $("#eventstable").trigger("update", [true]); +}; + +$(document).ready(function() { + // tablesorter for event list + $("#eventstable").tablesorter( + { + theme : 'blue', + dateFormat : "ddmmyyyy", + headers: { + 0: { sorter: "shortDate" } + }, + cssChildRow: "tablesorter-childRow", // this is the default setting + widgets: ["uitheme", "zebra", "filter", "pager"], // initialize zebra and filter widgets, "scroller" + widgetOptions: { + // possible variables: {page}, {totalPages}, {filteredPages}, {startRow}, {endRow}, {filteredRows} and {totalRows} + pager_output: '# {startRow} - {endRow} ({totalRows}) | Seite {page} ({totalPages})', + pager_removeRows: false, + pager_size: 35, + filter_childRows : true, + filter_cssFilter : 'tablesorter-filter', + filter_startsWith : false, + filter_ignoreCase : true, + scroller_height: $('div.map').height() - 250, + scroller_barWidth: 10, + scroller_jumpToHeader: false, + sortList: "[[0,1], [1,1], [2,1]]", + resort: true, + showProcessing: true, + } + }); + + // hide child rows + $('#eventstable > tbody > tr.tablesorter-childRow td').hide(); + + // update map after filtering + $('#eventstable').bind('filterEnd', function(){ + toggleFilteredMarkers(); + }); + + // highlight first event + $('#eventstable').bind('sortEnd', function(){ + highlightFirstEvent(); + }); + + // show / hide event info + $('#eventstable').delegate('.toggle', 'click' , function(){ + // toggle visibility of selected row + $(this).closest('tr').nextUntil('tr.tablesorter-hasChildRow').find('td').toggle('slow'); + + // mark currently selected row and remove class selected from all other rows + // hide other rows + $(this).closest('tr').nextUntil('tr.tablesorter-hasChildRow').find('td').addClass('selected-now'); + $(this).closest('tbody').find('td.selected').each(function(){ + if ( ! $(this).hasClass('selected-now') ) { + $(this).hide('slow'); + $(this).removeClass('selected'); + }; + }); + $(this).closest('tr').nextUntil('tr.tablesorter-hasChildRow').find('td').each(function(){ + $(this).removeClass('selected-now'); + var selected = $(this).hasClass('selected'); + if ( selected ) { + $(this).removeClass('selected'); + } else { + $(this).addClass('selected'); + }; + }); + + return false; + }); + +}); diff --git a/www/first.png b/www/first.png new file mode 100644 index 0000000000000000000000000000000000000000..6f11fcb086b1bfa51bc5070ca45fac0a988c624c GIT binary patch literal 720 zcmV;>0x$iEP)ITpohD^Ctgf=H~o==W*|y0)VM;-LQd9lR=YF)677| z!Jh8V_;KSkP5LJrlF9S+j0qkk+2iPm7~x{#{$ZSbvzK9J-4zqYVC)27V7~717pTZd znit9v$VwYJS3ROyLxp^?0)a!0U)oMn7(0Xv0eUoZ@gH)t)d5_J+J%bT22oSJ)g^nf zqQZVCEIYOm2+rB;rB+cID%~N1o%g50=A<=fWgC_GFUb) z%s4&22M=t~3G+RMgR^pz#KbcfK)ZtsdJ$j@d{400GnQJeAz+sPu#&f$`6hKh0J%~V zq(%oWs|qZyzh}{lfSK@dRK#JSxg@DDP3^*cD+kP0j(npKkSQvp3bk_uYtD5My##O+ z;RpcDs9R5c#9;NFP5{z^GN_^r%PX%(0OOZ~7+aNFP*XZk{E2|i#E`vI`YjCrsfz|V zndEsDXoqvug2CxaF}ZvhdOaY6!{9q~KO+jO!o5Vk0qt%NcD}`cvVR;6QTNzYGWq-= zUX+?7V0e7VLW2m6_>T!vT6W8eRsOC$*+0hNMWWwDsLfA)S*X-WV71;M{bCz + + + + + RUB SeisObs - Ereignis- und Stationskarte + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+
+ First + Prev + + Next + Last + + +
+ + + + + + + + + + + + + + + + + +
DatumZeitMag.Ort
+

Nominatim Search Courtesy of MapQuest

+
+ +
+
+ First + Prev + + Next + Last + + +
+ + + + + + + + + + + + + + + + + +
NetworkStationBreite [°]Länge [°]
+
+ +
+ +
+
+ +
+ diff --git a/www/jquery.localtime-0.9.1.min.js b/www/jquery.localtime-0.9.1.min.js new file mode 100644 index 0000000..319203d --- /dev/null +++ b/www/jquery.localtime-0.9.1.min.js @@ -0,0 +1,4 @@ +/*! jQuery localtime - v0.9.1 - 2014-01-11 +* https://github.com/GregDThomas/jquery-localtime +* Copyright (c) 2014 Greg Thomas; Licensed Apache-2.0 */ +(function(e){"use strict";e.localtime=function(){var a={localtime:"yyyy-MM-dd HH:mm:ss"},t=["January","February","March","April","May","June","July","August","September","October","November","December"],r=["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],c=["th","st","nd","rd"],s=function(e){return e>=13?e-12:"0"===e?12:e},i=function(e,i){var o=""+e.getFullYear(),n=""+(e.getMonth()+1),l=""+e.getDate(),m=e.getDay(),d=""+e.getHours(),u=""+e.getMinutes(),b=""+e.getSeconds(),f=""+e.getMilliseconds(),k=e.getTimezoneOffset(),h=k>0?"-":"+";if(k=Math.abs(k),void 0===i){var y;for(y in a)if(a.hasOwnProperty(y)){i=a[y];break}if(void 0===i)return""+e}for(var g="",p="",M=0;i.length>M;M++)if(p+=i.charAt(M),"'"===p)for(M++;i.length>M;M++){var T=i.charAt(M);if("'"===T){p="";break}g+=T}else if("\\"===p&&i.length-1>M&&"'"===i.charAt(M+1))M++,g+="'",p="";else if(M===i.length-1||i.charAt(M)!==i.charAt(M+1)){switch(p){case"d":g+=l;break;case"dd":g+=("0"+l).slice(-2);break;case"ddd":g+=r[m].substr(0,3);break;case"ddddd":g+=r[m];break;case"M":g+=n;break;case"MM":g+=("0"+n).slice(-2);break;case"MMM":g+=t[n-1].substr(0,3);break;case"MMMMM":g+=t[n-1];break;case"yy":g+=o.slice(-2);break;case"yyyy":g+=o;break;case"H":g+=d;break;case"HH":g+=("0"+d).slice(-2);break;case"h":g+=s(d);break;case"hh":g+=("0"+s(d)).slice(-2);break;case"m":g+=u;break;case"mm":g+=("0"+u).slice(-2);break;case"s":g+=b;break;case"ss":g+=("0"+b).slice(-2);break;case"S":g+=f;break;case"SS":g+=("0"+f).slice(-2);break;case"SSS":g+=("00"+f).slice(-3);break;case"o":switch(l){case"11":case"12":case"13":g+=c[0];break;default:var v=l%10;v>3&&(v=0),g+=c[v]}break;case"a":case"TT":g+=d>=12?"PM":"AM";break;case"tt":g+=d>=12?"pm":"am";break;case"T":g+=d>=12?"P":"A";break;case"t":g+=d>=12?"p":"a";break;case"z":g+=h+parseInt(k/60,10);break;case"zz":g+=h+("0"+parseInt(k/60,10)).slice(-2);break;case"zzz":g+=h+("0"+parseInt(k/60,10)).slice(-2)+":"+("0"+k%60).slice(-2);break;default:g+=p}p=""}return g};return{setFormat:function(e){a="object"==typeof e?e:{localtime:e}},getFormat:function(){return a},parseISOTimeString:function(a){a=e.trim(""+a);var t=/^(\d{4})-([01]\d)-([0-3]\d)[T| ]([0-2]\d):([0-5]\d)(?::([0-5]\d)(?:\.(\d{3}))?)?Z$/.exec(a);if(t){var r=parseInt(t[1],10),c=parseInt(t[2],10)-1,s=parseInt(t[3],10),i=parseInt(t[4],10),o=parseInt(t[5],10),n=t[6]?parseInt(t[6],10):0,l=t[7]?parseInt(t[7],10):0,m=new Date(Date.UTC(r,c,s,i,o,n,l));if(m.getUTCFullYear()!==r||m.getUTCMonth()!==c||m.getUTCDate()!==s)throw Error(t[1]+"-"+t[2]+"-"+t[3]+" is not a valid date");if(m.getUTCHours()!==i)throw Error(t[4]+":"+t[5]+" is not a valid time");return m}throw Error(a+" is not a supported date/time string")},toLocalTime:function(a,t){return"[object Date]"!==Object.prototype.toString.call(a)&&(a=e.localtime.parseISOTimeString(a)),""===t&&(t=void 0),i(a,t)},formatObject:function(a,t){a.is(":input")?a.val(e.localtime.toLocalTime(a.val(),t)):a.is("time")?a.text(e.localtime.toLocalTime(a.attr("datetime"),t)):a.text(e.localtime.toLocalTime(a.text(),t))},formatPage:function(){e.localtime.format()},format:function(a){var t,r,c=function(){e.localtime.formatObject(e(this),t)},s=e.localtime.getFormat();for(r in s)s.hasOwnProperty(r)&&(t=s[r],e("."+r,a).each(c));e("[data-localtime-format]",a).each(function(){e.localtime.formatObject(e(this),e(this).attr("data-localtime-format"))})}}}()})(jQuery),jQuery(document).ready(function(e){"use strict";e.localtime.format()}); diff --git a/www/jquery.tablesorter.min.js b/www/jquery.tablesorter.min.js new file mode 100644 index 0000000..7dc886e --- /dev/null +++ b/www/jquery.tablesorter.min.js @@ -0,0 +1,5 @@ +/*! +* TableSorter 2.16.2 min - Client-side table sorting with ease! +* Copyright (c) 2007 Christian Bach +*/ +!function(g){g.extend({tablesorter:new function(){function d(){var a=arguments[0],b=1':"";m.$headers=g(a).find(m.selectorHeaders).each(function(a){c=g(this);b=m.headers[a];m.headerContent[a]= g(this).html();t=m.headerTemplate.replace(/\{content\}/g,g(this).html()).replace(/\{icon\}/g,e);m.onRenderTemplate&&(h=m.onRenderTemplate.apply(c,[a,t]))&&"string"===typeof h&&(t=h);g(this).html('
'+t+"
");m.onRenderHeader&&m.onRenderHeader.apply(c,[a]);this.column=parseInt(g(this).attr("data-column"),10);this.order=C(f.getData(c,b,"sortInitialOrder")||m.sortInitialOrder)?[1,0,2]:[0,1,2];this.count=-1;this.lockedOrder=!1;k=f.getData(c,b,"lockedOrder")||!1;"undefined"!== typeof k&&!1!==k&&(this.order=this.lockedOrder=C(k)?[1,1,1]:[0,0,0]);c.addClass(f.css.header+" "+m.cssHeader);m.headerList[a]=this;c.parent().addClass(f.css.headerRow+" "+m.cssHeaderRow).attr("role","row");m.tabIndex&&c.attr("tabindex",0)}).attr({scope:"col",role:"columnheader"});B(a);m.debug&&(u("Built headers:",l),d(m.$headers))}function E(a,b,c){var h=a.config;h.$table.find(h.selectorRemove).remove();s(a);x(a);H(h.$table,b,c)}function B(a){var b,c,h=a.config;h.$headers.each(function(e,t){c=g(t); b="false"===f.getData(t,h.headers[e],"sorter");t.sortDisabled=b;c[b?"addClass":"removeClass"]("sorter-false").attr("aria-disabled",""+b);a.id&&(b?c.removeAttr("aria-controls"):c.attr("aria-controls",a.id))})}function G(a){var b,c,h=a.config,e=h.sortList,t=e.length,d=f.css.sortNone+" "+h.cssNone,l=[f.css.sortAsc+" "+h.cssAsc,f.css.sortDesc+" "+h.cssDesc],m=["ascending","descending"],n=g(a).find("tfoot tr").children().add(h.$extraHeaders).removeClass(l.join(" "));h.$headers.removeClass(l.join(" ")).addClass(d).attr("aria-sort", "none");for(b=0;b"),c=g(a).width();g(a.tBodies[0]).find("tr:first").children("td:visible").each(function(){b.append(g("").css("width",parseInt(g(this).width()/c*1E3,10)/10+"%"))});g(a).prepend(b)}}function M(a,b,c){var h,e,f,d=a.config;a=b||d.sortList;d.sortList=[];g.each(a,function(a, b){h=[parseInt(b[0],10),parseInt(b[1],10)];if(f=d.$headers.filter('[data-column="'+h[0]+'"]:last')[0])d.sortList.push(h),e=g.inArray(h[1],f.order),c&&(f.count+=1),f.count=0<=e?e:h[1]%(d.sortReset?3:2)})}function N(a,b){return a&&a[b]?a[b].type||"":""}function O(a,b,c){var h,e,d,k=a.config,l=!c[k.sortMultiSortKey],m=k.$table;m.trigger("sortStart",a);b.count=c[k.sortResetKey]?2:(b.count+1)%(k.sortReset?3:2);k.sortRestart&&(e=b,k.$headers.each(function(){this===e||!l&&g(this).is("."+f.css.sortDesc+",."+ f.css.sortAsc)||(this.count=-1)}));e=b.column;if(l){k.sortList=[];if(null!==k.sortForce)for(h=k.sortForce,c=0;ch&&(k.sortList.push([e,h]),1h&&(k.sortList.push([e,h]),1 thead th, > thead td",selectorSort:"th, td",selectorRemove:".remove-me",debug:!1,headerList:[],empties:{},strings:{},parsers:[]};f.css={table:"tablesorter",cssHasChild:"tablesorter-hasChildRow",childRow:"tablesorter-childRow",header:"tablesorter-header",headerRow:"tablesorter-headerRow",headerIn:"tablesorter-header-inner",icon:"tablesorter-icon",info:"tablesorter-infoOnly",processing:"tablesorter-processing", sortAsc:"tablesorter-headerAsc",sortDesc:"tablesorter-headerDesc",sortNone:"tablesorter-headerUnSorted"};f.language={sortAsc:"Ascending sort applied, ",sortDesc:"Descending sort applied, ",sortNone:"No sort applied, ",nextAsc:"activate to apply an ascending sort",nextDesc:"activate to apply a descending sort",nextNone:"activate to remove the sort"};f.log=d;f.benchmark=u;f.construct=function(a){return this.each(function(){var b=g.extend(!0,{},f.defaults,a);!this.hasInitialized&&f.buildTable&&"TABLE"!== this.tagName?f.buildTable(this,b):f.setup(this,b)})};f.setup=function(a,b){if(!a||!a.tHead||0===a.tBodies.length||!0===a.hasInitialized)return b.debug?d("ERROR: stopping initialization! No table, thead, tbody or tablesorter has already been initialized"):"";var c="",h=g(a),e=g.metadata;a.hasInitialized=!1;a.isProcessing=!0;a.config=b;g.data(a,"tablesorter",b);b.debug&&g.data(a,"startoveralltimer",new Date);b.supportsDataObject=function(a){a[0]=parseInt(a[0],10);return 1'),c=g.fn.detach?b.detach():b.remove();c=g(a).find("span.tablesorter-savemyplace");b.insertAfter(c);c.remove();a.isProcessing=!1};f.clearTableBody=function(a){g(a)[0].config.$tbodies.empty()};f.bindEvents= function(a,b,c){a=g(a)[0];var d,e=a.config;!0!==c&&(e.$extraHeaders=e.$extraHeaders?e.$extraHeaders.add(b):b);b.find(e.selectorSort).add(b.filter(e.selectorSort)).unbind(["mousedown","mouseup","sort","keyup",""].join(e.namespace+" ")).bind(["mousedown","mouseup","sort","keyup",""].join(e.namespace+" "),function(c,f){var l;l=c.type;if(!(1!==(c.which||c.button)&&!/sort|keyup/.test(l)||"keyup"===l&&13!==c.which||"mouseup"===l&&!0!==f&&250<(new Date).getTime()-d)){if("mousedown"===l)return d=(new Date).getTime(), "INPUT"===c.target.tagName?"":!e.cancelSelection;e.delayInit&&n(e.cache)&&x(a);l=/TH|TD/.test(this.tagName)?this:g(this).parents("th, td")[0];l=e.$headers[b.index(l)];l.sortDisabled||O(a,l,c)}});e.cancelSelection&&b.attr("unselectable","on").bind("selectstart",!1).css({"user-select":"none",MozUserSelect:"none"})};f.restoreHeaders=function(a){var b=g(a)[0].config;b.$table.find(b.selectorHeaders).each(function(a){g(this).find("."+f.css.headerIn).length&&g(this).html(b.headerContent[a])})};f.destroy= function(a,b,c){a=g(a)[0];if(a.hasInitialized){f.refreshWidgets(a,!0,!0);var d=g(a),e=a.config,t=d.find("thead:first"),k=t.find("tr."+f.css.headerRow).removeClass(f.css.headerRow+" "+e.cssHeaderRow),l=d.find("tfoot:first > tr").children("th, td");!1===b&&0<=g.inArray("uitheme",e.widgets)&&(d.trigger("applyWidgetId",["uitheme"]),d.trigger("applyWidgetId",["zebra"]));t.find("tr").not(k).remove();d.removeData("tablesorter").unbind("sortReset update updateAll updateRows updateCell addRows updateComplete sorton appendCache updateCache applyWidgetId applyWidgets refreshWidgets destroy mouseup mouseleave keypress sortBegin sortEnd ".split(" ").join(e.namespace+ " "));e.$headers.add(l).removeClass([f.css.header,e.cssHeader,e.cssAsc,e.cssDesc,f.css.sortAsc,f.css.sortDesc,f.css.sortNone].join(" ")).removeAttr("data-column").removeAttr("aria-label").attr("aria-disabled","true");k.find(e.selectorSort).unbind(["mousedown","mouseup","keypress",""].join(e.namespace+" "));f.restoreHeaders(a);d.toggleClass(f.css.table+" "+e.tableClass+" tablesorter-"+e.theme,!1===b);a.hasInitialized=!1;delete a.config.cache;"function"===typeof c&&c(a)}};f.regex={chunk:/(^([+\-]?(?:0|[1-9]\d*)(?:\.\d*)?(?:[eE][+\-]?\d+)?)?$|^0x[0-9a-f]+$|\d+)/gi, chunks:/(^\\0|\\0$)/,hex:/^0x[0-9a-f]+$/i};f.sortNatural=function(a,b){if(a===b)return 0;var c,d,e,g,k,l;d=f.regex;if(d.hex.test(b)){c=parseInt(a.match(d.hex),16);e=parseInt(b.match(d.hex),16);if(ce)return 1}c=a.replace(d.chunk,"\\0$1\\0").replace(d.chunks,"").split("\\0");d=b.replace(d.chunk,"\\0$1\\0").replace(d.chunks,"").split("\\0");l=Math.max(c.length,d.length);for(k=0;kg)return 1}return 0};f.sortNaturalAsc=function(a,b,c,d,e){if(a===b)return 0;c=e.string[e.empties[c]||e.emptyTo];return""===a&&0!==c?"boolean"===typeof c?c?-1:1:-c||-1:""===b&&0!==c?"boolean"===typeof c?c?1:-1:c||1:f.sortNatural(a,b)};f.sortNaturalDesc=function(a,b,c,d,e){if(a===b)return 0;c=e.string[e.empties[c]||e.emptyTo];return""===a&&0!==c?"boolean"===typeof c?c?-1:1:c||1:""===b&&0!==c?"boolean"===typeof c?c? 1:-1:-c||-1:f.sortNatural(b,a)};f.sortText=function(a,b){return a>b?1:ag.inArray(k[h].id,n))&&(e.debug&&d('Refeshing widgets: Removing "'+k[h].id+'"'),k[h].hasOwnProperty("remove")&&e.widgetInit[k[h].id]&&(k[h].remove(a,e,e.widgetOptions),e.widgetInit[k[h].id]=!1));!0!==c&&f.applyWidget(a,b)};f.getData=function(a,b,c){var d="";a=g(a); var e,f;if(!a.length)return"";e=g.metadata?a.metadata():!1;f=" "+(a.attr("class")||"");"undefined"!==typeof a.data(c)||"undefined"!==typeof a.data(c.toLowerCase())?d+=a.data(c)||a.data(c.toLowerCase()):e&&"undefined"!==typeof e[c]?d+=e[c]:b&&"undefined"!==typeof b[c]?d+=b[c]:" "!==f&&f.match(" "+c+"-")&&(d=f.match(RegExp("\\s"+c+"-([\\w-]+)"))[1]||"");return g.trim(d)};f.formatFloat=function(a,b){if("string"!==typeof a||""===a)return a;var c;a=(b&&b.config?!1!==b.config.usNumberFormat:"undefined"!== typeof b?b:1)?a.replace(/,/g,""):a.replace(/[\s|\.]/g,"").replace(/,/g,".");/^\s*\([.\d]+\)/.test(a)&&(a=a.replace(/^\s*\(([.\d]+)\)/,"-$1"));c=parseFloat(a);return isNaN(c)?g.trim(a):c};f.isDigit=function(a){return isNaN(a)?/^[\-+(]?\d+[)]?$/.test(a.toString().replace(/[,.'"\s]/g,"")):!0}}});var p=g.tablesorter;g.fn.extend({tablesorter:p.construct});p.addParser({id:"text",is:function(){return!0},format:function(d,u){var n=u.config;d&&(d=g.trim(n.ignoreCase?d.toLocaleLowerCase():d),d=n.sortLocaleCompare? p.replaceAccents(d):d);return d},type:"text"});p.addParser({id:"digit",is:function(d){return p.isDigit(d)},format:function(d,u){var n=p.formatFloat((d||"").replace(/[^\w,. \-()]/g,""),u);return d&&"number"===typeof n?n:d?g.trim(d&&u.config.ignoreCase?d.toLocaleLowerCase():d):d},type:"numeric"});p.addParser({id:"currency",is:function(d){return/^\(?\d+[\u00a3$\u20ac\u00a4\u00a5\u00a2?.]|[\u00a3$\u20ac\u00a4\u00a5\u00a2?.]\d+\)?$/.test((d||"").replace(/[+\-,. ]/g,""))},format:function(d,u){var n=p.formatFloat((d|| "").replace(/[^\w,. \-()]/g,""),u);return d&&"number"===typeof n?n:d?g.trim(d&&u.config.ignoreCase?d.toLocaleLowerCase():d):d},type:"numeric"});p.addParser({id:"ipAddress",is:function(d){return/^\d{1,3}[\.]\d{1,3}[\.]\d{1,3}[\.]\d{1,3}$/.test(d)},format:function(d,g){var n,v=d?d.split("."):"",s="",x=v.length;for(n=0;nd.length},format:function(d,g){return d?p.formatFloat(d.replace(/%/g,""),g):d},type:"numeric"});p.addParser({id:"usLongDate",is:function(d){return/^[A-Z]{3,10}\.?\s+\d{1,2},?\s+(\d{4})(\s+\d{1,2}:\d{2}(:\d{2})?(\s+[AP]M)?)?$/i.test(d)|| /^\d{1,2}\s+[A-Z]{3,10}\s+\d{4}/i.test(d)},format:function(d,g){return d?p.formatFloat((new Date(d.replace(/(\S)([AP]M)$/i,"$1 $2"))).getTime()||d,g):d},type:"numeric"});p.addParser({id:"shortDate",is:function(d){return/(^\d{1,2}[\/\s]\d{1,2}[\/\s]\d{4})|(^\d{4}[\/\s]\d{1,2}[\/\s]\d{1,2})/.test((d||"").replace(/\s+/g," ").replace(/[\-.,]/g,"/"))},format:function(d,g,n,v){if(d){n=g.config;var s=n.$headers.filter("[data-column="+v+"]:last");v=s.length&&s[0].dateFormat||p.getData(s,n.headers[v],"dateFormat")|| n.dateFormat;d=d.replace(/\s+/g," ").replace(/[\-.,]/g,"/");"mmddyyyy"===v?d=d.replace(/(\d{1,2})[\/\s](\d{1,2})[\/\s](\d{4})/,"$3/$1/$2"):"ddmmyyyy"===v?d=d.replace(/(\d{1,2})[\/\s](\d{1,2})[\/\s](\d{4})/,"$3/$2/$1"):"yyyymmdd"===v&&(d=d.replace(/(\d{4})[\/\s](\d{1,2})[\/\s](\d{1,2})/,"$1/$2/$3"))}return d?p.formatFloat((new Date(d)).getTime()||d,g):d},type:"numeric"});p.addParser({id:"time",is:function(d){return/^(([0-2]?\d:[0-5]\d)|([0-1]?\d:[0-5]\d\s?([AP]M)))$/i.test(d)},format:function(d,g){return d? p.formatFloat((new Date("2000/01/01 "+d.replace(/(\S)([AP]M)$/i,"$1 $2"))).getTime()||d,g):d},type:"numeric"});p.addParser({id:"metadata",is:function(){return!1},format:function(d,p,n){d=p.config;d=d.parserMetadataName?d.parserMetadataName:"sortValue";return g(n).metadata()[d]},type:"numeric"});p.addWidget({id:"zebra",priority:90,format:function(d,u,n){var v,s,x,y,C,D,E=RegExp(u.cssChildRow,"i"),B=u.$tbodies;u.debug&&(C=new Date);for(d=0;d