From 13f1390a55a79b7e3ef6d0558ea070c88bd06cb4 Mon Sep 17 00:00:00 2001 From: Thierry Parmentelat Date: Sat, 27 Dec 2008 21:48:32 +0000 Subject: [PATCH] moving the onelab www to a fresh location --- Makefile | 36 +- modules/planetlab.module | 13 +- planetlab/{includes/js => bsn}/bsn.Ajax.js | 0 .../{includes/js => bsn}/bsn.AutoSuggest.js | 0 planetlab/{includes/js => bsn}/bsn.DOM.js | 0 planetlab/css/demo.css | 258 ++++++ planetlab/{includes => css}/plc_style.css | 0 planetlab/css/tablesort.css | 258 ++++++ planetlab/events/index.php | 5 - planetlab/{includes => icons}/comon.png | Bin planetlab/{includes => icons}/delete.png | Bin planetlab/{includes => icons}/event.png | Bin planetlab/includes/plc_drupal.php | 2 +- planetlab/includes/plc_footer.php | 2 +- planetlab/includes/plc_functions.php | 8 +- planetlab/includes/plc_header.php | 4 +- planetlab/includes/plc_login.php | 2 +- planetlab/includes/plc_script.js | 42 +- planetlab/includes/plc_session.php | 2 +- planetlab/includes/plc_sorts.php | 6 + planetlab/nodes/add_node.php | 2 +- planetlab/nodes/comon.php | 6 +- planetlab/nodes/index.php | 22 +- planetlab/nodes/interfaces.php | 76 +- planetlab/nodes/newindex.php | 117 +++ planetlab/nodes/node_actions.php | 10 +- planetlab/nodes/node_groups.php | 9 +- planetlab/nodes/setting_action.php | 23 +- planetlab/nodes/settings.php | 32 +- planetlab/nodes/sliver_action.php | 10 +- planetlab/nodes/slivers.php | 42 +- planetlab/persons/index.php | 6 +- planetlab/sites/index.php | 6 +- planetlab/slices/attrib_action.php | 133 ---- planetlab/slices/attributes.php | 177 ----- planetlab/slices/index.php | 103 ++- planetlab/slices/slice_nodes.php | 45 +- planetlab/slices/tag_action.php | 136 ++++ planetlab/slices/tags.php | 198 +++++ planetlab/tablesort/customsort.js | 356 +++++++++ planetlab/tablesort/paginate.js | 479 +++++++++++ planetlab/tablesort/tablesort.js | 748 ++++++++++++++++++ 42 files changed, 2825 insertions(+), 549 deletions(-) rename planetlab/{includes/js => bsn}/bsn.Ajax.js (100%) rename planetlab/{includes/js => bsn}/bsn.AutoSuggest.js (100%) rename planetlab/{includes/js => bsn}/bsn.DOM.js (100%) create mode 100644 planetlab/css/demo.css rename planetlab/{includes => css}/plc_style.css (100%) create mode 100644 planetlab/css/tablesort.css rename planetlab/{includes => icons}/comon.png (100%) rename planetlab/{includes => icons}/delete.png (100%) rename planetlab/{includes => icons}/event.png (100%) create mode 100644 planetlab/nodes/newindex.php delete mode 100644 planetlab/slices/attrib_action.php delete mode 100644 planetlab/slices/attributes.php create mode 100644 planetlab/slices/tag_action.php create mode 100644 planetlab/slices/tags.php create mode 100644 planetlab/tablesort/customsort.js create mode 100644 planetlab/tablesort/paginate.js create mode 100644 planetlab/tablesort/tablesort.js diff --git a/Makefile b/Makefile index 3c771a1..d1c2f44 100644 --- a/Makefile +++ b/Makefile @@ -4,9 +4,22 @@ tags: .PHONY: tags -########## make sync PLCHOST=hostname +########## sync +# 2 forms are supported +# (*) if your plc root context has direct ssh access: +# make sync PLC=private.one-lab.org +# (*) otherwise, entering through the root context +# make sync PLCHOST=testbox1.inria.fr GUEST=vplc03.inria.fr + +ifdef GUEST ifdef PLCHOST -PLCSSH:=root@$(PLCHOST) +SSHURL:=root@$(PLCHOST):/vservers/$(GUEST) +SSHCOMMAND:=ssh root@$(PLCHOST) vserver $(GUEST) +endif +endif +ifdef PLC +SSHURL:=root@$(PLC):/ +SSHCOMMAND:=ssh root@$(PLC) endif LOCAL_RSYNC_EXCLUDES := --exclude '*.pyc' @@ -15,10 +28,21 @@ RSYNC_COND_DRY_RUN := $(if $(findstring n,$(MAKEFLAGS)),--dry-run,) RSYNC := rsync -a -v $(RSYNC_COND_DRY_RUN) $(RSYNC_EXCLUDES) sync: -ifeq (,$(PLCSSH)) - echo "sync: You must define target host as PLCHOST on the command line" - echo " e.g. make sync PLCHOST=private.one-lab.org" ; exit 1 +ifeq (,$(SSHURL)) + @echo "sync: You must define, either PLC, or PLCHOST & GUEST, on the command line" + @echo " e.g. make sync PLC=private.one-lab.org" + @echo " or make sync PLCHOST=testbox1.inria.fr GUEST=vplc03.inria.fr" + @exit 1 else - +$(RSYNC) planetlab modules $(PLCSSH):/plc/root/var/www/html/ + +$(RSYNC) planetlab modules $(SSHURL)/var/www/html/ endif +#################### convenience, for debugging only +# make +foo : prints the value of $(foo) +# make ++foo : idem but verbose, i.e. foo=$(foo) +++%: varname=$(subst +,,$@) +++%: + @echo "$(varname)=$($(varname))" ++%: varname=$(subst +,,$@) ++%: + @echo "$($(varname))" diff --git a/modules/planetlab.module b/modules/planetlab.module index 73523c3..73cd389 100644 --- a/modules/planetlab.module +++ b/modules/planetlab.module @@ -141,13 +141,24 @@ function planetlab_block($op = 'list', $delta = 0, $edit = array()) $slice_item .= ''; $items [] = $slice_item; + if( $is_admin || $is_pi ) { + $tag_item = ''; + $tag_item .= 'Tags'; + $tag_item .= ''; + $items [] = $tag_item; + } + + if ( $is_admin ) $items[] = l(t('Peers'),'db/peers/'); diff --git a/planetlab/includes/js/bsn.Ajax.js b/planetlab/bsn/bsn.Ajax.js similarity index 100% rename from planetlab/includes/js/bsn.Ajax.js rename to planetlab/bsn/bsn.Ajax.js diff --git a/planetlab/includes/js/bsn.AutoSuggest.js b/planetlab/bsn/bsn.AutoSuggest.js similarity index 100% rename from planetlab/includes/js/bsn.AutoSuggest.js rename to planetlab/bsn/bsn.AutoSuggest.js diff --git a/planetlab/includes/js/bsn.DOM.js b/planetlab/bsn/bsn.DOM.js similarity index 100% rename from planetlab/includes/js/bsn.DOM.js rename to planetlab/bsn/bsn.DOM.js diff --git a/planetlab/css/demo.css b/planetlab/css/demo.css new file mode 100644 index 0000000..0d55fcd --- /dev/null +++ b/planetlab/css/demo.css @@ -0,0 +1,258 @@ +/* + Add the following to your CSS file should you wish the cursor to + "wait" while the script is processing the sort + +body.sort-active * + { + cursor:wait; + } +*/ + +body + { + padding:0; + border:0; + margin:0; + text-align:center; + font-size:12px; + font-family: verdana,arial,sans-serif; + color:#545454; + min-width: 800px; + } +h2 span + { + font-variant:small-caps; + } +p a + { + font-weight:normal; + outline:none; + } +p a:link, +p a:visited + { + color:#333; + text-decoration:underline; + } +p a:hover + { + color:#fff; + text-decoration:none; + background:#000; + } +p a:active + { + color:#000; + text-decoration:underline; + } +code + { + font-family:'andale mono','lucida console','courier new',monospace; + font-size:1em; + } +p + { + line-height:1.6em; + margin:0 0 1em 0; + } +h1 + { + font-weight:lighter; + font-family:georgia, times new roman, times, georgia, palatino, serif; + text-align:center; + margin-top:0.6em; + color:#000; + font-size:2em; + } +h2 + { + font-weight:lighter; + font-family:verdana,arial,sans-serif; + text-align:center; + margin-top:1em; + color:#333; + text-transform:uppercase; + letter-spacing:1px; + font-size:1.2em; + } +h2 span + { + font-variant:small-caps; + text-transform:none; + } +table + { + width: auto; + padding: 0; + margin: 0 auto 1.5em auto; + border-left: 1px solid #C1DAD7; + border-collapse:collapse; + } +.cs1 + { + width:30em; + } +.cs2 + { + width:20em; + } +.cs1 td, +.cs2 td, +#scientificNotation + { + text-align:right; + } +caption + { + padding: 0 0 5px 0; + margin:0 auto; + width:auto; + font: italic 11px "Trebuchet MS", Verdana, Arial, Helvetica, sans-serif; + text-align: right; + } +th + { + font: bold 10px/22px "Trebuchet MS", Verdana, Arial, Helvetica, sans-serif; + color: #4f6b72; + border-right: 1px solid #C1DAD7; + border-bottom: 1px solid #C1DAD7; + border-top: 1px solid #C1DAD7; + letter-spacing: 1px; + text-transform: uppercase; + text-align: left; + padding: 8px 12px 4px 12px; + background: #CAE8EA url(../media/bg_header.jpg) no-repeat; + vertical-align:middle; + } +td.total + { + border-top: 0; + border-left: 0; + border-right: 1px solid #C1DAD7; + background: none; + text-align:right; + font-weight:bold; + text-transform:uppercase; + letter-spacing:1px; + } +th.sortable, +th.sortable-text, +th.sortable-date, +th.sortable-keep, +th.sortable-date-dmy, +th.sortable-numeric, +th.sortable-currency, +th.sortable-sortByTwelveHourTimestamp, +th.sortable-sortIPAddress, +th.sortable-sortEnglishLonghandDateFormat, +th.sortable-sortScientificNotation, +th.sortable-sortImage, +th.sortable-sortFileSize, +th.sortable-sortAlphaNumeric, +th.sortable-sortEnglishDateTime + + { + cursor:pointer; + background: #CAE8EA url(../media/bg_header_sortable.jpg) no-repeat; + padding: 8px 12px 4px 16px; + } +th.forwardSort + { + background:#CAE8EA url(../media/bg_header_down.jpg) no-repeat 0 0; + } +th.reverseSort + { + background:#CAE8EA url(../media/bg_header_up.jpg) no-repeat 0 0; + } +table thead th.forwardSort a, +table thead th.reverseSort a + { + color:#000; + text-decoration:none; + } +/* +These styles should be added when very long tables are expected +th.sort-active + { + background:#CAE8EA url(../media/bg_header_sorting.jpg) no-repeat 0 0; + cursor:wait; + } +th.sort-active a + { + color:#a80000 !important; + cursor:wait; + } +*/ +th a + { + text-decoration:none; + color: #4f6b72; + background:transparent; + } +td a + { + text-decoration:none; + color:#239; + background:transparent; + } +td img + { + margin:0 auto; + border:3px solid #ddd; + } +td a:hover + { + color:#a84444; + border-bottom:1px dotted #a80000; + background:transparent; + } +td + { + font: normal 11px "Trebuchet MS", Verdana, Arial, Helvetica, sans-serif; + border-right: 1px solid #C1DAD7; + border-bottom: 1px solid #C1DAD7; + padding: 6px 12px 6px 12px; + color: #4f6b72; + } +td.lft + { + text-align:left; + } +tr.alt + { + background: #F5FAFA; + color: #797268; + } + +/* Poor old Internet Explorer 6 has a bug that means we can't use background images for the table rows + as it trys to download the image each and every time that it is used (which means a 1000 row table + will produce 1000 http requests for the image in question) */ +tr[class="alt"] td + { + background: #F5FAFA url(../media/td_alt.jpg) no-repeat; + } +td[class~="alt"] + { + background: #edf3f3 url(../media/col_alt.jpg) no-repeat !important; + } +/* Poor old Internet Explorer won't see the next two rules either as it doesn't get :first-child */ +tbody tr.alt td:first-child + { + background: #F5FAFA url(../media/bullet2.gif) no-repeat; + font-weight:bold; + } +tbody tr td:first-child + { + background: #fff url(../media/bullet1.gif) no-repeat; + font-weight:bold; + } +/* Image free rules for Internet Explorer < 7 */ +* html tr.alt td + { + background-color:#F5FAFA; + } +* html tr td.alt, +* html tr.alt td.alt + { + background-color:#edf3f3; + } diff --git a/planetlab/includes/plc_style.css b/planetlab/css/plc_style.css similarity index 100% rename from planetlab/includes/plc_style.css rename to planetlab/css/plc_style.css diff --git a/planetlab/css/tablesort.css b/planetlab/css/tablesort.css new file mode 100644 index 0000000..0d55fcd --- /dev/null +++ b/planetlab/css/tablesort.css @@ -0,0 +1,258 @@ +/* + Add the following to your CSS file should you wish the cursor to + "wait" while the script is processing the sort + +body.sort-active * + { + cursor:wait; + } +*/ + +body + { + padding:0; + border:0; + margin:0; + text-align:center; + font-size:12px; + font-family: verdana,arial,sans-serif; + color:#545454; + min-width: 800px; + } +h2 span + { + font-variant:small-caps; + } +p a + { + font-weight:normal; + outline:none; + } +p a:link, +p a:visited + { + color:#333; + text-decoration:underline; + } +p a:hover + { + color:#fff; + text-decoration:none; + background:#000; + } +p a:active + { + color:#000; + text-decoration:underline; + } +code + { + font-family:'andale mono','lucida console','courier new',monospace; + font-size:1em; + } +p + { + line-height:1.6em; + margin:0 0 1em 0; + } +h1 + { + font-weight:lighter; + font-family:georgia, times new roman, times, georgia, palatino, serif; + text-align:center; + margin-top:0.6em; + color:#000; + font-size:2em; + } +h2 + { + font-weight:lighter; + font-family:verdana,arial,sans-serif; + text-align:center; + margin-top:1em; + color:#333; + text-transform:uppercase; + letter-spacing:1px; + font-size:1.2em; + } +h2 span + { + font-variant:small-caps; + text-transform:none; + } +table + { + width: auto; + padding: 0; + margin: 0 auto 1.5em auto; + border-left: 1px solid #C1DAD7; + border-collapse:collapse; + } +.cs1 + { + width:30em; + } +.cs2 + { + width:20em; + } +.cs1 td, +.cs2 td, +#scientificNotation + { + text-align:right; + } +caption + { + padding: 0 0 5px 0; + margin:0 auto; + width:auto; + font: italic 11px "Trebuchet MS", Verdana, Arial, Helvetica, sans-serif; + text-align: right; + } +th + { + font: bold 10px/22px "Trebuchet MS", Verdana, Arial, Helvetica, sans-serif; + color: #4f6b72; + border-right: 1px solid #C1DAD7; + border-bottom: 1px solid #C1DAD7; + border-top: 1px solid #C1DAD7; + letter-spacing: 1px; + text-transform: uppercase; + text-align: left; + padding: 8px 12px 4px 12px; + background: #CAE8EA url(../media/bg_header.jpg) no-repeat; + vertical-align:middle; + } +td.total + { + border-top: 0; + border-left: 0; + border-right: 1px solid #C1DAD7; + background: none; + text-align:right; + font-weight:bold; + text-transform:uppercase; + letter-spacing:1px; + } +th.sortable, +th.sortable-text, +th.sortable-date, +th.sortable-keep, +th.sortable-date-dmy, +th.sortable-numeric, +th.sortable-currency, +th.sortable-sortByTwelveHourTimestamp, +th.sortable-sortIPAddress, +th.sortable-sortEnglishLonghandDateFormat, +th.sortable-sortScientificNotation, +th.sortable-sortImage, +th.sortable-sortFileSize, +th.sortable-sortAlphaNumeric, +th.sortable-sortEnglishDateTime + + { + cursor:pointer; + background: #CAE8EA url(../media/bg_header_sortable.jpg) no-repeat; + padding: 8px 12px 4px 16px; + } +th.forwardSort + { + background:#CAE8EA url(../media/bg_header_down.jpg) no-repeat 0 0; + } +th.reverseSort + { + background:#CAE8EA url(../media/bg_header_up.jpg) no-repeat 0 0; + } +table thead th.forwardSort a, +table thead th.reverseSort a + { + color:#000; + text-decoration:none; + } +/* +These styles should be added when very long tables are expected +th.sort-active + { + background:#CAE8EA url(../media/bg_header_sorting.jpg) no-repeat 0 0; + cursor:wait; + } +th.sort-active a + { + color:#a80000 !important; + cursor:wait; + } +*/ +th a + { + text-decoration:none; + color: #4f6b72; + background:transparent; + } +td a + { + text-decoration:none; + color:#239; + background:transparent; + } +td img + { + margin:0 auto; + border:3px solid #ddd; + } +td a:hover + { + color:#a84444; + border-bottom:1px dotted #a80000; + background:transparent; + } +td + { + font: normal 11px "Trebuchet MS", Verdana, Arial, Helvetica, sans-serif; + border-right: 1px solid #C1DAD7; + border-bottom: 1px solid #C1DAD7; + padding: 6px 12px 6px 12px; + color: #4f6b72; + } +td.lft + { + text-align:left; + } +tr.alt + { + background: #F5FAFA; + color: #797268; + } + +/* Poor old Internet Explorer 6 has a bug that means we can't use background images for the table rows + as it trys to download the image each and every time that it is used (which means a 1000 row table + will produce 1000 http requests for the image in question) */ +tr[class="alt"] td + { + background: #F5FAFA url(../media/td_alt.jpg) no-repeat; + } +td[class~="alt"] + { + background: #edf3f3 url(../media/col_alt.jpg) no-repeat !important; + } +/* Poor old Internet Explorer won't see the next two rules either as it doesn't get :first-child */ +tbody tr.alt td:first-child + { + background: #F5FAFA url(../media/bullet2.gif) no-repeat; + font-weight:bold; + } +tbody tr td:first-child + { + background: #fff url(../media/bullet1.gif) no-repeat; + font-weight:bold; + } +/* Image free rules for Internet Explorer < 7 */ +* html tr.alt td + { + background-color:#F5FAFA; + } +* html tr td.alt, +* html tr.alt td.alt + { + background-color:#edf3f3; + } diff --git a/planetlab/events/index.php b/planetlab/events/index.php index 398530f..0e2f245 100644 --- a/planetlab/events/index.php +++ b/planetlab/events/index.php @@ -289,11 +289,6 @@ if ( !in_array ('10', $_roles)) { } else { - // // xxx this of any use at all ? - // drupal_set_html_head(' - // - // '); - // handle dates list($from_date,$from_time,$until_date,$until_time) = parse_dates (); if ( ($from_time != 0) && ($until_time != 0) && ($from_time > $until_time) ) { diff --git a/planetlab/includes/comon.png b/planetlab/icons/comon.png similarity index 100% rename from planetlab/includes/comon.png rename to planetlab/icons/comon.png diff --git a/planetlab/includes/delete.png b/planetlab/icons/delete.png similarity index 100% rename from planetlab/includes/delete.png rename to planetlab/icons/delete.png diff --git a/planetlab/includes/event.png b/planetlab/icons/event.png similarity index 100% rename from planetlab/includes/event.png rename to planetlab/icons/event.png diff --git a/planetlab/includes/plc_drupal.php b/planetlab/includes/plc_drupal.php index 8034d5c..103762a 100644 --- a/planetlab/includes/plc_drupal.php +++ b/planetlab/includes/plc_drupal.php @@ -5,7 +5,7 @@ // Mark Huang // Copyright (C) 2006 The Trustees of Princeton University // -// $Id: plc_drupal.php 144 2007-03-28 07:52:20Z thierry $ $ +// $Id$ $ // if (!function_exists('drupal_set_title')) { diff --git a/planetlab/includes/plc_footer.php b/planetlab/includes/plc_footer.php index 252a218..ad509af 100644 --- a/planetlab/includes/plc_footer.php +++ b/planetlab/includes/plc_footer.php @@ -6,7 +6,7 @@ // Mark Huang // Copyright (C) 2006 The Trustees of Princeton University // -// $Id: plc_footer.php 144 2007-03-28 07:52:20Z thierry $ $ +// $Id$ $ // require_once 'plc_drupal.php'; diff --git a/planetlab/includes/plc_functions.php b/planetlab/includes/plc_functions.php index 3809c76..9e7a81d 100644 --- a/planetlab/includes/plc_functions.php +++ b/planetlab/includes/plc_functions.php @@ -1,5 +1,7 @@ Delete this entry'; + return 'Delete this entry'; } function plc_js_confirm($message) { @@ -352,7 +354,7 @@ function plc_delete_link_button($url,$delete_message,$width=15) { } function plc_event_button($type,$param,$id) { - return ' '; + return ' '; } function plc_comon_button ($field, $value,$target="") { @@ -361,7 +363,7 @@ function plc_comon_button ($field, $value,$target="") { $result.='target="' . $target . '" '; } $result.='href="/db/nodes/comon.php?' . $field . "=" . $value . '">'; - $result.=' '; + $result.=' '; return $result; } diff --git a/planetlab/includes/plc_header.php b/planetlab/includes/plc_header.php index 34b552c..274ed54 100644 --- a/planetlab/includes/plc_header.php +++ b/planetlab/includes/plc_header.php @@ -6,11 +6,11 @@ // Mark Huang // Copyright (C) 2006 The Trustees of Princeton University // -// $Id: plc_header.php 144 2007-03-28 07:52:20Z thierry $ $ +// $Id$ $ // require_once 'plc_drupal.php'; -drupal_set_html_head(''); +drupal_set_html_head(''); if (!function_exists('drupal_page_header')) { $title = drupal_get_title(); diff --git a/planetlab/includes/plc_login.php b/planetlab/includes/plc_login.php index b8d5b63..db9440a 100644 --- a/planetlab/includes/plc_login.php +++ b/planetlab/includes/plc_login.php @@ -7,7 +7,7 @@ // Mark Huang // Copyright (C) 2006 The Trustees of Princeton University // -// $Id: plc_login.php 144 2007-03-28 07:52:20Z thierry $ $ +// $Id$ $ // require_once 'plc_session.php'; diff --git a/planetlab/includes/plc_script.js b/planetlab/includes/plc_script.js index 2c1e05d..d96af22 100644 --- a/planetlab/includes/plc_script.js +++ b/planetlab/includes/plc_script.js @@ -1,35 +1,37 @@ function addLoadEvent(func) { - if (!document.getElementById | !document.getElementsByTagName) return - var oldonload=window.onload - if (typeof window.onload != 'function') { window.onload=func } - else { - window.onload=function() { oldonload(); func() } - } + if (!document.getElementById | !document.getElementsByTagName) return; + var oldonload=window.onload + if (typeof window.onload != 'function') { + window.onload=func + } else { + window.onload=function() { oldonload(); func() } + } } // ----------------------------------------------------------------------------- // -function show(id){ - if (!document.getElementsByTagName) return - if (document.getElementById(id).style.display=='block'){ - document.getElementById(id).style.display='none' - } - else{ - document.getElementById(id).style.display='block' - } - // focus is moved by the href of the link to the start of the help +function show (id) { + if (!document.getElementsByTagName) return; + if (document.getElementById(id).style.display=='block') { + document.getElementById(id).style.display='none'; + } else{ + document.getElementById(id).style.display='block'; + } + // focus is moved by the href of the link to the start of the help } - -function hide(id){ - if (document.getElementById) {document.getElementById(id).style.display='none'} +function hide(id) { + if (document.getElementById) { + document.getElementById(id).style.display='none'; + } } function copyValue (id1,id2) { - if (document.getElementById) {document.getElementById(id2).value=document.getElementById(id1).value} + if (document.getElementById) { + document.getElementById(id2).value=document.getElementById(id1).value; + } } - // ----------------------------------------------------------------------------- // diff --git a/planetlab/includes/plc_session.php b/planetlab/includes/plc_session.php index f092f0f..afd008b 100644 --- a/planetlab/includes/plc_session.php +++ b/planetlab/includes/plc_session.php @@ -15,7 +15,7 @@ // Mark Huang // Copyright (C) 2006 The Trustees of Princeton University // -// $Id: plc_session.php 804 2007-08-31 13:58:58Z thierry $ $ +// $Id$ $ // // Usually in /etc/planetlab/php diff --git a/planetlab/includes/plc_sorts.php b/planetlab/includes/plc_sorts.php index c29bc5f..4b5b1d4 100644 --- a/planetlab/includes/plc_sorts.php +++ b/planetlab/includes/plc_sorts.php @@ -1,5 +1,7 @@ $hostname, "model"=>$model ); $site_id= $_person['site_ids'][0]; diff --git a/planetlab/nodes/comon.php b/planetlab/nodes/comon.php index 22ca872..18b2623 100644 --- a/planetlab/nodes/comon.php +++ b/planetlab/nodes/comon.php @@ -51,17 +51,17 @@ if ($_GET['node_id']) { $nodes=$api->GetNodes(array("node_id"=>array($node_id)),$fields); } else if ($_GET['site_id']) { $site_id=intval($_GET['site_id']); - $nodes=$api->GetNodes(array("site_id"=>array($site_id)),$fields); + $nodes=$api->GetNodes(array("node_type"=>"regular","site_id"=>array($site_id)),$fields); } else if ($_GET['slice_id']) { $slice_id=intval($_GET['slice_id']); $return=$api->GetSlices(array("slice_id"=>array($slice_id)),array("node_ids")); $node_ids=$return[0]['node_ids']; - $nodes=$api->GetNodes(array("node_id"=>$node_ids),$fields); + $nodes=$api->GetNodes(array("node_type"=>"regular","node_id"=>$node_ids),$fields); } else if (isset($_GET['peer_id'])) { $peer_id=intval($_GET['peer_id']); if ( ($peer_id == 0) || ($peer_id == "") ) $peer_id=NULL; - $nodes=$api->GetNodes(array("peer_id"=>$peer_id),$fields); + $nodes=$api->GetNodes(array("node_type"=>"regular","peer_id"=>$peer_id),$fields); } else { echo "
Unexpected args in comon.php
\n"; exit(); diff --git a/planetlab/nodes/index.php b/planetlab/nodes/index.php index 355ade4..395ddce 100644 --- a/planetlab/nodes/index.php +++ b/planetlab/nodes/index.php @@ -26,7 +26,7 @@ $_roles= $_person['role_ids']; // The set of columns to fetch // and the filter applied for fetching sites $columns = array( "node_id", "hostname", "boot_state", "peer_id" ) ; -$filter = array(); +$filter = array("node_type"=>"regular"); if ( in_array( '10', $_roles ) || in_array('20', $_roles) || in_array('40',$_roles)) { // admins, PIs and techs can see interface details $columns [] = "interface_ids"; @@ -162,9 +162,9 @@ elseif( !$_GET['id'] ) { $nodes = array_map(layout_node,$nodes); sort_nodes( $nodes ); - drupal_set_html_head(' - - '); + drupal_set_html_head(' + + '); echo "
\n
\n"; @@ -246,7 +246,7 @@ if ( $_GET['id'] ) { if( !empty( $conf_file_ids ) ) $conf_files= $api->GetConfFiles( $conf_file_ids ); - // get node network info + // get interface info if( !empty( $interface_ids ) ) $interfaces= $api->GetInterfaces( $interface_ids ); @@ -380,10 +380,10 @@ if ( $_GET['id'] ) { echo "
\n"; - // display node networks + // display interfaces if( $interfaces ) { echo "

\n"; - echo "\n"; + echo "\n"; echo ""; // placeholder for the delete buttons if ( $is_admin || ($is_pi && $in_site)) { @@ -411,9 +411,9 @@ if ( $_GET['id'] ) { if ( $is_admin || ($is_pi && $in_site)) { echo ""; } @@ -429,10 +429,10 @@ if ( $_GET['id'] ) { echo "
Node NetworksInterfaces
"; if (!$nn_primary) { - echo plc_delete_link_button('interfaces.php?id=' . $nn_id . '&delete=1&submitted=1', '\\nNode Network ' . $nn_ip); + echo plc_delete_link_button('interfaces.php?id=' . $nn_id . '&delete=1&submitted=1', '\\nInterface ' . $nn_ip); } else { - echo ' P '; + echo ' P '; } echo "
\n"; } else { - echo "

No Node Network. Please add a node network to make this a usable PLC node

.\n"; + echo "

No interface. Please add an interface to make this a usable PLC node

.\n"; } - echo "
Add a node network.\n"; + echo "
Add an interface.\n"; echo "

\n"; } diff --git a/planetlab/nodes/interfaces.php b/planetlab/nodes/interfaces.php index 7bada08..ab5e60e 100644 --- a/planetlab/nodes/interfaces.php +++ b/planetlab/nodes/interfaces.php @@ -188,48 +188,44 @@ echo << EOF; -// displays related settings, if supported by the API -if (method_exists ($api,'GetInterfaceTags')) { - - $is_admin=in_array( 10, $_roles ); - $is_pi=in_array( 20, $_roles ); - print "
"; - - if (empty ($interface['interface_tag_ids'])) { - print "

This network interface has no additional setting

"; - if( $is_admin || $is_pi ) - echo "

Add a Network Setting

\n"; - } else { - $interface_tags = $api->GetInterfaceTags($interface['interface_tag_ids']); - sort_interface_tags ($interface_tags); - print ""; - print ""; - // the column for the delete button - if( $is_admin ) - print ""; - print ""; - foreach ($interface_tags as $setting) { - echo ""; - if ($is_admin) { - echo(""); +$is_admin=in_array( 10, $_roles ); +$is_pi=in_array( 20, $_roles ); +print "
"; + +if (empty ($interface['interface_tag_ids'])) { + print "

This network interface has no additional setting

"; + if( $is_admin || $is_pi ) + echo "

Add an Interface Setting

\n"; + } else { + $interface_tags = $api->GetInterfaceTags($interface['interface_tag_ids']); + sort_interface_tags ($interface_tags); + print "
Additional Settings
NameCategoryDescriptionValue
"); - echo plc_delete_link_button('setting_action.php?rem_id=' . $setting['interface_tag_id'], - '\\n [ ' . $setting['name'] . ' = ' . $setting['value']); - echo("
"; + print ""; + // the column for the delete button + if( $is_admin ) + print ""; + print ""; + foreach ($interface_tags as $setting) { + echo ""; + if ($is_admin) { + echo(""); } - if ($is_admin || $is_pi) - printf ("",$setting['interface_tag_id'],$setting['name']); - else - printf ("",$setting['name']); - printf ("", - $setting['category'], - $setting['description'], - $setting['value']); - } - if( $is_admin || $is_pi ) - echo "
Additional Settings
NameCategoryDescriptionValue
"); + echo plc_delete_link_button('setting_action.php?rem_id=' . $setting['interface_tag_id'], + '\\n [ ' . $setting['tagname'] . ' = ' . $setting['value']); + echo(" %s %s %s %s %s
Add a Network Setting\n"; - - print "
"; + if ($is_admin || $is_pi) + printf (" %s ",$setting['interface_tag_id'],$setting['tagname']); + else + printf (" %s ",$setting['tagname']); + printf (" %s %s %s ", + $setting['category'], + $setting['description'], + $setting['value']); } + if( $is_admin || $is_pi ) + echo "Add a Network Setting\n"; + + print ""; } echo <<person; +$_roles= $_person['role_ids']; + +$header_js=' + + + + + +'; +$header_css=' + + + +'; + +$header_unused=' +'; + +drupal_set_html_head($header_js); +drupal_set_html_head($header_css); + +$site_columns=array("site_id","login_base"); +$site_filter=array("login_base"=>"*"); +$sites=$api->GetSites($site_filter,$site_columns); + +$site_hash=array(); +foreach ($sites as $site) { + $site_hash[$site["site_id"]]=$site; +} + +$node_columns=array("hostname","site_id","node_id","boot_state"); +$node_filter=array("hostname"=>"*"); +$nodes=$api->GetNodes($node_filter,$node_columns); + +$interface_columns=array("ip","node_id"); +$interface_filter=array("is_primary"=>TRUE); +$interfaces=$api->GetInterfaces($interface_filter,$interface_columns); + +$interface_hash=array(); +foreach ($interfaces as $interface) { + $interface_hash[$interface['node_id']]=$interface; +} + +?> + + + + + + + + + + + + + + + + +',$hostname); + printf ('',$hostname); + printf ('',$node['boot_state']); + printf ('',$hostname); + printf ('',$login_base); + printf ('',topdomain($hostname)); + printf ('',$ip); + printf (''); + printf (''); + printf ( ''); +} + +?> + + + +
Select StateHostnameSiteRegionIPLoadAvg Load
%s %s %s %s %s 1.0 10.0
+ diff --git a/planetlab/nodes/node_actions.php b/planetlab/nodes/node_actions.php index 5d17aa0..20a88de 100644 --- a/planetlab/nodes/node_actions.php +++ b/planetlab/nodes/node_actions.php @@ -357,7 +357,7 @@ a new node key, and any existing configuration file will be unusable and go into debug mode.

In order to create a configuration file for this node using this page, -all the node network settings must be up to date. Below is summary of these +all the interface settings must be up to date. Below is summary of these values. Any missing values must be entered before this can be used. EOF; @@ -366,7 +366,7 @@ EOF; show_download_confirm_button($api, $node_id, $action, $can_gen_config, false); print ("

"); - print ("

Current node network settings

\n"); + print ("

Current interface settings

\n"); if( $has_primary ) { print( "\n" ); @@ -378,7 +378,7 @@ if( $has_primary ) { print( "\n" ); $nn_id = $interface_detail['interface_id']; - print( "" ); + print( "" ); print( "" ); print( "\n" ); @@ -409,14 +409,14 @@ if( $has_primary ) { $settings=$api->GetInterfaceTags(array("interface_id" => array($nn_id))); foreach ($settings as $setting) { $category=$setting['category']; - $name=$setting['name']; + $name=$setting['tagname']; $value=$setting['value']; print (" \n"); } print( "
" . $node_detail['hostname'] . "
Node Network Details
Interface Details
Method:" . $interface_detail['method'] . "
$category $name $value
\n" ); } else { - print( "

This node has no configured primary network.

\n" ); + print( "

This node has no configured primary interface.

\n" ); } show_download_confirm_button($api, $node_id, $action, $can_gen_config, true); diff --git a/planetlab/nodes/node_groups.php b/planetlab/nodes/node_groups.php index aad5f18..e82b2b6 100644 --- a/planetlab/nodes/node_groups.php +++ b/planetlab/nodes/node_groups.php @@ -68,7 +68,8 @@ if( !$_GET['id'] && !$_GET['nodegroup_id'] ) { elseif( $_GET['id'] ) { $nodegroup_id= $_GET['id']; - $nodegroup_info= $api->GetNodeGroups( array( intval( $nodegroup_id ) ), array( "name", "nodegroup_id", "node_ids" ) ); + $nodegroup_info= $api->GetNodeGroups( array( intval( $nodegroup_id ) ), + array( "name", "nodegroup_id", "node_ids" ) ); $node_info= $api->GetNodes( $nodegroup_info[0]['node_ids'], array( "node_id", "hostname" ) ); //display info @@ -183,7 +184,8 @@ elseif( $_GET['nodegroup_id'] ) $api->UpdateNodeGroup( intval( $node_group_id ), $fields ); // get node_group info - $group_info= $api->GetNodeGroups( array( intval( $node_group_id ) ), array( "node_ids", "name", "conf_file_ids", "description" ) ); + $group_info= $api->GetNodeGroups( array( intval( $node_group_id ) ), + array( "node_ids", "name", "conf_file_ids", "description" ) ); $node_ids = $group_info[0]['node_ids']; $name = $group_info[0]['name']; @@ -192,7 +194,8 @@ elseif( $_GET['nodegroup_id'] ) // get node info if( !empty( $node_ids ) ) - $node_info= $api->GetNodes( $node_ids, array( "hostname", "node_id" ) ); + $node_info= $api->GetNodes( $node_ids, + array( "hostname", "node_id" ) ); // get site names and ids $site_info= $api->GetSites( NULL, array( "site_id", "name" ) ); diff --git a/planetlab/nodes/setting_action.php b/planetlab/nodes/setting_action.php index 22b5a79..1d1974b 100644 --- a/planetlab/nodes/setting_action.php +++ b/planetlab/nodes/setting_action.php @@ -27,7 +27,7 @@ $_roles= $_person['role_ids']; //plc_debug('GET',$_GET); //plc_debug('POST',$_POST); -// attribute type updates +// tag type updates if( $_POST['edit_type'] ) { $setting_type_id= intval( $_POST['interface_tag_type_id'] ); $setting_type = array ('category' => $_POST['category'], @@ -46,7 +46,7 @@ if( $_POST['edit_type'] ) { exit(); } -// attribute type adds +// tag type adds if( $_POST['add_type'] ) { $setting_type = array ('category' => $_POST['category'], 'name' => $_POST['name'], @@ -60,25 +60,25 @@ if( $_POST['add_type'] ) { } -// attribute deletion +// tag deletion if( $_GET['rem_id'] ) { - // get the id of the attrib to remove from GET + // get the id of the tag to remove from GET $setting_id= intval( $_GET['rem_id'] ); // get interface_id $setting= $api->GetInterfaceTags( array( $setting_id ), array( "interface_id" ) ); $interface_id= $setting[0]['interface_id']; - // delete the attribute + // delete the tag $api->DeleteInterfaceTag( $setting_id ); header( "location: interfaces.php?id=$interface_id" ); exit(); } -// attribute adds +// tag adds if( $_POST['add_setting'] ) { - // get the interface_id, attribute_type_id, and value from POST + // get the interface_id, tag_type_id, and value from POST $interface_id= intval( $_POST['interface_id'] ); $interface_tag_type_id= intval( $_POST['interface_tag_type_id'] ); $value= $_POST['value']; @@ -90,7 +90,7 @@ if( $_POST['add_setting'] ) { exit(); } -// attribute updates +// tag updates if( $_POST['edit_setting'] ) { // get the id of the setting to update and the value from POST $setting_id= intval( $_POST['setting_id'] ); @@ -104,12 +104,11 @@ if( $_POST['edit_setting'] ) { exit(); } -// down here is some code from attrib_action.php that was not converted yet // Settings ------------------------------------------------- -// ATTRIBUTE TYPES --------------------------------------------------- +// TAG TYPES --------------------------------------------------- -// delete attribute types +// delete tag types if( $_GET['del_type'] ) { // get vars $type_id= intval( $_GET['del_type'] ); @@ -120,8 +119,6 @@ if( $_GET['del_type'] ) { header( "location: settings.php" ); exit(); } - - /* // Print footer diff --git a/planetlab/nodes/settings.php b/planetlab/nodes/settings.php index a9c9d53..a535b19 100644 --- a/planetlab/nodes/settings.php +++ b/planetlab/nodes/settings.php @@ -24,7 +24,7 @@ $_roles= $_person['role_ids']; //plc_debug("person", $_person ); -$columns=array( "interface_tag_type_id", "category", "name", "description", "min_role_id" ); +$columns=array( "tag_type_id", "category", "tagname", "description", "min_role_id" ); // prepare dict role_id => role_name global $roles; @@ -60,11 +60,11 @@ function layout_setting_type ($setting_type) { return $setting_type; } -// if no id, display list of attributes types +// if no id, display list of tag types if( !$_GET['id'] && !$_GET['add'] && !$_GET['add_type'] && !$_GET['edit_type'] ) { // get types global $person_role; - $filter = array (']min_role_id'=>$person_role); + $filter = array (']min_role_id'=>$person_role,'category'=>'interface*'); $setting_types= $api->GetTagTypes( $filter, $columns ); $setting_types = array_map(layout_setting_type,$setting_types); sort_interface_tags ($setting_types); @@ -90,15 +90,15 @@ if( !$_GET['id'] && !$_GET['add'] && !$_GET['add_type'] && !$_GET['edit_type'] ) // if admin display delete links if( in_array( "10", $_person['role_ids'] ) ) { echo ""; - echo plc_delete_link_button('setting_action.php?del_type='. $type['interface_tag_type_id'], - $type['name']); + echo plc_delete_link_button('setting_action.php?del_type='. $type['tag_type_id'], + $type['tagname']); echo ""; } // if admin, the name is a link to edition if (in_array( "10", $_person['role_ids'])) { - echo "
" . $type['name'] . ""; + echo "" . $type['tagname'] . ""; } else { - echo "" . $type['name'] . ""; + echo "" . $type['tagname'] . ""; } echo "" . $type['category'] . ""; echo "" . $type['min_role'] . "" . $type['min_role_id'] . "" . $type['description'] . ""; @@ -116,13 +116,13 @@ if( !$_GET['id'] && !$_GET['add'] && !$_GET['add_type'] && !$_GET['edit_type'] ) } elseif( $_GET['add_type'] || $_GET['edit_type'] ) { - // if its edit get the attribute info + // if its edit get the tag info if( $_GET['edit_type'] ) { $type_id= intval( $_GET['edit_type'] ); $type= $api->GetTagTypes( array( $type_id ) ); $category=$type[0]['category']; - $name= $type[0]['name']; + $name= $type[0]['tagname']; $min_role_id= $type[0]['min_role_id']; $description= $type[0]['description']; @@ -151,7 +151,7 @@ elseif( $_GET['add_type'] || $_GET['edit_type'] ) { echo "\n"; echo ""; if( $_GET['edit_type'] ) { - echo "\n"; + echo "\n"; echo "\n"; } else { echo "\n"; @@ -170,8 +170,8 @@ elseif( $_GET['add'] ) { // get all setting types global $person_role; - $filter = array (']min_role_id'=>$person_role); - $setting_types= $api->GetTagTypes( $filter, array( "interface_tag_type_id", "name" , "category") ); + $filter = array (']min_role_id'=>$person_role,'category'=>'interface*'); + $setting_types= $api->GetTagTypes( $filter, array( "tag_type_id", "tagname" , "category") ); sort_interface_tags($setting_types); // get interface's settings @@ -185,10 +185,10 @@ elseif( $_GET['add'] ) { echo ""; - echo "
New Setting
Select
Select\n"; @@ -209,7 +209,7 @@ else { // interface info $interface= $api->GetInterfaces( array( $setting[0]['interface_id'] ), array( "ip" ) ); - drupal_set_title("Edit setting ". $setting[0]['name'] ." on ". $interface[0]['ip']); + drupal_set_title("Edit setting ". $setting[0]['tagname'] ." on ". $interface[0]['ip']); // start form and put values in to be edited. echo "\n"; @@ -218,7 +218,7 @@ else { echo ""; echo ""; - echo ""; + echo ""; echo ""; echo ""; echo "
Edit Setting
Category " . $setting[0]['category'] . "
Name " . $setting[0]['name'] . "
Name " . $setting[0]['tagname'] . "
Value
"; diff --git a/planetlab/nodes/sliver_action.php b/planetlab/nodes/sliver_action.php index 262530d..cf0b347 100644 --- a/planetlab/nodes/sliver_action.php +++ b/planetlab/nodes/sliver_action.php @@ -24,12 +24,12 @@ $_roles= $_person['role_ids']; if( !empty( $_POST['add_sub'] ) ) { - $attrib_type= $_POST['sliver']; + $tag_type= $_POST['sliver']; $value= $_POST['value']; $node_id= $_POST['node_id']; $slice_id= $_POST['slice_id']; - $api->AddSliceTag( intval( $slice_id ), intval( $attrib_type ), $value, intval( $node_id ) ); + $api->AddSliceTag( intval( $slice_id ), intval( $tag_type ), $value, intval( $node_id ) ); header( "location: slivers.php?slice=$slice_id&node=$node_id" ); exit(); @@ -39,12 +39,12 @@ if( !empty( $_POST['add_sub'] ) ) { // if( $_GET['rem_id'] ) { - $attrib_id= $_GET['rem_id']; + $tag_id= $_GET['rem_id']; // get the slivers for this node - $sliver_info= $api->GetSliceTags( array( "slice_tag_id"=>intval( $attrib_id ) ), array( "slice_id", "node_id" ) ); + $sliver_info= $api->GetSliceTags( array( "slice_tag_id"=>intval( $tag_id ) ), array( "slice_id", "node_id" ) ); - $api->DeleteSliceTag( intval( $attrib_id ) ); + $api->DeleteSliceTag( intval( $tag_id ) ); header( "location: slivers.php?slice=". $sliver_info[0]['slice_id'] ."&node=". $sliver_info[0]['node_id'] ); exit(); diff --git a/planetlab/nodes/slivers.php b/planetlab/nodes/slivers.php index 035a307..7389782 100644 --- a/planetlab/nodes/slivers.php +++ b/planetlab/nodes/slivers.php @@ -34,23 +34,23 @@ if( $_GET['add'] ) { // node info $node_info= $api->GetNodes( array( intval( $node_id ) ), array( "hostname" ) ); - // get attribute types - $type_info= $api->GetSliceTagTypes( NULL, array( "attribute_type_id", "name" ) ); + // get tag types + $type_info= $api->GetTagTypes( NULL, array( "tag_type_id", "tagname" ) ); // get the slivers for this node - $sliver_info= $api->GetSliceTags( array( "node_id"=>intval( $node_id ), "slice_id"=>intval( $slice_id ) ), array( "attribute_type_id", "name" ) ); + $sliver_info= $api->GetSliceTags( array( "node_id"=>intval( $node_id ), "slice_id"=>intval( $slice_id ) ), array( "tag_type_id", "name" ) ); $types_left= $type_info; // start form echo "\n -

Add a Sliver Attribute to ". $slice_info[0]['name'] ." on node ". $node_info[0]['hostname'] ."

\n +

Add a Sliver Tag to ". $slice_info[0]['name'] ." on node ". $node_info[0]['hostname'] ."

\n \n - \n
Attribute:
Tag:
Value:
\n -

\n"; +

\n"; echo "

Back to Node\n\n"; } -// if slice and node ids are passed display slivers and attribs +// if slice and node ids are passed display slivers and tags if( $_GET['slice'] && $_GET['node'] ) { $slice_id= $_GET['slice']; $node_id= $_GET['node']; @@ -80,16 +80,16 @@ if( $_GET['slice'] && $_GET['node'] ) { $sliver_info= $api->GetSliceTags( array( "node_id"=>intval( $node_id ), "slice_id"=>intval( $slice_id ) ), array( "slice_tag_id", "name", "value", "min_role_id", "description" ) ); // get the attrbibutes for this slice - $attrib_info= $api->GetSliceTags( array( intval( $slice_id ) ), array( "slice_tag_id", "name", "value", "min_role_id", "description" ) ); + $tag_info= $api->GetSliceTags( array( intval( $slice_id ) ), array( "slice_tag_id", "name", "value", "min_role_id", "description" ) ); // start form echo "

\n

Sliver Details for slice ". $slice_info[0]['name'] ." on node ". $node_info[0]['hostname'] ."

\n"; - // sliver attributes of slice + // sliver tags of slice if( empty( $sliver_info ) ) // if no sliver exists tell user - echo "No sliver attribute for this node/slice sliver combination.\n"; + echo "No sliver tag for this node/slice sliver combination.\n"; else { echo "

\n\n"; if ( in_array( 10, $_roles ) || ( in_array( 20, $_roles ) && in_array( $node_info, $_person['site_ids'] ) ) ) echo ""; @@ -97,7 +97,7 @@ if( $_GET['slice'] && $_GET['node'] ) { foreach( $sliver_info AS $sliver ) { echo ""; - if ( in_array( 10, $_roles ) || ( in_array( 20, $_roles ) && in_array( $node_info, $_person['site_ids'] ) ) ) echo ""; + if ( in_array( 10, $_roles ) || ( in_array( 20, $_roles ) && in_array( $node_info, $_person['site_ids'] ) ) ) echo ""; echo "\n"; @@ -107,22 +107,22 @@ if( $_GET['slice'] && $_GET['node'] ) { } - if ( in_array( 10, $_roles ) || ( in_array( 20, $_roles ) && in_array( $node_info, $_person['site_ids'] ) ) ) echo "

Add Sliver Attribute\n"; + if ( in_array( 10, $_roles ) || ( in_array( 20, $_roles ) && in_array( $node_info, $_person['site_ids'] ) ) ) echo "

Add Sliver Tag\n"; echo "


"; - // regular attributes of slice - if( empty( $attrib_info ) ) - // if no attributes exist tell user - echo "No Attributes for this slice.\n"; + // regular tags of slice + if( empty( $tag_info ) ) + // if no tags exist tell user + echo "No Tags for this slice.\n"; else { - echo "

Slivers
NameValueMin RollDescription
". $sliver['name'] ."". $sliver['value'] ."". $sliver['min_role_id'] ."". $sliver['description'] ."EditRemoveEditRemove
\n\n"; + echo "

Attributes
NameValueMin RollDescription
\n\n"; if ( in_array( 10, $_roles ) || ( in_array( 20, $_roles ) && in_array( $node_info, $_person['site_ids'] ) ) ) echo ""; echo "\n"; - foreach( $attrib_info AS $attrib ) { - echo ""; - if ( in_array( 10, $_roles ) || ( in_array( 20, $_roles ) && in_array( $node_info, $_person['site_ids'] ) ) ) echo ""; + foreach( $tag_info AS $tag ) { + echo ""; + if ( in_array( 10, $_roles ) || ( in_array( 20, $_roles ) && in_array( $node_info, $_person['site_ids'] ) ) ) echo ""; echo "\n"; diff --git a/planetlab/persons/index.php b/planetlab/persons/index.php index e49bc4b..3798b25 100644 --- a/planetlab/persons/index.php +++ b/planetlab/persons/index.php @@ -166,9 +166,9 @@ elseif( !$_GET['id'] ) { $persons= array_map(layout_person,$persons); sort_persons( $persons ); - drupal_set_html_head(' - - '); + drupal_set_html_head(' + + '); echo "
\n \n"; diff --git a/planetlab/sites/index.php b/planetlab/sites/index.php index 22970d1..c8f5514 100644 --- a/planetlab/sites/index.php +++ b/planetlab/sites/index.php @@ -155,9 +155,9 @@ elseif( !$_GET['id'] ) { } else { sort_sites( $sites ); - drupal_set_html_head(' - - '); + drupal_set_html_head(' + + '); echo "
\n \n"; diff --git a/planetlab/slices/attrib_action.php b/planetlab/slices/attrib_action.php deleted file mode 100644 index 230bb53..0000000 --- a/planetlab/slices/attrib_action.php +++ /dev/null @@ -1,133 +0,0 @@ -person; -$_roles= $_person['role_ids']; - - -// ATTRIBUTES ------------------------------------------------- - -// attribute deletion -if( $_GET['rem_id'] ) { - // get the id of the attrib to remove from GET - $attribute_id= intval( $_GET['rem_id'] ); - - // get slice_id - $attrib_info= $api->GetSliceTags( array( $attribute_id ), array( "slice_id" ) ); - $slice_id= $attrib_info[0]['slice_id']; - - // delete the attribute - $api->DeleteSliceTag( $attribute_id ); - - - header( "location: index.php?id=$slice_id" ); - exit(); -} - - -// attirbute updates -if( $_POST['edit_attribute'] ) { - // get the id of the attrib to update and teh value from POST - $attribute_id= intval( $_POST['attribute_id'] ); - $value= $_POST['value']; - $slice_id= $_POST['slice_id']; - - // update it! - $api->UpdateSliceTag( $attribute_id, $value ); - - header( "location: index.php?id=$slice_id" ); - exit(); -} - - -// attribute adds -if( $_POST['add_attribute'] ) { - // get the slice_id, attribute_type_id, and value from POST - $slice_id= intval( $_POST['slice_id'] ); - $attribute_type_id= intval( $_POST['attribute_type_id'] ); - $value= $_POST['value']; - - // add it! - $api->AddSliceTag( $slice_id, $attribute_type_id, $value ); - - header( "location: index.php?id=$slice_id" ); - exit(); -} - -// ATTRIBUTE TYPES --------------------------------------------------- - -// attribute type adds -if( $_POST['add_type'] ) { - // get post vars - $name= $_POST['name']; - $min_role_id= intval( $_POST['min_role_id'] ); - $description= $_POST['description']; - - // make the attribute_type_fields dict - $attribute_type_fields= array( "min_role_id" => $min_role_id, "name" => $name, "description" => $description ); - - // add it!! - $api->AddSliceTagType( $attribute_type_fields ); - - header( "location: attributes.php" ); - exit(); -} - - -// attribute type updates -if( $_POST['edit_type'] ) { - // get post vars - $name= $_POST['name']; - $min_role_id= intval( $_POST['min_role_id'] ); - $description= $_POST['description']; - $attribute_type_id= intval( $_POST['attribute_type_id'] ); - - // make attribute_type_fields dict - $attribute_type_fields= array( "min_role_id" => $min_role_id, "name" => $name, "description" => $description ); - - // Update it! - $api->UpdateSliceTagType( $attribute_type_id, $attribute_type_fields ); - - header( "location: attributes.php" ); - exit(); -} - - -// delete attribute types -if( $_GET['del_type'] ) { - // get vars - $type_id= intval( $_GET['del_type'] ); - - // delete it! - $api->DeleteSliceTagType( $type_id ); - - header( "location: attributes.php" ); - exit(); -} - - - -/* -// Print footer -include 'plc_footer.php'; -*/ - -?> diff --git a/planetlab/slices/attributes.php b/planetlab/slices/attributes.php deleted file mode 100644 index b134a87..0000000 --- a/planetlab/slices/attributes.php +++ /dev/null @@ -1,177 +0,0 @@ -person; -$_roles= $_person['role_ids']; - -//print_r( $_person ); - -// if no id, display list of attributes types -if( !$_GET['id'] && !$_GET['add'] && !$_GET['add_type'] && !$_GET['edit_type'] ) { - // get types - $attrib_types= $api->GetSliceTagTypes( NULL, array( "attribute_type_id", "name", "description", "min_role_id" ) ); - - // get role names for the min role_ids - foreach( $attrib_types as $attrib_type ) { - $roles= $api->GetRoles(); - foreach( $roles as $role ) { - if( $attrib_type['min_role_id'] == $role['role_id'] ) - $role_name= $role['name']; - } - - $attrib_type_info[]= array( "attribute_type_id" => $attrib_type['attribute_type_id'], "name" => $attrib_type['name'], "description" => $attrib_type['description'], "min_role" => $role_name ); - } - - // list them - echo "

Slice Attribute Types

\n"; - - echo "
Tags
NameValueMin RollDescription
". $attrib['name'] ."". $attrib['value'] ."". $attrib['min_role_id'] ."". $attrib['description'] ."Edit
". $tag['name'] ."". $tag['value'] ."". $tag['min_role_id'] ."". $tag['description'] ."Edit
"; - // if admin we need to more cells - if( in_array( "10", $_person['role_ids'] ) ) - echo ""; - echo ""; - - foreach( $attrib_type_info as $type ) { - echo ""; - // if admin display edit/delet links - if( in_array( "10", $_person['role_ids'] ) ) { - echo ""; - echo ""; - } - echo "\n"; - - } - - echo "
NameMin RoleDescription
". $type['name'] ."". $type['min_role'] ."". $type['description'] ."Edit"; - echo plc_delete_link_button ('attrib_action.php?del_type='. $type['attribute_type_id'], - $type['name']); - echo "
\n"; - - if( in_array( "10", $_person['role_ids'] ) ) - echo "

Add an Attribute Type"; - -} -elseif( $_GET['add_type'] || $_GET['edit_type'] ) { - // if its edit get the attribute info - if( $_GET['edit_type'] ) { - $type_id= intval( $_GET['edit_type'] ); - $type_info= $api->GetSliceTagTypes( array( $type_id ) ); - - $name= $type_info[0]['name']; - $min_role_id= $type_info[0]['min_role_id']; - $description= $type_info[0]['description']; - - } - - // display form for attribute types - echo "\n"; - echo "

Add Attribute Type

\n"; - echo "

Name: \n"; - echo "

Min Role: \n"; - echo "

Description:
\n"; - echo "\n"; - echo "

\n"; - echo "\n"; - } - else - echo "name='add_type' value='Add Attribute Type'>\n"; - - echo "

\n"; - -} -elseif( $_GET['add'] ) { - // get slice id from GET - $slice_id= intval( $_GET['add'] ); - - // get all attribute types - $attrib_types= $api->GetSliceTagTypes( NULL, array( "attribute_type_id", "name" ) ); - - foreach( $attrib_types as $attrib_type ) { - $all_attribs[$attrib_type['attribute_type_id']]= $attrib_type['name']; - } - - // get slice's attribute types - $slice_info= $api->GetSlices( array( $slice_id ), array( "slice_tag_ids" ) ); - $attrib_info= $api->GetSliceTags( $slice_info[0]['slice_tag_ids'], array( "attribute_type_id", "name" ) ); - - foreach( $attrib_info as $info ) { - $slice_attrib_types[$info['attribute_type_id']]= $info['name']; - } - - - $attribute_types= $all_attribs; - - // start form - echo "
\n"; - echo "

Edit ". $slice_info[0]['name'] ." attribute: ". $attrib_type[0]['name'] ."

\n"; - - echo "\n"; - - echo "

Value: \n"; - - echo "

\n"; - echo "\n"; - echo "

\n"; - -} -else { - $attribute_id= intval( $_GET['id'] ); - - // get attribute info - $slice_attib= $api->GetSliceTags( array( $attribute_id ), array( "slice_id", "slice_tag_id", "attribute_type_id", "value", "description", "min_role_id" ) ); - - // get type info - $attrib_type= $api->GetSliceTagTypes( array( $slice_attib[0]['attribute_type_id'] ), array( "attribute_type_id", "name", "description" ) ); - - // slice info - $slice_info= $api->GetSlices( array( $slice_attib[0]['slice_id'] ), array( "name" ) ); - - // start form and put values in to be edited. - echo "
\n"; - echo "

Edit ". $slice_info[0]['name'] ." attribute: ". $attrib_type[0]['name'] ."

\n"; - - echo $slice_attib[0]['description'] ."
\n"; - echo "Value:

\n"; - - echo "\n"; - echo "\n"; - echo "\n"; - echo "
\n"; - -} - -echo "

Back to Slices\n"; - -// Print footer -include 'plc_footer.php'; - -?> diff --git a/planetlab/slices/index.php b/planetlab/slices/index.php index 1df026a..d97e651 100644 --- a/planetlab/slices/index.php +++ b/planetlab/slices/index.php @@ -47,9 +47,9 @@ if( !$_GET['id'] ) { if( in_array( 10, $_roles ) ) { // auto complete box for finding a slice - drupal_set_html_head(' - - '); + drupal_set_html_head(' + + '); echo "

\n
\n"; @@ -122,7 +122,7 @@ if( !$_GET['id'] ) { echo "

No slice found, or all are expired."; } else { - $slice_info= $api->GetSlices( $slice_ids, array( "slice_id", "name", "site_id", "state", "person_ids", "expires", "peer_id" ) ); + $slice_info= $api->GetSlices( $slice_ids, array( "slice_id", "name", "site_id", "person_ids", "expires", "peer_id" ) ); //print '

'; print_r( $api->trace() ) ; print '
'; if ( ! $slice_info) { @@ -153,7 +153,6 @@ if( !$_GET['id'] ) { foreach( $slice_info as $slice ) { $slice_id= $slice['slice_id']; $slice_name= $slice['name']; - $slice_state= $slice['state']; $slice_expires= date( "M j, Y", $slice['expires'] ); $peer_id = $slice['peer_id']; @@ -252,24 +251,24 @@ else { } } - // slice attribute info + // slice tag info if( !empty( $slice_tag_ids ) ) $slice_attibs= $api->GetSliceTags( $slice_tag_ids, - array( "slice_tag_id", "attribute_type_id", "value", "description", "min_role_id", "node_id" ) ); + array( "slice_tag_id", "tag_type_id", "value", "description", "min_role_id", "node_id" ) ); - // gets attrib type info and combines it to form all attrib info array + // gets tag type info and combines it to form all tag info array if( $slice_attibs ) { foreach( $slice_attibs as $slice_attib ) { - $attrib_type= $api->GetSliceTagTypes( array( $slice_attib['attribute_type_id'] ), - array( "attribute_type_id", "name", "description" ) ); + $tag_type= $api->GetTagTypes( array( $slice_attib['tag_type_id'] ), + array( "tag_type_id", "tagname", "description" ) ); - $attributes[]= array( "slice_tag_id" => $slice_attib['slice_tag_id'], - "attribute_type_id" => $slice_attib['attribute_type_id'], - "name" => $attrib_type[0]['name'], - "value" => $slice_attib['value'], - "description" => $slice_attib['description'], - "min_role_id" => $slice_attib['min_role_id'], - "node_id" => $slice_attib['node_id'] ); + $tags[]= array( "slice_tag_id" => $slice_attib['slice_tag_id'], + "tag_type_id" => $slice_attib['tag_type_id'], + "tagname" => $tag_type[0]['tagname'], + "value" => $slice_attib['value'], + "description" => $slice_attib['description'], + "min_role_id" => $slice_attib['min_role_id'], + "node_id" => $slice_attib['node_id'] ); } } @@ -361,17 +360,17 @@ else { echo "

\n"; - // slice attributes - if( $attributes ) { + // slice tags + if( $tags ) { - // builds 2 arrays, one for attribs,one for slivers - foreach( $attributes as $attribute ) { - if( empty( $attribute['node_id'] ) ) { - $slice_attrib[]= $attribute; + // builds 2 arrays, one for tags, one for slivers + foreach( $tags as $tag ) { + if( empty( $tag['node_id'] ) ) { + $slice_tag[]= $tag; } else { - $sliver_attrib[]= $attribute; - $sliver_nodes[]= $attribute['node_id']; + $sliver_tag[]= $tag; + $sliver_nodes[]= $tag['node_id']; } } } @@ -389,37 +388,37 @@ else { echo "
\n"; } - // slice attributes + // slice tags $is_admin=in_array( 10, $_roles ); $is_in_slice=in_array( $slice_id, $_person['slice_ids'] ); $is_pi=in_array( 20, $_roles ); - if( $slice_attrib ) { - echo ""; + if( $slice_tag ) { + echo "
Slice Attributes
"; echo ""; if( $is_admin ) echo ""; - echo ""; + echo ""; echo "\n"; - foreach( $attributes as $attribute ) { - // ignore sliver attributes at this stage - if( empty( $attribute['node_id'] ) ) { + foreach( $tags as $tag ) { + // ignore sliver tags at this stage + if( empty( $tag['node_id'] ) ) { echo(""); if( $is_admin ) { printf(""; } if( $is_admin || ($is_pi && $is_in_slice) ) { - printf ("", - $attribute['slice_tag_id'],$attribute['name']); + printf ("", + $tag['slice_tag_id'],$tag['tagname']); } else { - printf("",$attribute['name']); + printf("",$tag['tagname']); } printf("", - $attribute['value'],$attribute['description']); + $tag['value'],$tag['description']); echo ""; } } @@ -429,39 +428,39 @@ else { } if( $is_admin || ($is_pi && $is_in_slice) ) - echo "Add a Slice Attribute\n"; + echo "Add a Slice Tag\n"; - // sliver attributes - if( $sliver_attrib ) { - echo "
Slice Tags
AttributeValueDescriptionTagValueDescription
"); - sprintf($label,"\\n [ %s = %s] \\n from %s",$attribute['name'],$attribute['value'],$name); - echo plc_delete_link_button ('attrib_action.php?rem_id=' . $attribute['slice_tag_id'], + sprintf($label,"\\n [ %s = %s] \\n from %s",$tag['tagname'],$tag['value'],$name); + echo plc_delete_link_button ('tag_action.php?rem_id=' . $tag['slice_tag_id'], $label); echo "%s%s%s%s%s%s
"; + // sliver tags + if( $sliver_tag ) { + echo "
Sliver Attributes
"; echo ""; if( $is_admin ) echo ""; - echo ""; + echo ""; echo "\n"; - foreach( $attributes as $attribute ) { - $nodename=$new_sliver_node_info[$attribute['node_id']]['hostname']; - // consider only sliver attributes at this stage - if( !empty( $attribute['node_id'] ) ) { + foreach( $tags as $tag ) { + $nodename=$new_sliver_node_info[$tag['node_id']]['hostname']; + // consider only sliver tags at this stage + if( !empty( $tag['node_id'] ) ) { echo(""); if( $is_admin ) { echo(""; } if( $is_admin ) { - printf("",$attribute['slice_tag_id'],$attribute['name']); + printf("",$tag['slice_tag_id'],$tag['tagname']); } else { - printf("",$attribute['name']); + printf("",$tag['tagname']); } printf("", - $attribute['value'],$attribute['description'],$attribute['node_id'],$nodename); + $tag['value'],$tag['description'],$tag['node_id'],$nodename); echo ""; } diff --git a/planetlab/slices/slice_nodes.php b/planetlab/slices/slice_nodes.php index 5a00ab0..916f95d 100644 --- a/planetlab/slices/slice_nodes.php +++ b/planetlab/slices/slice_nodes.php @@ -108,29 +108,30 @@ else // get site nodes for $site_id if( $site_id == 'all_site' ) { - $full_node_info= $adm->GetNodes( NULL, array( "hostname", "node_id" , "peer_id", "boot_state","last_updated") ); + $full_node_info= $adm->GetNodes( array("node_type","regular"), + array( "hostname", "node_id" , "peer_id", "boot_state","last_updated") ); - $snode_info= array(); - foreach( $full_node_info as $full_node ) { - if( !in_array( $full_node['node_id'], $slice_info[0]['node_ids'] ) ) - $snode_info[]= $full_node; - } + $snode_info= array(); + foreach( $full_node_info as $full_node ) { + if( !in_array( $full_node['node_id'], $slice_info[0]['node_ids'] ) ) + $snode_info[]= $full_node; + } } else { - $sid= intval( $site_id ); - $site_node_info= $adm->GetSites( array( $sid ), array( "node_ids" ) ); - $site_nodes= $site_node_info[0]['node_ids']; + $sid= intval( $site_id ); + $site_node_info= $adm->GetSites( array( $sid ), array( "node_ids" ) ); + $site_nodes= $site_node_info[0]['node_ids']; - // gets all node_ids from site that arent already associated with the slice - foreach( $site_nodes as $snode) { - if( !in_array( $snode, $slice_info[0]['node_ids'] ) ) - $snodes[]= $snode; - } + // gets all node_ids from site that arent already associated with the slice + foreach( $site_nodes as $snode) { + if( !in_array( $snode, $slice_info[0]['node_ids'] ) ) + $snodes[]= $snode; + } - // Get node info from new list - if( !empty( $snodes ) ) - $snode_info= $adm->GetNodes( $snodes, array( "hostname", "node_id" , "peer_id", "boot_state","last_updated" ) ); - + // Get node info from new list + if( !empty( $snodes ) ) + $snode_info= $adm->GetNodes( $snodes, array( "hostname", "node_id" , "peer_id", "boot_state","last_updated" ) ); + } // start form @@ -149,10 +150,10 @@ if ( ! $slice_readonly ) { echo "
Sliver Tags
AttributeValueDescriptionNodeTagValueDescriptionNode
"); $label=sprintf("\\n [ %s = %s ] \\n from %s \\n on node %s", - $attribute['name'],$attribute['value'],$name,$nodename); - echo plc_delete_link_label('/db/nodes/sliver_action.php?rem_id=' . $attribute['slice_tag_id'], + $tag['tagname'],$tag['value'],$name,$nodename); + echo plc_delete_link_label('/db/nodes/sliver_action.php?rem_id=' . $tag['slice_tag_id'], $label); echo "%s%s%s%s%s%s%s
"; } echo ""; + // if admin we need to more cells + if( in_array( "10", $_person['role_ids'] ) ) + echo ""; + echo ""; + + foreach( $tag_type_info as $type ) { + echo ""; + echo ""; + echo ""; + echo ""; + echo ""; + // if admin display edit/delet links + if( in_array( "10", $_person['role_ids'] ) ) { + echo ""; + echo ""; + } + echo "\n"; + + } + + echo "
NameCategory>Min RoleDescription
". $type['tagname'] ."". $type['category'] ."". $type['min_role'] ."". $type['description'] ."Edit"; + echo plc_delete_link_button ('tag_action.php?del_type='. $type['tag_type_id'], + $type['tagname']); + echo "
\n"; + + if( in_array( "10", $_person['role_ids'] ) ) + echo "

Add a Tag Type"; + + } +elseif( $_GET['add_type'] || $_GET['edit_type'] ) { + // if its edit get the tag info + if( $_GET['edit_type'] ) { + $type_id= intval( $_GET['edit_type'] ); + $type_info= $api->GetTagTypes( array( $type_id ) ); + + $tagname= $type_info[0]['tagname']; + $min_role_id= $type_info[0]['min_role_id']; + $description= $type_info[0]['description']; + $category=$type_info[0]['category']; + + } + + // display form for tag types + echo "\n"; + echo "

Add Tag Type

\n"; + echo "

Name: \n"; + echo "

Category: \n"; + echo "

Min Role: \n"; + echo "

Description:
\n"; + echo "\n"; + echo "

\n"; + echo "\n"; + } + else + echo "name='add_type' value='Add Tag Type'>\n"; + + echo "\n"; + +} +elseif( $_GET['add'] ) { + // get slice id from GET + $slice_id= intval( $_GET['add'] ); + + // get all tag types + $tag_types= $api->GetTagTypes( $tag_type_filter , array( "tag_type_id", "tagname" ) ); + + foreach( $tag_types as $tag_type ) { + $all_tags[$tag_type['tag_type_id']]= $tag_type['tagname']; + } + + // get slice's tag types + $slice_info= $api->GetSlices( array( $slice_id ), array( "slice_tag_ids" ) ); + $tag_info= $api->GetSliceTags( $slice_info[0]['slice_tag_ids'], array( "tag_type_id", "tagname" ) ); + + foreach( $tag_info as $info ) { + $slice_tag_types[$info['tag_type_id']]= $info['tagname']; + } + + + $tag_types= $all_tags; + + // start form + echo "

\n"; + echo "

Edit ". $slice_info[0]['name'] ." tag: ". $tag_type[0]['tagname'] ."

\n"; + + echo "\n"; + + echo "

Value: \n"; + + echo "

\n"; + echo "\n"; + echo "

\n"; + +} +else { + $tag_id= intval( $_GET['id'] ); + + // get tag + $slice_tag= $api->GetSliceTags( array( $tag_id ), array( "slice_id", "slice_tag_id", "tag_type_id", "value", "description", "min_role_id" ) ); + + // get type info + $tag_type= $api->GetTagTypes( array( $slice_tag[0]['tag_type_id'] ), array( "tag_type_id", "tagname", "description" ) ); + + // slice info + $slice_info= $api->GetSlices( array( $slice_tag[0]['slice_id'] ), array( "name" ) ); + + // start form and put values in to be edited. + echo "
\n"; + echo "

Edit ". $slice_info[0]['name'] ." tag: ". $tag_type[0]['tagname'] ."

\n"; + + echo $slice_tag[0]['description'] ."
\n"; + echo "Value:

\n"; + + echo "\n"; + echo "\n"; + echo "\n"; + echo "
\n"; + +} + +echo "

Back to Slices\n"; + +// Print footer +include 'plc_footer.php'; + +?> diff --git a/planetlab/tablesort/customsort.js b/planetlab/tablesort/customsort.js new file mode 100644 index 0000000..a766898 --- /dev/null +++ b/planetlab/tablesort/customsort.js @@ -0,0 +1,356 @@ +/* + sortEnglishDateTime + ----------------------- + + This function sorts English dateTime vaues such as: + + 1st January 2003, 23:32:01 + 23/03/1972 à 10:22:22 + 1970/13/03 at 23:22:01 + + The function is "safe" i.e. non-dateTime data (like the word "Unknown") can be passed in and is sorted properly. +*/ +var sortEnglishDateTime = fdTableSort.sortNumeric; + +function sortEnglishDateTimePrepareData(tdNode, innerText) { + // You can localise the function here + var months = ['january','february','march','april','may','june','july','august','september','october','november','december','jan','feb','mar','apr','may','jun','jul','aug','sep','oct','nov','dec']; + + // Lowercase the text + var aa = innerText.toLowerCase(); + + // Replace the longhand months with an integer equivalent + for(var i = 0; i < months.length; i++) { + aa = aa.replace(months[i], (i+13)%12); + }; + + // Replace multiple spaces and anything that is not valid in the parsing of the date, then trim + aa = aa.replace(/\s+/g, " ").replace(/([^\d\s\/-:.])/g, "").replace(/^\s\s*/, '').replace(/\s\s*$/, ''); + + // No timestamp at the end, then return -1 + if(aa.search(/(\d){2}:(\d){2}(:(\d){2})?$/) == -1) { return -1; }; + + // Grab the timestamp + var timestamp = aa.match(/(\d){2}:(\d){2}(:(\d){2})?$/)[0].replace(/:/g, ""); + + // Make the timestamp 6 characters by default + if(timestamp.length == 4) { timestamp += "00"; }; + + // Remove it from the string to assist the date parser, then trim + aa = aa.replace(/(\d){2}:(\d){2}(:(\d){2})?$/, "").replace(/\s\s*$/, ''); + + // If you want the parser to favour the parsing of European dd/mm/yyyy dates then leave this set to "true" + // If you want the parser to favour the parsing of American mm/dd/yyyy dates then set to "false" + var favourDMY = true; + + // If you have a regular expression you wish to add, add the Object to the end of the array + var dateTest = [ + { 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 + { 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 + { 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 + ]; + + var start,y,m,d; + var cnt = 0; + var numFormats = dateTest.length; + while(cnt < numFormats) { + start = (cnt + (favourDMY ? numFormats + 1 : numFormats)) % numFormats; + if(aa.match(dateTest[start].regExp)) { + res = aa.match(dateTest[start].regExp); + y = res[dateTest[start].y]; + m = res[dateTest[start].m]; + d = res[dateTest[start].d]; + if(m.length == 1) m = "0" + String(m); + if(d.length == 1) d = "0" + String(d); + if(y.length != 4) y = (parseInt(y) < 50) ? "20" + String(y) : "19" + String(y); + + return y+String(m)+d+String(timestamp); + }; + cnt++; + }; + return -1; +}; + +/* + sortAlphaNumeric + ----------------------- + + This function sorts alphaNumeric values e.g. 1, e, 1a, -23c, 54z + + Notice how the prepareData function actually returns an Array i.e. you are not limited + in the type of data you return to the tableSort script. +*/ +function sortAlphaNumericPrepareData(tdNode, innerText){ + var aa = innerText.toLowerCase().replace(" ", ""); + var reg = /((\-|\+)?(\s+)?[0-9]+\.([0-9]+)?|(\-|\+)?(\s+)?(\.)?[0-9]+)([a-z]+)/; + + if(reg.test(aa)) { + var aaP = aa.match(reg); + return [aaP[1], aaP[8]]; + }; + + // Return an array + return isNaN(aa) ? ["",aa] : [aa,""]; +} + +function sortAlphaNumeric(a, b){ + // Get the previously prepared array + var aa = a[fdTableSort.pos]; + var bb = b[fdTableSort.pos]; + + // If they are equal then return 0 + if(aa[0] == bb[0] && aa[1] == bb[1]) { return 0; }; + + // Check numeric parts if not equal + if(aa[0] != bb[0]) { + if(aa[0] != "" && bb[0] != "") { return aa[0] - bb[0]; }; + if(aa[0] == "" && bb[0] != "") { return -1; }; + return 1; + }; + + // Check alpha parts if numeric parts equal + if(aa[1] == bb[1]) return 0; + if(aa[1] < bb[1]) return -1; + return 1; +} + +/* + sortDutchCurrencyValues + ----------------------- + + This function sorts Dutch currency values (of the type 100.000,00) + The function is "safe" i.e. non-currency data (like the word "Unknown") can be passed in and is sorted properly. +*/ +var sortDutchCurrencyValues = fdTableSort.sortNumeric; + +function sortDutchCurrencyValuesPrepareData(tdNode, innerText) { + innerText = parseInt(innerText.replace(/[^0-9\.,]+/g, "").replace(/\./g,"").replace(",",".")); + return isNaN(innerText) ? "" : innerText; +} + +/* + sortByTwelveHourTimestamp + ------------------------- + + This custom sort function sorts 12 hour timestamps of an hour/minute nature. + The hour/minute dividor can be a full-stop or a colon and it correctly calculates that 12.30am is before 1am etc + The am/pm part can be written in lower or uppercase and can optionally contain full-stops e.g. + + am, a.m, a.m., AM, A.M etc + + Additionally, the values "12 midnight" and "12 noon" are also handled correctly. + + The question remains... does "12p.m." mean "midnight" or "12 noon"? I've decided here that it's 12 noon. + + The function is "safe" i.e. non-timestamp data (like the word "Unknown") can be passed in and is sorted properly. +*/ +var sortByTwelveHourTimestamp = fdTableSort.sortNumeric; + +function sortByTwelveHourTimestampPrepareData(tdNode, innerText) { + tmp = innerText + innerText = innerText.replace(":","."); + + // Check for the special cases of "12 noon" or "12 midnight" + if(innerText.search(/12([\s]*)?noon/i) != -1) return "12.00"; + if(innerText.search(/12([\s]*)?midnight/i) != -1) return "24.00"; + + var regExpPM = /^([0-9]{1,2}).([0-9]{2})([\s]*)?(p[\.]?m)/i; + var regExpAM = /^([0-9]{1,2}).([0-9]{2})([\s]*)?(a[\.]?m)/i; + + if(innerText.search(regExpPM) != -1) { + var bits = innerText.match(regExpPM); + if(parseInt(bits[1]) < 12) { bits[1] = parseInt(bits[1]) + 12; } + } else if(innerText.search(regExpAM) != -1) { + var bits = innerText.match(regExpAM); + if(bits[1] == "12") { bits[1] = "00"; } + } else return ""; + + if(bits[2].length < 2) { bits[2] = "0" + String(bits[2]); } + + innerText = bits[1] + "." + String(bits[2]); + + return isNaN(innerText) ? "" : innerText; +} +/* + sortEnglishLonghandDateFormat + ----------------------------- + + This custom sort function sorts dates of the format: + + "12th April, 2006" or "12 April 2006" or "12-4-2006" or "12 April" or "12 4" or "12 Apr 2006" etc + + The function expects dates to be in the format day/month/year. Should no year be stipulated, + the function treats the year as being the current year. + + The function is "safe" i.e. non-date data (like the word "Unknown") can be passed in and is sorted properly. +*/ +var sortEnglishLonghandDateFormat = fdTableSort.sortNumeric; + +function sortEnglishLonghandDateFormatPrepareData(tdNode, innerText) { + var months = ['january','february','march','april','may','june','july','august','september','october','november','december']; + + var aa = innerText.toLowerCase(); + + // Replace the longhand months with an integer equivalent + for(var i = 0; i < 12; i++) { + aa = aa.replace(months[i], i+1).replace(months[i].substring(0,3), i+1); + } + + // If there are still alpha characters then return -1 + if(aa.search(/a-z/) != -1) return -1; + + // Replace multiple spaces and anything that is not numeric + aa = aa.replace(/\s+/g, " ").replace(/[^\d\s]/g, ""); + + // If were left with nothing then return -1 + if(aa.replace(" ", "") == "") return -1; + + // Split on the (now) single spaces + aa = aa.split(" "); + + // If something has gone terribly wrong then return -1 + if(aa.length < 2) return -1; + + // If no year stipulated, then add this year as default + if(aa.length == 2) { + aa[2] = String(new Date().getFullYear()); + } + + // Equalise the day and month + if(aa[0].length < 2) aa[0] = "0" + String(aa[0]); + if(aa[1].length < 2) aa[1] = "0" + String(aa[1]); + + // Deal with Y2K issues + if(aa[2].length != 4) { + aa[2] = (parseInt(aa[2]) < 50) ? '20' + aa[2] : '19' + aa[2]; + } + + // YMD (can be used as integer during comparison) + return aa[2] + String(aa[1]) + aa[0]; +} +/* + sortIPAddress + ------------- + + This custom sort function correctly sorts IP addresses i.e. it checks all of the address parts and not just the first. + + The function is "safe" i.e. non-IP address data (like the word "Unknown") can be passed in and is sorted properly. +*/ +var sortIPAddress = fdTableSort.sortNumeric; + +function sortIPAddressPrepareData(tdNode, innerText) { + // Get the innerText of the TR nodes + var aa = innerText; + + // Remove spaces + aa = aa.replace(" ",""); + + // If not an IP address then return -1 + if(aa.search(/^([0-9]{1,3}).([0-9]{1,3}).([0-9]{1,3}).([0-9]{1,3})$/) == -1) return -1; + + // Split on the "." + aa = aa.split("."); + + // If we don't have 4 parts then return -1 + if(aa.length != 4) return -1; + + var retVal = ""; + + // Make all the parts an equal length and create a master integer + for(var i = 0; i < 4; i++) { + retVal += (String(aa[i]).length < 3) ? "0000".substr(0, 3 - String(aa[i]).length) + String(aa[i]) : aa[i]; + } + + return retVal; +} +/* + sortScientificNotation + ---------------------- + + This custom sort function sorts numbers stipulated in scientific notation + + The function is "safe" i.e. data like the word "Unknown" can be passed in and is sorted properly. + + N.B. The only way I can think to really sort scientific notation is to convert + it to a floating point number and then perform the sort on that. If you can think of + an easier/better way then please let me know. +*/ +var sortScientificNotation = fdTableSort.sortNumeric; + +function sortScientificNotationPrepareData(tdNode, innerText) { + var aa = innerText; + + var floatRegExp = /((\-|\+)?(\s+)?[0-9]+\.([0-9]+)?|(\-|\+)?(\s+)?(\.)?[0-9]+)/g; + + aa = aa.match(floatRegExp); + + if(!aa || aa.length != 2) return ""; + + var f1 = parseFloat(aa[0].replace(" ",""))*Math.pow(10,parseFloat(aa[1].replace(" ",""))); + return isNaN(f1) ? "" : f1; +} + +/* + sortImage + --------- + + This is the function called in order to sort the data previously prepared by the function + "sortImagePrepareData". It does a basic case sensitive comparison on the data using the + tableSort's in-built sortText method. +*/ +var sortImage = fdTableSort.sortText; + +/* + This is the function used to prepare i.e. parse data, to be used during the sort + of the images within the last table. + + In this case, we are checking to see if the TD node has any child nodes that are + images and, if an image exists, return it's "src" attribute. + If no image exists, then we return an empty string. + + The "prepareData" functions are passed the actual TD node and also the TD node inner text + which means you are free to check for child nodes etc and are not just limited to + sorting on the TD node's inner text. + + The prepareData functions are not required (only your bespoke sort function is required) + and only called by the script should they exist. +*/ +function sortImagePrepareData(td, innerText) { + var img = td.getElementsByTagName('img'); + return img.length ? img[0].src: ""; +} + +/* + sortFileSize + ------------ + + 1 Byte = 8 Bit + 1 Kilobyte = 1024 Bytes + 1 Megabyte = 1048576 Bytes + 1 Gigabyte = 1073741824 Bytes +*/ +var sortFileSize = fdTableSort.sortNumeric; + +function sortFileSizePrepareData(td, innerText) { + var regExp = /(kb|mb|gb)/i; + + var type = innerText.search(regExp) != -1 ? innerText.match(regExp)[0] : ""; + + switch (type.toLowerCase()) { + case "kb" : + mult = 1024; + break; + case "mb" : + mult = 1048576; + break; + case "gb" : + mult = 1073741824; + break; + default : + mult = 1; + }; + + innerText = parseFloat(innerText.replace(/[^0-9\.\-]/g,'')); + + return isNaN(innerText) ? "" : innerText * mult; +}; diff --git a/planetlab/tablesort/paginate.js b/planetlab/tablesort/paginate.js new file mode 100644 index 0000000..0dfcc7d --- /dev/null +++ b/planetlab/tablesort/paginate.js @@ -0,0 +1,479 @@ +/* + paginate table object v2.0 by frequency-decoder.com + + Released under a creative commons Attribution-ShareAlike 2.5 license (http://creativecommons.org/licenses/by-sa/2.5/) + + Please credit frequency decoder in any derivative work - thanks + + You are free: + + * to copy, distribute, display, and perform the work + * to make derivative works + * to make commercial use of the work + + Under the following conditions: + + by Attribution. + -------------- + You must attribute the work in the manner specified by the author or licensor. + + sa + -- + 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. + + * For any reuse or distribution, you must make clear to others the license terms of this work. + * Any of these conditions can be waived if you get permission from the copyright holder. +*/ + +var tablePaginater = (function() { + /* + + Localise the button titles here... + + %p is replaced with the appropriate page number + %t is replaced with the total number of pages + + */ + var tableInfo = {}, + uniqueID = 0, + text = ["First Page","Previous Page (Page %p)","Next Page (Page %p)","Last Page (Page %t)","Page %p of %t"]; + + var addClass = function(e,c) { + if(new RegExp("(^|\\s)" + c + "(\\s|$)").test(e.className)) return; + e.className += ( e.className ? " " : "" ) + c; + }; + + /*@cc_on + /*@if (@_win32) + var removeClass = function(e,c) { + e.className = !c ? "" : e.className.replace(new RegExp("(^|\\s)" + c + "(\\s|$)"), " ").replace(/^\s*((?:[\S\s]*\S)?)\s*$/, '$1'); + }; + @else @*/ + var removeClass = function(e,c) { + e.className = !c ? "" : (e.className || "").replace(new RegExp("(^|\\s)" + c + "(\\s|$)"), " ").replace(/^\s\s*/, '').replace(/\s\s*$/, ''); + }; + /*@end + @*/ + + var addEvent = function(obj, type, fn) { + if( obj.attachEvent ) { + obj["e"+type+fn] = fn; + obj[type+fn] = function(){obj["e"+type+fn]( window.event );}; + obj.attachEvent( "on"+type, obj[type+fn] ); + } else { + obj.addEventListener( type, fn, true ); + }; + }; + var removeEvent = function(obj, type, fn) { + try { + if( obj.detachEvent ) { + obj.detachEvent( "on"+type, obj[type+fn] ); + obj[type+fn] = null; + } else { + obj.removeEventListener( type, fn, true ); + }; + } catch(err) {}; + }; + var stopEvent = function(e) { + e = e || window.event; + if(e.stopPropagation) { + e.stopPropagation(); + e.preventDefault(); + }; + + /*@cc_on@*/ + /*@if(@_win32) + e.cancelBubble = true; + e.returnValue = false; + /*@end@*/ + return false; + }; + + var init = function(tableId) { + var tables = tableId && typeof(tableId) == "string" ? [document.getElementById(tableId)] : document.getElementsByTagName('table'), + hook, maxPages, visibleRows, numPages, cp, cb, rowList; + + for(var t = 0, tbl; tbl = tables[t]; t++) { + if(tbl.className.search(/paginate-([0-9]+)/) == -1) { continue; }; + + if(!tbl.id) { tbl.id = "fdUniqueTableId_" + uniqueID++; }; + + maxPages = tbl.className.search(/max-pages-([0-9]+)/) == -1 ? null : Number(tbl.className.match(/max-pages-([0-9]+)/)[1]); + if(maxPages % 2 == 0 && maxPages > 1) { maxPages--; }; + + hook = tbl.getElementsByTagName('tbody'); + hook = (hook.length) ? hook[0] : tbl; + + visibleRows = calculateVisibleRows(hook); + + if(maxPages > (visibleRows / Number(tbl.className.match(/paginate-([0-9]+)/)[1]))) { + maxPages = null; + }; + + numPages = Math.ceil(visibleRows / Number(tbl.className.match(/paginate-([0-9]+)/)[1])); + + if(numPages < 2 && !(tbl.id in tableInfo)) { + continue; + }; + + cp = (tbl.id in tableInfo) ? Math.min(tableInfo[tbl.id].currentPage, numPages) : 1; + + tableInfo[tbl.id] = { + rowsPerPage:Number(tbl.className.match(/paginate-([0-9]+)/)[1]), + currentPage:cp, + totalRows:hook.getElementsByTagName('tr').length, + hook:hook, + maxPages:maxPages, + numPages:numPages, + rowStyle:tbl.className.search(/rowstyle-([\S]+)/) != -1 ? tbl.className.match(/rowstyle-([\S]+)/)[1] : false, + callbacks:parseCallback(/^paginationcallback-/i, /paginationcallback-([\S-]+)/ig, tbl.className) + }; + + showPage(tbl.id); + hook = null; + }; + }; + + var parseCallback = function(head, regExp, cname) { + var cbs = [], + matchs = cname.match(regExp), + parts, obj, func; + + if(!matchs) { return []; }; + + for(var i = 0, mtch; mtch = matchs[i]; i++) { + mtch = mtch.replace(head, "").replace(/-/g, "."); + + try { + if(mtch.indexOf(".") != -1) { + parts = mtch.split('.'); + obj = window; + for (var x = 0, part; part = obj[parts[x]]; x++) { + if(part instanceof Function) { + (function() { + var method = part; + func = function (data) { method.apply(obj, [data]) }; + })(); + } else { + obj = part; + }; + }; + } else { + func = window[mtch]; + }; + + if(!(func instanceof Function)) continue; + cbs[cbs.length] = func; + } catch(err) {}; + }; + + return cbs; + }; + + var callback = function(tblId, opts) { + if(!(tblId in tableInfo) || !(tableInfo[tblId]["callbacks"].length)) return; + for(var i = 0, func; func = tableInfo[tblId]["callbacks"][i]; i++) { + func(opts || {}); + }; + }; + + var calculateVisibleRows = function(hook) { + var trs = hook.rows, + cnt = 0, + reg = /(^|\s)invisibleRow(\s|$)/; + + for(var i = 0, tr; tr = trs[i]; i++) { + if(tr.parentNode != hook || tr.getElementsByTagName("th").length || (tr.parentNode && tr.parentNode.tagName.toLowerCase().search(/thead|tfoot/) != -1)) continue; + if(tr.className.search(reg) == -1) { cnt++; }; + }; + + return cnt; + }; + + var createButton = function(details, ul, pseudo) { + var li = document.createElement("li"), + but = document.createElement(pseudo ? "div" : "a"), + span = document.createElement("span"); + + if(!pseudo) { + but.href = "#"; + but.title = details.title; + }; + + but.className = details.className; + + ul.appendChild(li); + li.appendChild(but); + but.appendChild(span); + span.appendChild(document.createTextNode(details.text)); + + if(!pseudo) { + li.onclick = but.onclick = buttonClick; + if(details.id) { but.id = details.id; }; + }; + + li = but = span = null; + }; + var removePagination = function(tableId) { + var wrapT = document.getElementById(tableId + "-fdtablePaginaterWrapTop"), + wrapB = document.getElementById(tableId + "-fdtablePaginaterWrapBottom"); + if(wrapT) { wrapT.parentNode.removeChild(wrapT); }; + if(wrapB) { wrapB.parentNode.removeChild(wrapB); }; + }; + var buildPagination = function(tblId) { + if(!(tblId in tableInfo)) { return; }; + + removePagination(tblId); + + var details = tableInfo[tblId]; + + if(details.numPages < 2) return; + + function resolveText(txt, curr) { + curr = curr || details.currentPage; + return txt.replace("%p", curr).replace("%t", details.numPages); + }; + + if(details.maxPages) { + findex = Math.max(0, Math.floor(Number(details.currentPage - 1) - (Number(details.maxPages - 1) / 2))); + lindex = findex + Number(details.maxPages); + if(lindex > details.numPages) { + lindex = details.numPages; + findex = Math.max(0, details.numPages - Number(details.maxPages)); + }; + } else { + findex = 0; + lindex = details.numPages; + }; + + + var wrapT = document.createElement("div"); + wrapT.className = "fdtablePaginaterWrap"; + wrapT.id = tblId + "-fdtablePaginaterWrapTop"; + + var wrapB = document.createElement("div"); + wrapB.className = "fdtablePaginaterWrap"; + wrapB.id = tblId + "-fdtablePaginaterWrapBottom"; + + // Create list scaffold + var ulT = document.createElement("ul"); + ulT.id = tblId + "-tablePaginater"; + + var ulB = document.createElement("ul"); + ulB.id = tblId + "-tablePaginaterClone"; + ulT.className = ulB.className = "fdtablePaginater"; + + // Add to the wrapper DIVs + wrapT.appendChild(ulT); + wrapB.appendChild(ulB); + + // FIRST (only created if maxPages set) + if(details.maxPages) { + createButton({title:text[0], className:"first-page", text:"\u00ab"}, ulT, !findex); + createButton({title:text[0], className:"first-page", text:"\u00ab"}, ulB, !findex); + }; + + // PREVIOUS (only created if there are more than two pages) + if(details.numPages > 2) { + createButton({title:resolveText(text[1], details.currentPage-1), className:"previous-page", text:"\u2039", id:tblId+"-previousPage"}, ulT, details.currentPage == 1); + createButton({title:resolveText(text[1], details.currentPage-1), className:"previous-page", text:"\u2039", id:tblId+"-previousPageC"}, ulB, details.currentPage == 1); + }; + + // NUMBERED + for(var i = findex; i < lindex; i++) { + createButton({title:resolveText(text[4], i+1), className:i != (details.currentPage-1) ? "page-"+(i+1) : "currentPage page-"+(i+1), text:(i+1), id:i == (details.currentPage-1) ? tblId + "-currentPage" : ""}, ulT); + createButton({title:resolveText(text[4], i+1), className:i != (details.currentPage-1) ? "page-"+(i+1) : "currentPage page-"+(i+1), text:(i+1), id:i == (details.currentPage-1) ? tblId + "-currentPageC" : ""}, ulB); + }; + + // NEXT (only created if there are more than two pages) + if(details.numPages > 2) { + createButton({title:resolveText(text[2], details.currentPage + 1), className:"next-page", text:"\u203a", id:tblId+"-nextPage"}, ulT, details.currentPage == details.numPages); + createButton({title:resolveText(text[2], details.currentPage + 1), className:"next-page", text:"\u203a", id:tblId+"-nextPageC"}, ulB, details.currentPage == details.numPages); + }; + + // LAST (only created if maxPages set) + if(details.maxPages) { + createButton({title:resolveText(text[3], details.numPages), className:"last-page", text:"\u00bb"}, ulT, lindex == details.numPages); + createButton({title:resolveText(text[3], details.numPages), className:"last-page", text:"\u00bb"}, ulB, lindex == details.numPages); + }; + + // DOM inject wrapper DIVs (FireFox 2.x Bug: this has to be done here if you use display:table) + if(document.getElementById(tblId+"-paginationListWrapTop")) { + document.getElementById(tblId+"-paginationListWrapTop").appendChild(wrapT); + } else { + document.getElementById(tblId).parentNode.insertBefore(wrapT, document.getElementById(tblId)); + }; + + if(document.getElementById(tblId+"-paginationListWrapBottom")) { + document.getElementById(tblId+"-paginationListWrapBottom").appendChild(wrapB); + } else { + document.getElementById(tblId).parentNode.insertBefore(wrapB, document.getElementById(tblId).nextSibling); + }; + }; + + // The tableSort script uses this function to redraw. + var tableSortRedraw = function(tableid, identical) { + if(!tableid || !(tableid in fdTableSort.tableCache) || !(tableid in tableInfo)) { return; }; + + var dataObj = fdTableSort.tableCache[tableid], + data = dataObj.data, + len1 = data.length, + len2 = len1 ? data[0].length - 1 : 0, + hook = dataObj.hook, + colStyle = dataObj.colStyle, + rowStyle = dataObj.rowStyle, + colOrder = dataObj.colOrder, + page = tableInfo[tableid].currentPage - 1, + d1 = tableInfo[tableid].rowsPerPage * page, + d2 = Math.min(tableInfo[tableid].totalRows, d1 + tableInfo[tableid].rowsPerPage), + cnt = 0, + rs = 0, + reg = /(^|\s)invisibleRow(\s|$)/, + tr, tds, cell, pos; + + for(var i = 0; i < len1; i++) { + tr = data[i][len2]; + + if(colStyle) { + tds = tr.cells; + for(thPos in colOrder) { + if(!colOrder[thPos]) removeClass(tds[thPos], colStyle); + else addClass(tds[thPos], colStyle); + }; + }; + + if(tr.className.search(reg) != -1) { continue; }; + + if(!identical) { + cnt++; + + if(cnt > d1 && cnt <= d2) { + if(rowStyle) { + if(rs++ & 1) addClass(tr, rowStyle); + else removeClass(tr, rowStyle); + }; + tr.style.display = ""; + } else { + tr.style.display = "none"; + }; + + // Netscape 8.1.2 requires the removeChild call or it freaks out, so add the line if you want to support this browser + // hook.removeChild(tr); + hook.appendChild(tr); + }; + }; + + tr = tds = hook = null; + }; + + var showPage = function(tblId, pageNum) { + if(!(tblId in tableInfo)) { return; }; + + var page = Math.max(0, !pageNum ? tableInfo[tblId].currentPage - 1 : pageNum - 1), + d1 = tableInfo[tblId].rowsPerPage * page, + d2 = Math.min(tableInfo[tblId].totalRows, d1 + tableInfo[tblId].rowsPerPage), + trs = tableInfo[tblId].hook.rows, + cnt = 0, + rc = 0, + len = trs.length, + rs = tableInfo[tblId].rowStyle, + reg = /(^|\s)invisibleRow(\s|$)/, + row = []; + + for(var i = 0; i < len; i++) { + if(trs[i].className.search(reg) != -1 || trs[i].getElementsByTagName("th").length || (trs[i].parentNode && trs[i].parentNode.tagName.toLowerCase().search(/thead|tfoot/) != -1)) { continue; }; + + cnt++; + + if(cnt > d1 && cnt <= d2) { + if(rs) { + if(rc++ & 1) { + addClass(trs[i], rs); + } else { + removeClass(trs[i], rs); + } + }; + trs[i].style.display = ""; + row[row.length] = trs[i]; + } else { + trs[i].style.display = "none"; + }; + }; + + buildPagination(tblId); + callback(tblId, {"totalRows":len, "currentPage":(page+1), "rowsPerPage":tableInfo[tblId].rowsPerPage, "visibleRows":row}); + }; + + var buttonClick = function(e) { + e = e || window.event; + + var a = this.tagName.toLowerCase() == "a" ? this : this.getElementsByTagName("a")[0]; + + if(a.className.search("currentPage") != -1) return false; + + var ul = this; + while(ul.tagName.toLowerCase() != "ul") ul = ul.parentNode; + + var tblId = ul.id.replace("-tablePaginaterClone","").replace("-tablePaginater", ""); + + tableInfo[tblId].lastPage = tableInfo[tblId].currentPage; + + var showPrevNext = 0; + + if(a.className.search("previous-page") != -1) { + tableInfo[tblId].currentPage = tableInfo[tblId].currentPage > 1 ? tableInfo[tblId].currentPage - 1 : tableInfo[tblId].numPages; + showPrevNext = 1; + } else if(a.className.search("next-page") != -1) { + tableInfo[tblId].currentPage = tableInfo[tblId].currentPage < tableInfo[tblId].numPages ? tableInfo[tblId].currentPage + 1 : 1; + showPrevNext = 2; + } else if(a.className.search("first-page") != -1) { + tableInfo[tblId].currentPage = 1; + } else if(a.className.search("last-page") != -1) { + tableInfo[tblId].currentPage = tableInfo[tblId].numPages; + } else { + tableInfo[tblId].currentPage = parseInt(a.className.match(/page-([0-9]+)/)[1]) || 1; + }; + + showPage(tblId); + + // Focus on the appropriate button (previous, next or the current page) + // I'm hoping screen readers are savvy enough to indicate the focus event to the user + if(showPrevNext == 1) { + var elem = document.getElementById(ul.id.search("-tablePaginaterClone") != -1 ? tblId + "-previousPageC" : tblId + "-previousPage"); + } else if(showPrevNext == 2) { + var elem = document.getElementById(ul.id.search("-tablePaginaterClone") != -1 ? tblId + "-nextPageC" : tblId + "-nextPage"); + } else { + var elem = document.getElementById(ul.id.search("-tablePaginaterClone") != -1 ? tblId + "-currentPageC" : tblId + "-currentPage"); + }; + + if(elem && elem.tagName.toLowerCase() == "a") { elem.focus(); }; + + return stopEvent(e); + }; + + var onUnLoad = function(e) { + var tbl, lis, pagination, uls; + for(tblId in tableInfo) { + uls = [tblId + "-tablePaginater", tblId + "-tablePaginaterClone"]; + for(var z = 0; z < 2; z++) { + pagination = document.getElementById(uls[z]); + if(!pagination) { continue; }; + lis = pagination.getElementsByTagName("li"); + for(var i = 0, li; li = lis[i]; i++) { + li.onclick = null; + if(li.getElementsByTagName("a").length) { li.getElementsByTagName("a")[0].onclick = null; }; + }; + }; + }; + }; + + addEvent(window, "load", init); + addEvent(window, "unload", onUnLoad); + + return { + init: function(tableId) { init(tableId); }, + redraw: function(tableid, identical) { tableSortRedraw(tableid, identical); }, + tableIsPaginated: function(tableId) { return (tableId in tableInfo); }, + changeTranslations: function(translations) { text = translations; } + }; +})(); \ No newline at end of file diff --git a/planetlab/tablesort/tablesort.js b/planetlab/tablesort/tablesort.js new file mode 100644 index 0000000..27e8c3c --- /dev/null +++ b/planetlab/tablesort/tablesort.js @@ -0,0 +1,748 @@ +/* + TableSort revisited v5.0 by frequency-decoder.com + + Released under a creative commons Attribution-ShareAlike 2.5 license (http://creativecommons.org/licenses/by-sa/2.5/) + + Please credit frequency decoder in any derivative work - thanks + + You are free: + + * to copy, distribute, display, and perform the work + * to make derivative works + * to make commercial use of the work + + Under the following conditions: + + by Attribution. + -------------- + You must attribute the work in the manner specified by the author or licensor. + + sa + -- + 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. + + * For any reuse or distribution, you must make clear to others the license terms of this work. + * Any of these conditions can be waived if you get permission from the copyright holder. +*/ + +(function() { +fdTableSort = { + regExp_Currency: /^[£$€¥¤]/, + regExp_Number: /^(\-)?[0-9]+(\.[0-9]*)?$/, + pos: -1, + uniqueHash: 1, + thNode: null, + tableId: null, + tableCache: {}, + tmpCache: {}, + sortActiveClass: "sort-active", + /*@cc_on + /*@if (@_win32) + colspan: "colSpan", + rowspan: "rowSpan", + @else @*/ + colspan: "colspan", + rowspan: "rowspan", + /*@end + @*/ + + addEvent: function(obj, type, fn, tmp) { + tmp || (tmp = true); + if( obj.attachEvent ) { + obj["e"+type+fn] = fn; + obj[type+fn] = function(){obj["e"+type+fn]( window.event );}; + obj.attachEvent( "on"+type, obj[type+fn] ); + } else { + obj.addEventListener( type, fn, true ); + }; + }, + removeEvent: function(obj, type, fn, tmp) { + tmp || (tmp = true); + try { + if( obj.detachEvent ) { + obj.detachEvent( "on"+type, obj[type+fn] ); + obj[type+fn] = null; + } else { + obj.removeEventListener( type, fn, true ); + }; + } catch(err) {}; + }, + stopEvent: function(e) { + e = e || window.event; + + if(e.stopPropagation) { + e.stopPropagation(); + e.preventDefault(); + }; + + /*@cc_on@*/ + /*@if(@_win32) + e.cancelBubble = true; + e.returnValue = false; + /*@end@*/ + return false; + }, + parseClassName: function(head, tbl) { + var colMatch = tbl.className.match(new RegExp(head + "((-[\\d]+([r]){0,1})+)")); + return colMatch && colMatch.length ? colMatch[0].replace(head, "").split("-") : []; + }, + disableSelection: function(element) { + element.onselectstart = function() { + return false; + }; + element.unselectable = "on"; + element.style.MozUserSelect = "none"; + }, + removeTableCache: function(tableId) { + if(!(tableId in fdTableSort.tableCache)) return; + + fdTableSort.tableCache[tableId] = null; + delete fdTableSort.tableCache[tableId]; + + var tbl = document.getElementById(tableId); + if(!tbl) return; + var ths = tbl.getElementsByTagName("th"); + var a; + for(var i = 0, th; th = ths[i]; i++) { + a = th.getElementsByTagName("a"); + if(a.length) a[0].onkeydown = a[0].onclick = null; + th.onclick = th.onselectstart = th = a = null; + }; + }, + removeTmpCache: function(tableId) { + if(!(tableId in fdTableSort.tmpCache)) return; + var headers = fdTableSort.tmpCache[tableId].headers; + var a; + for(var i = 0, row; row = headers[i]; i++) { + for(var j = 0, th; th = row[j]; j++) { + a = th.getElementsByTagName("a"); + if(a.length) a[0].onkeydown = a[0].onclick = null; + th.onclick = th.onselectstart = th = a = null; + }; + }; + fdTableSort.tmpCache[tableId] = null; + delete fdTableSort.tmpCache[tableId]; + }, + initEvt: function(e) { + fdTableSort.init(false); + }, + init: function(tableId) { + if (!document.getElementsByTagName || !document.createElement || !document.getElementById) return; + + var tables = tableId && document.getElementById(tableId) ? [document.getElementById(tableId)] : document.getElementsByTagName("table"); + var c, ii, len, colMatch, showOnly, match, showArrow, columnNumSortObj, obj, workArr, headers, thtext, aclone, multi, colCnt, cel, allRowArr, rowArr, sortableTable, celCount, colspan, rowspan, rowLength; + + var a = document.createElement("a"); + a.href = "#"; + a.className = "fdTableSortTrigger"; + + var span = document.createElement("span"); + + for(var k = 0, tbl; tbl = tables[k]; k++) { + + if(tbl.id) { + fdTableSort.removeTableCache(tbl.id); + fdTableSort.removeTmpCache(tbl.id); + }; + + allRowArr = tbl.getElementsByTagName('thead').length ? tbl.getElementsByTagName('thead')[0].getElementsByTagName('tr') : tbl.getElementsByTagName('tr'); + rowArr = []; + sortableTable = false; + + for(var i = 0, tr; tr = allRowArr[i]; i++) { + if(tr.getElementsByTagName('td').length || !tr.getElementsByTagName('th').length) { continue; }; + rowArr[rowArr.length] = tr.getElementsByTagName('th'); + for(var j = 0, th; th = rowArr[rowArr.length - 1][j]; j++) { + if(th.className.search(/sortable/) != -1) { sortableTable = true; }; + }; + }; + + if(!sortableTable) continue; + + if(!tbl.id) { tbl.id = "fd-table-" + fdTableSort.uniqueHash++; }; + + showArrow = tbl.className.search("no-arrow") == -1; + showOnly = tbl.className.search("sortable-onload-show") != -1; + + columnNumSortObj = {}; + colMatch = fdTableSort.parseClassName(showOnly ? "sortable-onload-show" : "sortable-onload", tbl); + for(match = 1; match < colMatch.length; match++) { + columnNumSortObj[parseInt(colMatch[match], 10)] = { "reverse":colMatch[match].search("r") != -1 }; + }; + + rowLength = rowArr[0].length; + + for(c = 0;c < rowArr[0].length;c++){ + if(rowArr[0][c].getAttribute(fdTableSort.colspan) && rowArr[0][c].getAttribute(fdTableSort.colspan) > 1){ + rowLength = rowLength + (rowArr[0][c].getAttribute(fdTableSort.colspan) - 1); + }; + }; + + workArr = new Array(rowArr.length); + for(c = rowArr.length;c--;){ workArr[c]= new Array(rowLength); }; + + for(c = 0;c < workArr.length;c++){ + celCount = 0; + for(i = 0;i < rowLength;i++){ + if(!workArr[c][i]){ + cel = rowArr[c][celCount]; + colspan = (cel.getAttribute(fdTableSort.colspan) > 1) ? cel.getAttribute(fdTableSort.colspan):1; + rowspan = (cel.getAttribute(fdTableSort.rowspan) > 1) ? cel.getAttribute(fdTableSort.rowspan):1; + for(var t = 0;((t < colspan)&&((i+t) < rowLength));t++){ + for(var n = 0;((n < rowspan)&&((c+n) < workArr.length));n++) { + workArr[(c+n)][(i+t)] = cel; + }; + }; + if(++celCount == rowArr[c].length) break; + }; + }; + }; + + for(c = 0;c < workArr.length;c++) { + for(i = 0;i < workArr[c].length;i++){ + + if(workArr[c][i].className.search("fd-column-") == -1 && workArr[c][i].className.search("sortable") != -1) workArr[c][i].className = workArr[c][i].className + " fd-column-" + i; + + if(workArr[c][i].className.match('sortable')) { + workArr[c][i].className = workArr[c][i].className.replace(/forwardSort|reverseSort/, ""); + + if(i in columnNumSortObj) { + columnNumSortObj[i]["thNode"] = workArr[c][i]; + columnNumSortObj["active"] = true; + }; + + thtext = fdTableSort.getInnerText(workArr[c][i], true); + + for(var cn = workArr[c][i].childNodes.length; cn--;) { + // Skip image nodes and links created by the filter script. + if(workArr[c][i].childNodes[cn].nodeType == 1 && (workArr[c][i].childNodes[cn].className == "fdFilterTrigger" || /img/i.test(workArr[c][i].childNodes[cn].nodeName))) { + continue; + }; + if(workArr[c][i].childNodes[cn].nodeType == 1 && /^a$/i.test(workArr[c][i].childNodes[cn].nodeName)) { + workArr[c][i].childNodes[cn].onclick = workArr[c][i].childNodes[cn].onkeydown = null; + }; + workArr[c][i].removeChild(workArr[c][i].childNodes[cn]); + }; + + aclone = a.cloneNode(true); + //aclone.appendChild(document.createTextNode(thtext)); + aclone.innerHTML = thtext; + aclone.title = "Sort on \u201c" + thtext.replace('
', '') + "\u201d"; + aclone.onclick = aclone.onkeydown = workArr[c][i].onclick = fdTableSort.initWrapper; + workArr[c][i].appendChild(aclone); + if(showArrow) workArr[c][i].appendChild(span.cloneNode(false)); + workArr[c][i].className = workArr[c][i].className.replace(/fd-identical|fd-not-identical/, ""); + fdTableSort.disableSelection(workArr[c][i]); + aclone = null; + }; + }; + }; + + fdTableSort.tmpCache[tbl.id] = {cols:rowLength, headers:workArr}; + + workArr = null; + multi = 0; + + if("active" in columnNumSortObj) { + fdTableSort.tableId = tbl.id; + fdTableSort.prepareTableData(document.getElementById(fdTableSort.tableId)); + + delete columnNumSortObj["active"]; + + for(col in columnNumSortObj) { + obj = columnNumSortObj[col]; + if(!("thNode" in obj)) { continue; }; + fdTableSort.multi = true; + + len = obj.reverse ? 2 : 1; + + for(ii = 0; ii < len; ii++) { + fdTableSort.thNode = obj.thNode; + if(!showOnly) { + fdTableSort.initSort(false, true); + } else { + fdTableSort.addThNode(); + }; + }; + + if(showOnly) { + fdTableSort.removeClass(obj.thNode, "(forwardSort|reverseSort)"); + fdTableSort.addClass(obj.thNode, obj.reverse ? "reverseSort" : "forwardSort"); + if(showArrow) { + span = fdTableSort.thNode.getElementsByTagName('span')[0]; + if(span.firstChild) { span.removeChild(span.firstChild); }; + span.appendChild(document.createTextNode(len == 1 ? " \u2193" : " \u2191")); + }; + }; + }; + if(showOnly && (fdTableSort.tableCache[tbl.id].colStyle || fdTableSort.tableCache[tbl.id].rowStyle)) { + fdTableSort.redraw(tbl.id, false); + }; + } else if(tbl.className.search(/onload-zebra/) != -1) { + fdTableSort.tableId = tbl.id; + fdTableSort.prepareTableData(tbl); + if(fdTableSort.tableCache[tbl.id].rowStyle) { fdTableSort.redraw(tbl.id, false); }; + }; + }; + + fdTableSort.thNode = aclone = a = span = columnNumSortObj = thNode = tbl = allRowArr = rowArr = null; + }, + initWrapper: function(e) { + e = e || window.event; + var kc = e.type == "keydown" ? e.keyCode != null ? e.keyCode : e.charCode : -1; + if(fdTableSort.thNode == null && (e.type == "click" || kc == 13)) { + var targ = this; + while(targ.tagName.toLowerCase() != "th") { targ = targ.parentNode; }; + fdTableSort.thNode = targ; + while(targ.tagName.toLowerCase() != "table") { targ = targ.parentNode; }; + fdTableSort.tableId = targ.id; + fdTableSort.multi = e.shiftKey; + fdTableSort.addSortActiveClass(); + setTimeout(fdTableSort.initSort,5,false); + return fdTableSort.stopEvent(e); + }; + return kc != -1 ? true : fdTableSort.stopEvent(e); + }, + jsWrapper: function(tableid, colNums) { + if(!(tableid in fdTableSort.tmpCache)) { return false; }; + if(!(tableid in fdTableSort.tableCache)) { fdTableSort.prepareTableData(document.getElementById(tableid)); }; + if(!(colNums instanceof Array)) { colNums = [colNums]; }; + + fdTableSort.tableId = tableid; + var len = colNums.length, colNum; + + if(fdTableSort.tableCache[tableid].thList.length == colNums.length) { + var identical = true; + var th; + for(var i = 0; i < len; i++) { + colNum = colNums[i]; + th = fdTableSort.tmpCache[tableid].headers[0][colNum]; + if(th != fdTableSort.tableCache[tableid].thList[i]) { + identical = false; + break; + }; + }; + if(identical) { + fdTableSort.thNode = th; + fdTableSort.initSort(true); + return; + }; + }; + + fdTableSort.addSortActiveClass(); + + for(var i = 0; i < len; i++) { + fdTableSort.multi = i; + colNum = colNums[i]; + fdTableSort.thNode = fdTableSort.tmpCache[tableid].headers[0][colNum]; + fdTableSort.initSort(true); + }; + }, + addSortActiveClass: function() { + if(fdTableSort.thNode == null) { return; }; + fdTableSort.addClass(fdTableSort.thNode, fdTableSort.sortActiveClass); + fdTableSort.addClass(document.getElementsByTagName('body')[0], fdTableSort.sortActiveClass); + }, + removeSortActiveClass: function() { + if(fdTableSort.thNode == null) return; + fdTableSort.removeClass(fdTableSort.thNode, fdTableSort.sortActiveClass); + fdTableSort.removeClass(document.getElementsByTagName('body')[0], fdTableSort.sortActiveClass); + }, + doCallback: function(init) { + if(!fdTableSort.tableId || !(fdTableSort.tableId in fdTableSort.tableCache)) { return; }; + fdTableSort.callback(fdTableSort.tableId, init ? fdTableSort.tableCache[fdTableSort.tableId].initiatedCallback : fdTableSort.tableCache[fdTableSort.tableId].completeCallback); + }, + addClass: function(e,c) { + if(new RegExp("(^|\\s)" + c + "(\\s|$)").test(e.className)) { return; }; + e.className += ( e.className ? " " : "" ) + c; + }, + /*@cc_on + /*@if (@_win32) + removeClass: function(e,c) { + e.className = !c ? "" : e.className.replace(new RegExp("(^|\\s)" + c + "(\\s|$)"), " ").replace(/^\s*((?:[\S\s]*\S)?)\s*$/, '$1'); + }, + @else @*/ + removeClass: function(e,c) { + e.className = !c ? "" : e.className.replace(new RegExp("(^|\\s)" + c + "(\\s|$)"), " ").replace(/^\s\s*/, '').replace(/\s\s*$/, ''); + }, + /*@end + @*/ + callback: function(tblId, cb) { + var func, parts; + try { + if(cb.indexOf(".") != -1) { + parts = cb.split('.'); + obj = window; + for (var x = 0, part; part = obj[parts[x]]; x++) { + if(part instanceof Function) { + (function() { + var method = part; + func = function (data) { method.apply(obj, [data]) }; + })(); + } else { + obj = part; + }; + }; + } else if(cb + tblId in window) { + func = window[cb + tblId]; + } else if(cb in window) { + func = window[cb]; + } else { + func = null; + }; + } catch(err) {}; + + if(!(func instanceof Function)) return; + func(tblId, fdTableSort.tableCache[tblId].thList); + }, + prepareTableData: function(table) { + var data = []; + + var start = table.getElementsByTagName('tbody'); + start = start.length ? start[0] : table; + + var trs = start.rows; + var ths = table.getElementsByTagName('th'); + + var numberOfRows = trs.length; + var numberOfCols = fdTableSort.tmpCache[table.id].cols; + + var data = []; + var identical = new Array(numberOfCols); + var identVal = new Array(numberOfCols); + + for(var tmp = 0; tmp < numberOfCols; tmp++) identical[tmp] = true; + + var tr, td, th, txt, tds, col, row; + + var re = new RegExp(/fd-column-([0-9]+)/); + var rowCnt = 0; + + var sortableColumnNumbers = []; + + for(var tmp = 0, th; th = ths[tmp]; tmp++) { + if(th.className.search(re) == -1) continue; + sortableColumnNumbers[sortableColumnNumbers.length] = th; + }; + + for(row = 0; row < numberOfRows; row++) { + + tr = trs[row]; + if(tr.parentNode != start || tr.getElementsByTagName("th").length || (tr.parentNode && tr.parentNode.tagName.toLowerCase().search(/thead|tfoot/) != -1)) continue; + data[rowCnt] = []; + tds = tr.cells; + + for(var tmp = 0, th; th = sortableColumnNumbers[tmp]; tmp++) { + col = th.className.match(re)[1]; + + td = tds[col]; + txt = fdTableSort.getInnerText(td) + " "; + txt = txt.replace(/^\s+/,'').replace(/\s+$/,''); + + if(th.className.search(/sortable-date/) != -1) { + txt = fdTableSort.dateFormat(txt, th.className.search(/sortable-date-dmy/) != -1); + } else if(th.className.search(/sortable-numeric|sortable-currency/) != -1) { + txt = parseFloat(txt.replace(/[^0-9\.\-]/g,'')); + if(isNaN(txt)) txt = ""; + } else if(th.className.search(/sortable-text/) != -1) { + txt = txt.toLowerCase(); + } else if (th.className.search(/sortable-keep/) != -1) { + txt = rowCnt; + } else if(th.className.search(/sortable-([a-zA-Z\_]+)/) != -1) { + if((th.className.match(/sortable-([a-zA-Z\_]+)/)[1] + "PrepareData") in window) { + txt = window[th.className.match(/sortable-([a-zA-Z\_]+)/)[1] + "PrepareData"](td, txt); + }; + } else if(txt != "") { + fdTableSort.removeClass(th, "sortable"); + if(fdTableSort.dateFormat(txt) != 0) { + fdTableSort.addClass(th, "sortable-date"); + txt = fdTableSort.dateFormat(txt); + } else if(txt.search(fdTableSort.regExp_Number) != -1 || txt.search(fdTableSort.regExp_Currency) != -1) { + fdTableSort.addClass(th, "sortable-numeric"); + txt = parseFloat(txt.replace(/[^0-9\.\-]/g,'')); + if(isNaN(txt)) txt = ""; + } else { + fdTableSort.addClass(th, "sortable-text"); + txt = txt.toLowerCase(); + }; + }; + + if(rowCnt > 0 && identical[col] && identVal[col] != txt) { identical[col] = false; }; + + identVal[col] = txt; + data[rowCnt][col] = txt; + }; + data[rowCnt][numberOfCols] = tr; + rowCnt++; + }; + + var colStyle = table.className.search(/colstyle-([\S]+)/) != -1 ? table.className.match(/colstyle-([\S]+)/)[1] : false; + var rowStyle = table.className.search(/rowstyle-([\S]+)/) != -1 ? table.className.match(/rowstyle-([\S]+)/)[1] : false; + var iCBack = table.className.search(/sortinitiatedcallback-([\S-]+)/) == -1 ? "sortInitiatedCallback" : table.className.match(/sortinitiatedcallback-([\S]+)/)[1]; + var cCBack = table.className.search(/sortcompletecallback-([\S-]+)/) == -1 ? "sortCompleteCallback" : table.className.match(/sortcompletecallback-([\S]+)/)[1]; + iCBack = iCBack.replace("-", "."); + cCBack = cCBack.replace("-", "."); + fdTableSort.tableCache[table.id] = { hook:start, initiatedCallback:iCBack, completeCallback:cCBack, thList:[], colOrder:{}, data:data, identical:identical, colStyle:colStyle, rowStyle:rowStyle, noArrow:table.className.search(/no-arrow/) != -1 }; + sortableColumnNumbers = data = tr = td = th = trs = identical = identVal = null; + }, + onUnload: function() { + for(tbl in fdTableSort.tableCache) { fdTableSort.removeTableCache(tbl); }; + for(tbl in fdTableSort.tmpCache) { fdTableSort.removeTmpCache(tbl); }; + fdTableSort.removeEvent(window, "load", fdTableSort.initEvt); + fdTableSort.removeEvent(window, "unload", fdTableSort.onUnload); + fdTableSort.tmpCache = fdTableSort.tableCache = null; + }, + addThNode: function() { + var dataObj = fdTableSort.tableCache[fdTableSort.tableId]; + var pos = fdTableSort.thNode.className.match(/fd-column-([0-9]+)/)[1]; + var alt = false; + + if(!fdTableSort.multi) { + if(dataObj.colStyle) { + var len = dataObj.thList.length; + for(var i = 0; i < len; i++) { + dataObj.colOrder[dataObj.thList[i].className.match(/fd-column-([0-9]+)/)[1]] = false; + }; + }; + if(dataObj.thList.length && dataObj.thList[0] == fdTableSort.thNode) alt = true; + dataObj.thList = []; + }; + + var found = false; + var l = dataObj.thList.length; + + for(var i = 0, n; n = dataObj.thList[i]; i++) { + if(n == fdTableSort.thNode) { + found = true; + break; + }; + }; + + if(!found) { + dataObj.thList.push(fdTableSort.thNode); + if(dataObj.colStyle) { dataObj.colOrder[pos] = true; }; + }; + + var ths = document.getElementById(fdTableSort.tableId).getElementsByTagName("th"); + for(var i = 0, th; th = ths[i]; i++) { + found = false; + for(var z = 0, n; n = dataObj.thList[z]; z++) { + if(n == th) { + found = true; + break; + }; + }; + if(!found) { + fdTableSort.removeClass(th, "(forwardSort|reverseSort)"); + if(!dataObj.noArrow) { + span = th.getElementsByTagName('span'); + if(span.length) { + span = span[0]; + while(span.firstChild) span.removeChild(span.firstChild); + }; + }; + }; + }; + + if(dataObj.thList.length > 1) { + classToAdd = fdTableSort.thNode.className.search(/forwardSort/) != -1 ? "reverseSort" : "forwardSort"; + fdTableSort.removeClass(fdTableSort.thNode, "(forwardSort|reverseSort)"); + fdTableSort.addClass(fdTableSort.thNode, classToAdd); + dataObj.pos = -1 + } else if(alt) { dataObj.pos = fdTableSort.thNode }; + }, + initSort: function(noCallback, ident) { + var thNode = fdTableSort.thNode; + var tableElem = document.getElementById(fdTableSort.tableId); + + if(!(fdTableSort.tableId in fdTableSort.tableCache)) { fdTableSort.prepareTableData(document.getElementById(fdTableSort.tableId)); }; + + fdTableSort.addThNode(); + + if(!noCallback) { fdTableSort.doCallback(true); }; + + fdTableSort.pos = thNode.className.match(/fd-column-([0-9]+)/)[1]; + var dataObj = fdTableSort.tableCache[tableElem.id]; + var lastPos = dataObj.pos && dataObj.pos.className ? dataObj.pos.className.match(/fd-column-([0-9]+)/)[1] : -1; + var len1 = dataObj.data.length; + var len2 = dataObj.data.length > 0 ? dataObj.data[0].length - 1 : 0; + var identical = dataObj.identical[fdTableSort.pos]; + var classToAdd = "forwardSort"; + + if(dataObj.thList.length > 1) { + var js = "var sortWrapper = function(a,b) {\n"; + var l = dataObj.thList.length; + var cnt = 0; + var e,d,th,p,f; + + for(var i=0; i < l; i++) { + th = dataObj.thList[i]; + p = th.className.match(/fd-column-([0-9]+)/)[1]; + if(dataObj.identical[p]) { continue; }; + cnt++; + + if(th.className.match(/sortable-(numeric|currency|date|keep)/)) { + f = "fdTableSort.sortNumeric"; + } else if(th.className.match('sortable-text')) { + f = "fdTableSort.sortText"; + } else if(th.className.search(/sortable-([a-zA-Z\_]+)/) != -1 && th.className.match(/sortable-([a-zA-Z\_]+)/)[1] in window) { + f = "window['" + th.className.match(/sortable-([a-zA-Z\_]+)/)[1] + "']"; + } else f = "fdTableSort.sortText"; + + e = "e" + i; + d = th.className.search('forwardSort') != -1 ? "a,b" : "b,a"; + js += "fdTableSort.pos = " + p + ";\n"; + js += "var " + e + " = "+f+"(" + d +");\n"; + js += "if(" + e + ") return " + e + ";\n"; + js += "else { \n"; + }; + + js += "return 0;\n"; + + for(var i=0; i < cnt; i++) { + js += "};\n"; + }; + + if(cnt) js += "return 0;\n"; + js += "};\n"; + + eval(js); + dataObj.data.sort(sortWrapper); + identical = false; + } else if((lastPos == fdTableSort.pos && !identical) || (thNode.className.search(/sortable-keep/) != -1 && lastPos == -1)) { + dataObj.data.reverse(); + classToAdd = thNode.className.search(/reverseSort/) != -1 ? "forwardSort" : "reverseSort"; + if(thNode.className.search(/sortable-keep/) != -1 && lastPos == -1) fdTableSort.tableCache[tableElem.id].pos = thNode; + } else { + fdTableSort.tableCache[tableElem.id].pos = thNode; + classToAdd = thNode.className.search(/forwardSort/) != -1 ? "reverseSort" : "forwardSort"; + if(!identical) { + if(thNode.className.match(/sortable-(numeric|currency|date|keep)/)) { + dataObj.data.sort(fdTableSort.sortNumeric); + } else if(thNode.className.match('sortable-text')) { + dataObj.data.sort(fdTableSort.sortText); + } else if(thNode.className.search(/sortable-([a-zA-Z\_]+)/) != -1 && thNode.className.match(/sortable-([a-zA-Z\_]+)/)[1] in window) { + dataObj.data.sort(window[thNode.className.match(/sortable-([a-zA-Z\_]+)/)[1]]); + }; + + if(thNode.className.search(/(^|\s)favour-reverse($|\s)/) != -1) { + classToAdd = classToAdd == "forwardSort" ? "reverseSort" : "forwardSort"; + dataObj.data.reverse(); + }; + }; + }; + if(ident) { identical = false; }; + if(dataObj.thList.length == 1) { + fdTableSort.removeClass(thNode, "(forwardSort|reverseSort)"); + fdTableSort.addClass(thNode, classToAdd); + }; + if(!dataObj.noArrow) { + var span = fdTableSort.thNode.getElementsByTagName('span')[0]; + if(span.firstChild) span.removeChild(span.firstChild); + span.appendChild(document.createTextNode(fdTableSort.thNode.className.search(/forwardSort/) != -1 ? " \u2193" : " \u2191")); + }; + if(!dataObj.rowStyle && !dataObj.colStyle && identical) { + fdTableSort.removeSortActiveClass(); + if(!noCallback) { fdTableSort.doCallback(false); }; + fdTableSort.thNode = null; + return; + }; + if("tablePaginater" in window && tablePaginater.tableIsPaginated(fdTableSort.tableId)) { + tablePaginater.redraw(fdTableSort.tableId, identical); + } else { + fdTableSort.redraw(fdTableSort.tableId, identical); + }; + fdTableSort.removeSortActiveClass(); + if(!noCallback) { fdTableSort.doCallback(false); }; + fdTableSort.thNode = null; + }, + redraw: function(tableid, identical) { + if(!tableid || !(tableid in fdTableSort.tableCache)) { return; }; + var dataObj = fdTableSort.tableCache[tableid]; + var data = dataObj.data; + var len1 = data.length; + var len2 = len1 ? data[0].length - 1 : 0; + var hook = dataObj.hook; + var colStyle = dataObj.colStyle; + var rowStyle = dataObj.rowStyle; + var colOrder = dataObj.colOrder; + var highLight = 0; + var reg = /(^|\s)invisibleRow(\s|$)/; + var tr, tds; + + for(var i = 0; i < len1; i++) { + tr = data[i][len2]; + if(colStyle) { + tds = tr.cells; + for(thPos in colOrder) { + if(!colOrder[thPos]) fdTableSort.removeClass(tds[thPos], colStyle); + else fdTableSort.addClass(tds[thPos], colStyle); + }; + }; + if(!identical) { + if(rowStyle && tr.className.search(reg) == -1) { + if(highLight++ & 1) fdTableSort.addClass(tr, rowStyle); + else fdTableSort.removeClass(tr, rowStyle); + }; + + // Netscape 8.1.2 requires the removeChild call or it freaks out, so add the line if you want to support this browser + // hook.removeChild(tr); + hook.appendChild(tr); + }; + }; + tr = tds = hook = null; + }, + getInnerText: function(el, allowBrTags) { + if (typeof el == "string" || typeof el == "undefined") return el; + if(el.innerText) return el.innerText; + var txt = '', i; + for(i = el.firstChild; i; i = i.nextSibling) { + if(allowBrTags && i.nodeName && i.nodeName == "BR") txt += "
"; + else if(i.nodeType == 3) txt += i.nodeValue; + else if(i.nodeType == 1) txt += fdTableSort.getInnerText(i); + }; + return txt; + }, + dateFormat: function(dateIn, favourDMY) { + var dateTest = [ + { 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 + { 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 + { 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 + ]; + var start, cnt = 0, numFormats = dateTest.length; + while(cnt < numFormats) { + start = (cnt + (favourDMY ? numFormats + 1 : numFormats)) % numFormats; + if(dateIn.match(dateTest[start].regExp)) { + res = dateIn.match(dateTest[start].regExp); + y = res[dateTest[start].y]; + m = res[dateTest[start].m]; + d = res[dateTest[start].d]; + if(m.length == 1) m = "0" + String(m); + if(d.length == 1) d = "0" + String(d); + if(y.length != 4) y = (parseInt(y) < 50) ? "20" + String(y) : "19" + String(y); + + return y+String(m)+d; + }; + cnt++; + }; + return 0; + }, + sortNumeric:function(a,b) { + var aa = a[fdTableSort.pos]; + var bb = b[fdTableSort.pos]; + if(aa == bb) return 0; + if(aa === "" && !isNaN(bb)) return -1; + if(bb === "" && !isNaN(aa)) return 1; + return aa - bb; + }, + sortText:function(a,b) { + var aa = a[fdTableSort.pos]; + var bb = b[fdTableSort.pos]; + if(aa == bb) return 0; + if(aa < bb) return -1; + return 1; + } +}; +})(); +fdTableSort.addEvent(window, "load", fdTableSort.initEvt); +fdTableSort.addEvent(window, "unload", fdTableSort.onUnload); -- 2.43.0