r4069 new feature: UI: live switchport info (port config, link status, learned mac...
authorAlexey Andriyanov <alan@al-an.info>
Sat, 25 Dec 2010 22:07:25 +0000 (22:07 +0000)
committerAlexey Andriyanov <alan@al-an.info>
Sat, 25 Dec 2010 22:07:25 +0000 (22:07 +0000)
update: selective including of JS and CSS files. No more unneeded js code loaded.

gateways/deviceconfig/nxos4.connector: added two more commands: getportstatus and getmaclist
gateways/deviceconfig/ios12.connector: idem
gateways/deviceconfig/vrp53.connector: idem
gateways/deviceconfig/vrp55.connector: idem

pi.css: moved into css/ dir, removed duplicated body attributes, many new styles added for popup interface
added jquery.contextmenu plugin: css/jquery.contextmenu.css and js/jquery.contextmenu.js files
index.php: buffering of output added to call printPageHeaders after page generation for adding nesessary JS/CSS into page header
added new pix: ajax-loader.gif, checkbox_yes.png, link-disabled.png, link-up.png, link-down.png, 1x1t.gif (transparent pixel)
inc/navigation.php: new object tab 'Live ports' added

inc/interface.php: changed mainly for reacting to js/css include policy change
 renderRack: add autogenerated css styles for rack atoms on-demand (addAtomCSS call), added common class atom to TDs
 renderMolecule: idem
 renderAtomGrid: idem
 renderGridForm: include js libs on-demand (function renders some JS code)
 renderRackSpaceForObject: idem
 renderLivePTR: idem
 renderCellFilterPortlet: idem
 renderTextEditor: idem
 renderRackObject: prepare portlist to add popup menu if needed, include js libs on-demand (function renders some JS code)
 renderPortsForObject: idem
 renderObject8021QPorts: idem
 renderDiscoveredNeighbors: idem
 renderObject8021QSync: idem, also preventive init port config popups (cause we already have info from switch)
 renderPortsInfo: new function, renders new 'Live ports' tab
 renderIPv4SpaceRecords: reflect renaming of getAutoScrollScript
 renderIPv6SpaceRecords: idem
 RenderIPv4Network: idem
 RenderIPv6Network: idem
 renderIPv4SpaceEditor: JS prefix syntax validator reformatted to reflect new JS include policy
 renderIPv6SpaceEditor: idem
 renderRackCodeEditor: JS reformatted reformatted to reflect new JS include policy
 formatPortLink: ability to pass <a>-class
 getAutoScrollScript: renamed to addAutoScrollScript, cause it does no renders anything now, only adds link to JS file
 switchportInfoJS: new function checking permissions and other requirements for portinfo popup menu, and including nesessary JS/CSS
 addAtomCSS: new function to generate rackatom css runtime based on config variable (legacy feature, BTW)

inc/init.php: $pageheaders cleaned up from JS and CSS, now they are included on-demand
inc/functions.php:
 ios12ShortenIfName: VRP formats iface names in short manner (GE, XGE) in some pages, concerning it
 printPageHeaders: adding links to remembered during page rendering JS/CSS files or inline blocks
 getColumnCoordinates: new util function (used in ios12 int status gw) to parse fixed-column-length-formatted tables
 addJS: new function to include JS files/block on demand
 addCSS: idem
 isEthernetPort: new function to check if popup menu is appiable for the specified port

inc/ajax-interface.php: new file like interface.php, but small enough to be included in ajax.php instead of huge interface.php
 formatPortLinkHints: prepares HTML code for inline and popup parts of popup interface
 formatPortMacHints: idem
 formatPortConfigHints: idem

inc/gateways.php: ability to fetch mac list, link status and port configs from ios12, vrp, nxos.
 ios12ScanTopLevel: 802.1q config parsing functions now saving every seen line to ['config'] subkey (for port config fetching)
 ios12PickSwitchportCommand: idem
 vrp53ScanTopLevel: idem
 vrp53PickInterfaceSubcommand: idem
 vrp55Read8021QConfig: idem
 nxos4ScanTopLevel: idem
 nxos4PickSwitchportCommand: idem
 ciscoReadInterfaceStatus: function for parsing 'show int status' IOS and NXOS command output
 vrpReadInterfaceStatus: idem for VRP 5.3/5.5
 maclist_sort: function for sorting mac list by VLAN id
 ios12ReadMacList: function for parsing 'show mac address-table dynamic' IOS command output
 nxos4ReadMacList: idem for NXOS
 vrp53ReadMacList: idem for VRP 5.3
 vrp55ReadMacList: idem for VRP 5.5/5.7

inc/triggers.php: new trigger for 'Live ports' tab
ajax.php: 3 new ops for port info data queries. Calling functions from ajax-interface.php and encoding their output in JSON
js/jquery.thumbhover.js: JS library to show stickable popups on hover. Rewritten by me from unknown source

js/jquery.contextmenu.js, css/jquery.contextmenu.css: third-party library for displaying popup menus

js/racktables.js: new util function to parse query string and extract GET param value from it
js/jquery-1.3.1.min.js was replaced by the new version: js/jquery-1.4.4.min.js
js/portinfo.js: JS code implementing popup switchport info logic

Hooray!!!

29 files changed:
ChangeLog
README
ajax.php
css/jquery.contextmenu.css [new file with mode: 0644]
css/pi.css [moved from pi.css with 83% similarity]
gateways/deviceconfig/ios12.connector
gateways/deviceconfig/nxos4.connector
gateways/deviceconfig/vrp53.connector
gateways/deviceconfig/vrp55.connector
inc/ajax-interface.php [new file with mode: 0644]
inc/functions.php
inc/gateways.php
inc/init.php
inc/interface.php
inc/navigation.php
inc/triggers.php
index.php
js/jquery-1.3.1.min.js [deleted file]
js/jquery-1.4.4.min.js [new file with mode: 0644]
js/jquery.contextmenu.js [new file with mode: 0644]
js/jquery.thumbhover.js [new file with mode: 0644]
js/portinfo.js [new file with mode: 0644]
js/racktables.js
pix/1x1t.gif [new file with mode: 0644]
pix/ajax-loader.gif [new file with mode: 0644]
pix/checkbox_yes.png [new file with mode: 0644]
pix/link-disabled.png [new file with mode: 0644]
pix/link-down.png [new file with mode: 0644]
pix/link-up.png [new file with mode: 0644]

index 3875416..2b507ae 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -16,6 +16,8 @@
        update: custom rearch results provided by users' plugins now supported
        new feature: syncdomain.php now can create child processes to speed up 802.1Q sync
        update: Huawei VRP 5.70 pseudo-interactive telnet support (fixes multiple problems caused by fast commands post through netcat)
+       new feature: UI: live switchport info (port config, link status, learned mac list) showed inline on any object tab
+       update: selective including of JS and CSS files. No more unneeded js code loaded.
 0.18.7
        bugfix: adjust 802.1Q command generation
        bugfix: fixed telnet session hanging in NX-OS4 connector
diff --git a/README b/README
index aae9fc0..128c122 100644 (file)
--- a/README
+++ b/README
@@ -103,6 +103,11 @@ should be sufficient:
 This release utilizes database triggers, which are only available in
 MySQL >= 5.0.2.
 
+RackTables is now using PHP JSON extension which is included in the PHP core since 5.2.0.
+Installation process does not check for this extension because the lack of it does not affect
+base functionality. If some of ajax features are not working correctly, check if JSON extension
+is availible in your installation of PHP.
+
 *** Upgrading to 0.18.x ***
 
 RackTables from its version 0.18.0 and later is not compatible with
index edd147a..e90af04 100644 (file)
--- a/ajax.php
+++ b/ajax.php
@@ -3,6 +3,7 @@ ob_start();
 try {
 
 require 'inc/init.php';
+require_once 'inc/ajax-interface.php';
 assertStringArg ('ac');
 
 switch ($_REQUEST['ac'])
@@ -23,6 +24,33 @@ case 'verifyCode':
        else
                echo "NAK\n" . $result['load'];
        break;
+       case 'get-port-link': // returns JSON-encoded text
+               assertUIntArg ('object_id');
+               $object = spotEntity ('object', $_REQUEST['object_id']);
+               fixContext ($object);
+               if (! permitted ('object', 'liveports', 'get_link_status'))
+                       throw new RacktablesError ('Permission denied: $op_get_link_status check failed');
+               $data = formatPortLinkHints ($_REQUEST['object_id']);
+               echo json_encode ($data);
+       break;
+       case 'get-port-mac': // returns JSON-encoded text
+               assertUIntArg ('object_id');
+               $object = spotEntity ('object', $_REQUEST['object_id']);
+               fixContext ($object);
+               if (! permitted ('object', 'liveports', 'get_mac_list'))
+                       throw new RacktablesError ('Permission denied: $op_get_mac_list check failed');
+               $data = formatPortMacHints ($_REQUEST['object_id']);
+               echo json_encode ($data);
+       break;
+       case 'get-port-conf': // returns JSON-encoded text
+               assertUIntArg ('object_id');
+               $object = spotEntity ('object', $_REQUEST['object_id']);
+               fixContext ($object);
+               if (! permitted ('object', 'liveports', 'get_port_conf'))
+                       throw new RacktablesError ('Permission denied: $op_get_port_conf check failed');
+               $data = formatPortConfigHints ($_REQUEST['object_id']);
+               echo json_encode ($data);
+       break;
 default:
        throw new InvalidRequestArgException ('ac', $_REQUEST['ac']);
 }
@@ -36,7 +64,7 @@ catch (InvalidRequestArgException $e)
 catch (Exception $e)
 {
        ob_end_clean();
-       echo "NAK\nRuntime exception";
+       echo "NAK\nRuntime exception: ". $e->getMessage();
 }
 
 ?>
diff --git a/css/jquery.contextmenu.css b/css/jquery.contextmenu.css
new file mode 100644 (file)
index 0000000..25c9709
--- /dev/null
@@ -0,0 +1,242 @@
+/* Classic Windows Theme (default) */
+/* =============================== */
+.context-menu-theme-default {
+       border:2px outset white;
+       background-color:#D4D0C8;
+}
+.context-menu-theme-default .context-menu-item {
+       text-align:left;
+       cursor:pointer;
+       padding:4px 28px 4px 16px;
+       color:black;
+       font-family:Tahoma,Arial;
+       font-size:11px;
+}
+.context-menu-theme-default .context-menu-separator {
+       margin:4px 2px;
+       font-size:0px;
+       border-top:1px solid #808080;
+       border-bottom:1px solid white;
+}
+.context-menu-theme-default .context-menu-item-disabled {
+       color:#808080;
+}
+.context-menu-theme-default .context-menu-item .context-menu-item-inner {
+       background:none no-repeat fixed 999px 999px; /* Make sure icons don't appear */
+}
+.context-menu-theme-default .context-menu-item-hover {
+       background-color:#0A246A;
+       color:white;
+}
+.context-menu-theme-default .context-menu-item-disabled-hover {
+       background-color:#0A246A;
+}
+
+/* Windows XP Theme */
+/* ================ */
+.context-menu-theme-xp {
+       border:1px solid #666;
+       padding:1px;
+       background:#F9F8F7 url(cmenu-xp-bg.gif) repeat-y top left;
+}
+.context-menu-theme-xp .context-menu-separator {
+       margin:4px 2px;
+       font-size:0px;
+       border-top:1px solid #808080;
+       border-bottom:1px solid white;
+}
+.context-menu-theme-xp .context-menu-item {
+       text-align:left;
+       color:black;
+       font-family:arial;
+       font-size:11px;
+       cursor:pointer;
+}
+.context-menu-theme-xp .context-menu-item .context-menu-item-inner {
+       background:none no-repeat 2px center;
+       padding:4px 10px 4px 30px;
+}
+.context-menu-theme-xp .context-menu-item-hover .context-menu-item-inner {
+       background:#B6BDD2 none no-repeat 2px center;
+       padding:3px 9px 3px 29px;
+       border:1px solid #0A246A;
+}
+
+/* Windows Vista Theme */
+/* =================== */
+.context-menu-theme-vista {
+       background:#FAFAFA url(cmenu-vista-bg.gif) repeat-y left top;
+       border:1px solid #868686;
+}
+.context-menu-theme-vista .context-menu-item {
+       text-align:left;
+       cursor:pointer;
+       color:black;
+       font-family:Tahoma,Arial;
+       font-size:11px;
+}
+.context-menu-theme-vista .context-menu-separator {
+       margin:0px 0px 0px 32px;
+       font-size:0px;
+       border-top:1px solid #C5C5C5;
+       border-bottom:1px solid #F5F5F5;
+}
+.context-menu-theme-vista .context-menu-item-hover {
+       background:transparent url(cmenu-vista-menu-item-hover.gif) repeat-x left center;
+       border:1px solid #D7D0B3;
+}
+.context-menu-theme-vista .context-menu-item .context-menu-item-inner {
+       padding:4px 16px 4px 35px;
+       margin-left:1px;
+       background-color:none;
+       background-repeat:no-repeat;
+       background-position:3px center;
+       background-image:none;
+}
+.context-menu-theme-vista .context-menu-item-hover .context-menu-item-inner {
+       padding:3px 15px 3px 35px;
+       margin-left:0px;
+}
+.context-menu-theme-vista .context-menu-item-disabled {
+       color:#A7A7A7;
+}
+
+/* OSX Theme */
+/* ========= */
+.context-menu-theme-osx {
+       background-color:white;
+       opacity: .93;
+       filter: alpha(opacity=93);
+       zoom:1.0;
+       border:1px solid #b2b2b2;
+}
+.context-menu-theme-osx .context-menu-item {
+       text-align:left;
+       cursor:pointer;
+       color:black;
+       font-family:Lucida Grande,Arial;
+       font-weight:700;
+       font-size:12px;
+       opacity: 1.0;
+       filter: alpha(opacity=100);
+       z-index:1;
+}
+.context-menu-theme-osx .context-menu-separator {
+       margin:5px 1px 4px 1px;
+       font-size:0px;
+       border-top:1px solid #e4e4e4;
+}
+.context-menu-theme-osx .context-menu-item-hover {
+       background-color:#1C44F2;
+       color:white;
+}
+.context-menu-theme-osx .context-menu-item .context-menu-item-inner {
+       padding:2px 10px 2px 22px;
+       background-color:none;
+       background-repeat:no-repeat;
+       background-position:4px center;
+       background-image:none;
+}
+.context-menu-theme-osx .context-menu-item-disabled {
+       color:#939393;
+}
+
+/* Linux Human Theme */
+/* ================= */
+.context-menu-theme-human {
+       background:#F9F5F2;
+       border:1px solid #963;
+}
+.context-menu-theme-human .context-menu-item {
+       text-align:left;
+       cursor:pointer;
+       color:black;
+       font-family:Helvetica,DejaVu Sans,Arial;
+       font-size:12px;
+       line-height:20px;
+       height:28px;
+       border:1px solid #F9F5F2;
+       border-left:0;
+       border-right:0;
+}
+.context-menu-theme-human .context-menu-separator {
+       margin:0px 0px 0px 32px;
+       font-size:0px;
+       border-top:1px solid #C5C5C5;
+       border-bottom:1px solid #F5F5F5;
+}
+.context-menu-theme-human .context-menu-item-hover {
+       background:transparent url(cmenu-human-menu-item-hover.gif) repeat-x left center;
+       border-color:#963;
+}
+.context-menu-theme-human .context-menu-item .context-menu-item-inner {
+       padding:4px 16px 4px 35px;
+       margin-left:0px;
+       background-color:none;
+       background-repeat:no-repeat;
+       background-position:3px center;
+       background-image:none;
+}
+.context-menu-theme-human .context-menu-item-hover .context-menu-item-inner {
+}
+.context-menu-theme-human .context-menu-item-disabled {
+       color:#A7A7A7;
+}
+
+/* Gloss Theme */
+/* =========== */
+.context-menu-theme-gloss {
+       background:#f4f4f4 url(cmenu-gloss-bg.gif) repeat-y left center;
+       border:1px solid #f4f4f4;
+       padding:1px;
+       padding-right:0;
+}
+.context-menu-theme-gloss .context-menu-item {
+       text-align:left;
+       cursor:pointer;
+       color:black;
+       font-family:Helvetica,DejaVu Sans,Arial;
+       font-size:12px;
+       line-height:20px;
+       height:27px;
+       border:1px solid transparent;
+}
+.context-menu-theme-gloss .context-menu-separator {
+       margin:0px 0px 0px 32px;
+       font-size:0px;
+       border-top:1px solid #C5C5C5;
+       border-bottom:1px solid #F5F5F5;
+}
+.context-menu-theme-gloss .context-menu-item-hover {
+       background:transparent url(cmenu-gloss-menu-item-hover.gif) repeat-x left center;
+       color:#fff;
+       border-color:#000;
+       border-radius: 3px;
+       -webkit-border-radius: 3px;
+       -moz-border-radius: 3px;
+}
+.context-menu-theme-gloss .context-menu-item .context-menu-item-inner {
+       padding:4px 16px 4px 35px;
+       margin-left:0px;
+       background-color:none;
+       background-repeat:no-repeat;
+       background-position:3px center;
+       background-image:none;
+}
+.context-menu-theme-gloss .context-menu-item-hover .context-menu-item-inner {
+}
+.context-menu-theme-gloss .context-menu-item-disabled {
+       color:#A7A7A7;
+}
+
+.context-menu-theme-gloss-cyan .context-menu-item-hover {
+       background-image:url(cmenu-gloss-cyan-menu-item-hover.gif);
+       border-color:#00c;
+}
+
+.context-menu-theme-gloss-semitransparent .context-menu-item-hover {
+       background-image:url(cmenu-item-gloss-semitransparent-menu-item-hover.png);
+       border-color:#00c;
+       background-color:#30f;
+}
+
similarity index 83%
rename from pi.css
rename to css/pi.css
index aea3b4f..e9b5dc8 100644 (file)
--- a/pi.css
@@ -208,8 +208,6 @@ body {
   margin: 0px;
   background-attachment : fixed;
   background-color : #FCFCFC;
-  font-family: Arial, Sans-Serif, sans-serif;
-  font-size : small;
 }
 /* collapse space between headings, and where paragraph follows heading */
 hr {
@@ -544,3 +542,85 @@ a.toggleTreeMode {
 .border_highlight {
        border: solid 4px lime !important;
 }
+
+/*this style is used for <a>s which does not contain href (ancors), to make them look like plain text*/
+.nolink {
+       text-decoration: none;
+       color: black;
+       font-family: Arial,Sans-Serif,sans-serif;
+       font-size: small;
+}
+.nolink:hover {
+       text-decoration: none;
+}
+
+/*this class controls popup switch info. It should be on the element which contains portname in plain text*/
+.interactive-portname {
+       cursor: default;
+}
+
+/*item to the left of portname (link indicator)*/
+.port-link {
+       margin-right: 10px;
+}
+
+/*item to the right of portname (mac count)*/
+.mac-count {
+       display: inline;
+       margin-left: 3px;
+       font-size: 80%;
+}
+
+/*general class for popup div*/
+.popup-box {
+       display: none;
+       border: 1px solid #000000;
+       background: #FFFFFF;
+       padding: 0px 5px;
+}
+
+/*popup div with MAC list*/
+.mac-list {
+       font-family: monospace;
+       overflow: auto;
+       max-height: 200px;
+       min-width: 200px;
+}
+
+/*popup div with port configuration lines*/
+.port-config {
+       display: none;
+       border: 1px solid #000000;
+       background-color: #FFFFFF;
+       padding: 5px;
+       font-family: monospace;
+}
+
+/*header line in port conf popup div*/
+.port-config .line-header {
+       font-weight: bold;
+       font-size: 105%;
+}
+
+/*8021q line in port conf popup div*/
+.port-config .line-8021q {
+       color: #9b9b9b
+}
+
+/*other lines in port conf popup div*/
+.port-config .line-other {
+       color: #f52328
+}
+
+/*link to popup menu (...) showed on td hover*/
+.port-popup {
+       margin-left: 3px;
+       font-family: Arial,Sans-Serif,sans-serif;
+}
+
+/*common rack item attributes*/
+.atom {
+       text-align: center;
+       font: bold 10px Verdana, sans-serif;
+}
+
index 8714a4d..abfe98a 100755 (executable)
@@ -60,6 +60,14 @@ getlldpstatus)
        printf 'term len 0\nshow lldp neighbors\n' >> "$SESSION"
        outfile="$WORKFILE"
        ;;
+getportstatus)
+       printf 'term len 0\nshow int status\n' >> "$SESSION"
+       outfile="$WORKFILE"
+       ;;
+getmaclist)
+       printf 'term len 0\nshow mac address-table dynamic\n' >> "$SESSION"
+       outfile="$WORKFILE"
+       ;;
 deploy)
        cat "$WORKFILE" >> "$SESSION"
        outfile=/dev/null
index 761e870..767f7b7 100755 (executable)
@@ -66,6 +66,22 @@ if ($command eq "getcdpstatus") {
     print WORKFILE @r, "\n\n";;
     exit(0);
 }
+if ($command eq "getportstatus") {
+    open(WORKFILE, ">$workfile") || die "$workfile: $!";
+    $session->cmd ('terminal length 0');
+    $session->cmd ('terminal no monitor');
+    my @r = $session->cmd ('show int status');
+    print WORKFILE @r, "\n\n";;
+    exit(0);
+}
+if ($command eq "getmaclist") {
+    open(WORKFILE, ">$workfile") || die "$workfile: $!";
+    $session->cmd ('terminal length 0');
+    $session->cmd ('terminal no monitor');
+    my @r = $session->cmd ('show mac address-table dynamic');
+    print WORKFILE @r, "\n\n";;
+    exit(0);
+}
 if ($command eq "deploy") {
     open(WORKFILE, "<$workfile") || die "$workfile: $!";
     while (<WORKFILE>) {
index d1bae88..61e3204 100755 (executable)
@@ -55,6 +55,14 @@ getlldpstatus)
        printf 'display lldp neighbor\n' >> "$SESSION"
        outfile="$WORKFILE"
        ;;
+getportstatus)
+       printf 'display interface brief\n' >> "$SESSION"
+       outfile="$WORKFILE"
+       ;;
+getmaclist)
+       printf 'display mac-address dynamic\n' >> "$SESSION"
+       outfile="$WORKFILE"
+       ;;
 gethndp)
        printf 'display ndp\n' >> "$SESSION"
        outfile="$WORKFILE"
index 6fe5bf1..3d9ed34 100755 (executable)
@@ -57,6 +57,14 @@ getlldpstatus)
        printf 'display lldp neighbor\n' >> "$SESSION"
        outfile="$WORKFILE"
        ;;
+getportstatus)
+       printf 'display interface brief\n' >> "$SESSION"
+       outfile="$WORKFILE"
+       ;;
+getmaclist)
+       printf 'display mac-address dynamic\n' >> "$SESSION"
+       outfile="$WORKFILE"
+       ;;
 gethndp)
        printf 'display ndp\n' >> "$SESSION"
        outfile="$WORKFILE"
diff --git a/inc/ajax-interface.php b/inc/ajax-interface.php
new file mode 100644 (file)
index 0000000..fe87987
--- /dev/null
@@ -0,0 +1,91 @@
+<?php
+/*
+ *
+ *  This file contains HTML-generating funcitons which are needed in ajax handler
+ *
+ *
+*/
+
+// retrieves ports link status from switch and formats results to dynamic-HTML
+// returns array which could be packed into json and passed to client's browser
+function formatPortLinkHints ($object_id)
+{
+       $result = array();
+       $linkStatus = gwRetrieveDeviceConfig ($object_id, 'getportstatus');
+       foreach ($linkStatus as $portname => $link_info)
+       {
+               $link_info = $linkStatus[$portname];
+               switch ($link_info['status'])
+               {
+                       case 'up':
+                               $img_filename = 'link-up.png';
+                               break;
+                       case 'down':
+                               $img_filename = 'link-down.png';
+                               break;
+                       case 'disabled':
+                               $img_filename = 'link-disabled.png';
+                               break;
+               }
+
+               $hidden_lines = array();
+               $hidden_lines[] = $portname . ': ' . $link_info['status'];
+               if (isset ($link_info['speed']))
+                       $hidden_lines[] = 'Speed: ' . $link_info['speed'];
+               if (isset ($link_info['duplex']))
+                       $hidden_lines[] = 'Duplex: ' . $link_info['duplex'];
+               if (count ($hidden_lines))
+                       $result[$portname]['popup'] = implode ('<br>', $hidden_lines);
+               $visible_part = '<img width="16" height="16" src="pix/' . $img_filename . '">';
+               $result[$portname]['inline'] = $visible_part;
+       }
+       // put empty pictures for not-found ports
+       $object = spotEntity ('object', $object_id);
+       amplifyCell ($object);
+       foreach ($object['ports'] as $port)
+               if (! isset ($result[$port['name']]))
+                       $result[$port['name']]['inline'] = '<img width="16" height="16" src="pix/1x1t.gif">';
+       return $result;
+}
+
+// retrieves MAC address list from switch and formats results to dynamic-HTML
+// returns array which could be packed into json and passed to client's browser
+function formatPortMacHints ($object_id)
+{
+       $result = array();
+       $macList = gwRetrieveDeviceConfig ($object_id, 'getmaclist');
+       foreach ($macList as $portname => $list)
+       {
+               $list = $macList[$portname];
+               $visible_part = count ($list) . ' MACs';
+               $result[$portname]['inline'] = $visible_part;
+               if (count ($list))
+               {
+                       $hidden_part = '<table width="100%"><tr><th>MAC<th>VID</tr>';
+                       foreach ($list as $mac)
+                               $hidden_part .= '<tr><td>' . $mac['mac'] . '<td>' . $mac['vid'] . '</tr>';
+                       $result[$portname]['popup'] = $hidden_part;
+               }
+       }
+       return $result;
+}
+
+// retrieves port configs from switch and formats results to dynamic-HTML
+// returns array which could be packed into json and passed to client's browser
+function formatPortConfigHints ($object_id, $R = NULL)
+{
+       $result = array();
+       if (! isset ($R))
+               $R = getRunning8021QConfig ($object_id);
+       foreach ($R['portdata'] as $portname => $portdata)
+               if (isset ($portdata['config']))
+               {
+                       $hidden_part = '';
+                       foreach ($portdata['config'] as $line)
+                               $hidden_part .= '<span class="'. $line['type'] . '">' . htmlentities ($line['line']) . '</span><br />';
+                       $result[$portname]['popup'] = $hidden_part;
+               }
+       return $result;
+}
+
+?>
index 7d20d32..29d7582 100644 (file)
@@ -2654,10 +2654,10 @@ function ios12ShortenIfName ($ifname)
 {
        $ifname = preg_replace ('@^Eth(?:ernet)?(.+)$@', 'e\\1', $ifname);
        $ifname = preg_replace ('@^FastEthernet(.+)$@', 'fa\\1', $ifname);
-       $ifname = preg_replace ('@^GigabitEthernet(.+)$@', 'gi\\1', $ifname);
+       $ifname = preg_replace ('@^(?:GigabitEthernet|GE)(.+)$@', 'gi\\1', $ifname);
        $ifname = preg_replace ('@^TenGigabitEthernet(.+)$@', 'te\\1', $ifname);
        $ifname = preg_replace ('@^Port-channel(.+)$@', 'po\\1', $ifname);
-       $ifname = preg_replace ('@^XGigabitEthernet(.+)$@', 'xg\\1', $ifname);
+       $ifname = preg_replace ('@^(?:XGigabitEthernet|XGE)(.+)$@', 'xg\\1', $ifname);
        $ifname = strtolower ($ifname);
        return $ifname;
 }
@@ -3462,16 +3462,21 @@ function printPageHeaders ()
        ksort ($pageheaders);
        foreach ($pageheaders as $s)
                echo $s . "\n";
-       echo "<style type='text/css'>\n";
-       foreach (array ('F', 'A', 'U', 'T', 'Th', 'Tw', 'Thw') as $statecode)
-       {
-               echo "td.state_${statecode} {\n";
-               echo "\ttext-align: center;\n";
-               echo "\tbackground-color: #" . (getConfigVar ('color_' . $statecode)) . ";\n";
-               echo "\tfont: bold 10px Verdana, sans-serif;\n";
-               echo "}\n\n";
-       }
-       echo '</style>';
+
+       // add CSS styles
+       foreach (addCSS (NULL) as $item)
+               if ($item['type'] == 'inline')
+                       echo '<style type="text/css">' . "\n" . trim ($item['style'], "\r\n") . "\n</style>\n";
+               elseif ($item['type'] == 'file')
+                       echo '<link rel="stylesheet" type="text/css" href="' . htmlspecialchars ($item['style']) . "\" />\n";
+
+       // add JS scripts
+       foreach (addJS (NULL) as $group_name => $js_list)
+               foreach ($js_list as $item)
+                       if ($item['type'] == 'inline')
+                               echo '<script type="text/javascript">' . "\n" . trim ($item['script'], "\r\n") . "\n</script>\n";
+                       elseif ($item['type'] == 'file')
+                               echo '<script type="text/javascript" src="' . htmlspecialchars($item['script']) . "\"></script>\n";
 }
 
 function strerror8021Q ($errno)
@@ -4131,4 +4136,126 @@ function getRackCode ($text)
        return semanticFilter ($synt['load']);
 }
 
+// returns array with 'from', 'length' keys.
+// if not found, 'from' is NULL;
+// if length is not defined (to the end of line), length is -1
+function getColumnCoordinates ($line, $column_name, $align = 'left')
+{
+       $result = array ('from' => NULL, 'length' => -1);
+       $items = preg_split('/\s+/', $line);
+       for ($i = 0; $i < count ($items); $i++)
+       {
+               $item = $items[$i];
+               if ($column_name == $item)
+               {
+                       $current_start = strpos ($line, $items[$i]);
+                       if ($align == 'left')
+                       {
+                               $result['from'] = $current_start;
+                               if ($i < count ($items) - 1)
+                               {
+                                       $next_start = strpos ($line, $items[$i + 1]);
+                                       $result['length'] = $next_start - $result['from'] - 1;
+                               }
+                               else
+                                       $result['length'] = -1;
+                       }
+                       elseif ($align == 'right')
+                       {
+                               if ($i > 0)
+                                       $prev_end = strpos ($line, $items[$i - 1]) + strlen ($items[$i - 1]);
+                               else
+                                       $prev_end = -1;
+                               $result['from'] = $prev_end + 1;
+                               $result['length'] = $current_start - $result['from'] + strlen ($column_name);
+                       }
+                       break;
+               }
+       }
+       return $result;
+}
+
+// JS scripts should be included through this function.
+// They automatically appear in the <head> of your page.
+// $data is a JS filename, or JS code w/o tags around, if $inline = TRUE
+// Scripts are included in the order of adding within the same group, and groups are sorted alphabetically.
+function addJS ($data, $inline = FALSE, $group = 'default')
+{
+       static $javascript = array();
+       static $seen_filenames = array();
+       
+       if (! isset ($data))
+       {
+               ksort ($javascript);
+               return $javascript;
+       }
+       // Add jquery.js and racktables.js the first time a Javascript file is added.
+       if (empty($javascript))
+       {
+               $javascript = array
+               (
+                       'a_core' => array
+                       (
+                               array('type' => 'file', 'script' => 'js/jquery-1.4.4.min.js'),
+                               array('type' => 'file', 'script' => 'js/racktables.js'),
+                       ),
+               );
+
+               // initialize core js filelist
+               foreach ($javascript as $group_name => $group_array)
+                       foreach ($group_array as $item)
+                               if ($item['type'] == 'file')
+                                       $seen_filenames[$item['script']] = 1;
+       }
+
+       if ($inline)
+               $javascript[$group][] = array
+               (
+                       'type' => 'inline',
+                       'script' => $data,
+               );
+       elseif (! isset ($seen_filenames[$data]))
+       {
+               $javascript[$group][] = array
+               (
+                       'type' => 'file',
+                       'script' => $data,
+               );
+               $seen_filenames[$data] = 1;
+       }
+}
+
+// CSS styles should be included through this function.
+// They automatically appear in the <head> of your page.
+// $data is a CSS filename, or CSS code w/o tags around, if $inline = TRUE
+// Styles are included in the order of adding.
+function addCSS ($data, $inline = FALSE)
+{
+       static $styles = array();
+       static $seen_filenames = array();
+       
+       if (! isset ($data))
+               return $styles;
+       if ($inline)
+               $styles[] = array
+               (
+                       'type' => 'inline',
+                       'style' => $data,
+               );
+       elseif (! isset ($seen_filenames[$data]))
+       {
+               $styles[] = array
+               (
+                       'type' => 'file',
+                       'style' => $data,
+               );
+               $seen_filenames[$data] = 1;
+       }
+}
+
+function isEthernetPort($port)
+{
+       return ($port['iif_id'] != 1 or preg_match('/Base|LACP/i', $port['oif_name']));
+}
+
 ?>
index 371d674..3f91607 100644 (file)
@@ -36,6 +36,20 @@ $gwrxlator['get8021q'] = array
        'nxos4' => 'nxos4Read8021QConfig',
        'xos12' => 'xos12Read8021QConfig',
 );
+$gwrxlator['getportstatus'] = array
+(
+       'ios12' => 'ciscoReadInterfaceStatus',
+       'vrp53' => 'vrpReadInterfaceStatus',
+       'vrp55' => 'vrpReadInterfaceStatus',
+       'nxos4' => 'ciscoReadInterfaceStatus',
+);
+$gwrxlator['getmaclist'] = array
+(
+       'ios12' => 'ios12ReadMacList',
+       'vrp53' => 'vrp53ReadMacList',
+       'vrp55' => 'vrp55ReadMacList',
+       'nxos4' => 'nxos4ReadMacList',
+);
 
 $gwrxlator['gethndp']['vrp53'] = 'vrp53ReadHNDPStatus';
 
@@ -625,6 +639,7 @@ function ios12ScanTopLevel (&$work, $line)
        {
        case (preg_match ('@^interface ((Ethernet|FastEthernet|GigabitEthernet|TenGigabitEthernet|Port-channel)[[:digit:]]+(/[[:digit:]]+)*)$@', $line, $matches)):
                $work['current'] = array ('port_name' => ios12ShortenIfName ($matches[1]));
+               $work['current']['config'][] = array ('type' => 'line-header', 'line' => $line);
                return 'ios12PickSwitchportCommand'; // switch to interface block reading
        case (preg_match ('/^VLAN Name                             Status    Ports$/', $line, $matches)):
                return 'ios12PickVLANCommand';
@@ -685,11 +700,14 @@ function ios12PickSwitchportCommand (&$work, $line)
                        );
                        break;
                }
+               if (isset ($work['portdata'][$work['current']['port_name']]))
+                       $work['portdata'][$work['current']['port_name']]['config'] = $work['current']['config'];
                unset ($work['current']);
                return 'ios12ScanTopLevel';
        }
        // not yet
        $matches = array();
+       $line_class = 'line-8021q';
        switch (TRUE)
        {
        case (preg_match ('@^ switchport mode (.+)$@', $line, $matches)):
@@ -720,7 +738,9 @@ function ios12PickSwitchportCommand (&$work, $line)
                $work['current']['mode'] = 'IP';
                break;
        default: // suppress warning on irrelevant config clause
+               $line_class = 'line-other';
        }
+       $work['current']['config'][] = array ('type' => $line_class, 'line' => $line);
        return __FUNCTION__;
 }
 
@@ -941,6 +961,7 @@ function vrp53ScanTopLevel (&$work, $line)
                $matches[1] = preg_replace ('@^XGigabitEthernet(.+)$@', 'xg\\1', $matches[1]);
                $matches[1] = preg_replace ('@^Eth-Trunk(.+)$@', 'et\\1', $matches[1]);
                $work['current'] = array ('port_name' => $matches[1]);
+               $work['current']['config'][] = array ('type' => 'line-header', 'line' => $line);
                return 'vrp53PickInterfaceSubcommand';
        default:
                return __FUNCTION__;
@@ -1002,10 +1023,13 @@ function vrp53PickInterfaceSubcommand (&$work, $line)
                        break;
                default: // dot1q-tunnel ?
                }
+               if (isset ($work['portdata'][$work['current']['port_name']]))
+                       $work['portdata'][$work['current']['port_name']]['config'] = $work['current']['config'];
                unset ($work['current']);
                return 'vrp53ScanTopLevel';
        }
        $matches = array();
+       $line_class = 'line-8021q';
        switch (TRUE)
        {
        case (preg_match ('@^ port default vlan ([[:digit:]]+)$@', $line, $matches)):
@@ -1027,7 +1051,9 @@ function vrp53PickInterfaceSubcommand (&$work, $line)
                break;
        // TODO: make sure, that a port with "eth-trunk" clause always ends up in "none" mode
        default: // nom-nom
+               $line_class = 'line-other';
        }
+       $work['current']['config'][] = array('type' => $line_class, 'line' => $line);
        return __FUNCTION__;
 }
 
@@ -1043,21 +1069,24 @@ function vrp55Read8021QConfig ($input)
                $matches = array();
                // top level
                if (!array_key_exists ('current', $ret))
+               {
                        switch (TRUE)
                        {
                        case (preg_match ('@^ vlan batch (.+)$@', $line, $matches)):
                                foreach (vrp53ParseVLANString ($matches[1]) as $vlan_id)
                                        $ret['vlanlist'][] = $vlan_id;
-                               continue 2;
+                               break;
                        case (preg_match ('@^interface ((GigabitEthernet|XGigabitEthernet|Eth-Trunk)([[:digit:]]+(/[[:digit:]]+)*))$@', $line, $matches)):
                                $matches[1] = preg_replace ('@^GigabitEthernet(.+)$@', 'gi\\1', $matches[1]);
                                $matches[1] = preg_replace ('@^XGigabitEthernet(.+)$@', 'xg\\1', $matches[1]);
                                $ret['current'] = array ('port_name' => $matches[1]);
-                               continue 2;
-                       default:
-                               continue 2;
+                               $ret['current']['config'][] = array ('type' => 'line-header', 'line' => $line);
+                               break;
                        }
+                       continue;
+               }
                // inside an interface block
+               $line_class = 'line-8021q';
                switch (TRUE)
                {
                case preg_match ('/^ port (link-type )?hybrid /', $line):
@@ -1134,10 +1163,14 @@ function vrp55Read8021QConfig ($input)
                        case 'SKIP':
                        default: // dot1q-tunnel ?
                        }
+                       if (isset ($ret['portdata'][$ret['current']['port_name']]))
+                               $ret['portdata'][$ret['current']['port_name']]['config'] = $ret['current']['config'];
                        unset ($ret['current']);
-                       break;
+                       continue 2;
                default: // nom-nom
+                       $line_class = 'line-other';
                }
+               $ret['current']['config'][] = array ('type' => $line_class, 'line' => $line);
        }
        return $ret;
 }
@@ -1164,6 +1197,7 @@ function nxos4ScanTopLevel (&$work, $line)
                $matches[1] = preg_replace ('@^Ethernet(.+)$@i', 'e\\1', $matches[1]);
                $matches[1] = preg_replace ('@^Port-channel(.+)$@i', 'po\\1', $matches[1]);
                $work['current'] = array ('port_name' => $matches[1]);
+               $work['current']['config'][] = array ('type' => 'line-header', 'line' => $line);
                return 'nxos4PickSwitchportCommand';
        case (preg_match ('@^vlan (.+)$@', $line, $matches)):
                foreach (iosParseVLANString ($matches[1]) as $vlan_id)
@@ -1227,11 +1261,14 @@ function nxos4PickSwitchportCommand (&$work, $line)
                        );
                        // unset (routed), dot1q-tunnel, dynamic, private-vlan --- skip these
                }
+               if (isset ($work['portdata'][$work['current']['port_name']]))
+                       $work['portdata'][$work['current']['port_name']]['config'] = $work['current']['config'];
                unset ($work['current']);
                return 'nxos4ScanTopLevel';
        }
        // not yet
        $matches = array();
+       $line_class = 'line-8021q';
        switch (TRUE)
        {
        case (preg_match ('@^  switchport mode (.+)$@', $line, $matches)):
@@ -1257,7 +1294,9 @@ function nxos4PickSwitchportCommand (&$work, $line)
                $work['current']['mode'] = 'SKIP';
                break;
        default: // suppress warning on irrelevant config clause
+               $line_class = 'line-other';
        }
+       $work['current']['config'][] = array ('type' => $line_class, 'line' => $line);
        return __FUNCTION__;
 }
 
@@ -1598,4 +1637,203 @@ function xos12Read8021QConfig ($input)
        return $ret;
 }
 
+function ciscoReadInterfaceStatus ($text)
+{
+       $result = array();
+       $state = 'headerSearch';
+       foreach (explode ("\n", $text) as $line)
+       {
+               switch ($state)
+               {
+                       case 'headerSearch':
+                               if (preg_match('/^Port\s+Name\s+Status/', $line))
+                               {
+                                       $name_field_borders = getColumnCoordinates($line, 'Name');
+                                       if (isset ($name_field_borders['from']))
+                                               $state = 'readPort';
+                               }
+                               break;
+                       case 'readPort':
+                               $portname = ios12ShortenIfName (trim (substr ($line, 0, $name_field_borders['from'])));
+                               $rest = trim (substr ($line, $name_field_borders['from'] + $name_field_borders['length'] + 1));
+                               $field_list = preg_split('/\s+/', $rest);
+                               if (count ($field_list) < 4)
+                                       break;
+                               list ($status_raw, $vlan, $duplex, $speed, $type) = $field_list;
+                               if ($status_raw == 'connected' || $status_raw == 'up')
+                                       $status = 'up';
+                               elseif ($status_raw == 'notconnect' || $status_raw == 'down')
+                                       $status = 'down';
+                               else
+                                       $status = 'disabled';
+                               $result[$portname] = array
+                               (
+                                       'status' => $status,
+                                       'speed' => $speed,
+                                       'duplex' => $duplex,
+                               );
+                               break;
+               }
+       }
+       return $result;
+}
+
+function vrpReadInterfaceStatus ($text)
+{
+       $result = array();
+       $state = 'headerSearch';
+       foreach (explode ("\n", $text) as $line)
+       {
+               switch ($state)
+               {
+                       case 'headerSearch':
+                               if (preg_match('/^Interface\s+Phy\w*\s+Protocol/i', $line))
+                                       $state = 'readPort';
+                               break;
+                       case 'readPort':
+                               if (preg_match('/[\$><\]]/', $line))
+                                       break 2;
+                               $field_list = preg_split('/\s+/', $line);
+                               if (count ($field_list) < 7)
+                                       break;
+                               list ($portname, $status_raw) = $field_list;
+                               $portname = ios12ShortenIfName ($portname);
+
+                               if ($status_raw == 'up' || $status_raw == 'down')
+                                       $status = $status_raw;
+                               else
+                                       $status = 'disabled';
+                               $result[$portname] = array
+                               (
+                                       'status' => $status,
+                               );
+                               break;
+               }
+       }
+       return $result;
+}
+
+function maclist_sort ($a, $b)
+{
+       if ($a['vid'] == $b['vid'])
+               return 0;
+       return ($a['vid'] < $b['vid']) ? -1 : 1;
+}
+
+function ios12ReadMacList ($text)
+{
+       $result = array();
+       $state = 'headerSearch';
+       foreach (explode ("\n", $text) as $line)
+       {
+               switch ($state)
+               {
+                       case 'headerSearch':
+                               if (preg_match('/Vlan\s+Mac Address\s+Type.*Ports?\s*$/i', $line))
+                                       $state = 'readPort';
+                               break;
+                       case 'readPort':
+                               if (! preg_match ('/(\d+)\s+([a-f0-9]{4}\.[a-f0-9]{4}\.[a-f0-9]{4})\s.*?(\S+)$/', trim ($line), $matches))
+                                       break;
+                               $portname = ios12ShortenIfName ($matches[3]);
+                               $result[$portname][] = array
+                               (
+                                       'mac' => $matches[2],
+                                       'vid' => $matches[1],
+                               );
+                               break;
+               }
+       }
+       foreach ($result as $portname => &$maclist)
+               usort ($maclist, 'maclist_sort');
+       return $result;
+}
+
+function nxos4ReadMacList ($text)
+{
+       $result = array();
+       $state = 'headerSearch';
+       foreach (explode ("\n", $text) as $line)
+       {
+               switch ($state)
+               {
+                       case 'headerSearch':
+                               if (preg_match('/VLAN\s+MAC Address\s+Type\s+age\s+Secure\s+NTFY\s+Ports/i', $line))
+                                       $state = 'readPort';
+                               break;
+                       case 'readPort':
+                               if (! preg_match ('/(\d+)\s+([a-f0-9]{4}\.[a-f0-9]{4}\.[a-f0-9]{4})\s.*?(\S+)$/', trim ($line), $matches))
+                                       break;
+                               $portname = ios12ShortenIfName ($matches[3]);
+                               $result[$portname][] = array
+                               (
+                                       'mac' => $matches[2],
+                                       'vid' => $matches[1],
+                               );
+                               break;
+               }
+       }
+       foreach ($result as $portname => &$maclist)
+               usort ($maclist, 'maclist_sort');
+       return $result;
+}
+
+function vrp53ReadMacList ($text)
+{
+       $result = array();
+       $state = 'headerSearch';
+       foreach (explode ("\n", $text) as $line)
+       {
+               switch ($state)
+               {
+                       case 'headerSearch':
+                               if (preg_match('/MAC Address\s+VLAN\/VSI\s+Port/i', $line))
+                                       $state = 'readPort';
+                               break;
+                       case 'readPort':
+                               if (! preg_match ('/([a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4})\s+(\d+)\s+(\S+)/', trim ($line), $matches))
+                                       break;
+                               $portname = ios12ShortenIfName ($matches[3]);
+                               $result[$portname][] = array
+                               (
+                                       'mac' => str_replace ('-', '.', $matches[1]),
+                                       'vid' => $matches[2],
+                               );
+                               break;
+               }
+       }
+       foreach ($result as $portname => &$maclist)
+               usort ($maclist, 'maclist_sort');
+       return $result;
+}
+
+function vrp55ReadMacList ($text)
+{
+       $result = array();
+       $state = 'headerSearch';
+       foreach (explode ("\n", $text) as $line)
+       {
+               switch ($state)
+               {
+                       case 'headerSearch':
+                               if (preg_match('/MAC Address\s+VLAN\/\S*\s+PEVLAN\s+CEVLAN\s+Port/i', $line))
+                                       $state = 'readPort';
+                               break;
+                       case 'readPort':
+                               if (! preg_match ('/([a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4})\s+(\d+)(?:\s+\S+){2}\s+(\S+)/', trim ($line), $matches))
+                                       break;
+                               $portname = ios12ShortenIfName ($matches[3]);
+                               $result[$portname][] = array
+                               (
+                                       'mac' => str_replace ('-', '.', $matches[1]),
+                                       'vid' => $matches[2],
+                               );
+                               break;
+               }
+       }
+       foreach ($result as $portname => &$maclist)
+               usort ($maclist, 'maclist_sort');
+       return $result;
+}
+
 ?>
index 4d345ad..aeb2588 100644 (file)
@@ -167,13 +167,9 @@ $user_given_tags = array();
 // This also can be modified in local.php.
 $pageheaders = array
 (
-       100 => "<link rel='STYLESHEET' type='text/css' href='pi.css' />",
-       102 => "<link rel='ICON' type='image/x-icon' href='favicon.ico' />",
-       200 => "<script language='javascript' type='text/javascript' src='js/jquery-1.3.1.min.js'></script>",
-       201 => "<script language='javascript' type='text/javascript' src='js/racktables.js'></script>",
-       202 => "<script language='javascript' type='text/javascript' src='js/live_validation.js'></script>",
-       203 => "<script language='javascript' type='text/javascript' src='js/codepress/codepress.js'></script>",
+       100 => "<link rel='ICON' type='image/x-icon' href='favicon.ico' />",
 );
+addCSS ('css/pi.css');
 
 if (!isset ($script_mode) or $script_mode !== TRUE)
 {
index 1fda794..f2767f6 100644 (file)
@@ -5,6 +5,8 @@
 *
 */
 
+include_once 'ajax-interface.php';
+
 // Interface function's special.
 $nextorder['odd'] = 'even';
 $nextorder['even'] = 'odd';
@@ -580,6 +582,7 @@ function renderRack ($rack_id, $hl_obj_id = 0)
        echo "<table class=rack border=0 cellspacing=0 cellpadding=1>\n";
        echo "<tr><th width='10%'>&nbsp;</th><th width='20%'>Front</th>";
        echo "<th width='50%'>Interior</th><th width='20%'>Back</th></tr>\n";
+       addAtomCSS();
        for ($i = $rackData['height']; $i > 0; $i--)
        {
                echo "<tr><th>${i}</th>";
@@ -588,9 +591,10 @@ function renderRack ($rack_id, $hl_obj_id = 0)
                        if (isset ($rackData[$i][$locidx]['skipped']))
                                continue;
                        $state = $rackData[$i][$locidx]['state'];
-                       echo "<td class=state_${state}";
+                       echo "<td class='atom state_${state}";
                        if (isset ($rackData[$i][$locidx]['hl']))
                                echo $rackData[$i][$locidx]['hl'];
+                       echo "'";
                        if (isset ($rackData[$i][$locidx]['colspan']))
                                echo ' colspan=' . $rackData[$i][$locidx]['colspan'];
                        if (isset ($rackData[$i][$locidx]['rowspan']))
@@ -889,6 +893,7 @@ function renderGridForm ($rack_id, $filter, $header, $submit, $state1, $state2)
 
        // Grid form.
        startPortlet ($header);
+       addJS ('js/racktables.js');
        echo "<center>\n";
        echo "<table class=rack border=0 cellspacing=0 cellpadding=1>\n";
        echo "<tr><th width='10%'>&nbsp;</th>";
@@ -1008,6 +1013,7 @@ function renderRackObject ($object_id)
                finishPortlet();
        }
 
+       switchportInfoJS ($object_id); // load JS code to make portnames interactive
        renderFilesPortlet ('object', $object_id);
 
        if (count ($info['ports']))
@@ -1018,7 +1024,7 @@ function renderRackObject ($object_id)
                {
                        assertUIntArg ('hl_port_id');
                        $hl_port_id = $_REQUEST['hl_port_id'];
-                       echo getAutoScrollScript ("port-$hl_port_id");
+                       addAutoScrollScript ("port-$hl_port_id");
                }
                echo "<table cellspacing=0 cellpadding='5' align='center' class='widetable'>";
                echo '<tr><th class=tdleft>Local name</th><th class=tdleft>Visible label</th>';
@@ -1030,8 +1036,10 @@ function renderRackObject ($object_id)
                        echo '<tr';
                        if ($hl_port_id == $port['id'])
                                echo ' class=port_highlight';
-                       echo "><td class=tdleft>${port['name']}<a name='port-${port['id']}'>&nbsp;</a></td><td class=tdleft>${port['label']}</td><td class=tdleft>";
-                       echo formatPortIIFOIF ($port) . "</td><td class=tdleft><tt>${port['l2address']}</tt></td>";
+                       $a_class = isEthernetPort ($port) ? 'port-menu' : '';
+                       echo "><td class='tdleft' NOWRAP><a name='port-${port['id']}' class='interactive-portname nolink $a_class'>${port['name']}</a></td>";
+                       echo "<td class=tdleft>${port['label']}</td>";
+                       echo "<td class=tdleft>" . formatPortIIFOIF ($port) . "</td><td class=tdleft><tt>${port['l2address']}</tt></td>";
                        if ($port['remote_object_id'])
                        {
                                $remote_object = spotEntity ('object', $port['remote_object_id']);
@@ -1069,7 +1077,7 @@ function renderRackObject ($object_id)
                elseif (isset ($_REQUEST['hl_ipv4_addr']))
                        $hl_ip_addr = $_REQUEST['hl_ipv4_addr'];
                if ($hl_ip_addr)
-                       echo getAutoScrollScript ("ip-$hl_ip_addr");
+                       addAutoScrollScript ("ip-$hl_ip_addr");
 
                // group IP allocations by interface name instead of address family
                $allocs_by_iface = array();
@@ -1295,7 +1303,7 @@ function renderPortsForObject ($object_id)
                printOpFormIntro ('addPort');
                echo "<tr><td>";
                printImageHREF ('add', 'add a port', TRUE);
-               echo "</td><td><input type=text size=8 name=port_name tabindex=100></td>\n";
+               echo "</td><td class='tdleft'><input type=text size=8 name=port_name tabindex=100></td>\n";
                echo "<td><input type=text name=port_label tabindex=101></td><td>";
                printNiftySelect (getNewPortTypeOptions(), array ('name' => 'port_type_id', 'tabindex' => 102), $prefs['selected']);
                echo "<td><input type=text name=port_l2address tabindex=103 size=18 maxlength=24></td>\n";
@@ -1336,8 +1344,9 @@ function renderPortsForObject ($object_id)
        {
                assertUIntArg ('hl_port_id');
                $hl_port_id = intval ($_REQUEST['hl_port_id']);
-               echo getAutoScrollScript ("port-$hl_port_id");
+               addAutoScrollScript ("port-$hl_port_id");
        }
+       switchportInfoJS ($object_id); // load JS code to make portnames interactive
        foreach ($object['ports'] as $port)
        {
                $tr_class = isset ($hl_port_id) && $hl_port_id == $port['id'] ? 'class="port_highlight"' : '';
@@ -1345,7 +1354,8 @@ function renderPortsForObject ($object_id)
                echo "<tr $tr_class><td><a name='port-${port['id']}' href='".makeHrefProcess(array('op'=>'delPort', 'port_id'=>$port['id'], 'object_id'=>$object_id, 'port_name'=>$port['name']))."'>";
                printImageHREF ('delete', 'Unlink and Delete this port');
                echo "</a></td>\n";
-               echo "<td><input type=text name=name value='${port['name']}' size=8></td>";
+               $a_class = isEthernetPort ($port) ? 'port-menu' : '';
+               echo "<td class='tdleft' NOWRAP><input type=text name=name class='interactive-portname $a_class' value='${port['name']}' size=8></td>";
                echo "<td><input type=text name=label value='${port['label']}'></td>";
                if (!$port['remote_object_id'])
                {
@@ -1949,6 +1959,83 @@ function showMessageOrError ()
        unset($_SESSION['log']);
 }
 
+// renders two tables: port link status and learned MAC list
+function renderPortsInfo($object_id)
+{
+       global $nextorder;
+       echo "<table width='100%'><tr>";
+       
+       if (permitted (NULL, NULL, 'get_link_status'))
+       {
+               try
+               {
+                       $linkStatus = gwRetrieveDeviceConfig ($object_id, 'getportstatus');
+               }
+               catch (RackTablesError $e) {}
+               if (! empty ($linkStatus))
+               {
+                       echo "<td valign='top' width='50%'>";
+                       startPortlet('Link status');
+                       echo "<table width='80%' class='widetable' cellspacing=0 cellpadding='5px' align='center'><tr><th>Port<th>Link status<th>Link info</tr>";
+                       $order = 'even';
+                       foreach ($linkStatus as $pn => $link)
+                       {
+                               echo "<tr class='row_$order'>";
+                               $order = $nextorder[$order];
+                               echo '<td>' . $pn;
+                               echo '<td>' . $link['status'];
+                               $info = '';
+                               if (isset ($link['speed']))
+                                       $info .= $link['speed'];
+                               if (isset ($link['duplex']))
+                               {
+                                       if (! empty ($info))
+                                               $info .= ', ';
+                                       $info .= $link['duplex'];
+                               }
+                               echo '<td>' . $info;
+                               echo '</tr>';
+                       }
+                       echo "</table></td>";
+                       finishPortlet();
+               }
+       }
+
+       try
+       {
+               $macList = sortPortList (gwRetrieveDeviceConfig ($object_id, 'getmaclist'));
+       }
+       catch (RackTablesError $e) {}   
+       if (! empty ($macList))
+       {
+               echo "<td valign='top' width='50%'>";
+               $rendered_macs = '';
+               $mac_count = 0;
+               $rendered_macs .=  "<table width='80%' class='widetable' cellspacing=0 cellpadding='5px' align='center'><tr><th>MAC<th>Vlan<th>Port</tr>";
+               $order = 'even';
+               foreach ($macList as $pn => $list)
+               {
+                       $order = $nextorder[$order];
+                       foreach ($list as $item)
+                       {
+                               ++$mac_count;
+                               $rendered_macs .= "<tr class='row_$order'>";
+                               $rendered_macs .= '<td style="font-family: monospace">' . $item['mac'];
+                               $rendered_macs .= '<td>' . $item['vid'];
+                               $rendered_macs .= '<td>' . $pn;
+                               $rendered_macs .= '</tr>';
+                       }
+               }
+               $rendered_macs .= "</table></td>";
+       
+               startPortlet("Learned MACs ($mac_count)");
+               echo $rendered_macs;
+               finishPortlet();
+       }
+
+       echo "</td></tr></table>";
+}
+
 /*
 The following conditions must be met:
 1. We can mount onto free atoms only. This means: if any record for an atom
@@ -2006,6 +2093,7 @@ function renderRackSpaceForObject ($object_id)
        // reflect the former state of the grid in current form.
        echo "<td class=pcright rowspan=2 height='1%'>";
        startPortlet ('Working copy');
+       addJS ('js/racktables.js');
        echo '<table border=0 cellspacing=10 align=center><tr>';
        foreach ($workingRacksData as $rack_id => $rackData)
        {
@@ -2062,6 +2150,7 @@ function renderMolecule ($mdata, $object_id)
                $rackpack[$rack_id][$unit_no][$loclist[$atom]]['object_id'] = $object_id;
        }
        // now we have some racks to render
+       addAtomCSS();
        foreach ($rackpack as $rackData)
        {
                markAllSpans ($rackData);
@@ -2074,7 +2163,7 @@ function renderMolecule ($mdata, $object_id)
                        for ($locidx = 0; $locidx < 3; $locidx++)
                        {
                                $state = $rackData[$i][$locidx]['state'];
-                               echo "<td class=state_${state}>&nbsp;</td>\n";
+                               echo "<td class='atom state_${state}'>&nbsp;</td>\n";
                        }
                        echo "</tr>\n";
                }
@@ -2274,7 +2363,7 @@ function renderIPv4SpaceRecords ($tree, $baseurl, $target = 0, $knight, $level =
 
        // scroll page to the highlighted item
        if ($target && isset ($_REQUEST['hl_net']))
-               echo getAutoScrollScript ("net-$target");
+               addAutoScrollScript ("net-$target");
 
        foreach ($tree as $item)
        {
@@ -2358,7 +2447,7 @@ function renderIPv6SpaceRecords ($tree, $baseurl, $target = 0, $knight, $level =
 
        // scroll page to the highlighted item
        if ($target && isset ($_REQUEST['hl_net']))
-               echo getAutoScrollScript ("net-$target");
+               addAutoScrollScript ("net-$target");
 
        foreach ($tree as $item)
        {
@@ -2653,16 +2742,15 @@ function renderIPv4SLB ()
 function renderIPv4SpaceEditor ()
 {
        // IPv4 validator
-?>
-       <script type="text/javascript">
-       function init() {
-               document.add_new_range.range.setAttribute('match', "^\\d\\d?\\d?\\.\\d\\d?\\d?\\.\\d\\d?\\d?\\.\\d\\d?\\d?\\/\\d\\d?$");
-
-               Validate.init();
-       }
-       window.onload=init;
-       </script>
-<?php
+       addJs ('js/live_validation.js');
+       $regexp = addslashes ('^(\d{1,3}\.){3}\d{1,3}/\d{1,2}$');
+       addJs (<<<END
+$(document).ready(function () {
+       document.add_new_range.range.setAttribute('match', '$regexp');
+       Validate.init();
+});
+END
+       , TRUE);
 
        function printNewItemTR ()
        {
@@ -2736,16 +2824,15 @@ function renderIPv4SpaceEditor ()
 function renderIPv6SpaceEditor ()
 {
        // IPv6 validator
-?>
-       <script type="text/javascript">
-       function init() {
-               document.add_new_range.range.setAttribute ('match', '^[a-fA-F0-9:]*:[a-fA-F0-9:\\.]*\/\\d{1,3}$');
-
-               Validate.init();
-       }
-       window.onload=init;
-       </script>
-<?php
+       addJs ('js/live_validation.js');
+       $regexp = addslashes ('^[a-fA-F0-9:]*:[a-fA-F0-9:\.]*/\d{1,3}$');
+       addJs (<<<END
+$(document).ready(function () {
+       document.add_new_range.range.setAttribute('match', '$regexp');
+       Validate.init();
+});
+END
+       , TRUE);
 
        function printNewItemTR ()
        {
@@ -2914,7 +3001,7 @@ function renderIPv4Network ($id)
        {
                $hl_ip = ip2long ($_REQUEST['hl_ipv4_addr']);
                $hl_dottedquad = ip_long2quad ($hl_ip);
-               echo getAutoScrollScript ("ip-$hl_dottedquad"); // scroll page to highlighted ip
+               addAutoScrollScript ("ip-$hl_dottedquad"); // scroll page to highlighted ip
        }
 
        // pager
@@ -3143,7 +3230,7 @@ function renderIPv6NetworkAddresses ($netinfo)
        if (! isset ($_REQUEST['hl_ipv6_addr']) || ! $hl_ip->parse ($_REQUEST['hl_ipv6_addr']))
                $hl_ip = NULL;
        else
-               echo getAutoScrollScript('ip-' . $hl_ip->format());
+               addAutoScrollScript ('ip-' . $hl_ip->format());
 
        $prev_ip = $netinfo['ip_bin']; // really this is the next to previosly seen ip.
        $addresses = $netinfo['addrlist'];
@@ -3965,6 +4052,8 @@ function renderSearchResults ($terms, $summary)
 function renderAtomGrid ($data)
 {
        $rack_id = $data['id'];
+       addAtomCSS();
+       addJS ('js/racktables.js');
        for ($unit_no = $data['height']; $unit_no > 0; $unit_no--)
        {
                echo "<tr><th><a href='javascript:;' oncontextmenu=\"blockToggleRowOfAtoms('${rack_id}','${unit_no}'); return false;\" onclick=\"toggleRowOfAtoms('${rack_id}','${unit_no}')\">${unit_no}</a></th>";
@@ -3972,10 +4061,10 @@ function renderAtomGrid ($data)
                {
                        $name = "atom_${rack_id}_${unit_no}_${locidx}";
                        $state = $data[$unit_no][$locidx]['state'];
-                       echo "<td class=state_${state}";
+                       echo "<td class='atom state_${state}";
                        if (isset ($data[$unit_no][$locidx]['hl']))
                                echo $data[$unit_no][$locidx]['hl'];
-                       echo ">";
+                       echo "'>";
                        if (!($data[$unit_no][$locidx]['enabled'] === TRUE))
                                echo "<input type=checkbox id=${name} disabled>";
                        else
@@ -5773,6 +5862,7 @@ function renderLivePTR ($id)
                $idx++;
        }
        echo "<tr><td colspan=3 align=center><input type=submit value='Import selected records'></td><td>";
+       addJS ('js/racktables.js');
        echo --$box_counter ? "<a href='javascript:;' onclick=\"toggleColumnOfAtoms(1, 1, ${box_counter})\">(toggle selection)</a>" : '&nbsp;';
        echo "</td></tr>";
        echo "</table>";
@@ -5990,7 +6080,7 @@ function renderEntityTags ($entity_id)
                // It could happen, that none of existing tags have been used in the current realm.
                if (count ($minilist))
                {
-                       $js_code = "<script type=\"text/javascript\">\ntagShortList = {";
+                       $js_code = "tagShortList = {";
                        $is_first = TRUE;
                        foreach($minilist as $tag) {
                                if (! $is_first)
@@ -5998,8 +6088,8 @@ function renderEntityTags ($entity_id)
                                $is_first = FALSE;
                                $js_code .= "\n\t${tag['id']} : 1";
                        }
-                       $js_code .= "\n};\n$(document).ready(compactTreeMode);\n</script>";
-                       echo $js_code;
+                       $js_code .= "\n};\n$(document).ready(compactTreeMode);";
+                       addJS ($js_code, TRUE);
                }
        }
 
@@ -6085,7 +6175,7 @@ function renderCellFilterPortlet ($preselect, $realm, $cell_list = array(), $byp
                }
                
                if (getConfigVar('SHRINK_TAG_TREE_ON_CLICK') == 'yes')
-                       echo "\n" . '<script type="text/javascript">init_cb_click();</script>' . "\n";
+                       addJS ('init_cb_click()', TRUE);
        }
        // predicates block
        if (getConfigVar ('FILTER_SUGGEST_PREDICATES') == 'yes' or count ($preselect['pnamelist']))
@@ -6248,10 +6338,8 @@ function renderRackCodeViewer ()
 
 function renderRackCodeEditor ()
 {
-       $text = loadScript ('RackCode');
-       printOpFormIntro ('saveRackCode');
-       echo <<<ENDJAVASCRIPT
-<script type="text/javascript">
+       addJS ('js/codepress/codepress.js');
+       addJS (<<<ENDJAVASCRIPT
 var prevCode = '';
 function verify()
 {
@@ -6279,9 +6367,7 @@ function verify()
        });
 }
 
-
-function invalidate()
-{
+$(document).ready(function() {
        if (prevCode != RCTA.getCode())
        {
                prevCode = RCTA.getCode();
@@ -6289,12 +6375,12 @@ function invalidate()
                $("#ShowMessage")[0].innerHTML = "";
                $("#ShowMessage")[0].className = "";
        }
-}
-
-setInterval(invalidate, 1000);
-</script>
-ENDJAVASCRIPT;
+});
+ENDJAVASCRIPT
+       , TRUE);
 
+       $text = loadScript ('RackCode');
+       printOpFormIntro ('saveRackCode');
        echo '<table border=0 align=center>';
        echo "<tr><td><textarea rows=40 cols=100 name=rackcode id=RCTA class='codepress rackcode'>";
        echo $text . "</textarea></td></tr>\n";
@@ -7016,6 +7102,7 @@ function renderTextEditor ($file_id)
        else
                $syntax = "text";
        echo '<table border=0 align=center>';
+       addJS ('js/codepress/codepress.js');
        echo "<tr><td><textarea rows=45 cols=180 id=file_text name=file_text tabindex=101 class='codepress " . $syntax . "'>\n";
        echo htmlspecialchars ($fullInfo['contents']) . '</textarea></td></tr>';
        echo "<tr><td class=submit><input type=submit value='Save' onclick='file_text.toggleEditor();'>";
@@ -7859,7 +7946,7 @@ function renderObject8021QPorts ($object_id)
                assertUIntArg ('hl_port_id');
                $hl_port_id = intval ($_REQUEST['hl_port_id']);
                $hl_port_name = NULL;
-               echo getAutoScrollScript ("port-$hl_port_id");
+               addAutoScrollScript ("port-$hl_port_id");
        }
        foreach ($object['ports'] as $port)
                if (mb_strlen ($port['name']) and array_key_exists ($port['name'], $desired_config))
@@ -7880,6 +7967,7 @@ function renderObject8021QPorts ($object_id)
                }
        unset ($object);
        $nports = 0; // count only access ports
+       switchportInfoJS ($object_id); // load JS code to make portnames interactive
        foreach ($desired_config as $port_name => $port)
        {
                $text_left = same8021QConfigs ($cached_config[$port_name], $port) ? '' :
@@ -7946,9 +8034,9 @@ function renderObject8021QPorts ($object_id)
                if ($hl_port_name == $port_name)
                {
                        $tdclass .= 'class="border_highlight"';
-                       $ancor = "<a name='port-$hl_port_id'>&nbsp;</a>";
+                       $ancor = "name='port-$hl_port_id'";
                }
-               echo "<tr class='${trclass}' valign=top><td${td_extra} ${tdclass}>${port_name}${ancor}</td>" . $socket_columns;
+               echo "<tr class='${trclass}' valign=top><td${td_extra} ${tdclass} NOWRAP><a class='interactive-portname port-menu nolink' $ancor>${port_name}</a></td>" . $socket_columns;
                echo "<td${td_extra}>${text_left}</td><td class=tdright nowrap${td_extra}>${text_right}</td></tr>";
                if (!array_key_exists ($port_name, $sockets))
                        continue;
@@ -8412,7 +8500,7 @@ function renderObject8021QSync ($object_id)
                assertUIntArg ('hl_port_id');
                $hl_port_id = intval ($_REQUEST['hl_port_id']);
                $hl_port_name = NULL;
-               echo getAutoScrollScript ("port-$hl_port_id");
+               addAutoScrollScript ("port-$hl_port_id");
 
                $object = spotEntity ('object', $object_id);
                amplifyCell ($object);
@@ -8472,12 +8560,27 @@ function renderObject8021QSync ($object_id)
        echo '</td><td class=pcright>';
 
        startPortlet ('preview/resolve');
+
+       switchportInfoJS ($object_id); // load JS code to make portnames interactive
+       // initialize one of three popups: we've got data already
+       $port_config = addslashes (json_encode (formatPortConfigHints ($object_id, $R)));
+       addJS (<<<END
+$(document).ready(function(){
+       var confData = $.parseJSON('$port_config');
+       applyConfData(confData);
+       var menuItem = $('.context-menu-item.itemname-conf');
+       menuItem.addClass($.contextMenu.disabledItemClassName);
+       setItemIcon(menuItem[0], 'ok');
+});
+END
+       , TRUE);
        echo '<table cellspacing=0 cellpadding=5 align=center class=widetable width="100%">';
        if ($maxdecisions)
                echo '<tr><th colspan=2>&nbsp;</th><th colspan=3>discard</th><th>&nbsp;</th></tr>';
        echo '<tr valign=top><th>port</th><th width="40%">last&nbsp;saved&nbsp;version</th>';
        if ($maxdecisions)
        {
+               addJS ('js/racktables.js');
                printOpFormIntro ('resolve8021QConflicts', array ('mutex_rev' => $vswitch['mutex_rev']));
                foreach (array ('left', 'asis', 'right') as $pos)
                        echo "<th class=tdcenter><input type=radio name=column_radio value=${pos} " .
@@ -8608,15 +8711,15 @@ function renderObject8021QSync ($object_id)
                        $left_text = $right_text = 'internal rendering error';
                        break;
                }
-               
+
                $ancor = '';
                $td_class = '';
                if (isset ($hl_port_id) && $hl_port_name == $port_name)
                {
-                       $ancor = "<a name='port-$hl_port_id'>&nbsp;</a>";
+                       $ancor = "name='port-$hl_port_id'";
                        $td_class = ' border_highlight';
                }
-               echo "<tr class='${trclass}'><td class='tdleft${td_class}'>${port_name}${ancor}</td>";
+               echo "<tr class='${trclass}'><td class='tdleft${td_class}' NOWRAP><a class='interactive-portname port-menu nolink' $ancor>${port_name}</a></td>";
                if (!count ($radio_attrs))
                {
                        echo "<td class='tdleft${left_extra}'>${left_text}</td>";
@@ -8842,7 +8945,7 @@ function renderDeployQueue ($dqcode)
 
 // returns '<a...</a>' html string containing a link to specified port or object.
 // link title is "hostname portname" if both parts are defined
-function formatPortLink($host_id, $hostname, $port_id, $portname)
+function formatPortLink($host_id, $hostname, $port_id, $portname, $a_class = '')
 {
        $href = 'index.php?page=object&object_id=' . urlencode($host_id);
        $additional = '';
@@ -8851,6 +8954,8 @@ function formatPortLink($host_id, $hostname, $port_id, $portname)
                $href .= '&hl_port_id=' . urlencode($port_id);
                $additional = "name=\"port-$port_id\"";
        }
+       if (! empty($a_class))
+               $additional .= (empty($additional) ? '' : ' '). "class='$a_class'";
        
        $text_items = array();
        if (isset ($hostname))
@@ -8894,9 +8999,10 @@ function renderDiscoveredNeighbors ($object_id)
        {
                assertUIntArg('hl_port_id');
                $hl_port_id = intval ($_REQUEST['hl_port_id']);
-               echo getAutoScrollScript ("port-$hl_port_id");
+               addAutoScrollScript ("port-$hl_port_id");
        }
 
+       switchportInfoJS($object_id); // load JS code to make portnames interactive
        printOpFormIntro ('importDPData');
        echo '<br><table cellspacing=0 cellpadding=5 align=center class=widetable>';
        echo '<tr><th colspan=2>local port</th><th>remote device</th><th colspan=2>remote port</th><th>&nbsp;</th></tr>';
@@ -9011,9 +9117,12 @@ function renderDiscoveredNeighbors ($object_id)
                                $td_class = '';
                                if (isset ($hl_port_id) and $hl_port_id == $portinfo_local['id'])
                                        $td_class = "class='border_highlight'";
-                               echo "<td rowspan=\"$count\" $td_class>" .
-                                       ($portinfo_local ? formatPortLink ($mydevice['id'], NULL, $portinfo_local['id'], $portinfo_local['name']) : $local_port) .
-                                       ($count > 1 ? " ($count neighbors)" : '') .
+                               echo "<td rowspan=\"$count\" $td_class NOWRAP>" .
+                                       ($portinfo_local ?
+                                               formatPortLink ($mydevice['id'], NULL, $portinfo_local['id'], $portinfo_local['name'], 'interactive-portname port-menu') :
+                                               "<a class='interactive-portname port-menu nolink'>$local_port</a>"
+                                       ) .
+                                       ($count > 1 ? "<br> ($count neighbors)" : '') .
                                        '</td>';
                                $initial_row = FALSE;
                        }
@@ -9062,17 +9171,16 @@ function formatAttributeValue($attribute_id, $record)
        return isset($href) ? "<a href=\"$href\">${record['a_value']}</a>" : $record['a_value'];        
 }
 
-function getAutoScrollScript ($ancor_name)
+function addAutoScrollScript ($ancor_name)
 {
-       echo <<<END
-<script type="text/javascript">
-       $(document).ready(function() {
-               var ancor = document.getElementsByName('$ancor_name')[0];
-               if (ancor)
-                       ancor.scrollIntoView(false);
-       });
-</script>
-END;
+       addJS (<<<END
+$(document).ready(function() {
+       var ancor = document.getElementsByName('$ancor_name')[0];
+       if (ancor)
+               ancor.scrollIntoView(false);
+});
+END
+       , TRUE);
 }
 
 //
@@ -9147,4 +9255,53 @@ function renderGlobalLogEditor()
        echo '</table>';
 }
 
+function switchportInfoJS($object_id)
+{
+       global $gwrxlator;
+       $availible_ops = array
+       (
+               'link' => array ('op' => 'get_link_status', 'gw' => 'getportstatus'),
+               'conf' => array ('op' => 'get_port_conf', 'gw' => 'get8021q'),
+               'mac' =>  array ('op' => 'get_mac_list', 'gw' => 'getmaclist'),
+       );
+       $allowed_ops = array();
+       foreach ($availible_ops as $prefix => $data)
+       {
+               // do not add item unless permitted
+               if (! permitted ('object', 'liveports', $data['op']))
+                       continue;
+               // do not add item unless gwrxlator exists
+               $breed = detectDeviceBreed ($object_id);
+               if (! isset ($breed) || ! isset ($gwrxlator[$data['gw']][$breed]))
+                       continue;
+               $allowed_ops[] = $prefix;
+       }
+
+       // make JS array with allowed items
+       $list = '';
+       foreach ($allowed_ops as $item)
+               $list .= "'" . addslashes ($item) . "', ";
+       $list = trim ($list, ", ");
+
+       addJS ('js/jquery.thumbhover.js');
+       addCSS ('css/jquery.contextmenu.css');
+       addJS ('js/jquery.contextmenu.js');
+       addJS ("enabled_elements = [ $list ];", TRUE);
+       addJS ('js/portinfo.js');
+}
+
+function addAtomCSS()
+{
+       // do not add generated css to page twice
+       static $is_first_call = TRUE;
+       if (! $is_first_call)
+               return;
+       $is_first_call = FALSE;
+
+       $style = '';
+       foreach (array ('F', 'A', 'U', 'T', 'Th', 'Tw', 'Thw') as $statecode)
+               $style .= "td.atom.state_${statecode} { background-color: #" . (getConfigVar ('color_' . $statecode)) . "; }\n";
+       addCSS ($style, TRUE);
+}
+
 ?>
index 7afd9a8..a5b457c 100644 (file)
@@ -94,6 +94,7 @@ $tab['object']['ipv4'] = 'IPv4';
 $tab['object']['ipv6'] = 'IPv6';
 $tab['object']['nat4'] = 'NATv4';
 $tab['object']['livevlans'] = 'Live VLANs';
+$tab['object']['liveports'] = 'Live ports';
 $tab['object']['livecdp'] = 'Live CDP';
 $tab['object']['livelldp'] = 'Live LLDP';
 $tab['object']['livehndp'] = 'Live HNDP';
@@ -115,6 +116,7 @@ $tabhandler['object']['ipv4'] = 'renderIPv4ForObject';
 $tabhandler['object']['ipv6'] = 'renderIPv6ForObject';
 $tabhandler['object']['nat4'] = 'renderNATv4ForObject';
 $tabhandler['object']['livevlans'] = 'renderVLANMembership';
+$tabhandler['object']['liveports'] = 'renderPortsInfo';
 $tabhandler['object']['livecdp'] = 'renderDiscoveredNeighbors';
 $tabhandler['object']['livelldp'] = 'renderDiscoveredNeighbors';
 $tabhandler['object']['livehndp'] = 'renderDiscoveredNeighbors';
@@ -132,6 +134,7 @@ $trigger['object']['ipv4'] = 'trigger_ipv4';
 $trigger['object']['ipv6'] = 'trigger_ipv6';
 $trigger['object']['nat4'] = 'trigger_natv4';
 $trigger['object']['livevlans'] = 'trigger_livevlans';
+$trigger['object']['liveports'] = 'trigger_liveports';
 $trigger['object']['livecdp'] = 'trigger_LiveCDP';
 $trigger['object']['livelldp'] = 'trigger_LiveLLDP';
 $trigger['object']['livehndp'] = 'trigger_LiveHNDP';
index 4d9195b..8bd5dc0 100644 (file)
@@ -79,6 +79,15 @@ function trigger_livevlans ()
        );
 }
 
+// This trigger is on when any of the (get_mac_list, get_link_status) ops permitted
+function trigger_liveports ()
+{
+       if (permitted (NULL, 'liveports', 'get_mac_list') or
+               permitted (NULL, 'liveports', 'get_link_status'))
+               return 'std';
+       return '';
+}
+
 // SNMP port finder tab trigger. At the moment we decide on showing it
 // for pristine switches/PDUs only. Once a user has begun
 // filling the data in, we stop showing the tab.
index 24b2a84..50f1a43 100644 (file)
--- a/index.php
+++ b/index.php
@@ -14,13 +14,7 @@ header ('Content-Type: text/html; charset=UTF-8');
 if (isset ($_REQUEST['tab']) and ! isset ($_SESSION['RTLT'][$pageno]['dont_remember']))
        $_SESSION['RTLT'][$pageno] = array ('tabname' => $tabno, 'time' => time());
 
-echo '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">'."\n";
-echo '<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">'."\n";
-echo '<head><title>' . getTitle ($pageno) . "</title>\n";
-printPageHeaders();
 ?>
-</head>
-<body>
  <table border=0 cellpadding=0 cellspacing=0 width='100%' height='100%' class=maintable>
  <tr class=mainheader>
   <td colspan=2>
@@ -93,11 +87,19 @@ else
        </td>
        </tr>
        </table>
-</body>
-</html>
 <?php
-       ob_end_flush();
+       $body = ob_get_clean();
+       ob_start();
+       echo '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">'."\n";
+       echo '<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">'."\n";
+       echo '<head><title>' . getTitle ($pageno) . "</title>\n";
+       printPageHeaders();
+       echo "</head>\n";
+       echo "<body>\n$body</body>\n";
+       echo '</html>';
+       ob_flush();
 } catch (Exception $e) {
        ob_end_clean();
        printException($e);
 }
+
diff --git a/js/jquery-1.3.1.min.js b/js/jquery-1.3.1.min.js
deleted file mode 100644 (file)
index c327fae..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * jQuery JavaScript Library v1.3.1
- * http://jquery.com/
- *
- * Copyright (c) 2009 John Resig
- * Dual licensed under the MIT and GPL licenses.
- * http://docs.jquery.com/License
- *
- * Date: 2009-01-21 20:42:16 -0500 (Wed, 21 Jan 2009)
- * Revision: 6158
- */
-(function(){var l=this,g,y=l.jQuery,p=l.$,o=l.jQuery=l.$=function(E,F){return new o.fn.init(E,F)},D=/^[^<]*(<(.|\s)+>)[^>]*$|^#([\w-]+)$/,f=/^.[^:#\[\.,]*$/;o.fn=o.prototype={init:function(E,H){E=E||document;if(E.nodeType){this[0]=E;this.length=1;this.context=E;return this}if(typeof E==="string"){var G=D.exec(E);if(G&&(G[1]||!H)){if(G[1]){E=o.clean([G[1]],H)}else{var I=document.getElementById(G[3]);if(I&&I.id!=G[3]){return o().find(E)}var F=o(I||[]);F.context=document;F.selector=E;return F}}else{return o(H).find(E)}}else{if(o.isFunction(E)){return o(document).ready(E)}}if(E.selector&&E.context){this.selector=E.selector;this.context=E.context}return this.setArray(o.makeArray(E))},selector:"",jquery:"1.3.1",size:function(){return this.length},get:function(E){return E===g?o.makeArray(this):this[E]},pushStack:function(F,H,E){var G=o(F);G.prevObject=this;G.context=this.context;if(H==="find"){G.selector=this.selector+(this.selector?" ":"")+E}else{if(H){G.selector=this.selector+"."+H+"("+E+")"}}return G},setArray:function(E){this.length=0;Array.prototype.push.apply(this,E);return this},each:function(F,E){return o.each(this,F,E)},index:function(E){return o.inArray(E&&E.jquery?E[0]:E,this)},attr:function(F,H,G){var E=F;if(typeof F==="string"){if(H===g){return this[0]&&o[G||"attr"](this[0],F)}else{E={};E[F]=H}}return this.each(function(I){for(F in E){o.attr(G?this.style:this,F,o.prop(this,E[F],G,I,F))}})},css:function(E,F){if((E=="width"||E=="height")&&parseFloat(F)<0){F=g}return this.attr(E,F,"curCSS")},text:function(F){if(typeof F!=="object"&&F!=null){return this.empty().append((this[0]&&this[0].ownerDocument||document).createTextNode(F))}var E="";o.each(F||this,function(){o.each(this.childNodes,function(){if(this.nodeType!=8){E+=this.nodeType!=1?this.nodeValue:o.fn.text([this])}})});return E},wrapAll:function(E){if(this[0]){var F=o(E,this[0].ownerDocument).clone();if(this[0].parentNode){F.insertBefore(this[0])}F.map(function(){var G=this;while(G.firstChild){G=G.firstChild}return G}).append(this)}return this},wrapInner:function(E){return this.each(function(){o(this).contents().wrapAll(E)})},wrap:function(E){return this.each(function(){o(this).wrapAll(E)})},append:function(){return this.domManip(arguments,true,function(E){if(this.nodeType==1){this.appendChild(E)}})},prepend:function(){return this.domManip(arguments,true,function(E){if(this.nodeType==1){this.insertBefore(E,this.firstChild)}})},before:function(){return this.domManip(arguments,false,function(E){this.parentNode.insertBefore(E,this)})},after:function(){return this.domManip(arguments,false,function(E){this.parentNode.insertBefore(E,this.nextSibling)})},end:function(){return this.prevObject||o([])},push:[].push,find:function(E){if(this.length===1&&!/,/.test(E)){var G=this.pushStack([],"find",E);G.length=0;o.find(E,this[0],G);return G}else{var F=o.map(this,function(H){return o.find(E,H)});return this.pushStack(/[^+>] [^+>]/.test(E)?o.unique(F):F,"find",E)}},clone:function(F){var E=this.map(function(){if(!o.support.noCloneEvent&&!o.isXMLDoc(this)){var I=this.cloneNode(true),H=document.createElement("div");H.appendChild(I);return o.clean([H.innerHTML])[0]}else{return this.cloneNode(true)}});var G=E.find("*").andSelf().each(function(){if(this[h]!==g){this[h]=null}});if(F===true){this.find("*").andSelf().each(function(I){if(this.nodeType==3){return}var H=o.data(this,"events");for(var K in H){for(var J in H[K]){o.event.add(G[I],K,H[K][J],H[K][J].data)}}})}return E},filter:function(E){return this.pushStack(o.isFunction(E)&&o.grep(this,function(G,F){return E.call(G,F)})||o.multiFilter(E,o.grep(this,function(F){return F.nodeType===1})),"filter",E)},closest:function(E){var F=o.expr.match.POS.test(E)?o(E):null;return this.map(function(){var G=this;while(G&&G.ownerDocument){if(F?F.index(G)>-1:o(G).is(E)){return G}G=G.parentNode}})},not:function(E){if(typeof E==="string"){if(f.test(E)){return this.pushStack(o.multiFilter(E,this,true),"not",E)}else{E=o.multiFilter(E,this)}}var F=E.length&&E[E.length-1]!==g&&!E.nodeType;return this.filter(function(){return F?o.inArray(this,E)<0:this!=E})},add:function(E){return this.pushStack(o.unique(o.merge(this.get(),typeof E==="string"?o(E):o.makeArray(E))))},is:function(E){return !!E&&o.multiFilter(E,this).length>0},hasClass:function(E){return !!E&&this.is("."+E)},val:function(K){if(K===g){var E=this[0];if(E){if(o.nodeName(E,"option")){return(E.attributes.value||{}).specified?E.value:E.text}if(o.nodeName(E,"select")){var I=E.selectedIndex,L=[],M=E.options,H=E.type=="select-one";if(I<0){return null}for(var F=H?I:0,J=H?I+1:M.length;F<J;F++){var G=M[F];if(G.selected){K=o(G).val();if(H){return K}L.push(K)}}return L}return(E.value||"").replace(/\r/g,"")}return g}if(typeof K==="number"){K+=""}return this.each(function(){if(this.nodeType!=1){return}if(o.isArray(K)&&/radio|checkbox/.test(this.type)){this.checked=(o.inArray(this.value,K)>=0||o.inArray(this.name,K)>=0)}else{if(o.nodeName(this,"select")){var N=o.makeArray(K);o("option",this).each(function(){this.selected=(o.inArray(this.value,N)>=0||o.inArray(this.text,N)>=0)});if(!N.length){this.selectedIndex=-1}}else{this.value=K}}})},html:function(E){return E===g?(this[0]?this[0].innerHTML:null):this.empty().append(E)},replaceWith:function(E){return this.after(E).remove()},eq:function(E){return this.slice(E,+E+1)},slice:function(){return this.pushStack(Array.prototype.slice.apply(this,arguments),"slice",Array.prototype.slice.call(arguments).join(","))},map:function(E){return this.pushStack(o.map(this,function(G,F){return E.call(G,F,G)}))},andSelf:function(){return this.add(this.prevObject)},domManip:function(K,N,M){if(this[0]){var J=(this[0].ownerDocument||this[0]).createDocumentFragment(),G=o.clean(K,(this[0].ownerDocument||this[0]),J),I=J.firstChild,E=this.length>1?J.cloneNode(true):J;if(I){for(var H=0,F=this.length;H<F;H++){M.call(L(this[H],I),H>0?E.cloneNode(true):J)}}if(G){o.each(G,z)}}return this;function L(O,P){return N&&o.nodeName(O,"table")&&o.nodeName(P,"tr")?(O.getElementsByTagName("tbody")[0]||O.appendChild(O.ownerDocument.createElement("tbody"))):O}}};o.fn.init.prototype=o.fn;function z(E,F){if(F.src){o.ajax({url:F.src,async:false,dataType:"script"})}else{o.globalEval(F.text||F.textContent||F.innerHTML||"")}if(F.parentNode){F.parentNode.removeChild(F)}}function e(){return +new Date}o.extend=o.fn.extend=function(){var J=arguments[0]||{},H=1,I=arguments.length,E=false,G;if(typeof J==="boolean"){E=J;J=arguments[1]||{};H=2}if(typeof J!=="object"&&!o.isFunction(J)){J={}}if(I==H){J=this;--H}for(;H<I;H++){if((G=arguments[H])!=null){for(var F in G){var K=J[F],L=G[F];if(J===L){continue}if(E&&L&&typeof L==="object"&&!L.nodeType){J[F]=o.extend(E,K||(L.length!=null?[]:{}),L)}else{if(L!==g){J[F]=L}}}}}return J};var b=/z-?index|font-?weight|opacity|zoom|line-?height/i,q=document.defaultView||{},s=Object.prototype.toString;o.extend({noConflict:function(E){l.$=p;if(E){l.jQuery=y}return o},isFunction:function(E){return s.call(E)==="[object Function]"},isArray:function(E){return s.call(E)==="[object Array]"},isXMLDoc:function(E){return E.nodeType===9&&E.documentElement.nodeName!=="HTML"||!!E.ownerDocument&&o.isXMLDoc(E.ownerDocument)},globalEval:function(G){G=o.trim(G);if(G){var F=document.getElementsByTagName("head")[0]||document.documentElement,E=document.createElement("script");E.type="text/javascript";if(o.support.scriptEval){E.appendChild(document.createTextNode(G))}else{E.text=G}F.insertBefore(E,F.firstChild);F.removeChild(E)}},nodeName:function(F,E){return F.nodeName&&F.nodeName.toUpperCase()==E.toUpperCase()},each:function(G,K,F){var E,H=0,I=G.length;if(F){if(I===g){for(E in G){if(K.apply(G[E],F)===false){break}}}else{for(;H<I;){if(K.apply(G[H++],F)===false){break}}}}else{if(I===g){for(E in G){if(K.call(G[E],E,G[E])===false){break}}}else{for(var J=G[0];H<I&&K.call(J,H,J)!==false;J=G[++H]){}}}return G},prop:function(H,I,G,F,E){if(o.isFunction(I)){I=I.call(H,F)}return typeof I==="number"&&G=="curCSS"&&!b.test(E)?I+"px":I},className:{add:function(E,F){o.each((F||"").split(/\s+/),function(G,H){if(E.nodeType==1&&!o.className.has(E.className,H)){E.className+=(E.className?" ":"")+H}})},remove:function(E,F){if(E.nodeType==1){E.className=F!==g?o.grep(E.className.split(/\s+/),function(G){return !o.className.has(F,G)}).join(" "):""}},has:function(F,E){return F&&o.inArray(E,(F.className||F).toString().split(/\s+/))>-1}},swap:function(H,G,I){var E={};for(var F in G){E[F]=H.style[F];H.style[F]=G[F]}I.call(H);for(var F in G){H.style[F]=E[F]}},css:function(G,E,I){if(E=="width"||E=="height"){var K,F={position:"absolute",visibility:"hidden",display:"block"},J=E=="width"?["Left","Right"]:["Top","Bottom"];function H(){K=E=="width"?G.offsetWidth:G.offsetHeight;var M=0,L=0;o.each(J,function(){M+=parseFloat(o.curCSS(G,"padding"+this,true))||0;L+=parseFloat(o.curCSS(G,"border"+this+"Width",true))||0});K-=Math.round(M+L)}if(o(G).is(":visible")){H()}else{o.swap(G,F,H)}return Math.max(0,K)}return o.curCSS(G,E,I)},curCSS:function(I,F,G){var L,E=I.style;if(F=="opacity"&&!o.support.opacity){L=o.attr(E,"opacity");return L==""?"1":L}if(F.match(/float/i)){F=w}if(!G&&E&&E[F]){L=E[F]}else{if(q.getComputedStyle){if(F.match(/float/i)){F="float"}F=F.replace(/([A-Z])/g,"-$1").toLowerCase();var M=q.getComputedStyle(I,null);if(M){L=M.getPropertyValue(F)}if(F=="opacity"&&L==""){L="1"}}else{if(I.currentStyle){var J=F.replace(/\-(\w)/g,function(N,O){return O.toUpperCase()});L=I.currentStyle[F]||I.currentStyle[J];if(!/^\d+(px)?$/i.test(L)&&/^\d/.test(L)){var H=E.left,K=I.runtimeStyle.left;I.runtimeStyle.left=I.currentStyle.left;E.left=L||0;L=E.pixelLeft+"px";E.left=H;I.runtimeStyle.left=K}}}}return L},clean:function(F,K,I){K=K||document;if(typeof K.createElement==="undefined"){K=K.ownerDocument||K[0]&&K[0].ownerDocument||document}if(!I&&F.length===1&&typeof F[0]==="string"){var H=/^<(\w+)\s*\/?>$/.exec(F[0]);if(H){return[K.createElement(H[1])]}}var G=[],E=[],L=K.createElement("div");o.each(F,function(P,R){if(typeof R==="number"){R+=""}if(!R){return}if(typeof R==="string"){R=R.replace(/(<(\w+)[^>]*?)\/>/g,function(T,U,S){return S.match(/^(abbr|br|col|img|input|link|meta|param|hr|area|embed)$/i)?T:U+"></"+S+">"});var O=o.trim(R).toLowerCase();var Q=!O.indexOf("<opt")&&[1,"<select multiple='multiple'>","</select>"]||!O.indexOf("<leg")&&[1,"<fieldset>","</fieldset>"]||O.match(/^<(thead|tbody|tfoot|colg|cap)/)&&[1,"<table>","</table>"]||!O.indexOf("<tr")&&[2,"<table><tbody>","</tbody></table>"]||(!O.indexOf("<td")||!O.indexOf("<th"))&&[3,"<table><tbody><tr>","</tr></tbody></table>"]||!O.indexOf("<col")&&[2,"<table><tbody></tbody><colgroup>","</colgroup></table>"]||!o.support.htmlSerialize&&[1,"div<div>","</div>"]||[0,"",""];L.innerHTML=Q[1]+R+Q[2];while(Q[0]--){L=L.lastChild}if(!o.support.tbody){var N=!O.indexOf("<table")&&O.indexOf("<tbody")<0?L.firstChild&&L.firstChild.childNodes:Q[1]=="<table>"&&O.indexOf("<tbody")<0?L.childNodes:[];for(var M=N.length-1;M>=0;--M){if(o.nodeName(N[M],"tbody")&&!N[M].childNodes.length){N[M].parentNode.removeChild(N[M])}}}if(!o.support.leadingWhitespace&&/^\s/.test(R)){L.insertBefore(K.createTextNode(R.match(/^\s*/)[0]),L.firstChild)}R=o.makeArray(L.childNodes)}if(R.nodeType){G.push(R)}else{G=o.merge(G,R)}});if(I){for(var J=0;G[J];J++){if(o.nodeName(G[J],"script")&&(!G[J].type||G[J].type.toLowerCase()==="text/javascript")){E.push(G[J].parentNode?G[J].parentNode.removeChild(G[J]):G[J])}else{if(G[J].nodeType===1){G.splice.apply(G,[J+1,0].concat(o.makeArray(G[J].getElementsByTagName("script"))))}I.appendChild(G[J])}}return E}return G},attr:function(J,G,K){if(!J||J.nodeType==3||J.nodeType==8){return g}var H=!o.isXMLDoc(J),L=K!==g;G=H&&o.props[G]||G;if(J.tagName){var F=/href|src|style/.test(G);if(G=="selected"&&J.parentNode){J.parentNode.selectedIndex}if(G in J&&H&&!F){if(L){if(G=="type"&&o.nodeName(J,"input")&&J.parentNode){throw"type property can't be changed"}J[G]=K}if(o.nodeName(J,"form")&&J.getAttributeNode(G)){return J.getAttributeNode(G).nodeValue}if(G=="tabIndex"){var I=J.getAttributeNode("tabIndex");return I&&I.specified?I.value:J.nodeName.match(/(button|input|object|select|textarea)/i)?0:J.nodeName.match(/^(a|area)$/i)&&J.href?0:g}return J[G]}if(!o.support.style&&H&&G=="style"){return o.attr(J.style,"cssText",K)}if(L){J.setAttribute(G,""+K)}var E=!o.support.hrefNormalized&&H&&F?J.getAttribute(G,2):J.getAttribute(G);return E===null?g:E}if(!o.support.opacity&&G=="opacity"){if(L){J.zoom=1;J.filter=(J.filter||"").replace(/alpha\([^)]*\)/,"")+(parseInt(K)+""=="NaN"?"":"alpha(opacity="+K*100+")")}return J.filter&&J.filter.indexOf("opacity=")>=0?(parseFloat(J.filter.match(/opacity=([^)]*)/)[1])/100)+"":""}G=G.replace(/-([a-z])/ig,function(M,N){return N.toUpperCase()});if(L){J[G]=K}return J[G]},trim:function(E){return(E||"").replace(/^\s+|\s+$/g,"")},makeArray:function(G){var E=[];if(G!=null){var F=G.length;if(F==null||typeof G==="string"||o.isFunction(G)||G.setInterval){E[0]=G}else{while(F){E[--F]=G[F]}}}return E},inArray:function(G,H){for(var E=0,F=H.length;E<F;E++){if(H[E]===G){return E}}return -1},merge:function(H,E){var F=0,G,I=H.length;if(!o.support.getAll){while((G=E[F++])!=null){if(G.nodeType!=8){H[I++]=G}}}else{while((G=E[F++])!=null){H[I++]=G}}return H},unique:function(K){var F=[],E={};try{for(var G=0,H=K.length;G<H;G++){var J=o.data(K[G]);if(!E[J]){E[J]=true;F.push(K[G])}}}catch(I){F=K}return F},grep:function(F,J,E){var G=[];for(var H=0,I=F.length;H<I;H++){if(!E!=!J(F[H],H)){G.push(F[H])}}return G},map:function(E,J){var F=[];for(var G=0,H=E.length;G<H;G++){var I=J(E[G],G);if(I!=null){F[F.length]=I}}return F.concat.apply([],F)}});var C=navigator.userAgent.toLowerCase();o.browser={version:(C.match(/.+(?:rv|it|ra|ie)[\/: ]([\d.]+)/)||[0,"0"])[1],safari:/webkit/.test(C),opera:/opera/.test(C),msie:/msie/.test(C)&&!/opera/.test(C),mozilla:/mozilla/.test(C)&&!/(compatible|webkit)/.test(C)};o.each({parent:function(E){return E.parentNode},parents:function(E){return o.dir(E,"parentNode")},next:function(E){return o.nth(E,2,"nextSibling")},prev:function(E){return o.nth(E,2,"previousSibling")},nextAll:function(E){return o.dir(E,"nextSibling")},prevAll:function(E){return o.dir(E,"previousSibling")},siblings:function(E){return o.sibling(E.parentNode.firstChild,E)},children:function(E){return o.sibling(E.firstChild)},contents:function(E){return o.nodeName(E,"iframe")?E.contentDocument||E.contentWindow.document:o.makeArray(E.childNodes)}},function(E,F){o.fn[E]=function(G){var H=o.map(this,F);if(G&&typeof G=="string"){H=o.multiFilter(G,H)}return this.pushStack(o.unique(H),E,G)}});o.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(E,F){o.fn[E]=function(){var G=arguments;return this.each(function(){for(var H=0,I=G.length;H<I;H++){o(G[H])[F](this)}})}});o.each({removeAttr:function(E){o.attr(this,E,"");if(this.nodeType==1){this.removeAttribute(E)}},addClass:function(E){o.className.add(this,E)},removeClass:function(E){o.className.remove(this,E)},toggleClass:function(F,E){if(typeof E!=="boolean"){E=!o.className.has(this,F)}o.className[E?"add":"remove"](this,F)},remove:function(E){if(!E||o.filter(E,[this]).length){o("*",this).add([this]).each(function(){o.event.remove(this);o.removeData(this)});if(this.parentNode){this.parentNode.removeChild(this)}}},empty:function(){o(">*",this).remove();while(this.firstChild){this.removeChild(this.firstChild)}}},function(E,F){o.fn[E]=function(){return this.each(F,arguments)}});function j(E,F){return E[0]&&parseInt(o.curCSS(E[0],F,true),10)||0}var h="jQuery"+e(),v=0,A={};o.extend({cache:{},data:function(F,E,G){F=F==l?A:F;var H=F[h];if(!H){H=F[h]=++v}if(E&&!o.cache[H]){o.cache[H]={}}if(G!==g){o.cache[H][E]=G}return E?o.cache[H][E]:H},removeData:function(F,E){F=F==l?A:F;var H=F[h];if(E){if(o.cache[H]){delete o.cache[H][E];E="";for(E in o.cache[H]){break}if(!E){o.removeData(F)}}}else{try{delete F[h]}catch(G){if(F.removeAttribute){F.removeAttribute(h)}}delete o.cache[H]}},queue:function(F,E,H){if(F){E=(E||"fx")+"queue";var G=o.data(F,E);if(!G||o.isArray(H)){G=o.data(F,E,o.makeArray(H))}else{if(H){G.push(H)}}}return G},dequeue:function(H,G){var E=o.queue(H,G),F=E.shift();if(!G||G==="fx"){F=E[0]}if(F!==g){F.call(H)}}});o.fn.extend({data:function(E,G){var H=E.split(".");H[1]=H[1]?"."+H[1]:"";if(G===g){var F=this.triggerHandler("getData"+H[1]+"!",[H[0]]);if(F===g&&this.length){F=o.data(this[0],E)}return F===g&&H[1]?this.data(H[0]):F}else{return this.trigger("setData"+H[1]+"!",[H[0],G]).each(function(){o.data(this,E,G)})}},removeData:function(E){return this.each(function(){o.removeData(this,E)})},queue:function(E,F){if(typeof E!=="string"){F=E;E="fx"}if(F===g){return o.queue(this[0],E)}return this.each(function(){var G=o.queue(this,E,F);if(E=="fx"&&G.length==1){G[0].call(this)}})},dequeue:function(E){return this.each(function(){o.dequeue(this,E)})}});
-/*
- * Sizzle CSS Selector Engine - v0.9.3
- *  Copyright 2009, The Dojo Foundation
- *  Released under the MIT, BSD, and GPL Licenses.
- *  More information: http://sizzlejs.com/
- */
-(function(){var Q=/((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^[\]]*\]|['"][^'"]+['"]|[^[\]'"]+)+\]|\\.|[^ >+~,(\[]+)+|[>+~])(\s*,\s*)?/g,K=0,G=Object.prototype.toString;var F=function(X,T,aa,ab){aa=aa||[];T=T||document;if(T.nodeType!==1&&T.nodeType!==9){return[]}if(!X||typeof X!=="string"){return aa}var Y=[],V,ae,ah,S,ac,U,W=true;Q.lastIndex=0;while((V=Q.exec(X))!==null){Y.push(V[1]);if(V[2]){U=RegExp.rightContext;break}}if(Y.length>1&&L.exec(X)){if(Y.length===2&&H.relative[Y[0]]){ae=I(Y[0]+Y[1],T)}else{ae=H.relative[Y[0]]?[T]:F(Y.shift(),T);while(Y.length){X=Y.shift();if(H.relative[X]){X+=Y.shift()}ae=I(X,ae)}}}else{var ad=ab?{expr:Y.pop(),set:E(ab)}:F.find(Y.pop(),Y.length===1&&T.parentNode?T.parentNode:T,P(T));ae=F.filter(ad.expr,ad.set);if(Y.length>0){ah=E(ae)}else{W=false}while(Y.length){var ag=Y.pop(),af=ag;if(!H.relative[ag]){ag=""}else{af=Y.pop()}if(af==null){af=T}H.relative[ag](ah,af,P(T))}}if(!ah){ah=ae}if(!ah){throw"Syntax error, unrecognized expression: "+(ag||X)}if(G.call(ah)==="[object Array]"){if(!W){aa.push.apply(aa,ah)}else{if(T.nodeType===1){for(var Z=0;ah[Z]!=null;Z++){if(ah[Z]&&(ah[Z]===true||ah[Z].nodeType===1&&J(T,ah[Z]))){aa.push(ae[Z])}}}else{for(var Z=0;ah[Z]!=null;Z++){if(ah[Z]&&ah[Z].nodeType===1){aa.push(ae[Z])}}}}}else{E(ah,aa)}if(U){F(U,T,aa,ab)}return aa};F.matches=function(S,T){return F(S,null,null,T)};F.find=function(Z,S,aa){var Y,W;if(!Z){return[]}for(var V=0,U=H.order.length;V<U;V++){var X=H.order[V],W;if((W=H.match[X].exec(Z))){var T=RegExp.leftContext;if(T.substr(T.length-1)!=="\\"){W[1]=(W[1]||"").replace(/\\/g,"");Y=H.find[X](W,S,aa);if(Y!=null){Z=Z.replace(H.match[X],"");break}}}}if(!Y){Y=S.getElementsByTagName("*")}return{set:Y,expr:Z}};F.filter=function(ab,aa,ae,V){var U=ab,ag=[],Y=aa,X,S;while(ab&&aa.length){for(var Z in H.filter){if((X=H.match[Z].exec(ab))!=null){var T=H.filter[Z],af,ad;S=false;if(Y==ag){ag=[]}if(H.preFilter[Z]){X=H.preFilter[Z](X,Y,ae,ag,V);if(!X){S=af=true}else{if(X===true){continue}}}if(X){for(var W=0;(ad=Y[W])!=null;W++){if(ad){af=T(ad,X,W,Y);var ac=V^!!af;if(ae&&af!=null){if(ac){S=true}else{Y[W]=false}}else{if(ac){ag.push(ad);S=true}}}}}if(af!==g){if(!ae){Y=ag}ab=ab.replace(H.match[Z],"");if(!S){return[]}break}}}ab=ab.replace(/\s*,\s*/,"");if(ab==U){if(S==null){throw"Syntax error, unrecognized expression: "+ab}else{break}}U=ab}return Y};var H=F.selectors={order:["ID","NAME","TAG"],match:{ID:/#((?:[\w\u00c0-\uFFFF_-]|\\.)+)/,CLASS:/\.((?:[\w\u00c0-\uFFFF_-]|\\.)+)/,NAME:/\[name=['"]*((?:[\w\u00c0-\uFFFF_-]|\\.)+)['"]*\]/,ATTR:/\[\s*((?:[\w\u00c0-\uFFFF_-]|\\.)+)\s*(?:(\S?=)\s*(['"]*)(.*?)\3|)\s*\]/,TAG:/^((?:[\w\u00c0-\uFFFF\*_-]|\\.)+)/,CHILD:/:(only|nth|last|first)-child(?:\((even|odd|[\dn+-]*)\))?/,POS:/:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^-]|$)/,PSEUDO:/:((?:[\w\u00c0-\uFFFF_-]|\\.)+)(?:\((['"]*)((?:\([^\)]+\)|[^\2\(\)]*)+)\2\))?/},attrMap:{"class":"className","for":"htmlFor"},attrHandle:{href:function(S){return S.getAttribute("href")}},relative:{"+":function(W,T){for(var U=0,S=W.length;U<S;U++){var V=W[U];if(V){var X=V.previousSibling;while(X&&X.nodeType!==1){X=X.previousSibling}W[U]=typeof T==="string"?X||false:X===T}}if(typeof T==="string"){F.filter(T,W,true)}},">":function(X,T,Y){if(typeof T==="string"&&!/\W/.test(T)){T=Y?T:T.toUpperCase();for(var U=0,S=X.length;U<S;U++){var W=X[U];if(W){var V=W.parentNode;X[U]=V.nodeName===T?V:false}}}else{for(var U=0,S=X.length;U<S;U++){var W=X[U];if(W){X[U]=typeof T==="string"?W.parentNode:W.parentNode===T}}if(typeof T==="string"){F.filter(T,X,true)}}},"":function(V,T,X){var U="done"+(K++),S=R;if(!T.match(/\W/)){var W=T=X?T:T.toUpperCase();S=O}S("parentNode",T,U,V,W,X)},"~":function(V,T,X){var U="done"+(K++),S=R;if(typeof T==="string"&&!T.match(/\W/)){var W=T=X?T:T.toUpperCase();S=O}S("previousSibling",T,U,V,W,X)}},find:{ID:function(T,U,V){if(typeof U.getElementById!=="undefined"&&!V){var S=U.getElementById(T[1]);return S?[S]:[]}},NAME:function(S,T,U){if(typeof T.getElementsByName!=="undefined"&&!U){return T.getElementsByName(S[1])}},TAG:function(S,T){return T.getElementsByTagName(S[1])}},preFilter:{CLASS:function(V,T,U,S,Y){V=" "+V[1].replace(/\\/g,"")+" ";var X;for(var W=0;(X=T[W])!=null;W++){if(X){if(Y^(" "+X.className+" ").indexOf(V)>=0){if(!U){S.push(X)}}else{if(U){T[W]=false}}}}return false},ID:function(S){return S[1].replace(/\\/g,"")},TAG:function(T,S){for(var U=0;S[U]===false;U++){}return S[U]&&P(S[U])?T[1]:T[1].toUpperCase()},CHILD:function(S){if(S[1]=="nth"){var T=/(-?)(\d*)n((?:\+|-)?\d*)/.exec(S[2]=="even"&&"2n"||S[2]=="odd"&&"2n+1"||!/\D/.test(S[2])&&"0n+"+S[2]||S[2]);S[2]=(T[1]+(T[2]||1))-0;S[3]=T[3]-0}S[0]="done"+(K++);return S},ATTR:function(T){var S=T[1].replace(/\\/g,"");if(H.attrMap[S]){T[1]=H.attrMap[S]}if(T[2]==="~="){T[4]=" "+T[4]+" "}return T},PSEUDO:function(W,T,U,S,X){if(W[1]==="not"){if(W[3].match(Q).length>1){W[3]=F(W[3],null,null,T)}else{var V=F.filter(W[3],T,U,true^X);if(!U){S.push.apply(S,V)}return false}}else{if(H.match.POS.test(W[0])){return true}}return W},POS:function(S){S.unshift(true);return S}},filters:{enabled:function(S){return S.disabled===false&&S.type!=="hidden"},disabled:function(S){return S.disabled===true},checked:function(S){return S.checked===true},selected:function(S){S.parentNode.selectedIndex;return S.selected===true},parent:function(S){return !!S.firstChild},empty:function(S){return !S.firstChild},has:function(U,T,S){return !!F(S[3],U).length},header:function(S){return/h\d/i.test(S.nodeName)},text:function(S){return"text"===S.type},radio:function(S){return"radio"===S.type},checkbox:function(S){return"checkbox"===S.type},file:function(S){return"file"===S.type},password:function(S){return"password"===S.type},submit:function(S){return"submit"===S.type},image:function(S){return"image"===S.type},reset:function(S){return"reset"===S.type},button:function(S){return"button"===S.type||S.nodeName.toUpperCase()==="BUTTON"},input:function(S){return/input|select|textarea|button/i.test(S.nodeName)}},setFilters:{first:function(T,S){return S===0},last:function(U,T,S,V){return T===V.length-1},even:function(T,S){return S%2===0},odd:function(T,S){return S%2===1},lt:function(U,T,S){return T<S[3]-0},gt:function(U,T,S){return T>S[3]-0},nth:function(U,T,S){return S[3]-0==T},eq:function(U,T,S){return S[3]-0==T}},filter:{CHILD:function(S,V){var Y=V[1],Z=S.parentNode;var X=V[0];if(Z&&(!Z[X]||!S.nodeIndex)){var W=1;for(var T=Z.firstChild;T;T=T.nextSibling){if(T.nodeType==1){T.nodeIndex=W++}}Z[X]=W-1}if(Y=="first"){return S.nodeIndex==1}else{if(Y=="last"){return S.nodeIndex==Z[X]}else{if(Y=="only"){return Z[X]==1}else{if(Y=="nth"){var ab=false,U=V[2],aa=V[3];if(U==1&&aa==0){return true}if(U==0){if(S.nodeIndex==aa){ab=true}}else{if((S.nodeIndex-aa)%U==0&&(S.nodeIndex-aa)/U>=0){ab=true}}return ab}}}}},PSEUDO:function(Y,U,V,Z){var T=U[1],W=H.filters[T];if(W){return W(Y,V,U,Z)}else{if(T==="contains"){return(Y.textContent||Y.innerText||"").indexOf(U[3])>=0}else{if(T==="not"){var X=U[3];for(var V=0,S=X.length;V<S;V++){if(X[V]===Y){return false}}return true}}}},ID:function(T,S){return T.nodeType===1&&T.getAttribute("id")===S},TAG:function(T,S){return(S==="*"&&T.nodeType===1)||T.nodeName===S},CLASS:function(T,S){return S.test(T.className)},ATTR:function(W,U){var S=H.attrHandle[U[1]]?H.attrHandle[U[1]](W):W[U[1]]||W.getAttribute(U[1]),X=S+"",V=U[2],T=U[4];return S==null?V==="!=":V==="="?X===T:V==="*="?X.indexOf(T)>=0:V==="~="?(" "+X+" ").indexOf(T)>=0:!U[4]?S:V==="!="?X!=T:V==="^="?X.indexOf(T)===0:V==="$="?X.substr(X.length-T.length)===T:V==="|="?X===T||X.substr(0,T.length+1)===T+"-":false},POS:function(W,T,U,X){var S=T[2],V=H.setFilters[S];if(V){return V(W,U,T,X)}}}};var L=H.match.POS;for(var N in H.match){H.match[N]=RegExp(H.match[N].source+/(?![^\[]*\])(?![^\(]*\))/.source)}var E=function(T,S){T=Array.prototype.slice.call(T);if(S){S.push.apply(S,T);return S}return T};try{Array.prototype.slice.call(document.documentElement.childNodes)}catch(M){E=function(W,V){var T=V||[];if(G.call(W)==="[object Array]"){Array.prototype.push.apply(T,W)}else{if(typeof W.length==="number"){for(var U=0,S=W.length;U<S;U++){T.push(W[U])}}else{for(var U=0;W[U];U++){T.push(W[U])}}}return T}}(function(){var T=document.createElement("form"),U="script"+(new Date).getTime();T.innerHTML="<input name='"+U+"'/>";var S=document.documentElement;S.insertBefore(T,S.firstChild);if(!!document.getElementById(U)){H.find.ID=function(W,X,Y){if(typeof X.getElementById!=="undefined"&&!Y){var V=X.getElementById(W[1]);return V?V.id===W[1]||typeof V.getAttributeNode!=="undefined"&&V.getAttributeNode("id").nodeValue===W[1]?[V]:g:[]}};H.filter.ID=function(X,V){var W=typeof X.getAttributeNode!=="undefined"&&X.getAttributeNode("id");return X.nodeType===1&&W&&W.nodeValue===V}}S.removeChild(T)})();(function(){var S=document.createElement("div");S.appendChild(document.createComment(""));if(S.getElementsByTagName("*").length>0){H.find.TAG=function(T,X){var W=X.getElementsByTagName(T[1]);if(T[1]==="*"){var V=[];for(var U=0;W[U];U++){if(W[U].nodeType===1){V.push(W[U])}}W=V}return W}}S.innerHTML="<a href='#'></a>";if(S.firstChild&&S.firstChild.getAttribute("href")!=="#"){H.attrHandle.href=function(T){return T.getAttribute("href",2)}}})();if(document.querySelectorAll){(function(){var S=F,T=document.createElement("div");T.innerHTML="<p class='TEST'></p>";if(T.querySelectorAll&&T.querySelectorAll(".TEST").length===0){return}F=function(X,W,U,V){W=W||document;if(!V&&W.nodeType===9&&!P(W)){try{return E(W.querySelectorAll(X),U)}catch(Y){}}return S(X,W,U,V)};F.find=S.find;F.filter=S.filter;F.selectors=S.selectors;F.matches=S.matches})()}if(document.getElementsByClassName&&document.documentElement.getElementsByClassName){H.order.splice(1,0,"CLASS");H.find.CLASS=function(S,T){return T.getElementsByClassName(S[1])}}function O(T,Z,Y,ac,aa,ab){for(var W=0,U=ac.length;W<U;W++){var S=ac[W];if(S){S=S[T];var X=false;while(S&&S.nodeType){var V=S[Y];if(V){X=ac[V];break}if(S.nodeType===1&&!ab){S[Y]=W}if(S.nodeName===Z){X=S;break}S=S[T]}ac[W]=X}}}function R(T,Y,X,ab,Z,aa){for(var V=0,U=ab.length;V<U;V++){var S=ab[V];if(S){S=S[T];var W=false;while(S&&S.nodeType){if(S[X]){W=ab[S[X]];break}if(S.nodeType===1){if(!aa){S[X]=V}if(typeof Y!=="string"){if(S===Y){W=true;break}}else{if(F.filter(Y,[S]).length>0){W=S;break}}}S=S[T]}ab[V]=W}}}var J=document.compareDocumentPosition?function(T,S){return T.compareDocumentPosition(S)&16}:function(T,S){return T!==S&&(T.contains?T.contains(S):true)};var P=function(S){return S.nodeType===9&&S.documentElement.nodeName!=="HTML"||!!S.ownerDocument&&P(S.ownerDocument)};var I=function(S,Z){var V=[],W="",X,U=Z.nodeType?[Z]:Z;while((X=H.match.PSEUDO.exec(S))){W+=X[0];S=S.replace(H.match.PSEUDO,"")}S=H.relative[S]?S+"*":S;for(var Y=0,T=U.length;Y<T;Y++){F(S,U[Y],V)}return F.filter(W,V)};o.find=F;o.filter=F.filter;o.expr=F.selectors;o.expr[":"]=o.expr.filters;F.selectors.filters.hidden=function(S){return"hidden"===S.type||o.css(S,"display")==="none"||o.css(S,"visibility")==="hidden"};F.selectors.filters.visible=function(S){return"hidden"!==S.type&&o.css(S,"display")!=="none"&&o.css(S,"visibility")!=="hidden"};F.selectors.filters.animated=function(S){return o.grep(o.timers,function(T){return S===T.elem}).length};o.multiFilter=function(U,S,T){if(T){U=":not("+U+")"}return F.matches(U,S)};o.dir=function(U,T){var S=[],V=U[T];while(V&&V!=document){if(V.nodeType==1){S.push(V)}V=V[T]}return S};o.nth=function(W,S,U,V){S=S||1;var T=0;for(;W;W=W[U]){if(W.nodeType==1&&++T==S){break}}return W};o.sibling=function(U,T){var S=[];for(;U;U=U.nextSibling){if(U.nodeType==1&&U!=T){S.push(U)}}return S};return;l.Sizzle=F})();o.event={add:function(I,F,H,K){if(I.nodeType==3||I.nodeType==8){return}if(I.setInterval&&I!=l){I=l}if(!H.guid){H.guid=this.guid++}if(K!==g){var G=H;H=this.proxy(G);H.data=K}var E=o.data(I,"events")||o.data(I,"events",{}),J=o.data(I,"handle")||o.data(I,"handle",function(){return typeof o!=="undefined"&&!o.event.triggered?o.event.handle.apply(arguments.callee.elem,arguments):g});J.elem=I;o.each(F.split(/\s+/),function(M,N){var O=N.split(".");N=O.shift();H.type=O.slice().sort().join(".");var L=E[N];if(o.event.specialAll[N]){o.event.specialAll[N].setup.call(I,K,O)}if(!L){L=E[N]={};if(!o.event.special[N]||o.event.special[N].setup.call(I,K,O)===false){if(I.addEventListener){I.addEventListener(N,J,false)}else{if(I.attachEvent){I.attachEvent("on"+N,J)}}}}L[H.guid]=H;o.event.global[N]=true});I=null},guid:1,global:{},remove:function(K,H,J){if(K.nodeType==3||K.nodeType==8){return}var G=o.data(K,"events"),F,E;if(G){if(H===g||(typeof H==="string"&&H.charAt(0)==".")){for(var I in G){this.remove(K,I+(H||""))}}else{if(H.type){J=H.handler;H=H.type}o.each(H.split(/\s+/),function(M,O){var Q=O.split(".");O=Q.shift();var N=RegExp("(^|\\.)"+Q.slice().sort().join(".*\\.")+"(\\.|$)");if(G[O]){if(J){delete G[O][J.guid]}else{for(var P in G[O]){if(N.test(G[O][P].type)){delete G[O][P]}}}if(o.event.specialAll[O]){o.event.specialAll[O].teardown.call(K,Q)}for(F in G[O]){break}if(!F){if(!o.event.special[O]||o.event.special[O].teardown.call(K,Q)===false){if(K.removeEventListener){K.removeEventListener(O,o.data(K,"handle"),false)}else{if(K.detachEvent){K.detachEvent("on"+O,o.data(K,"handle"))}}}F=null;delete G[O]}}})}for(F in G){break}if(!F){var L=o.data(K,"handle");if(L){L.elem=null}o.removeData(K,"events");o.removeData(K,"handle")}}},trigger:function(I,K,H,E){var G=I.type||I;if(!E){I=typeof I==="object"?I[h]?I:o.extend(o.Event(G),I):o.Event(G);if(G.indexOf("!")>=0){I.type=G=G.slice(0,-1);I.exclusive=true}if(!H){I.stopPropagation();if(this.global[G]){o.each(o.cache,function(){if(this.events&&this.events[G]){o.event.trigger(I,K,this.handle.elem)}})}}if(!H||H.nodeType==3||H.nodeType==8){return g}I.result=g;I.target=H;K=o.makeArray(K);K.unshift(I)}I.currentTarget=H;var J=o.data(H,"handle");if(J){J.apply(H,K)}if((!H[G]||(o.nodeName(H,"a")&&G=="click"))&&H["on"+G]&&H["on"+G].apply(H,K)===false){I.result=false}if(!E&&H[G]&&!I.isDefaultPrevented()&&!(o.nodeName(H,"a")&&G=="click")){this.triggered=true;try{H[G]()}catch(L){}}this.triggered=false;if(!I.isPropagationStopped()){var F=H.parentNode||H.ownerDocument;if(F){o.event.trigger(I,K,F,true)}}},handle:function(K){var J,E;K=arguments[0]=o.event.fix(K||l.event);var L=K.type.split(".");K.type=L.shift();J=!L.length&&!K.exclusive;var I=RegExp("(^|\\.)"+L.slice().sort().join(".*\\.")+"(\\.|$)");E=(o.data(this,"events")||{})[K.type];for(var G in E){var H=E[G];if(J||I.test(H.type)){K.handler=H;K.data=H.data;var F=H.apply(this,arguments);if(F!==g){K.result=F;if(F===false){K.preventDefault();K.stopPropagation()}}if(K.isImmediatePropagationStopped()){break}}}},props:"altKey attrChange attrName bubbles button cancelable charCode clientX clientY ctrlKey currentTarget data detail eventPhase fromElement handler keyCode metaKey newValue originalTarget pageX pageY prevValue relatedNode relatedTarget screenX screenY shiftKey srcElement target toElement view wheelDelta which".split(" "),fix:function(H){if(H[h]){return H}var F=H;H=o.Event(F);for(var G=this.props.length,J;G;){J=this.props[--G];H[J]=F[J]}if(!H.target){H.target=H.srcElement||document}if(H.target.nodeType==3){H.target=H.target.parentNode}if(!H.relatedTarget&&H.fromElement){H.relatedTarget=H.fromElement==H.target?H.toElement:H.fromElement}if(H.pageX==null&&H.clientX!=null){var I=document.documentElement,E=document.body;H.pageX=H.clientX+(I&&I.scrollLeft||E&&E.scrollLeft||0)-(I.clientLeft||0);H.pageY=H.clientY+(I&&I.scrollTop||E&&E.scrollTop||0)-(I.clientTop||0)}if(!H.which&&((H.charCode||H.charCode===0)?H.charCode:H.keyCode)){H.which=H.charCode||H.keyCode}if(!H.metaKey&&H.ctrlKey){H.metaKey=H.ctrlKey}if(!H.which&&H.button){H.which=(H.button&1?1:(H.button&2?3:(H.button&4?2:0)))}return H},proxy:function(F,E){E=E||function(){return F.apply(this,arguments)};E.guid=F.guid=F.guid||E.guid||this.guid++;return E},special:{ready:{setup:B,teardown:function(){}}},specialAll:{live:{setup:function(E,F){o.event.add(this,F[0],c)},teardown:function(G){if(G.length){var E=0,F=RegExp("(^|\\.)"+G[0]+"(\\.|$)");o.each((o.data(this,"events").live||{}),function(){if(F.test(this.type)){E++}});if(E<1){o.event.remove(this,G[0],c)}}}}}};o.Event=function(E){if(!this.preventDefault){return new o.Event(E)}if(E&&E.type){this.originalEvent=E;this.type=E.type}else{this.type=E}this.timeStamp=e();this[h]=true};function k(){return false}function u(){return true}o.Event.prototype={preventDefault:function(){this.isDefaultPrevented=u;var E=this.originalEvent;if(!E){return}if(E.preventDefault){E.preventDefault()}E.returnValue=false},stopPropagation:function(){this.isPropagationStopped=u;var E=this.originalEvent;if(!E){return}if(E.stopPropagation){E.stopPropagation()}E.cancelBubble=true},stopImmediatePropagation:function(){this.isImmediatePropagationStopped=u;this.stopPropagation()},isDefaultPrevented:k,isPropagationStopped:k,isImmediatePropagationStopped:k};var a=function(F){var E=F.relatedTarget;while(E&&E!=this){try{E=E.parentNode}catch(G){E=this}}if(E!=this){F.type=F.data;o.event.handle.apply(this,arguments)}};o.each({mouseover:"mouseenter",mouseout:"mouseleave"},function(F,E){o.event.special[E]={setup:function(){o.event.add(this,F,a,E)},teardown:function(){o.event.remove(this,F,a)}}});o.fn.extend({bind:function(F,G,E){return F=="unload"?this.one(F,G,E):this.each(function(){o.event.add(this,F,E||G,E&&G)})},one:function(G,H,F){var E=o.event.proxy(F||H,function(I){o(this).unbind(I,E);return(F||H).apply(this,arguments)});return this.each(function(){o.event.add(this,G,E,F&&H)})},unbind:function(F,E){return this.each(function(){o.event.remove(this,F,E)})},trigger:function(E,F){return this.each(function(){o.event.trigger(E,F,this)})},triggerHandler:function(E,G){if(this[0]){var F=o.Event(E);F.preventDefault();F.stopPropagation();o.event.trigger(F,G,this[0]);return F.result}},toggle:function(G){var E=arguments,F=1;while(F<E.length){o.event.proxy(G,E[F++])}return this.click(o.event.proxy(G,function(H){this.lastToggle=(this.lastToggle||0)%F;H.preventDefault();return E[this.lastToggle++].apply(this,arguments)||false}))},hover:function(E,F){return this.mouseenter(E).mouseleave(F)},ready:function(E){B();if(o.isReady){E.call(document,o)}else{o.readyList.push(E)}return this},live:function(G,F){var E=o.event.proxy(F);E.guid+=this.selector+G;o(document).bind(i(G,this.selector),this.selector,E);return this},die:function(F,E){o(document).unbind(i(F,this.selector),E?{guid:E.guid+this.selector+F}:null);return this}});function c(H){var E=RegExp("(^|\\.)"+H.type+"(\\.|$)"),G=true,F=[];o.each(o.data(this,"events").live||[],function(I,J){if(E.test(J.type)){var K=o(H.target).closest(J.data)[0];if(K){F.push({elem:K,fn:J})}}});o.each(F,function(){if(this.fn.call(this.elem,H,this.fn.data)===false){G=false}});return G}function i(F,E){return["live",F,E.replace(/\./g,"`").replace(/ /g,"|")].join(".")}o.extend({isReady:false,readyList:[],ready:function(){if(!o.isReady){o.isReady=true;if(o.readyList){o.each(o.readyList,function(){this.call(document,o)});o.readyList=null}o(document).triggerHandler("ready")}}});var x=false;function B(){if(x){return}x=true;if(document.addEventListener){document.addEventListener("DOMContentLoaded",function(){document.removeEventListener("DOMContentLoaded",arguments.callee,false);o.ready()},false)}else{if(document.attachEvent){document.attachEvent("onreadystatechange",function(){if(document.readyState==="complete"){document.detachEvent("onreadystatechange",arguments.callee);o.ready()}});if(document.documentElement.doScroll&&typeof l.frameElement==="undefined"){(function(){if(o.isReady){return}try{document.documentElement.doScroll("left")}catch(E){setTimeout(arguments.callee,0);return}o.ready()})()}}}o.event.add(l,"load",o.ready)}o.each(("blur,focus,load,resize,scroll,unload,click,dblclick,mousedown,mouseup,mousemove,mouseover,mouseout,mouseenter,mouseleave,change,select,submit,keydown,keypress,keyup,error").split(","),function(F,E){o.fn[E]=function(G){return G?this.bind(E,G):this.trigger(E)}});o(l).bind("unload",function(){for(var E in o.cache){if(E!=1&&o.cache[E].handle){o.event.remove(o.cache[E].handle.elem)}}});(function(){o.support={};var F=document.documentElement,G=document.createElement("script"),K=document.createElement("div"),J="script"+(new Date).getTime();K.style.display="none";K.innerHTML='   <link/><table></table><a href="/a" style="color:red;float:left;opacity:.5;">a</a><select><option>text</option></select><object><param/></object>';var H=K.getElementsByTagName("*"),E=K.getElementsByTagName("a")[0];if(!H||!H.length||!E){return}o.support={leadingWhitespace:K.firstChild.nodeType==3,tbody:!K.getElementsByTagName("tbody").length,objectAll:!!K.getElementsByTagName("object")[0].getElementsByTagName("*").length,htmlSerialize:!!K.getElementsByTagName("link").length,style:/red/.test(E.getAttribute("style")),hrefNormalized:E.getAttribute("href")==="/a",opacity:E.style.opacity==="0.5",cssFloat:!!E.style.cssFloat,scriptEval:false,noCloneEvent:true,boxModel:null};G.type="text/javascript";try{G.appendChild(document.createTextNode("window."+J+"=1;"))}catch(I){}F.insertBefore(G,F.firstChild);if(l[J]){o.support.scriptEval=true;delete l[J]}F.removeChild(G);if(K.attachEvent&&K.fireEvent){K.attachEvent("onclick",function(){o.support.noCloneEvent=false;K.detachEvent("onclick",arguments.callee)});K.cloneNode(true).fireEvent("onclick")}o(function(){var L=document.createElement("div");L.style.width="1px";L.style.paddingLeft="1px";document.body.appendChild(L);o.boxModel=o.support.boxModel=L.offsetWidth===2;document.body.removeChild(L)})})();var w=o.support.cssFloat?"cssFloat":"styleFloat";o.props={"for":"htmlFor","class":"className","float":w,cssFloat:w,styleFloat:w,readonly:"readOnly",maxlength:"maxLength",cellspacing:"cellSpacing",rowspan:"rowSpan",tabindex:"tabIndex"};o.fn.extend({_load:o.fn.load,load:function(G,J,K){if(typeof G!=="string"){return this._load(G)}var I=G.indexOf(" ");if(I>=0){var E=G.slice(I,G.length);G=G.slice(0,I)}var H="GET";if(J){if(o.isFunction(J)){K=J;J=null}else{if(typeof J==="object"){J=o.param(J);H="POST"}}}var F=this;o.ajax({url:G,type:H,dataType:"html",data:J,complete:function(M,L){if(L=="success"||L=="notmodified"){F.html(E?o("<div/>").append(M.responseText.replace(/<script(.|\s)*?\/script>/g,"")).find(E):M.responseText)}if(K){F.each(K,[M.responseText,L,M])}}});return this},serialize:function(){return o.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?o.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||/select|textarea/i.test(this.nodeName)||/text|hidden|password/i.test(this.type))}).map(function(E,F){var G=o(this).val();return G==null?null:o.isArray(G)?o.map(G,function(I,H){return{name:F.name,value:I}}):{name:F.name,value:G}}).get()}});o.each("ajaxStart,ajaxStop,ajaxComplete,ajaxError,ajaxSuccess,ajaxSend".split(","),function(E,F){o.fn[F]=function(G){return this.bind(F,G)}});var r=e();o.extend({get:function(E,G,H,F){if(o.isFunction(G)){H=G;G=null}return o.ajax({type:"GET",url:E,data:G,success:H,dataType:F})},getScript:function(E,F){return o.get(E,null,F,"script")},getJSON:function(E,F,G){return o.get(E,F,G,"json")},post:function(E,G,H,F){if(o.isFunction(G)){H=G;G={}}return o.ajax({type:"POST",url:E,data:G,success:H,dataType:F})},ajaxSetup:function(E){o.extend(o.ajaxSettings,E)},ajaxSettings:{url:location.href,global:true,type:"GET",contentType:"application/x-www-form-urlencoded",processData:true,async:true,xhr:function(){return l.ActiveXObject?new ActiveXObject("Microsoft.XMLHTTP"):new XMLHttpRequest()},accepts:{xml:"application/xml, text/xml",html:"text/html",script:"text/javascript, application/javascript",json:"application/json, text/javascript",text:"text/plain",_default:"*/*"}},lastModified:{},ajax:function(M){M=o.extend(true,M,o.extend(true,{},o.ajaxSettings,M));var W,F=/=\?(&|$)/g,R,V,G=M.type.toUpperCase();if(M.data&&M.processData&&typeof M.data!=="string"){M.data=o.param(M.data)}if(M.dataType=="jsonp"){if(G=="GET"){if(!M.url.match(F)){M.url+=(M.url.match(/\?/)?"&":"?")+(M.jsonp||"callback")+"=?"}}else{if(!M.data||!M.data.match(F)){M.data=(M.data?M.data+"&":"")+(M.jsonp||"callback")+"=?"}}M.dataType="json"}if(M.dataType=="json"&&(M.data&&M.data.match(F)||M.url.match(F))){W="jsonp"+r++;if(M.data){M.data=(M.data+"").replace(F,"="+W+"$1")}M.url=M.url.replace(F,"="+W+"$1");M.dataType="script";l[W]=function(X){V=X;I();L();l[W]=g;try{delete l[W]}catch(Y){}if(H){H.removeChild(T)}}}if(M.dataType=="script"&&M.cache==null){M.cache=false}if(M.cache===false&&G=="GET"){var E=e();var U=M.url.replace(/(\?|&)_=.*?(&|$)/,"$1_="+E+"$2");M.url=U+((U==M.url)?(M.url.match(/\?/)?"&":"?")+"_="+E:"")}if(M.data&&G=="GET"){M.url+=(M.url.match(/\?/)?"&":"?")+M.data;M.data=null}if(M.global&&!o.active++){o.event.trigger("ajaxStart")}var Q=/^(\w+:)?\/\/([^\/?#]+)/.exec(M.url);if(M.dataType=="script"&&G=="GET"&&Q&&(Q[1]&&Q[1]!=location.protocol||Q[2]!=location.host)){var H=document.getElementsByTagName("head")[0];var T=document.createElement("script");T.src=M.url;if(M.scriptCharset){T.charset=M.scriptCharset}if(!W){var O=false;T.onload=T.onreadystatechange=function(){if(!O&&(!this.readyState||this.readyState=="loaded"||this.readyState=="complete")){O=true;I();L();H.removeChild(T)}}}H.appendChild(T);return g}var K=false;var J=M.xhr();if(M.username){J.open(G,M.url,M.async,M.username,M.password)}else{J.open(G,M.url,M.async)}try{if(M.data){J.setRequestHeader("Content-Type",M.contentType)}if(M.ifModified){J.setRequestHeader("If-Modified-Since",o.lastModified[M.url]||"Thu, 01 Jan 1970 00:00:00 GMT")}J.setRequestHeader("X-Requested-With","XMLHttpRequest");J.setRequestHeader("Accept",M.dataType&&M.accepts[M.dataType]?M.accepts[M.dataType]+", */*":M.accepts._default)}catch(S){}if(M.beforeSend&&M.beforeSend(J,M)===false){if(M.global&&!--o.active){o.event.trigger("ajaxStop")}J.abort();return false}if(M.global){o.event.trigger("ajaxSend",[J,M])}var N=function(X){if(J.readyState==0){if(P){clearInterval(P);P=null;if(M.global&&!--o.active){o.event.trigger("ajaxStop")}}}else{if(!K&&J&&(J.readyState==4||X=="timeout")){K=true;if(P){clearInterval(P);P=null}R=X=="timeout"?"timeout":!o.httpSuccess(J)?"error":M.ifModified&&o.httpNotModified(J,M.url)?"notmodified":"success";if(R=="success"){try{V=o.httpData(J,M.dataType,M)}catch(Z){R="parsererror"}}if(R=="success"){var Y;try{Y=J.getResponseHeader("Last-Modified")}catch(Z){}if(M.ifModified&&Y){o.lastModified[M.url]=Y}if(!W){I()}}else{o.handleError(M,J,R)}L();if(X){J.abort()}if(M.async){J=null}}}};if(M.async){var P=setInterval(N,13);if(M.timeout>0){setTimeout(function(){if(J&&!K){N("timeout")}},M.timeout)}}try{J.send(M.data)}catch(S){o.handleError(M,J,null,S)}if(!M.async){N()}function I(){if(M.success){M.success(V,R)}if(M.global){o.event.trigger("ajaxSuccess",[J,M])}}function L(){if(M.complete){M.complete(J,R)}if(M.global){o.event.trigger("ajaxComplete",[J,M])}if(M.global&&!--o.active){o.event.trigger("ajaxStop")}}return J},handleError:function(F,H,E,G){if(F.error){F.error(H,E,G)}if(F.global){o.event.trigger("ajaxError",[H,F,G])}},active:0,httpSuccess:function(F){try{return !F.status&&location.protocol=="file:"||(F.status>=200&&F.status<300)||F.status==304||F.status==1223}catch(E){}return false},httpNotModified:function(G,E){try{var H=G.getResponseHeader("Last-Modified");return G.status==304||H==o.lastModified[E]}catch(F){}return false},httpData:function(J,H,G){var F=J.getResponseHeader("content-type"),E=H=="xml"||!H&&F&&F.indexOf("xml")>=0,I=E?J.responseXML:J.responseText;if(E&&I.documentElement.tagName=="parsererror"){throw"parsererror"}if(G&&G.dataFilter){I=G.dataFilter(I,H)}if(typeof I==="string"){if(H=="script"){o.globalEval(I)}if(H=="json"){I=l["eval"]("("+I+")")}}return I},param:function(E){var G=[];function H(I,J){G[G.length]=encodeURIComponent(I)+"="+encodeURIComponent(J)}if(o.isArray(E)||E.jquery){o.each(E,function(){H(this.name,this.value)})}else{for(var F in E){if(o.isArray(E[F])){o.each(E[F],function(){H(F,this)})}else{H(F,o.isFunction(E[F])?E[F]():E[F])}}}return G.join("&").replace(/%20/g,"+")}});var m={},n,d=[["height","marginTop","marginBottom","paddingTop","paddingBottom"],["width","marginLeft","marginRight","paddingLeft","paddingRight"],["opacity"]];function t(F,E){var G={};o.each(d.concat.apply([],d.slice(0,E)),function(){G[this]=F});return G}o.fn.extend({show:function(J,L){if(J){return this.animate(t("show",3),J,L)}else{for(var H=0,F=this.length;H<F;H++){var E=o.data(this[H],"olddisplay");this[H].style.display=E||"";if(o.css(this[H],"display")==="none"){var G=this[H].tagName,K;if(m[G]){K=m[G]}else{var I=o("<"+G+" />").appendTo("body");K=I.css("display");if(K==="none"){K="block"}I.remove();m[G]=K}this[H].style.display=o.data(this[H],"olddisplay",K)}}return this}},hide:function(H,I){if(H){return this.animate(t("hide",3),H,I)}else{for(var G=0,F=this.length;G<F;G++){var E=o.data(this[G],"olddisplay");if(!E&&E!=="none"){o.data(this[G],"olddisplay",o.css(this[G],"display"))}this[G].style.display="none"}return this}},_toggle:o.fn.toggle,toggle:function(G,F){var E=typeof G==="boolean";return o.isFunction(G)&&o.isFunction(F)?this._toggle.apply(this,arguments):G==null||E?this.each(function(){var H=E?G:o(this).is(":hidden");o(this)[H?"show":"hide"]()}):this.animate(t("toggle",3),G,F)},fadeTo:function(E,G,F){return this.animate({opacity:G},E,F)},animate:function(I,F,H,G){var E=o.speed(F,H,G);return this[E.queue===false?"each":"queue"](function(){var K=o.extend({},E),M,L=this.nodeType==1&&o(this).is(":hidden"),J=this;for(M in I){if(I[M]=="hide"&&L||I[M]=="show"&&!L){return K.complete.call(this)}if((M=="height"||M=="width")&&this.style){K.display=o.css(this,"display");K.overflow=this.style.overflow}}if(K.overflow!=null){this.style.overflow="hidden"}K.curAnim=o.extend({},I);o.each(I,function(O,S){var R=new o.fx(J,K,O);if(/toggle|show|hide/.test(S)){R[S=="toggle"?L?"show":"hide":S](I)}else{var Q=S.toString().match(/^([+-]=)?([\d+-.]+)(.*)$/),T=R.cur(true)||0;if(Q){var N=parseFloat(Q[2]),P=Q[3]||"px";if(P!="px"){J.style[O]=(N||1)+P;T=((N||1)/R.cur(true))*T;J.style[O]=T+P}if(Q[1]){N=((Q[1]=="-="?-1:1)*N)+T}R.custom(T,N,P)}else{R.custom(T,S,"")}}});return true})},stop:function(F,E){var G=o.timers;if(F){this.queue([])}this.each(function(){for(var H=G.length-1;H>=0;H--){if(G[H].elem==this){if(E){G[H](true)}G.splice(H,1)}}});if(!E){this.dequeue()}return this}});o.each({slideDown:t("show",1),slideUp:t("hide",1),slideToggle:t("toggle",1),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"}},function(E,F){o.fn[E]=function(G,H){return this.animate(F,G,H)}});o.extend({speed:function(G,H,F){var E=typeof G==="object"?G:{complete:F||!F&&H||o.isFunction(G)&&G,duration:G,easing:F&&H||H&&!o.isFunction(H)&&H};E.duration=o.fx.off?0:typeof E.duration==="number"?E.duration:o.fx.speeds[E.duration]||o.fx.speeds._default;E.old=E.complete;E.complete=function(){if(E.queue!==false){o(this).dequeue()}if(o.isFunction(E.old)){E.old.call(this)}};return E},easing:{linear:function(G,H,E,F){return E+F*G},swing:function(G,H,E,F){return((-Math.cos(G*Math.PI)/2)+0.5)*F+E}},timers:[],fx:function(F,E,G){this.options=E;this.elem=F;this.prop=G;if(!E.orig){E.orig={}}}});o.fx.prototype={update:function(){if(this.options.step){this.options.step.call(this.elem,this.now,this)}(o.fx.step[this.prop]||o.fx.step._default)(this);if((this.prop=="height"||this.prop=="width")&&this.elem.style){this.elem.style.display="block"}},cur:function(F){if(this.elem[this.prop]!=null&&(!this.elem.style||this.elem.style[this.prop]==null)){return this.elem[this.prop]}var E=parseFloat(o.css(this.elem,this.prop,F));return E&&E>-10000?E:parseFloat(o.curCSS(this.elem,this.prop))||0},custom:function(I,H,G){this.startTime=e();this.start=I;this.end=H;this.unit=G||this.unit||"px";this.now=this.start;this.pos=this.state=0;var E=this;function F(J){return E.step(J)}F.elem=this.elem;if(F()&&o.timers.push(F)==1){n=setInterval(function(){var K=o.timers;for(var J=0;J<K.length;J++){if(!K[J]()){K.splice(J--,1)}}if(!K.length){clearInterval(n)}},13)}},show:function(){this.options.orig[this.prop]=o.attr(this.elem.style,this.prop);this.options.show=true;this.custom(this.prop=="width"||this.prop=="height"?1:0,this.cur());o(this.elem).show()},hide:function(){this.options.orig[this.prop]=o.attr(this.elem.style,this.prop);this.options.hide=true;this.custom(this.cur(),0)},step:function(H){var G=e();if(H||G>=this.options.duration+this.startTime){this.now=this.end;this.pos=this.state=1;this.update();this.options.curAnim[this.prop]=true;var E=true;for(var F in this.options.curAnim){if(this.options.curAnim[F]!==true){E=false}}if(E){if(this.options.display!=null){this.elem.style.overflow=this.options.overflow;this.elem.style.display=this.options.display;if(o.css(this.elem,"display")=="none"){this.elem.style.display="block"}}if(this.options.hide){o(this.elem).hide()}if(this.options.hide||this.options.show){for(var I in this.options.curAnim){o.attr(this.elem.style,I,this.options.orig[I])}}this.options.complete.call(this.elem)}return false}else{var J=G-this.startTime;this.state=J/this.options.duration;this.pos=o.easing[this.options.easing||(o.easing.swing?"swing":"linear")](this.state,J,0,1,this.options.duration);this.now=this.start+((this.end-this.start)*this.pos);this.update()}return true}};o.extend(o.fx,{speeds:{slow:600,fast:200,_default:400},step:{opacity:function(E){o.attr(E.elem.style,"opacity",E.now)},_default:function(E){if(E.elem.style&&E.elem.style[E.prop]!=null){E.elem.style[E.prop]=E.now+E.unit}else{E.elem[E.prop]=E.now}}}});if(document.documentElement.getBoundingClientRect){o.fn.offset=function(){if(!this[0]){return{top:0,left:0}}if(this[0]===this[0].ownerDocument.body){return o.offset.bodyOffset(this[0])}var G=this[0].getBoundingClientRect(),J=this[0].ownerDocument,F=J.body,E=J.documentElement,L=E.clientTop||F.clientTop||0,K=E.clientLeft||F.clientLeft||0,I=G.top+(self.pageYOffset||o.boxModel&&E.scrollTop||F.scrollTop)-L,H=G.left+(self.pageXOffset||o.boxModel&&E.scrollLeft||F.scrollLeft)-K;return{top:I,left:H}}}else{o.fn.offset=function(){if(!this[0]){return{top:0,left:0}}if(this[0]===this[0].ownerDocument.body){return o.offset.bodyOffset(this[0])}o.offset.initialized||o.offset.initialize();var J=this[0],G=J.offsetParent,F=J,O=J.ownerDocument,M,H=O.documentElement,K=O.body,L=O.defaultView,E=L.getComputedStyle(J,null),N=J.offsetTop,I=J.offsetLeft;while((J=J.parentNode)&&J!==K&&J!==H){M=L.getComputedStyle(J,null);N-=J.scrollTop,I-=J.scrollLeft;if(J===G){N+=J.offsetTop,I+=J.offsetLeft;if(o.offset.doesNotAddBorder&&!(o.offset.doesAddBorderForTableAndCells&&/^t(able|d|h)$/i.test(J.tagName))){N+=parseInt(M.borderTopWidth,10)||0,I+=parseInt(M.borderLeftWidth,10)||0}F=G,G=J.offsetParent}if(o.offset.subtractsBorderForOverflowNotVisible&&M.overflow!=="visible"){N+=parseInt(M.borderTopWidth,10)||0,I+=parseInt(M.borderLeftWidth,10)||0}E=M}if(E.position==="relative"||E.position==="static"){N+=K.offsetTop,I+=K.offsetLeft}if(E.position==="fixed"){N+=Math.max(H.scrollTop,K.scrollTop),I+=Math.max(H.scrollLeft,K.scrollLeft)}return{top:N,left:I}}}o.offset={initialize:function(){if(this.initialized){return}var L=document.body,F=document.createElement("div"),H,G,N,I,M,E,J=L.style.marginTop,K='<div style="position:absolute;top:0;left:0;margin:0;border:5px solid #000;padding:0;width:1px;height:1px;"><div></div></div><table style="position:absolute;top:0;left:0;margin:0;border:5px solid #000;padding:0;width:1px;height:1px;" cellpadding="0" cellspacing="0"><tr><td></td></tr></table>';M={position:"absolute",top:0,left:0,margin:0,border:0,width:"1px",height:"1px",visibility:"hidden"};for(E in M){F.style[E]=M[E]}F.innerHTML=K;L.insertBefore(F,L.firstChild);H=F.firstChild,G=H.firstChild,I=H.nextSibling.firstChild.firstChild;this.doesNotAddBorder=(G.offsetTop!==5);this.doesAddBorderForTableAndCells=(I.offsetTop===5);H.style.overflow="hidden",H.style.position="relative";this.subtractsBorderForOverflowNotVisible=(G.offsetTop===-5);L.style.marginTop="1px";this.doesNotIncludeMarginInBodyOffset=(L.offsetTop===0);L.style.marginTop=J;L.removeChild(F);this.initialized=true},bodyOffset:function(E){o.offset.initialized||o.offset.initialize();var G=E.offsetTop,F=E.offsetLeft;if(o.offset.doesNotIncludeMarginInBodyOffset){G+=parseInt(o.curCSS(E,"marginTop",true),10)||0,F+=parseInt(o.curCSS(E,"marginLeft",true),10)||0}return{top:G,left:F}}};o.fn.extend({position:function(){var I=0,H=0,F;if(this[0]){var G=this.offsetParent(),J=this.offset(),E=/^body|html$/i.test(G[0].tagName)?{top:0,left:0}:G.offset();J.top-=j(this,"marginTop");J.left-=j(this,"marginLeft");E.top+=j(G,"borderTopWidth");E.left+=j(G,"borderLeftWidth");F={top:J.top-E.top,left:J.left-E.left}}return F},offsetParent:function(){var E=this[0].offsetParent||document.body;while(E&&(!/^body|html$/i.test(E.tagName)&&o.css(E,"position")=="static")){E=E.offsetParent}return o(E)}});o.each(["Left","Top"],function(F,E){var G="scroll"+E;o.fn[G]=function(H){if(!this[0]){return null}return H!==g?this.each(function(){this==l||this==document?l.scrollTo(!F?H:o(l).scrollLeft(),F?H:o(l).scrollTop()):this[G]=H}):this[0]==l||this[0]==document?self[F?"pageYOffset":"pageXOffset"]||o.boxModel&&document.documentElement[G]||document.body[G]:this[0][G]}});o.each(["Height","Width"],function(H,F){var E=H?"Left":"Top",G=H?"Right":"Bottom";o.fn["inner"+F]=function(){return this[F.toLowerCase()]()+j(this,"padding"+E)+j(this,"padding"+G)};o.fn["outer"+F]=function(J){return this["inner"+F]()+j(this,"border"+E+"Width")+j(this,"border"+G+"Width")+(J?j(this,"margin"+E)+j(this,"margin"+G):0)};var I=F.toLowerCase();o.fn[I]=function(J){return this[0]==l?document.compatMode=="CSS1Compat"&&document.documentElement["client"+F]||document.body["client"+F]:this[0]==document?Math.max(document.documentElement["client"+F],document.body["scroll"+F],document.documentElement["scroll"+F],document.body["offset"+F],document.documentElement["offset"+F]):J===g?(this.length?o.css(this[0],I):null):this.css(I,typeof J==="string"?J:J+"px")}})})();
\ No newline at end of file
diff --git a/js/jquery-1.4.4.min.js b/js/jquery-1.4.4.min.js
new file mode 100644 (file)
index 0000000..8f3ca2e
--- /dev/null
@@ -0,0 +1,167 @@
+/*!
+ * jQuery JavaScript Library v1.4.4
+ * http://jquery.com/
+ *
+ * Copyright 2010, John Resig
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * Includes Sizzle.js
+ * http://sizzlejs.com/
+ * Copyright 2010, The Dojo Foundation
+ * Released under the MIT, BSD, and GPL Licenses.
+ *
+ * Date: Thu Nov 11 19:04:53 2010 -0500
+ */
+(function(E,B){function ka(a,b,d){if(d===B&&a.nodeType===1){d=a.getAttribute("data-"+b);if(typeof d==="string"){try{d=d==="true"?true:d==="false"?false:d==="null"?null:!c.isNaN(d)?parseFloat(d):Ja.test(d)?c.parseJSON(d):d}catch(e){}c.data(a,b,d)}else d=B}return d}function U(){return false}function ca(){return true}function la(a,b,d){d[0].type=a;return c.event.handle.apply(b,d)}function Ka(a){var b,d,e,f,h,l,k,o,x,r,A,C=[];f=[];h=c.data(this,this.nodeType?"events":"__events__");if(typeof h==="function")h=
+h.events;if(!(a.liveFired===this||!h||!h.live||a.button&&a.type==="click")){if(a.namespace)A=RegExp("(^|\\.)"+a.namespace.split(".").join("\\.(?:.*\\.)?")+"(\\.|$)");a.liveFired=this;var J=h.live.slice(0);for(k=0;k<J.length;k++){h=J[k];h.origType.replace(X,"")===a.type?f.push(h.selector):J.splice(k--,1)}f=c(a.target).closest(f,a.currentTarget);o=0;for(x=f.length;o<x;o++){r=f[o];for(k=0;k<J.length;k++){h=J[k];if(r.selector===h.selector&&(!A||A.test(h.namespace))){l=r.elem;e=null;if(h.preType==="mouseenter"||
+h.preType==="mouseleave"){a.type=h.preType;e=c(a.relatedTarget).closest(h.selector)[0]}if(!e||e!==l)C.push({elem:l,handleObj:h,level:r.level})}}}o=0;for(x=C.length;o<x;o++){f=C[o];if(d&&f.level>d)break;a.currentTarget=f.elem;a.data=f.handleObj.data;a.handleObj=f.handleObj;A=f.handleObj.origHandler.apply(f.elem,arguments);if(A===false||a.isPropagationStopped()){d=f.level;if(A===false)b=false;if(a.isImmediatePropagationStopped())break}}return b}}function Y(a,b){return(a&&a!=="*"?a+".":"")+b.replace(La,
+"`").replace(Ma,"&")}function ma(a,b,d){if(c.isFunction(b))return c.grep(a,function(f,h){return!!b.call(f,h,f)===d});else if(b.nodeType)return c.grep(a,function(f){return f===b===d});else if(typeof b==="string"){var e=c.grep(a,function(f){return f.nodeType===1});if(Na.test(b))return c.filter(b,e,!d);else b=c.filter(b,e)}return c.grep(a,function(f){return c.inArray(f,b)>=0===d})}function na(a,b){var d=0;b.each(function(){if(this.nodeName===(a[d]&&a[d].nodeName)){var e=c.data(a[d++]),f=c.data(this,
+e);if(e=e&&e.events){delete f.handle;f.events={};for(var h in e)for(var l in e[h])c.event.add(this,h,e[h][l],e[h][l].data)}}})}function Oa(a,b){b.src?c.ajax({url:b.src,async:false,dataType:"script"}):c.globalEval(b.text||b.textContent||b.innerHTML||"");b.parentNode&&b.parentNode.removeChild(b)}function oa(a,b,d){var e=b==="width"?a.offsetWidth:a.offsetHeight;if(d==="border")return e;c.each(b==="width"?Pa:Qa,function(){d||(e-=parseFloat(c.css(a,"padding"+this))||0);if(d==="margin")e+=parseFloat(c.css(a,
+"margin"+this))||0;else e-=parseFloat(c.css(a,"border"+this+"Width"))||0});return e}function da(a,b,d,e){if(c.isArray(b)&&b.length)c.each(b,function(f,h){d||Ra.test(a)?e(a,h):da(a+"["+(typeof h==="object"||c.isArray(h)?f:"")+"]",h,d,e)});else if(!d&&b!=null&&typeof b==="object")c.isEmptyObject(b)?e(a,""):c.each(b,function(f,h){da(a+"["+f+"]",h,d,e)});else e(a,b)}function S(a,b){var d={};c.each(pa.concat.apply([],pa.slice(0,b)),function(){d[this]=a});return d}function qa(a){if(!ea[a]){var b=c("<"+
+a+">").appendTo("body"),d=b.css("display");b.remove();if(d==="none"||d==="")d="block";ea[a]=d}return ea[a]}function fa(a){return c.isWindow(a)?a:a.nodeType===9?a.defaultView||a.parentWindow:false}var t=E.document,c=function(){function a(){if(!b.isReady){try{t.documentElement.doScroll("left")}catch(j){setTimeout(a,1);return}b.ready()}}var b=function(j,s){return new b.fn.init(j,s)},d=E.jQuery,e=E.$,f,h=/^(?:[^<]*(<[\w\W]+>)[^>]*$|#([\w\-]+)$)/,l=/\S/,k=/^\s+/,o=/\s+$/,x=/\W/,r=/\d/,A=/^<(\w+)\s*\/?>(?:<\/\1>)?$/,
+C=/^[\],:{}\s]*$/,J=/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,w=/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,I=/(?:^|:|,)(?:\s*\[)+/g,L=/(webkit)[ \/]([\w.]+)/,g=/(opera)(?:.*version)?[ \/]([\w.]+)/,i=/(msie) ([\w.]+)/,n=/(mozilla)(?:.*? rv:([\w.]+))?/,m=navigator.userAgent,p=false,q=[],u,y=Object.prototype.toString,F=Object.prototype.hasOwnProperty,M=Array.prototype.push,N=Array.prototype.slice,O=String.prototype.trim,D=Array.prototype.indexOf,R={};b.fn=b.prototype={init:function(j,
+s){var v,z,H;if(!j)return this;if(j.nodeType){this.context=this[0]=j;this.length=1;return this}if(j==="body"&&!s&&t.body){this.context=t;this[0]=t.body;this.selector="body";this.length=1;return this}if(typeof j==="string")if((v=h.exec(j))&&(v[1]||!s))if(v[1]){H=s?s.ownerDocument||s:t;if(z=A.exec(j))if(b.isPlainObject(s)){j=[t.createElement(z[1])];b.fn.attr.call(j,s,true)}else j=[H.createElement(z[1])];else{z=b.buildFragment([v[1]],[H]);j=(z.cacheable?z.fragment.cloneNode(true):z.fragment).childNodes}return b.merge(this,
+j)}else{if((z=t.getElementById(v[2]))&&z.parentNode){if(z.id!==v[2])return f.find(j);this.length=1;this[0]=z}this.context=t;this.selector=j;return this}else if(!s&&!x.test(j)){this.selector=j;this.context=t;j=t.getElementsByTagName(j);return b.merge(this,j)}else return!s||s.jquery?(s||f).find(j):b(s).find(j);else if(b.isFunction(j))return f.ready(j);if(j.selector!==B){this.selector=j.selector;this.context=j.context}return b.makeArray(j,this)},selector:"",jquery:"1.4.4",length:0,size:function(){return this.length},
+toArray:function(){return N.call(this,0)},get:function(j){return j==null?this.toArray():j<0?this.slice(j)[0]:this[j]},pushStack:function(j,s,v){var z=b();b.isArray(j)?M.apply(z,j):b.merge(z,j);z.prevObject=this;z.context=this.context;if(s==="find")z.selector=this.selector+(this.selector?" ":"")+v;else if(s)z.selector=this.selector+"."+s+"("+v+")";return z},each:function(j,s){return b.each(this,j,s)},ready:function(j){b.bindReady();if(b.isReady)j.call(t,b);else q&&q.push(j);return this},eq:function(j){return j===
+-1?this.slice(j):this.slice(j,+j+1)},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},slice:function(){return this.pushStack(N.apply(this,arguments),"slice",N.call(arguments).join(","))},map:function(j){return this.pushStack(b.map(this,function(s,v){return j.call(s,v,s)}))},end:function(){return this.prevObject||b(null)},push:M,sort:[].sort,splice:[].splice};b.fn.init.prototype=b.fn;b.extend=b.fn.extend=function(){var j,s,v,z,H,G=arguments[0]||{},K=1,Q=arguments.length,ga=false;
+if(typeof G==="boolean"){ga=G;G=arguments[1]||{};K=2}if(typeof G!=="object"&&!b.isFunction(G))G={};if(Q===K){G=this;--K}for(;K<Q;K++)if((j=arguments[K])!=null)for(s in j){v=G[s];z=j[s];if(G!==z)if(ga&&z&&(b.isPlainObject(z)||(H=b.isArray(z)))){if(H){H=false;v=v&&b.isArray(v)?v:[]}else v=v&&b.isPlainObject(v)?v:{};G[s]=b.extend(ga,v,z)}else if(z!==B)G[s]=z}return G};b.extend({noConflict:function(j){E.$=e;if(j)E.jQuery=d;return b},isReady:false,readyWait:1,ready:function(j){j===true&&b.readyWait--;
+if(!b.readyWait||j!==true&&!b.isReady){if(!t.body)return setTimeout(b.ready,1);b.isReady=true;if(!(j!==true&&--b.readyWait>0))if(q){var s=0,v=q;for(q=null;j=v[s++];)j.call(t,b);b.fn.trigger&&b(t).trigger("ready").unbind("ready")}}},bindReady:function(){if(!p){p=true;if(t.readyState==="complete")return setTimeout(b.ready,1);if(t.addEventListener){t.addEventListener("DOMContentLoaded",u,false);E.addEventListener("load",b.ready,false)}else if(t.attachEvent){t.attachEvent("onreadystatechange",u);E.attachEvent("onload",
+b.ready);var j=false;try{j=E.frameElement==null}catch(s){}t.documentElement.doScroll&&j&&a()}}},isFunction:function(j){return b.type(j)==="function"},isArray:Array.isArray||function(j){return b.type(j)==="array"},isWindow:function(j){return j&&typeof j==="object"&&"setInterval"in j},isNaN:function(j){return j==null||!r.test(j)||isNaN(j)},type:function(j){return j==null?String(j):R[y.call(j)]||"object"},isPlainObject:function(j){if(!j||b.type(j)!=="object"||j.nodeType||b.isWindow(j))return false;if(j.constructor&&
+!F.call(j,"constructor")&&!F.call(j.constructor.prototype,"isPrototypeOf"))return false;for(var s in j);return s===B||F.call(j,s)},isEmptyObject:function(j){for(var s in j)return false;return true},error:function(j){throw j;},parseJSON:function(j){if(typeof j!=="string"||!j)return null;j=b.trim(j);if(C.test(j.replace(J,"@").replace(w,"]").replace(I,"")))return E.JSON&&E.JSON.parse?E.JSON.parse(j):(new Function("return "+j))();else b.error("Invalid JSON: "+j)},noop:function(){},globalEval:function(j){if(j&&
+l.test(j)){var s=t.getElementsByTagName("head")[0]||t.documentElement,v=t.createElement("script");v.type="text/javascript";if(b.support.scriptEval)v.appendChild(t.createTextNode(j));else v.text=j;s.insertBefore(v,s.firstChild);s.removeChild(v)}},nodeName:function(j,s){return j.nodeName&&j.nodeName.toUpperCase()===s.toUpperCase()},each:function(j,s,v){var z,H=0,G=j.length,K=G===B||b.isFunction(j);if(v)if(K)for(z in j){if(s.apply(j[z],v)===false)break}else for(;H<G;){if(s.apply(j[H++],v)===false)break}else if(K)for(z in j){if(s.call(j[z],
+z,j[z])===false)break}else for(v=j[0];H<G&&s.call(v,H,v)!==false;v=j[++H]);return j},trim:O?function(j){return j==null?"":O.call(j)}:function(j){return j==null?"":j.toString().replace(k,"").replace(o,"")},makeArray:function(j,s){var v=s||[];if(j!=null){var z=b.type(j);j.length==null||z==="string"||z==="function"||z==="regexp"||b.isWindow(j)?M.call(v,j):b.merge(v,j)}return v},inArray:function(j,s){if(s.indexOf)return s.indexOf(j);for(var v=0,z=s.length;v<z;v++)if(s[v]===j)return v;return-1},merge:function(j,
+s){var v=j.length,z=0;if(typeof s.length==="number")for(var H=s.length;z<H;z++)j[v++]=s[z];else for(;s[z]!==B;)j[v++]=s[z++];j.length=v;return j},grep:function(j,s,v){var z=[],H;v=!!v;for(var G=0,K=j.length;G<K;G++){H=!!s(j[G],G);v!==H&&z.push(j[G])}return z},map:function(j,s,v){for(var z=[],H,G=0,K=j.length;G<K;G++){H=s(j[G],G,v);if(H!=null)z[z.length]=H}return z.concat.apply([],z)},guid:1,proxy:function(j,s,v){if(arguments.length===2)if(typeof s==="string"){v=j;j=v[s];s=B}else if(s&&!b.isFunction(s)){v=
+s;s=B}if(!s&&j)s=function(){return j.apply(v||this,arguments)};if(j)s.guid=j.guid=j.guid||s.guid||b.guid++;return s},access:function(j,s,v,z,H,G){var K=j.length;if(typeof s==="object"){for(var Q in s)b.access(j,Q,s[Q],z,H,v);return j}if(v!==B){z=!G&&z&&b.isFunction(v);for(Q=0;Q<K;Q++)H(j[Q],s,z?v.call(j[Q],Q,H(j[Q],s)):v,G);return j}return K?H(j[0],s):B},now:function(){return(new Date).getTime()},uaMatch:function(j){j=j.toLowerCase();j=L.exec(j)||g.exec(j)||i.exec(j)||j.indexOf("compatible")<0&&n.exec(j)||
+[];return{browser:j[1]||"",version:j[2]||"0"}},browser:{}});b.each("Boolean Number String Function Array Date RegExp Object".split(" "),function(j,s){R["[object "+s+"]"]=s.toLowerCase()});m=b.uaMatch(m);if(m.browser){b.browser[m.browser]=true;b.browser.version=m.version}if(b.browser.webkit)b.browser.safari=true;if(D)b.inArray=function(j,s){return D.call(s,j)};if(!/\s/.test("\u00a0")){k=/^[\s\xA0]+/;o=/[\s\xA0]+$/}f=b(t);if(t.addEventListener)u=function(){t.removeEventListener("DOMContentLoaded",u,
+false);b.ready()};else if(t.attachEvent)u=function(){if(t.readyState==="complete"){t.detachEvent("onreadystatechange",u);b.ready()}};return E.jQuery=E.$=b}();(function(){c.support={};var a=t.documentElement,b=t.createElement("script"),d=t.createElement("div"),e="script"+c.now();d.style.display="none";d.innerHTML="   <link/><table></table><a href='/a' style='color:red;float:left;opacity:.55;'>a</a><input type='checkbox'/>";var f=d.getElementsByTagName("*"),h=d.getElementsByTagName("a")[0],l=t.createElement("select"),
+k=l.appendChild(t.createElement("option"));if(!(!f||!f.length||!h)){c.support={leadingWhitespace:d.firstChild.nodeType===3,tbody:!d.getElementsByTagName("tbody").length,htmlSerialize:!!d.getElementsByTagName("link").length,style:/red/.test(h.getAttribute("style")),hrefNormalized:h.getAttribute("href")==="/a",opacity:/^0.55$/.test(h.style.opacity),cssFloat:!!h.style.cssFloat,checkOn:d.getElementsByTagName("input")[0].value==="on",optSelected:k.selected,deleteExpando:true,optDisabled:false,checkClone:false,
+scriptEval:false,noCloneEvent:true,boxModel:null,inlineBlockNeedsLayout:false,shrinkWrapBlocks:false,reliableHiddenOffsets:true};l.disabled=true;c.support.optDisabled=!k.disabled;b.type="text/javascript";try{b.appendChild(t.createTextNode("window."+e+"=1;"))}catch(o){}a.insertBefore(b,a.firstChild);if(E[e]){c.support.scriptEval=true;delete E[e]}try{delete b.test}catch(x){c.support.deleteExpando=false}a.removeChild(b);if(d.attachEvent&&d.fireEvent){d.attachEvent("onclick",function r(){c.support.noCloneEvent=
+false;d.detachEvent("onclick",r)});d.cloneNode(true).fireEvent("onclick")}d=t.createElement("div");d.innerHTML="<input type='radio' name='radiotest' checked='checked'/>";a=t.createDocumentFragment();a.appendChild(d.firstChild);c.support.checkClone=a.cloneNode(true).cloneNode(true).lastChild.checked;c(function(){var r=t.createElement("div");r.style.width=r.style.paddingLeft="1px";t.body.appendChild(r);c.boxModel=c.support.boxModel=r.offsetWidth===2;if("zoom"in r.style){r.style.display="inline";r.style.zoom=
+1;c.support.inlineBlockNeedsLayout=r.offsetWidth===2;r.style.display="";r.innerHTML="<div style='width:4px;'></div>";c.support.shrinkWrapBlocks=r.offsetWidth!==2}r.innerHTML="<table><tr><td style='padding:0;display:none'></td><td>t</td></tr></table>";var A=r.getElementsByTagName("td");c.support.reliableHiddenOffsets=A[0].offsetHeight===0;A[0].style.display="";A[1].style.display="none";c.support.reliableHiddenOffsets=c.support.reliableHiddenOffsets&&A[0].offsetHeight===0;r.innerHTML="";t.body.removeChild(r).style.display=
+"none"});a=function(r){var A=t.createElement("div");r="on"+r;var C=r in A;if(!C){A.setAttribute(r,"return;");C=typeof A[r]==="function"}return C};c.support.submitBubbles=a("submit");c.support.changeBubbles=a("change");a=b=d=f=h=null}})();var ra={},Ja=/^(?:\{.*\}|\[.*\])$/;c.extend({cache:{},uuid:0,expando:"jQuery"+c.now(),noData:{embed:true,object:"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000",applet:true},data:function(a,b,d){if(c.acceptData(a)){a=a==E?ra:a;var e=a.nodeType,f=e?a[c.expando]:null,h=
+c.cache;if(!(e&&!f&&typeof b==="string"&&d===B)){if(e)f||(a[c.expando]=f=++c.uuid);else h=a;if(typeof b==="object")if(e)h[f]=c.extend(h[f],b);else c.extend(h,b);else if(e&&!h[f])h[f]={};a=e?h[f]:h;if(d!==B)a[b]=d;return typeof b==="string"?a[b]:a}}},removeData:function(a,b){if(c.acceptData(a)){a=a==E?ra:a;var d=a.nodeType,e=d?a[c.expando]:a,f=c.cache,h=d?f[e]:e;if(b){if(h){delete h[b];d&&c.isEmptyObject(h)&&c.removeData(a)}}else if(d&&c.support.deleteExpando)delete a[c.expando];else if(a.removeAttribute)a.removeAttribute(c.expando);
+else if(d)delete f[e];else for(var l in a)delete a[l]}},acceptData:function(a){if(a.nodeName){var b=c.noData[a.nodeName.toLowerCase()];if(b)return!(b===true||a.getAttribute("classid")!==b)}return true}});c.fn.extend({data:function(a,b){var d=null;if(typeof a==="undefined"){if(this.length){var e=this[0].attributes,f;d=c.data(this[0]);for(var h=0,l=e.length;h<l;h++){f=e[h].name;if(f.indexOf("data-")===0){f=f.substr(5);ka(this[0],f,d[f])}}}return d}else if(typeof a==="object")return this.each(function(){c.data(this,
+a)});var k=a.split(".");k[1]=k[1]?"."+k[1]:"";if(b===B){d=this.triggerHandler("getData"+k[1]+"!",[k[0]]);if(d===B&&this.length){d=c.data(this[0],a);d=ka(this[0],a,d)}return d===B&&k[1]?this.data(k[0]):d}else return this.each(function(){var o=c(this),x=[k[0],b];o.triggerHandler("setData"+k[1]+"!",x);c.data(this,a,b);o.triggerHandler("changeData"+k[1]+"!",x)})},removeData:function(a){return this.each(function(){c.removeData(this,a)})}});c.extend({queue:function(a,b,d){if(a){b=(b||"fx")+"queue";var e=
+c.data(a,b);if(!d)return e||[];if(!e||c.isArray(d))e=c.data(a,b,c.makeArray(d));else e.push(d);return e}},dequeue:function(a,b){b=b||"fx";var d=c.queue(a,b),e=d.shift();if(e==="inprogress")e=d.shift();if(e){b==="fx"&&d.unshift("inprogress");e.call(a,function(){c.dequeue(a,b)})}}});c.fn.extend({queue:function(a,b){if(typeof a!=="string"){b=a;a="fx"}if(b===B)return c.queue(this[0],a);return this.each(function(){var d=c.queue(this,a,b);a==="fx"&&d[0]!=="inprogress"&&c.dequeue(this,a)})},dequeue:function(a){return this.each(function(){c.dequeue(this,
+a)})},delay:function(a,b){a=c.fx?c.fx.speeds[a]||a:a;b=b||"fx";return this.queue(b,function(){var d=this;setTimeout(function(){c.dequeue(d,b)},a)})},clearQueue:function(a){return this.queue(a||"fx",[])}});var sa=/[\n\t]/g,ha=/\s+/,Sa=/\r/g,Ta=/^(?:href|src|style)$/,Ua=/^(?:button|input)$/i,Va=/^(?:button|input|object|select|textarea)$/i,Wa=/^a(?:rea)?$/i,ta=/^(?:radio|checkbox)$/i;c.props={"for":"htmlFor","class":"className",readonly:"readOnly",maxlength:"maxLength",cellspacing:"cellSpacing",rowspan:"rowSpan",
+colspan:"colSpan",tabindex:"tabIndex",usemap:"useMap",frameborder:"frameBorder"};c.fn.extend({attr:function(a,b){return c.access(this,a,b,true,c.attr)},removeAttr:function(a){return this.each(function(){c.attr(this,a,"");this.nodeType===1&&this.removeAttribute(a)})},addClass:function(a){if(c.isFunction(a))return this.each(function(x){var r=c(this);r.addClass(a.call(this,x,r.attr("class")))});if(a&&typeof a==="string")for(var b=(a||"").split(ha),d=0,e=this.length;d<e;d++){var f=this[d];if(f.nodeType===
+1)if(f.className){for(var h=" "+f.className+" ",l=f.className,k=0,o=b.length;k<o;k++)if(h.indexOf(" "+b[k]+" ")<0)l+=" "+b[k];f.className=c.trim(l)}else f.className=a}return this},removeClass:function(a){if(c.isFunction(a))return this.each(function(o){var x=c(this);x.removeClass(a.call(this,o,x.attr("class")))});if(a&&typeof a==="string"||a===B)for(var b=(a||"").split(ha),d=0,e=this.length;d<e;d++){var f=this[d];if(f.nodeType===1&&f.className)if(a){for(var h=(" "+f.className+" ").replace(sa," "),
+l=0,k=b.length;l<k;l++)h=h.replace(" "+b[l]+" "," ");f.className=c.trim(h)}else f.className=""}return this},toggleClass:function(a,b){var d=typeof a,e=typeof b==="boolean";if(c.isFunction(a))return this.each(function(f){var h=c(this);h.toggleClass(a.call(this,f,h.attr("class"),b),b)});return this.each(function(){if(d==="string")for(var f,h=0,l=c(this),k=b,o=a.split(ha);f=o[h++];){k=e?k:!l.hasClass(f);l[k?"addClass":"removeClass"](f)}else if(d==="undefined"||d==="boolean"){this.className&&c.data(this,
+"__className__",this.className);this.className=this.className||a===false?"":c.data(this,"__className__")||""}})},hasClass:function(a){a=" "+a+" ";for(var b=0,d=this.length;b<d;b++)if((" "+this[b].className+" ").replace(sa," ").indexOf(a)>-1)return true;return false},val:function(a){if(!arguments.length){var b=this[0];if(b){if(c.nodeName(b,"option")){var d=b.attributes.value;return!d||d.specified?b.value:b.text}if(c.nodeName(b,"select")){var e=b.selectedIndex;d=[];var f=b.options;b=b.type==="select-one";
+if(e<0)return null;var h=b?e:0;for(e=b?e+1:f.length;h<e;h++){var l=f[h];if(l.selected&&(c.support.optDisabled?!l.disabled:l.getAttribute("disabled")===null)&&(!l.parentNode.disabled||!c.nodeName(l.parentNode,"optgroup"))){a=c(l).val();if(b)return a;d.push(a)}}return d}if(ta.test(b.type)&&!c.support.checkOn)return b.getAttribute("value")===null?"on":b.value;return(b.value||"").replace(Sa,"")}return B}var k=c.isFunction(a);return this.each(function(o){var x=c(this),r=a;if(this.nodeType===1){if(k)r=
+a.call(this,o,x.val());if(r==null)r="";else if(typeof r==="number")r+="";else if(c.isArray(r))r=c.map(r,function(C){return C==null?"":C+""});if(c.isArray(r)&&ta.test(this.type))this.checked=c.inArray(x.val(),r)>=0;else if(c.nodeName(this,"select")){var A=c.makeArray(r);c("option",this).each(function(){this.selected=c.inArray(c(this).val(),A)>=0});if(!A.length)this.selectedIndex=-1}else this.value=r}})}});c.extend({attrFn:{val:true,css:true,html:true,text:true,data:true,width:true,height:true,offset:true},
+attr:function(a,b,d,e){if(!a||a.nodeType===3||a.nodeType===8)return B;if(e&&b in c.attrFn)return c(a)[b](d);e=a.nodeType!==1||!c.isXMLDoc(a);var f=d!==B;b=e&&c.props[b]||b;var h=Ta.test(b);if((b in a||a[b]!==B)&&e&&!h){if(f){b==="type"&&Ua.test(a.nodeName)&&a.parentNode&&c.error("type property can't be changed");if(d===null)a.nodeType===1&&a.removeAttribute(b);else a[b]=d}if(c.nodeName(a,"form")&&a.getAttributeNode(b))return a.getAttributeNode(b).nodeValue;if(b==="tabIndex")return(b=a.getAttributeNode("tabIndex"))&&
+b.specified?b.value:Va.test(a.nodeName)||Wa.test(a.nodeName)&&a.href?0:B;return a[b]}if(!c.support.style&&e&&b==="style"){if(f)a.style.cssText=""+d;return a.style.cssText}f&&a.setAttribute(b,""+d);if(!a.attributes[b]&&a.hasAttribute&&!a.hasAttribute(b))return B;a=!c.support.hrefNormalized&&e&&h?a.getAttribute(b,2):a.getAttribute(b);return a===null?B:a}});var X=/\.(.*)$/,ia=/^(?:textarea|input|select)$/i,La=/\./g,Ma=/ /g,Xa=/[^\w\s.|`]/g,Ya=function(a){return a.replace(Xa,"\\$&")},ua={focusin:0,focusout:0};
+c.event={add:function(a,b,d,e){if(!(a.nodeType===3||a.nodeType===8)){if(c.isWindow(a)&&a!==E&&!a.frameElement)a=E;if(d===false)d=U;else if(!d)return;var f,h;if(d.handler){f=d;d=f.handler}if(!d.guid)d.guid=c.guid++;if(h=c.data(a)){var l=a.nodeType?"events":"__events__",k=h[l],o=h.handle;if(typeof k==="function"){o=k.handle;k=k.events}else if(!k){a.nodeType||(h[l]=h=function(){});h.events=k={}}if(!o)h.handle=o=function(){return typeof c!=="undefined"&&!c.event.triggered?c.event.handle.apply(o.elem,
+arguments):B};o.elem=a;b=b.split(" ");for(var x=0,r;l=b[x++];){h=f?c.extend({},f):{handler:d,data:e};if(l.indexOf(".")>-1){r=l.split(".");l=r.shift();h.namespace=r.slice(0).sort().join(".")}else{r=[];h.namespace=""}h.type=l;if(!h.guid)h.guid=d.guid;var A=k[l],C=c.event.special[l]||{};if(!A){A=k[l]=[];if(!C.setup||C.setup.call(a,e,r,o)===false)if(a.addEventListener)a.addEventListener(l,o,false);else a.attachEvent&&a.attachEvent("on"+l,o)}if(C.add){C.add.call(a,h);if(!h.handler.guid)h.handler.guid=
+d.guid}A.push(h);c.event.global[l]=true}a=null}}},global:{},remove:function(a,b,d,e){if(!(a.nodeType===3||a.nodeType===8)){if(d===false)d=U;var f,h,l=0,k,o,x,r,A,C,J=a.nodeType?"events":"__events__",w=c.data(a),I=w&&w[J];if(w&&I){if(typeof I==="function"){w=I;I=I.events}if(b&&b.type){d=b.handler;b=b.type}if(!b||typeof b==="string"&&b.charAt(0)==="."){b=b||"";for(f in I)c.event.remove(a,f+b)}else{for(b=b.split(" ");f=b[l++];){r=f;k=f.indexOf(".")<0;o=[];if(!k){o=f.split(".");f=o.shift();x=RegExp("(^|\\.)"+
+c.map(o.slice(0).sort(),Ya).join("\\.(?:.*\\.)?")+"(\\.|$)")}if(A=I[f])if(d){r=c.event.special[f]||{};for(h=e||0;h<A.length;h++){C=A[h];if(d.guid===C.guid){if(k||x.test(C.namespace)){e==null&&A.splice(h--,1);r.remove&&r.remove.call(a,C)}if(e!=null)break}}if(A.length===0||e!=null&&A.length===1){if(!r.teardown||r.teardown.call(a,o)===false)c.removeEvent(a,f,w.handle);delete I[f]}}else for(h=0;h<A.length;h++){C=A[h];if(k||x.test(C.namespace)){c.event.remove(a,r,C.handler,h);A.splice(h--,1)}}}if(c.isEmptyObject(I)){if(b=
+w.handle)b.elem=null;delete w.events;delete w.handle;if(typeof w==="function")c.removeData(a,J);else c.isEmptyObject(w)&&c.removeData(a)}}}}},trigger:function(a,b,d,e){var f=a.type||a;if(!e){a=typeof a==="object"?a[c.expando]?a:c.extend(c.Event(f),a):c.Event(f);if(f.indexOf("!")>=0){a.type=f=f.slice(0,-1);a.exclusive=true}if(!d){a.stopPropagation();c.event.global[f]&&c.each(c.cache,function(){this.events&&this.events[f]&&c.event.trigger(a,b,this.handle.elem)})}if(!d||d.nodeType===3||d.nodeType===
+8)return B;a.result=B;a.target=d;b=c.makeArray(b);b.unshift(a)}a.currentTarget=d;(e=d.nodeType?c.data(d,"handle"):(c.data(d,"__events__")||{}).handle)&&e.apply(d,b);e=d.parentNode||d.ownerDocument;try{if(!(d&&d.nodeName&&c.noData[d.nodeName.toLowerCase()]))if(d["on"+f]&&d["on"+f].apply(d,b)===false){a.result=false;a.preventDefault()}}catch(h){}if(!a.isPropagationStopped()&&e)c.event.trigger(a,b,e,true);else if(!a.isDefaultPrevented()){var l;e=a.target;var k=f.replace(X,""),o=c.nodeName(e,"a")&&k===
+"click",x=c.event.special[k]||{};if((!x._default||x._default.call(d,a)===false)&&!o&&!(e&&e.nodeName&&c.noData[e.nodeName.toLowerCase()])){try{if(e[k]){if(l=e["on"+k])e["on"+k]=null;c.event.triggered=true;e[k]()}}catch(r){}if(l)e["on"+k]=l;c.event.triggered=false}}},handle:function(a){var b,d,e,f;d=[];var h=c.makeArray(arguments);a=h[0]=c.event.fix(a||E.event);a.currentTarget=this;b=a.type.indexOf(".")<0&&!a.exclusive;if(!b){e=a.type.split(".");a.type=e.shift();d=e.slice(0).sort();e=RegExp("(^|\\.)"+
+d.join("\\.(?:.*\\.)?")+"(\\.|$)")}a.namespace=a.namespace||d.join(".");f=c.data(this,this.nodeType?"events":"__events__");if(typeof f==="function")f=f.events;d=(f||{})[a.type];if(f&&d){d=d.slice(0);f=0;for(var l=d.length;f<l;f++){var k=d[f];if(b||e.test(k.namespace)){a.handler=k.handler;a.data=k.data;a.handleObj=k;k=k.handler.apply(this,h);if(k!==B){a.result=k;if(k===false){a.preventDefault();a.stopPropagation()}}if(a.isImmediatePropagationStopped())break}}}return a.result},props:"altKey attrChange attrName bubbles button cancelable charCode clientX clientY ctrlKey currentTarget data detail eventPhase fromElement handler keyCode layerX layerY metaKey newValue offsetX offsetY pageX pageY prevValue relatedNode relatedTarget screenX screenY shiftKey srcElement target toElement view wheelDelta which".split(" "),
+fix:function(a){if(a[c.expando])return a;var b=a;a=c.Event(b);for(var d=this.props.length,e;d;){e=this.props[--d];a[e]=b[e]}if(!a.target)a.target=a.srcElement||t;if(a.target.nodeType===3)a.target=a.target.parentNode;if(!a.relatedTarget&&a.fromElement)a.relatedTarget=a.fromElement===a.target?a.toElement:a.fromElement;if(a.pageX==null&&a.clientX!=null){b=t.documentElement;d=t.body;a.pageX=a.clientX+(b&&b.scrollLeft||d&&d.scrollLeft||0)-(b&&b.clientLeft||d&&d.clientLeft||0);a.pageY=a.clientY+(b&&b.scrollTop||
+d&&d.scrollTop||0)-(b&&b.clientTop||d&&d.clientTop||0)}if(a.which==null&&(a.charCode!=null||a.keyCode!=null))a.which=a.charCode!=null?a.charCode:a.keyCode;if(!a.metaKey&&a.ctrlKey)a.metaKey=a.ctrlKey;if(!a.which&&a.button!==B)a.which=a.button&1?1:a.button&2?3:a.button&4?2:0;return a},guid:1E8,proxy:c.proxy,special:{ready:{setup:c.bindReady,teardown:c.noop},live:{add:function(a){c.event.add(this,Y(a.origType,a.selector),c.extend({},a,{handler:Ka,guid:a.handler.guid}))},remove:function(a){c.event.remove(this,
+Y(a.origType,a.selector),a)}},beforeunload:{setup:function(a,b,d){if(c.isWindow(this))this.onbeforeunload=d},teardown:function(a,b){if(this.onbeforeunload===b)this.onbeforeunload=null}}}};c.removeEvent=t.removeEventListener?function(a,b,d){a.removeEventListener&&a.removeEventListener(b,d,false)}:function(a,b,d){a.detachEvent&&a.detachEvent("on"+b,d)};c.Event=function(a){if(!this.preventDefault)return new c.Event(a);if(a&&a.type){this.originalEvent=a;this.type=a.type}else this.type=a;this.timeStamp=
+c.now();this[c.expando]=true};c.Event.prototype={preventDefault:function(){this.isDefaultPrevented=ca;var a=this.originalEvent;if(a)if(a.preventDefault)a.preventDefault();else a.returnValue=false},stopPropagation:function(){this.isPropagationStopped=ca;var a=this.originalEvent;if(a){a.stopPropagation&&a.stopPropagation();a.cancelBubble=true}},stopImmediatePropagation:function(){this.isImmediatePropagationStopped=ca;this.stopPropagation()},isDefaultPrevented:U,isPropagationStopped:U,isImmediatePropagationStopped:U};
+var va=function(a){var b=a.relatedTarget;try{for(;b&&b!==this;)b=b.parentNode;if(b!==this){a.type=a.data;c.event.handle.apply(this,arguments)}}catch(d){}},wa=function(a){a.type=a.data;c.event.handle.apply(this,arguments)};c.each({mouseenter:"mouseover",mouseleave:"mouseout"},function(a,b){c.event.special[a]={setup:function(d){c.event.add(this,b,d&&d.selector?wa:va,a)},teardown:function(d){c.event.remove(this,b,d&&d.selector?wa:va)}}});if(!c.support.submitBubbles)c.event.special.submit={setup:function(){if(this.nodeName.toLowerCase()!==
+"form"){c.event.add(this,"click.specialSubmit",function(a){var b=a.target,d=b.type;if((d==="submit"||d==="image")&&c(b).closest("form").length){a.liveFired=B;return la("submit",this,arguments)}});c.event.add(this,"keypress.specialSubmit",function(a){var b=a.target,d=b.type;if((d==="text"||d==="password")&&c(b).closest("form").length&&a.keyCode===13){a.liveFired=B;return la("submit",this,arguments)}})}else return false},teardown:function(){c.event.remove(this,".specialSubmit")}};if(!c.support.changeBubbles){var V,
+xa=function(a){var b=a.type,d=a.value;if(b==="radio"||b==="checkbox")d=a.checked;else if(b==="select-multiple")d=a.selectedIndex>-1?c.map(a.options,function(e){return e.selected}).join("-"):"";else if(a.nodeName.toLowerCase()==="select")d=a.selectedIndex;return d},Z=function(a,b){var d=a.target,e,f;if(!(!ia.test(d.nodeName)||d.readOnly)){e=c.data(d,"_change_data");f=xa(d);if(a.type!=="focusout"||d.type!=="radio")c.data(d,"_change_data",f);if(!(e===B||f===e))if(e!=null||f){a.type="change";a.liveFired=
+B;return c.event.trigger(a,b,d)}}};c.event.special.change={filters:{focusout:Z,beforedeactivate:Z,click:function(a){var b=a.target,d=b.type;if(d==="radio"||d==="checkbox"||b.nodeName.toLowerCase()==="select")return Z.call(this,a)},keydown:function(a){var b=a.target,d=b.type;if(a.keyCode===13&&b.nodeName.toLowerCase()!=="textarea"||a.keyCode===32&&(d==="checkbox"||d==="radio")||d==="select-multiple")return Z.call(this,a)},beforeactivate:function(a){a=a.target;c.data(a,"_change_data",xa(a))}},setup:function(){if(this.type===
+"file")return false;for(var a in V)c.event.add(this,a+".specialChange",V[a]);return ia.test(this.nodeName)},teardown:function(){c.event.remove(this,".specialChange");return ia.test(this.nodeName)}};V=c.event.special.change.filters;V.focus=V.beforeactivate}t.addEventListener&&c.each({focus:"focusin",blur:"focusout"},function(a,b){function d(e){e=c.event.fix(e);e.type=b;return c.event.trigger(e,null,e.target)}c.event.special[b]={setup:function(){ua[b]++===0&&t.addEventListener(a,d,true)},teardown:function(){--ua[b]===
+0&&t.removeEventListener(a,d,true)}}});c.each(["bind","one"],function(a,b){c.fn[b]=function(d,e,f){if(typeof d==="object"){for(var h in d)this[b](h,e,d[h],f);return this}if(c.isFunction(e)||e===false){f=e;e=B}var l=b==="one"?c.proxy(f,function(o){c(this).unbind(o,l);return f.apply(this,arguments)}):f;if(d==="unload"&&b!=="one")this.one(d,e,f);else{h=0;for(var k=this.length;h<k;h++)c.event.add(this[h],d,l,e)}return this}});c.fn.extend({unbind:function(a,b){if(typeof a==="object"&&!a.preventDefault)for(var d in a)this.unbind(d,
+a[d]);else{d=0;for(var e=this.length;d<e;d++)c.event.remove(this[d],a,b)}return this},delegate:function(a,b,d,e){return this.live(b,d,e,a)},undelegate:function(a,b,d){return arguments.length===0?this.unbind("live"):this.die(b,null,d,a)},trigger:function(a,b){return this.each(function(){c.event.trigger(a,b,this)})},triggerHandler:function(a,b){if(this[0]){var d=c.Event(a);d.preventDefault();d.stopPropagation();c.event.trigger(d,b,this[0]);return d.result}},toggle:function(a){for(var b=arguments,d=
+1;d<b.length;)c.proxy(a,b[d++]);return this.click(c.proxy(a,function(e){var f=(c.data(this,"lastToggle"+a.guid)||0)%d;c.data(this,"lastToggle"+a.guid,f+1);e.preventDefault();return b[f].apply(this,arguments)||false}))},hover:function(a,b){return this.mouseenter(a).mouseleave(b||a)}});var ya={focus:"focusin",blur:"focusout",mouseenter:"mouseover",mouseleave:"mouseout"};c.each(["live","die"],function(a,b){c.fn[b]=function(d,e,f,h){var l,k=0,o,x,r=h||this.selector;h=h?this:c(this.context);if(typeof d===
+"object"&&!d.preventDefault){for(l in d)h[b](l,e,d[l],r);return this}if(c.isFunction(e)){f=e;e=B}for(d=(d||"").split(" ");(l=d[k++])!=null;){o=X.exec(l);x="";if(o){x=o[0];l=l.replace(X,"")}if(l==="hover")d.push("mouseenter"+x,"mouseleave"+x);else{o=l;if(l==="focus"||l==="blur"){d.push(ya[l]+x);l+=x}else l=(ya[l]||l)+x;if(b==="live"){x=0;for(var A=h.length;x<A;x++)c.event.add(h[x],"live."+Y(l,r),{data:e,selector:r,handler:f,origType:l,origHandler:f,preType:o})}else h.unbind("live."+Y(l,r),f)}}return this}});
+c.each("blur focus focusin focusout load resize scroll unload click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup error".split(" "),function(a,b){c.fn[b]=function(d,e){if(e==null){e=d;d=null}return arguments.length>0?this.bind(b,d,e):this.trigger(b)};if(c.attrFn)c.attrFn[b]=true});E.attachEvent&&!E.addEventListener&&c(E).bind("unload",function(){for(var a in c.cache)if(c.cache[a].handle)try{c.event.remove(c.cache[a].handle.elem)}catch(b){}});
+(function(){function a(g,i,n,m,p,q){p=0;for(var u=m.length;p<u;p++){var y=m[p];if(y){var F=false;for(y=y[g];y;){if(y.sizcache===n){F=m[y.sizset];break}if(y.nodeType===1&&!q){y.sizcache=n;y.sizset=p}if(y.nodeName.toLowerCase()===i){F=y;break}y=y[g]}m[p]=F}}}function b(g,i,n,m,p,q){p=0;for(var u=m.length;p<u;p++){var y=m[p];if(y){var F=false;for(y=y[g];y;){if(y.sizcache===n){F=m[y.sizset];break}if(y.nodeType===1){if(!q){y.sizcache=n;y.sizset=p}if(typeof i!=="string"){if(y===i){F=true;break}}else if(k.filter(i,
+[y]).length>0){F=y;break}}y=y[g]}m[p]=F}}}var d=/((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^\[\]]*\]|['"][^'"]*['"]|[^\[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g,e=0,f=Object.prototype.toString,h=false,l=true;[0,0].sort(function(){l=false;return 0});var k=function(g,i,n,m){n=n||[];var p=i=i||t;if(i.nodeType!==1&&i.nodeType!==9)return[];if(!g||typeof g!=="string")return n;var q,u,y,F,M,N=true,O=k.isXML(i),D=[],R=g;do{d.exec("");if(q=d.exec(R)){R=q[3];D.push(q[1]);if(q[2]){F=q[3];
+break}}}while(q);if(D.length>1&&x.exec(g))if(D.length===2&&o.relative[D[0]])u=L(D[0]+D[1],i);else for(u=o.relative[D[0]]?[i]:k(D.shift(),i);D.length;){g=D.shift();if(o.relative[g])g+=D.shift();u=L(g,u)}else{if(!m&&D.length>1&&i.nodeType===9&&!O&&o.match.ID.test(D[0])&&!o.match.ID.test(D[D.length-1])){q=k.find(D.shift(),i,O);i=q.expr?k.filter(q.expr,q.set)[0]:q.set[0]}if(i){q=m?{expr:D.pop(),set:C(m)}:k.find(D.pop(),D.length===1&&(D[0]==="~"||D[0]==="+")&&i.parentNode?i.parentNode:i,O);u=q.expr?k.filter(q.expr,
+q.set):q.set;if(D.length>0)y=C(u);else N=false;for(;D.length;){q=M=D.pop();if(o.relative[M])q=D.pop();else M="";if(q==null)q=i;o.relative[M](y,q,O)}}else y=[]}y||(y=u);y||k.error(M||g);if(f.call(y)==="[object Array]")if(N)if(i&&i.nodeType===1)for(g=0;y[g]!=null;g++){if(y[g]&&(y[g]===true||y[g].nodeType===1&&k.contains(i,y[g])))n.push(u[g])}else for(g=0;y[g]!=null;g++)y[g]&&y[g].nodeType===1&&n.push(u[g]);else n.push.apply(n,y);else C(y,n);if(F){k(F,p,n,m);k.uniqueSort(n)}return n};k.uniqueSort=function(g){if(w){h=
+l;g.sort(w);if(h)for(var i=1;i<g.length;i++)g[i]===g[i-1]&&g.splice(i--,1)}return g};k.matches=function(g,i){return k(g,null,null,i)};k.matchesSelector=function(g,i){return k(i,null,null,[g]).length>0};k.find=function(g,i,n){var m;if(!g)return[];for(var p=0,q=o.order.length;p<q;p++){var u,y=o.order[p];if(u=o.leftMatch[y].exec(g)){var F=u[1];u.splice(1,1);if(F.substr(F.length-1)!=="\\"){u[1]=(u[1]||"").replace(/\\/g,"");m=o.find[y](u,i,n);if(m!=null){g=g.replace(o.match[y],"");break}}}}m||(m=i.getElementsByTagName("*"));
+return{set:m,expr:g}};k.filter=function(g,i,n,m){for(var p,q,u=g,y=[],F=i,M=i&&i[0]&&k.isXML(i[0]);g&&i.length;){for(var N in o.filter)if((p=o.leftMatch[N].exec(g))!=null&&p[2]){var O,D,R=o.filter[N];D=p[1];q=false;p.splice(1,1);if(D.substr(D.length-1)!=="\\"){if(F===y)y=[];if(o.preFilter[N])if(p=o.preFilter[N](p,F,n,y,m,M)){if(p===true)continue}else q=O=true;if(p)for(var j=0;(D=F[j])!=null;j++)if(D){O=R(D,p,j,F);var s=m^!!O;if(n&&O!=null)if(s)q=true;else F[j]=false;else if(s){y.push(D);q=true}}if(O!==
+B){n||(F=y);g=g.replace(o.match[N],"");if(!q)return[];break}}}if(g===u)if(q==null)k.error(g);else break;u=g}return F};k.error=function(g){throw"Syntax error, unrecognized expression: "+g;};var o=k.selectors={order:["ID","NAME","TAG"],match:{ID:/#((?:[\w\u00c0-\uFFFF\-]|\\.)+)/,CLASS:/\.((?:[\w\u00c0-\uFFFF\-]|\\.)+)/,NAME:/\[name=['"]*((?:[\w\u00c0-\uFFFF\-]|\\.)+)['"]*\]/,ATTR:/\[\s*((?:[\w\u00c0-\uFFFF\-]|\\.)+)\s*(?:(\S?=)\s*(['"]*)(.*?)\3|)\s*\]/,TAG:/^((?:[\w\u00c0-\uFFFF\*\-]|\\.)+)/,CHILD:/:(only|nth|last|first)-child(?:\((even|odd|[\dn+\-]*)\))?/,
+POS:/:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^\-]|$)/,PSEUDO:/:((?:[\w\u00c0-\uFFFF\-]|\\.)+)(?:\((['"]?)((?:\([^\)]+\)|[^\(\)]*)+)\2\))?/},leftMatch:{},attrMap:{"class":"className","for":"htmlFor"},attrHandle:{href:function(g){return g.getAttribute("href")}},relative:{"+":function(g,i){var n=typeof i==="string",m=n&&!/\W/.test(i);n=n&&!m;if(m)i=i.toLowerCase();m=0;for(var p=g.length,q;m<p;m++)if(q=g[m]){for(;(q=q.previousSibling)&&q.nodeType!==1;);g[m]=n||q&&q.nodeName.toLowerCase()===
+i?q||false:q===i}n&&k.filter(i,g,true)},">":function(g,i){var n,m=typeof i==="string",p=0,q=g.length;if(m&&!/\W/.test(i))for(i=i.toLowerCase();p<q;p++){if(n=g[p]){n=n.parentNode;g[p]=n.nodeName.toLowerCase()===i?n:false}}else{for(;p<q;p++)if(n=g[p])g[p]=m?n.parentNode:n.parentNode===i;m&&k.filter(i,g,true)}},"":function(g,i,n){var m,p=e++,q=b;if(typeof i==="string"&&!/\W/.test(i)){m=i=i.toLowerCase();q=a}q("parentNode",i,p,g,m,n)},"~":function(g,i,n){var m,p=e++,q=b;if(typeof i==="string"&&!/\W/.test(i)){m=
+i=i.toLowerCase();q=a}q("previousSibling",i,p,g,m,n)}},find:{ID:function(g,i,n){if(typeof i.getElementById!=="undefined"&&!n)return(g=i.getElementById(g[1]))&&g.parentNode?[g]:[]},NAME:function(g,i){if(typeof i.getElementsByName!=="undefined"){for(var n=[],m=i.getElementsByName(g[1]),p=0,q=m.length;p<q;p++)m[p].getAttribute("name")===g[1]&&n.push(m[p]);return n.length===0?null:n}},TAG:function(g,i){return i.getElementsByTagName(g[1])}},preFilter:{CLASS:function(g,i,n,m,p,q){g=" "+g[1].replace(/\\/g,
+"")+" ";if(q)return g;q=0;for(var u;(u=i[q])!=null;q++)if(u)if(p^(u.className&&(" "+u.className+" ").replace(/[\t\n]/g," ").indexOf(g)>=0))n||m.push(u);else if(n)i[q]=false;return false},ID:function(g){return g[1].replace(/\\/g,"")},TAG:function(g){return g[1].toLowerCase()},CHILD:function(g){if(g[1]==="nth"){var i=/(-?)(\d*)n((?:\+|-)?\d*)/.exec(g[2]==="even"&&"2n"||g[2]==="odd"&&"2n+1"||!/\D/.test(g[2])&&"0n+"+g[2]||g[2]);g[2]=i[1]+(i[2]||1)-0;g[3]=i[3]-0}g[0]=e++;return g},ATTR:function(g,i,n,
+m,p,q){i=g[1].replace(/\\/g,"");if(!q&&o.attrMap[i])g[1]=o.attrMap[i];if(g[2]==="~=")g[4]=" "+g[4]+" ";return g},PSEUDO:function(g,i,n,m,p){if(g[1]==="not")if((d.exec(g[3])||"").length>1||/^\w/.test(g[3]))g[3]=k(g[3],null,null,i);else{g=k.filter(g[3],i,n,true^p);n||m.push.apply(m,g);return false}else if(o.match.POS.test(g[0])||o.match.CHILD.test(g[0]))return true;return g},POS:function(g){g.unshift(true);return g}},filters:{enabled:function(g){return g.disabled===false&&g.type!=="hidden"},disabled:function(g){return g.disabled===
+true},checked:function(g){return g.checked===true},selected:function(g){return g.selected===true},parent:function(g){return!!g.firstChild},empty:function(g){return!g.firstChild},has:function(g,i,n){return!!k(n[3],g).length},header:function(g){return/h\d/i.test(g.nodeName)},text:function(g){return"text"===g.type},radio:function(g){return"radio"===g.type},checkbox:function(g){return"checkbox"===g.type},file:function(g){return"file"===g.type},password:function(g){return"password"===g.type},submit:function(g){return"submit"===
+g.type},image:function(g){return"image"===g.type},reset:function(g){return"reset"===g.type},button:function(g){return"button"===g.type||g.nodeName.toLowerCase()==="button"},input:function(g){return/input|select|textarea|button/i.test(g.nodeName)}},setFilters:{first:function(g,i){return i===0},last:function(g,i,n,m){return i===m.length-1},even:function(g,i){return i%2===0},odd:function(g,i){return i%2===1},lt:function(g,i,n){return i<n[3]-0},gt:function(g,i,n){return i>n[3]-0},nth:function(g,i,n){return n[3]-
+0===i},eq:function(g,i,n){return n[3]-0===i}},filter:{PSEUDO:function(g,i,n,m){var p=i[1],q=o.filters[p];if(q)return q(g,n,i,m);else if(p==="contains")return(g.textContent||g.innerText||k.getText([g])||"").indexOf(i[3])>=0;else if(p==="not"){i=i[3];n=0;for(m=i.length;n<m;n++)if(i[n]===g)return false;return true}else k.error("Syntax error, unrecognized expression: "+p)},CHILD:function(g,i){var n=i[1],m=g;switch(n){case "only":case "first":for(;m=m.previousSibling;)if(m.nodeType===1)return false;if(n===
+"first")return true;m=g;case "last":for(;m=m.nextSibling;)if(m.nodeType===1)return false;return true;case "nth":n=i[2];var p=i[3];if(n===1&&p===0)return true;var q=i[0],u=g.parentNode;if(u&&(u.sizcache!==q||!g.nodeIndex)){var y=0;for(m=u.firstChild;m;m=m.nextSibling)if(m.nodeType===1)m.nodeIndex=++y;u.sizcache=q}m=g.nodeIndex-p;return n===0?m===0:m%n===0&&m/n>=0}},ID:function(g,i){return g.nodeType===1&&g.getAttribute("id")===i},TAG:function(g,i){return i==="*"&&g.nodeType===1||g.nodeName.toLowerCase()===
+i},CLASS:function(g,i){return(" "+(g.className||g.getAttribute("class"))+" ").indexOf(i)>-1},ATTR:function(g,i){var n=i[1];n=o.attrHandle[n]?o.attrHandle[n](g):g[n]!=null?g[n]:g.getAttribute(n);var m=n+"",p=i[2],q=i[4];return n==null?p==="!=":p==="="?m===q:p==="*="?m.indexOf(q)>=0:p==="~="?(" "+m+" ").indexOf(q)>=0:!q?m&&n!==false:p==="!="?m!==q:p==="^="?m.indexOf(q)===0:p==="$="?m.substr(m.length-q.length)===q:p==="|="?m===q||m.substr(0,q.length+1)===q+"-":false},POS:function(g,i,n,m){var p=o.setFilters[i[2]];
+if(p)return p(g,n,i,m)}}},x=o.match.POS,r=function(g,i){return"\\"+(i-0+1)},A;for(A in o.match){o.match[A]=RegExp(o.match[A].source+/(?![^\[]*\])(?![^\(]*\))/.source);o.leftMatch[A]=RegExp(/(^(?:.|\r|\n)*?)/.source+o.match[A].source.replace(/\\(\d+)/g,r))}var C=function(g,i){g=Array.prototype.slice.call(g,0);if(i){i.push.apply(i,g);return i}return g};try{Array.prototype.slice.call(t.documentElement.childNodes,0)}catch(J){C=function(g,i){var n=0,m=i||[];if(f.call(g)==="[object Array]")Array.prototype.push.apply(m,
+g);else if(typeof g.length==="number")for(var p=g.length;n<p;n++)m.push(g[n]);else for(;g[n];n++)m.push(g[n]);return m}}var w,I;if(t.documentElement.compareDocumentPosition)w=function(g,i){if(g===i){h=true;return 0}if(!g.compareDocumentPosition||!i.compareDocumentPosition)return g.compareDocumentPosition?-1:1;return g.compareDocumentPosition(i)&4?-1:1};else{w=function(g,i){var n,m,p=[],q=[];n=g.parentNode;m=i.parentNode;var u=n;if(g===i){h=true;return 0}else if(n===m)return I(g,i);else if(n){if(!m)return 1}else return-1;
+for(;u;){p.unshift(u);u=u.parentNode}for(u=m;u;){q.unshift(u);u=u.parentNode}n=p.length;m=q.length;for(u=0;u<n&&u<m;u++)if(p[u]!==q[u])return I(p[u],q[u]);return u===n?I(g,q[u],-1):I(p[u],i,1)};I=function(g,i,n){if(g===i)return n;for(g=g.nextSibling;g;){if(g===i)return-1;g=g.nextSibling}return 1}}k.getText=function(g){for(var i="",n,m=0;g[m];m++){n=g[m];if(n.nodeType===3||n.nodeType===4)i+=n.nodeValue;else if(n.nodeType!==8)i+=k.getText(n.childNodes)}return i};(function(){var g=t.createElement("div"),
+i="script"+(new Date).getTime(),n=t.documentElement;g.innerHTML="<a name='"+i+"'/>";n.insertBefore(g,n.firstChild);if(t.getElementById(i)){o.find.ID=function(m,p,q){if(typeof p.getElementById!=="undefined"&&!q)return(p=p.getElementById(m[1]))?p.id===m[1]||typeof p.getAttributeNode!=="undefined"&&p.getAttributeNode("id").nodeValue===m[1]?[p]:B:[]};o.filter.ID=function(m,p){var q=typeof m.getAttributeNode!=="undefined"&&m.getAttributeNode("id");return m.nodeType===1&&q&&q.nodeValue===p}}n.removeChild(g);
+n=g=null})();(function(){var g=t.createElement("div");g.appendChild(t.createComment(""));if(g.getElementsByTagName("*").length>0)o.find.TAG=function(i,n){var m=n.getElementsByTagName(i[1]);if(i[1]==="*"){for(var p=[],q=0;m[q];q++)m[q].nodeType===1&&p.push(m[q]);m=p}return m};g.innerHTML="<a href='#'></a>";if(g.firstChild&&typeof g.firstChild.getAttribute!=="undefined"&&g.firstChild.getAttribute("href")!=="#")o.attrHandle.href=function(i){return i.getAttribute("href",2)};g=null})();t.querySelectorAll&&
+function(){var g=k,i=t.createElement("div");i.innerHTML="<p class='TEST'></p>";if(!(i.querySelectorAll&&i.querySelectorAll(".TEST").length===0)){k=function(m,p,q,u){p=p||t;m=m.replace(/\=\s*([^'"\]]*)\s*\]/g,"='$1']");if(!u&&!k.isXML(p))if(p.nodeType===9)try{return C(p.querySelectorAll(m),q)}catch(y){}else if(p.nodeType===1&&p.nodeName.toLowerCase()!=="object"){var F=p.getAttribute("id"),M=F||"__sizzle__";F||p.setAttribute("id",M);try{return C(p.querySelectorAll("#"+M+" "+m),q)}catch(N){}finally{F||
+p.removeAttribute("id")}}return g(m,p,q,u)};for(var n in g)k[n]=g[n];i=null}}();(function(){var g=t.documentElement,i=g.matchesSelector||g.mozMatchesSelector||g.webkitMatchesSelector||g.msMatchesSelector,n=false;try{i.call(t.documentElement,"[test!='']:sizzle")}catch(m){n=true}if(i)k.matchesSelector=function(p,q){q=q.replace(/\=\s*([^'"\]]*)\s*\]/g,"='$1']");if(!k.isXML(p))try{if(n||!o.match.PSEUDO.test(q)&&!/!=/.test(q))return i.call(p,q)}catch(u){}return k(q,null,null,[p]).length>0}})();(function(){var g=
+t.createElement("div");g.innerHTML="<div class='test e'></div><div class='test'></div>";if(!(!g.getElementsByClassName||g.getElementsByClassName("e").length===0)){g.lastChild.className="e";if(g.getElementsByClassName("e").length!==1){o.order.splice(1,0,"CLASS");o.find.CLASS=function(i,n,m){if(typeof n.getElementsByClassName!=="undefined"&&!m)return n.getElementsByClassName(i[1])};g=null}}})();k.contains=t.documentElement.contains?function(g,i){return g!==i&&(g.contains?g.contains(i):true)}:t.documentElement.compareDocumentPosition?
+function(g,i){return!!(g.compareDocumentPosition(i)&16)}:function(){return false};k.isXML=function(g){return(g=(g?g.ownerDocument||g:0).documentElement)?g.nodeName!=="HTML":false};var L=function(g,i){for(var n,m=[],p="",q=i.nodeType?[i]:i;n=o.match.PSEUDO.exec(g);){p+=n[0];g=g.replace(o.match.PSEUDO,"")}g=o.relative[g]?g+"*":g;n=0;for(var u=q.length;n<u;n++)k(g,q[n],m);return k.filter(p,m)};c.find=k;c.expr=k.selectors;c.expr[":"]=c.expr.filters;c.unique=k.uniqueSort;c.text=k.getText;c.isXMLDoc=k.isXML;
+c.contains=k.contains})();var Za=/Until$/,$a=/^(?:parents|prevUntil|prevAll)/,ab=/,/,Na=/^.[^:#\[\.,]*$/,bb=Array.prototype.slice,cb=c.expr.match.POS;c.fn.extend({find:function(a){for(var b=this.pushStack("","find",a),d=0,e=0,f=this.length;e<f;e++){d=b.length;c.find(a,this[e],b);if(e>0)for(var h=d;h<b.length;h++)for(var l=0;l<d;l++)if(b[l]===b[h]){b.splice(h--,1);break}}return b},has:function(a){var b=c(a);return this.filter(function(){for(var d=0,e=b.length;d<e;d++)if(c.contains(this,b[d]))return true})},
+not:function(a){return this.pushStack(ma(this,a,false),"not",a)},filter:function(a){return this.pushStack(ma(this,a,true),"filter",a)},is:function(a){return!!a&&c.filter(a,this).length>0},closest:function(a,b){var d=[],e,f,h=this[0];if(c.isArray(a)){var l,k={},o=1;if(h&&a.length){e=0;for(f=a.length;e<f;e++){l=a[e];k[l]||(k[l]=c.expr.match.POS.test(l)?c(l,b||this.context):l)}for(;h&&h.ownerDocument&&h!==b;){for(l in k){e=k[l];if(e.jquery?e.index(h)>-1:c(h).is(e))d.push({selector:l,elem:h,level:o})}h=
+h.parentNode;o++}}return d}l=cb.test(a)?c(a,b||this.context):null;e=0;for(f=this.length;e<f;e++)for(h=this[e];h;)if(l?l.index(h)>-1:c.find.matchesSelector(h,a)){d.push(h);break}else{h=h.parentNode;if(!h||!h.ownerDocument||h===b)break}d=d.length>1?c.unique(d):d;return this.pushStack(d,"closest",a)},index:function(a){if(!a||typeof a==="string")return c.inArray(this[0],a?c(a):this.parent().children());return c.inArray(a.jquery?a[0]:a,this)},add:function(a,b){var d=typeof a==="string"?c(a,b||this.context):
+c.makeArray(a),e=c.merge(this.get(),d);return this.pushStack(!d[0]||!d[0].parentNode||d[0].parentNode.nodeType===11||!e[0]||!e[0].parentNode||e[0].parentNode.nodeType===11?e:c.unique(e))},andSelf:function(){return this.add(this.prevObject)}});c.each({parent:function(a){return(a=a.parentNode)&&a.nodeType!==11?a:null},parents:function(a){return c.dir(a,"parentNode")},parentsUntil:function(a,b,d){return c.dir(a,"parentNode",d)},next:function(a){return c.nth(a,2,"nextSibling")},prev:function(a){return c.nth(a,
+2,"previousSibling")},nextAll:function(a){return c.dir(a,"nextSibling")},prevAll:function(a){return c.dir(a,"previousSibling")},nextUntil:function(a,b,d){return c.dir(a,"nextSibling",d)},prevUntil:function(a,b,d){return c.dir(a,"previousSibling",d)},siblings:function(a){return c.sibling(a.parentNode.firstChild,a)},children:function(a){return c.sibling(a.firstChild)},contents:function(a){return c.nodeName(a,"iframe")?a.contentDocument||a.contentWindow.document:c.makeArray(a.childNodes)}},function(a,
+b){c.fn[a]=function(d,e){var f=c.map(this,b,d);Za.test(a)||(e=d);if(e&&typeof e==="string")f=c.filter(e,f);f=this.length>1?c.unique(f):f;if((this.length>1||ab.test(e))&&$a.test(a))f=f.reverse();return this.pushStack(f,a,bb.call(arguments).join(","))}});c.extend({filter:function(a,b,d){if(d)a=":not("+a+")";return b.length===1?c.find.matchesSelector(b[0],a)?[b[0]]:[]:c.find.matches(a,b)},dir:function(a,b,d){var e=[];for(a=a[b];a&&a.nodeType!==9&&(d===B||a.nodeType!==1||!c(a).is(d));){a.nodeType===1&&
+e.push(a);a=a[b]}return e},nth:function(a,b,d){b=b||1;for(var e=0;a;a=a[d])if(a.nodeType===1&&++e===b)break;return a},sibling:function(a,b){for(var d=[];a;a=a.nextSibling)a.nodeType===1&&a!==b&&d.push(a);return d}});var za=/ jQuery\d+="(?:\d+|null)"/g,$=/^\s+/,Aa=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/ig,Ba=/<([\w:]+)/,db=/<tbody/i,eb=/<|&#?\w+;/,Ca=/<(?:script|object|embed|option|style)/i,Da=/checked\s*(?:[^=]|=\s*.checked.)/i,fb=/\=([^="'>\s]+\/)>/g,P={option:[1,
+"<select multiple='multiple'>","</select>"],legend:[1,"<fieldset>","</fieldset>"],thead:[1,"<table>","</table>"],tr:[2,"<table><tbody>","</tbody></table>"],td:[3,"<table><tbody><tr>","</tr></tbody></table>"],col:[2,"<table><tbody></tbody><colgroup>","</colgroup></table>"],area:[1,"<map>","</map>"],_default:[0,"",""]};P.optgroup=P.option;P.tbody=P.tfoot=P.colgroup=P.caption=P.thead;P.th=P.td;if(!c.support.htmlSerialize)P._default=[1,"div<div>","</div>"];c.fn.extend({text:function(a){if(c.isFunction(a))return this.each(function(b){var d=
+c(this);d.text(a.call(this,b,d.text()))});if(typeof a!=="object"&&a!==B)return this.empty().append((this[0]&&this[0].ownerDocument||t).createTextNode(a));return c.text(this)},wrapAll:function(a){if(c.isFunction(a))return this.each(function(d){c(this).wrapAll(a.call(this,d))});if(this[0]){var b=c(a,this[0].ownerDocument).eq(0).clone(true);this[0].parentNode&&b.insertBefore(this[0]);b.map(function(){for(var d=this;d.firstChild&&d.firstChild.nodeType===1;)d=d.firstChild;return d}).append(this)}return this},
+wrapInner:function(a){if(c.isFunction(a))return this.each(function(b){c(this).wrapInner(a.call(this,b))});return this.each(function(){var b=c(this),d=b.contents();d.length?d.wrapAll(a):b.append(a)})},wrap:function(a){return this.each(function(){c(this).wrapAll(a)})},unwrap:function(){return this.parent().each(function(){c.nodeName(this,"body")||c(this).replaceWith(this.childNodes)}).end()},append:function(){return this.domManip(arguments,true,function(a){this.nodeType===1&&this.appendChild(a)})},
+prepend:function(){return this.domManip(arguments,true,function(a){this.nodeType===1&&this.insertBefore(a,this.firstChild)})},before:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,false,function(b){this.parentNode.insertBefore(b,this)});else if(arguments.length){var a=c(arguments[0]);a.push.apply(a,this.toArray());return this.pushStack(a,"before",arguments)}},after:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,false,function(b){this.parentNode.insertBefore(b,
+this.nextSibling)});else if(arguments.length){var a=this.pushStack(this,"after",arguments);a.push.apply(a,c(arguments[0]).toArray());return a}},remove:function(a,b){for(var d=0,e;(e=this[d])!=null;d++)if(!a||c.filter(a,[e]).length){if(!b&&e.nodeType===1){c.cleanData(e.getElementsByTagName("*"));c.cleanData([e])}e.parentNode&&e.parentNode.removeChild(e)}return this},empty:function(){for(var a=0,b;(b=this[a])!=null;a++)for(b.nodeType===1&&c.cleanData(b.getElementsByTagName("*"));b.firstChild;)b.removeChild(b.firstChild);
+return this},clone:function(a){var b=this.map(function(){if(!c.support.noCloneEvent&&!c.isXMLDoc(this)){var d=this.outerHTML,e=this.ownerDocument;if(!d){d=e.createElement("div");d.appendChild(this.cloneNode(true));d=d.innerHTML}return c.clean([d.replace(za,"").replace(fb,'="$1">').replace($,"")],e)[0]}else return this.cloneNode(true)});if(a===true){na(this,b);na(this.find("*"),b.find("*"))}return b},html:function(a){if(a===B)return this[0]&&this[0].nodeType===1?this[0].innerHTML.replace(za,""):null;
+else if(typeof a==="string"&&!Ca.test(a)&&(c.support.leadingWhitespace||!$.test(a))&&!P[(Ba.exec(a)||["",""])[1].toLowerCase()]){a=a.replace(Aa,"<$1></$2>");try{for(var b=0,d=this.length;b<d;b++)if(this[b].nodeType===1){c.cleanData(this[b].getElementsByTagName("*"));this[b].innerHTML=a}}catch(e){this.empty().append(a)}}else c.isFunction(a)?this.each(function(f){var h=c(this);h.html(a.call(this,f,h.html()))}):this.empty().append(a);return this},replaceWith:function(a){if(this[0]&&this[0].parentNode){if(c.isFunction(a))return this.each(function(b){var d=
+c(this),e=d.html();d.replaceWith(a.call(this,b,e))});if(typeof a!=="string")a=c(a).detach();return this.each(function(){var b=this.nextSibling,d=this.parentNode;c(this).remove();b?c(b).before(a):c(d).append(a)})}else return this.pushStack(c(c.isFunction(a)?a():a),"replaceWith",a)},detach:function(a){return this.remove(a,true)},domManip:function(a,b,d){var e,f,h,l=a[0],k=[];if(!c.support.checkClone&&arguments.length===3&&typeof l==="string"&&Da.test(l))return this.each(function(){c(this).domManip(a,
+b,d,true)});if(c.isFunction(l))return this.each(function(x){var r=c(this);a[0]=l.call(this,x,b?r.html():B);r.domManip(a,b,d)});if(this[0]){e=l&&l.parentNode;e=c.support.parentNode&&e&&e.nodeType===11&&e.childNodes.length===this.length?{fragment:e}:c.buildFragment(a,this,k);h=e.fragment;if(f=h.childNodes.length===1?h=h.firstChild:h.firstChild){b=b&&c.nodeName(f,"tr");f=0;for(var o=this.length;f<o;f++)d.call(b?c.nodeName(this[f],"table")?this[f].getElementsByTagName("tbody")[0]||this[f].appendChild(this[f].ownerDocument.createElement("tbody")):
+this[f]:this[f],f>0||e.cacheable||this.length>1?h.cloneNode(true):h)}k.length&&c.each(k,Oa)}return this}});c.buildFragment=function(a,b,d){var e,f,h;b=b&&b[0]?b[0].ownerDocument||b[0]:t;if(a.length===1&&typeof a[0]==="string"&&a[0].length<512&&b===t&&!Ca.test(a[0])&&(c.support.checkClone||!Da.test(a[0]))){f=true;if(h=c.fragments[a[0]])if(h!==1)e=h}if(!e){e=b.createDocumentFragment();c.clean(a,b,e,d)}if(f)c.fragments[a[0]]=h?e:1;return{fragment:e,cacheable:f}};c.fragments={};c.each({appendTo:"append",
+prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){c.fn[a]=function(d){var e=[];d=c(d);var f=this.length===1&&this[0].parentNode;if(f&&f.nodeType===11&&f.childNodes.length===1&&d.length===1){d[b](this[0]);return this}else{f=0;for(var h=d.length;f<h;f++){var l=(f>0?this.clone(true):this).get();c(d[f])[b](l);e=e.concat(l)}return this.pushStack(e,a,d.selector)}}});c.extend({clean:function(a,b,d,e){b=b||t;if(typeof b.createElement==="undefined")b=b.ownerDocument||
+b[0]&&b[0].ownerDocument||t;for(var f=[],h=0,l;(l=a[h])!=null;h++){if(typeof l==="number")l+="";if(l){if(typeof l==="string"&&!eb.test(l))l=b.createTextNode(l);else if(typeof l==="string"){l=l.replace(Aa,"<$1></$2>");var k=(Ba.exec(l)||["",""])[1].toLowerCase(),o=P[k]||P._default,x=o[0],r=b.createElement("div");for(r.innerHTML=o[1]+l+o[2];x--;)r=r.lastChild;if(!c.support.tbody){x=db.test(l);k=k==="table"&&!x?r.firstChild&&r.firstChild.childNodes:o[1]==="<table>"&&!x?r.childNodes:[];for(o=k.length-
+1;o>=0;--o)c.nodeName(k[o],"tbody")&&!k[o].childNodes.length&&k[o].parentNode.removeChild(k[o])}!c.support.leadingWhitespace&&$.test(l)&&r.insertBefore(b.createTextNode($.exec(l)[0]),r.firstChild);l=r.childNodes}if(l.nodeType)f.push(l);else f=c.merge(f,l)}}if(d)for(h=0;f[h];h++)if(e&&c.nodeName(f[h],"script")&&(!f[h].type||f[h].type.toLowerCase()==="text/javascript"))e.push(f[h].parentNode?f[h].parentNode.removeChild(f[h]):f[h]);else{f[h].nodeType===1&&f.splice.apply(f,[h+1,0].concat(c.makeArray(f[h].getElementsByTagName("script"))));
+d.appendChild(f[h])}return f},cleanData:function(a){for(var b,d,e=c.cache,f=c.event.special,h=c.support.deleteExpando,l=0,k;(k=a[l])!=null;l++)if(!(k.nodeName&&c.noData[k.nodeName.toLowerCase()]))if(d=k[c.expando]){if((b=e[d])&&b.events)for(var o in b.events)f[o]?c.event.remove(k,o):c.removeEvent(k,o,b.handle);if(h)delete k[c.expando];else k.removeAttribute&&k.removeAttribute(c.expando);delete e[d]}}});var Ea=/alpha\([^)]*\)/i,gb=/opacity=([^)]*)/,hb=/-([a-z])/ig,ib=/([A-Z])/g,Fa=/^-?\d+(?:px)?$/i,
+jb=/^-?\d/,kb={position:"absolute",visibility:"hidden",display:"block"},Pa=["Left","Right"],Qa=["Top","Bottom"],W,Ga,aa,lb=function(a,b){return b.toUpperCase()};c.fn.css=function(a,b){if(arguments.length===2&&b===B)return this;return c.access(this,a,b,true,function(d,e,f){return f!==B?c.style(d,e,f):c.css(d,e)})};c.extend({cssHooks:{opacity:{get:function(a,b){if(b){var d=W(a,"opacity","opacity");return d===""?"1":d}else return a.style.opacity}}},cssNumber:{zIndex:true,fontWeight:true,opacity:true,
+zoom:true,lineHeight:true},cssProps:{"float":c.support.cssFloat?"cssFloat":"styleFloat"},style:function(a,b,d,e){if(!(!a||a.nodeType===3||a.nodeType===8||!a.style)){var f,h=c.camelCase(b),l=a.style,k=c.cssHooks[h];b=c.cssProps[h]||h;if(d!==B){if(!(typeof d==="number"&&isNaN(d)||d==null)){if(typeof d==="number"&&!c.cssNumber[h])d+="px";if(!k||!("set"in k)||(d=k.set(a,d))!==B)try{l[b]=d}catch(o){}}}else{if(k&&"get"in k&&(f=k.get(a,false,e))!==B)return f;return l[b]}}},css:function(a,b,d){var e,f=c.camelCase(b),
+h=c.cssHooks[f];b=c.cssProps[f]||f;if(h&&"get"in h&&(e=h.get(a,true,d))!==B)return e;else if(W)return W(a,b,f)},swap:function(a,b,d){var e={},f;for(f in b){e[f]=a.style[f];a.style[f]=b[f]}d.call(a);for(f in b)a.style[f]=e[f]},camelCase:function(a){return a.replace(hb,lb)}});c.curCSS=c.css;c.each(["height","width"],function(a,b){c.cssHooks[b]={get:function(d,e,f){var h;if(e){if(d.offsetWidth!==0)h=oa(d,b,f);else c.swap(d,kb,function(){h=oa(d,b,f)});if(h<=0){h=W(d,b,b);if(h==="0px"&&aa)h=aa(d,b,b);
+if(h!=null)return h===""||h==="auto"?"0px":h}if(h<0||h==null){h=d.style[b];return h===""||h==="auto"?"0px":h}return typeof h==="string"?h:h+"px"}},set:function(d,e){if(Fa.test(e)){e=parseFloat(e);if(e>=0)return e+"px"}else return e}}});if(!c.support.opacity)c.cssHooks.opacity={get:function(a,b){return gb.test((b&&a.currentStyle?a.currentStyle.filter:a.style.filter)||"")?parseFloat(RegExp.$1)/100+"":b?"1":""},set:function(a,b){var d=a.style;d.zoom=1;var e=c.isNaN(b)?"":"alpha(opacity="+b*100+")",f=
+d.filter||"";d.filter=Ea.test(f)?f.replace(Ea,e):d.filter+" "+e}};if(t.defaultView&&t.defaultView.getComputedStyle)Ga=function(a,b,d){var e;d=d.replace(ib,"-$1").toLowerCase();if(!(b=a.ownerDocument.defaultView))return B;if(b=b.getComputedStyle(a,null)){e=b.getPropertyValue(d);if(e===""&&!c.contains(a.ownerDocument.documentElement,a))e=c.style(a,d)}return e};if(t.documentElement.currentStyle)aa=function(a,b){var d,e,f=a.currentStyle&&a.currentStyle[b],h=a.style;if(!Fa.test(f)&&jb.test(f)){d=h.left;
+e=a.runtimeStyle.left;a.runtimeStyle.left=a.currentStyle.left;h.left=b==="fontSize"?"1em":f||0;f=h.pixelLeft+"px";h.left=d;a.runtimeStyle.left=e}return f===""?"auto":f};W=Ga||aa;if(c.expr&&c.expr.filters){c.expr.filters.hidden=function(a){var b=a.offsetHeight;return a.offsetWidth===0&&b===0||!c.support.reliableHiddenOffsets&&(a.style.display||c.css(a,"display"))==="none"};c.expr.filters.visible=function(a){return!c.expr.filters.hidden(a)}}var mb=c.now(),nb=/<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi,
+ob=/^(?:select|textarea)/i,pb=/^(?:color|date|datetime|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i,qb=/^(?:GET|HEAD)$/,Ra=/\[\]$/,T=/\=\?(&|$)/,ja=/\?/,rb=/([?&])_=[^&]*/,sb=/^(\w+:)?\/\/([^\/?#]+)/,tb=/%20/g,ub=/#.*$/,Ha=c.fn.load;c.fn.extend({load:function(a,b,d){if(typeof a!=="string"&&Ha)return Ha.apply(this,arguments);else if(!this.length)return this;var e=a.indexOf(" ");if(e>=0){var f=a.slice(e,a.length);a=a.slice(0,e)}e="GET";if(b)if(c.isFunction(b)){d=b;b=null}else if(typeof b===
+"object"){b=c.param(b,c.ajaxSettings.traditional);e="POST"}var h=this;c.ajax({url:a,type:e,dataType:"html",data:b,complete:function(l,k){if(k==="success"||k==="notmodified")h.html(f?c("<div>").append(l.responseText.replace(nb,"")).find(f):l.responseText);d&&h.each(d,[l.responseText,k,l])}});return this},serialize:function(){return c.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?c.makeArray(this.elements):this}).filter(function(){return this.name&&
+!this.disabled&&(this.checked||ob.test(this.nodeName)||pb.test(this.type))}).map(function(a,b){var d=c(this).val();return d==null?null:c.isArray(d)?c.map(d,function(e){return{name:b.name,value:e}}):{name:b.name,value:d}}).get()}});c.each("ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split(" "),function(a,b){c.fn[b]=function(d){return this.bind(b,d)}});c.extend({get:function(a,b,d,e){if(c.isFunction(b)){e=e||d;d=b;b=null}return c.ajax({type:"GET",url:a,data:b,success:d,dataType:e})},
+getScript:function(a,b){return c.get(a,null,b,"script")},getJSON:function(a,b,d){return c.get(a,b,d,"json")},post:function(a,b,d,e){if(c.isFunction(b)){e=e||d;d=b;b={}}return c.ajax({type:"POST",url:a,data:b,success:d,dataType:e})},ajaxSetup:function(a){c.extend(c.ajaxSettings,a)},ajaxSettings:{url:location.href,global:true,type:"GET",contentType:"application/x-www-form-urlencoded",processData:true,async:true,xhr:function(){return new E.XMLHttpRequest},accepts:{xml:"application/xml, text/xml",html:"text/html",
+script:"text/javascript, application/javascript",json:"application/json, text/javascript",text:"text/plain",_default:"*/*"}},ajax:function(a){var b=c.extend(true,{},c.ajaxSettings,a),d,e,f,h=b.type.toUpperCase(),l=qb.test(h);b.url=b.url.replace(ub,"");b.context=a&&a.context!=null?a.context:b;if(b.data&&b.processData&&typeof b.data!=="string")b.data=c.param(b.data,b.traditional);if(b.dataType==="jsonp"){if(h==="GET")T.test(b.url)||(b.url+=(ja.test(b.url)?"&":"?")+(b.jsonp||"callback")+"=?");else if(!b.data||
+!T.test(b.data))b.data=(b.data?b.data+"&":"")+(b.jsonp||"callback")+"=?";b.dataType="json"}if(b.dataType==="json"&&(b.data&&T.test(b.data)||T.test(b.url))){d=b.jsonpCallback||"jsonp"+mb++;if(b.data)b.data=(b.data+"").replace(T,"="+d+"$1");b.url=b.url.replace(T,"="+d+"$1");b.dataType="script";var k=E[d];E[d]=function(m){if(c.isFunction(k))k(m);else{E[d]=B;try{delete E[d]}catch(p){}}f=m;c.handleSuccess(b,w,e,f);c.handleComplete(b,w,e,f);r&&r.removeChild(A)}}if(b.dataType==="script"&&b.cache===null)b.cache=
+false;if(b.cache===false&&l){var o=c.now(),x=b.url.replace(rb,"$1_="+o);b.url=x+(x===b.url?(ja.test(b.url)?"&":"?")+"_="+o:"")}if(b.data&&l)b.url+=(ja.test(b.url)?"&":"?")+b.data;b.global&&c.active++===0&&c.event.trigger("ajaxStart");o=(o=sb.exec(b.url))&&(o[1]&&o[1].toLowerCase()!==location.protocol||o[2].toLowerCase()!==location.host);if(b.dataType==="script"&&h==="GET"&&o){var r=t.getElementsByTagName("head")[0]||t.documentElement,A=t.createElement("script");if(b.scriptCharset)A.charset=b.scriptCharset;
+A.src=b.url;if(!d){var C=false;A.onload=A.onreadystatechange=function(){if(!C&&(!this.readyState||this.readyState==="loaded"||this.readyState==="complete")){C=true;c.handleSuccess(b,w,e,f);c.handleComplete(b,w,e,f);A.onload=A.onreadystatechange=null;r&&A.parentNode&&r.removeChild(A)}}}r.insertBefore(A,r.firstChild);return B}var J=false,w=b.xhr();if(w){b.username?w.open(h,b.url,b.async,b.username,b.password):w.open(h,b.url,b.async);try{if(b.data!=null&&!l||a&&a.contentType)w.setRequestHeader("Content-Type",
+b.contentType);if(b.ifModified){c.lastModified[b.url]&&w.setRequestHeader("If-Modified-Since",c.lastModified[b.url]);c.etag[b.url]&&w.setRequestHeader("If-None-Match",c.etag[b.url])}o||w.setRequestHeader("X-Requested-With","XMLHttpRequest");w.setRequestHeader("Accept",b.dataType&&b.accepts[b.dataType]?b.accepts[b.dataType]+", */*; q=0.01":b.accepts._default)}catch(I){}if(b.beforeSend&&b.beforeSend.call(b.context,w,b)===false){b.global&&c.active--===1&&c.event.trigger("ajaxStop");w.abort();return false}b.global&&
+c.triggerGlobal(b,"ajaxSend",[w,b]);var L=w.onreadystatechange=function(m){if(!w||w.readyState===0||m==="abort"){J||c.handleComplete(b,w,e,f);J=true;if(w)w.onreadystatechange=c.noop}else if(!J&&w&&(w.readyState===4||m==="timeout")){J=true;w.onreadystatechange=c.noop;e=m==="timeout"?"timeout":!c.httpSuccess(w)?"error":b.ifModified&&c.httpNotModified(w,b.url)?"notmodified":"success";var p;if(e==="success")try{f=c.httpData(w,b.dataType,b)}catch(q){e="parsererror";p=q}if(e==="success"||e==="notmodified")d||
+c.handleSuccess(b,w,e,f);else c.handleError(b,w,e,p);d||c.handleComplete(b,w,e,f);m==="timeout"&&w.abort();if(b.async)w=null}};try{var g=w.abort;w.abort=function(){w&&Function.prototype.call.call(g,w);L("abort")}}catch(i){}b.async&&b.timeout>0&&setTimeout(function(){w&&!J&&L("timeout")},b.timeout);try{w.send(l||b.data==null?null:b.data)}catch(n){c.handleError(b,w,null,n);c.handleComplete(b,w,e,f)}b.async||L();return w}},param:function(a,b){var d=[],e=function(h,l){l=c.isFunction(l)?l():l;d[d.length]=
+encodeURIComponent(h)+"="+encodeURIComponent(l)};if(b===B)b=c.ajaxSettings.traditional;if(c.isArray(a)||a.jquery)c.each(a,function(){e(this.name,this.value)});else for(var f in a)da(f,a[f],b,e);return d.join("&").replace(tb,"+")}});c.extend({active:0,lastModified:{},etag:{},handleError:function(a,b,d,e){a.error&&a.error.call(a.context,b,d,e);a.global&&c.triggerGlobal(a,"ajaxError",[b,a,e])},handleSuccess:function(a,b,d,e){a.success&&a.success.call(a.context,e,d,b);a.global&&c.triggerGlobal(a,"ajaxSuccess",
+[b,a])},handleComplete:function(a,b,d){a.complete&&a.complete.call(a.context,b,d);a.global&&c.triggerGlobal(a,"ajaxComplete",[b,a]);a.global&&c.active--===1&&c.event.trigger("ajaxStop")},triggerGlobal:function(a,b,d){(a.context&&a.context.url==null?c(a.context):c.event).trigger(b,d)},httpSuccess:function(a){try{return!a.status&&location.protocol==="file:"||a.status>=200&&a.status<300||a.status===304||a.status===1223}catch(b){}return false},httpNotModified:function(a,b){var d=a.getResponseHeader("Last-Modified"),
+e=a.getResponseHeader("Etag");if(d)c.lastModified[b]=d;if(e)c.etag[b]=e;return a.status===304},httpData:function(a,b,d){var e=a.getResponseHeader("content-type")||"",f=b==="xml"||!b&&e.indexOf("xml")>=0;a=f?a.responseXML:a.responseText;f&&a.documentElement.nodeName==="parsererror"&&c.error("parsererror");if(d&&d.dataFilter)a=d.dataFilter(a,b);if(typeof a==="string")if(b==="json"||!b&&e.indexOf("json")>=0)a=c.parseJSON(a);else if(b==="script"||!b&&e.indexOf("javascript")>=0)c.globalEval(a);return a}});
+if(E.ActiveXObject)c.ajaxSettings.xhr=function(){if(E.location.protocol!=="file:")try{return new E.XMLHttpRequest}catch(a){}try{return new E.ActiveXObject("Microsoft.XMLHTTP")}catch(b){}};c.support.ajax=!!c.ajaxSettings.xhr();var ea={},vb=/^(?:toggle|show|hide)$/,wb=/^([+\-]=)?([\d+.\-]+)(.*)$/,ba,pa=[["height","marginTop","marginBottom","paddingTop","paddingBottom"],["width","marginLeft","marginRight","paddingLeft","paddingRight"],["opacity"]];c.fn.extend({show:function(a,b,d){if(a||a===0)return this.animate(S("show",
+3),a,b,d);else{d=0;for(var e=this.length;d<e;d++){a=this[d];b=a.style.display;if(!c.data(a,"olddisplay")&&b==="none")b=a.style.display="";b===""&&c.css(a,"display")==="none"&&c.data(a,"olddisplay",qa(a.nodeName))}for(d=0;d<e;d++){a=this[d];b=a.style.display;if(b===""||b==="none")a.style.display=c.data(a,"olddisplay")||""}return this}},hide:function(a,b,d){if(a||a===0)return this.animate(S("hide",3),a,b,d);else{a=0;for(b=this.length;a<b;a++){d=c.css(this[a],"display");d!=="none"&&c.data(this[a],"olddisplay",
+d)}for(a=0;a<b;a++)this[a].style.display="none";return this}},_toggle:c.fn.toggle,toggle:function(a,b,d){var e=typeof a==="boolean";if(c.isFunction(a)&&c.isFunction(b))this._toggle.apply(this,arguments);else a==null||e?this.each(function(){var f=e?a:c(this).is(":hidden");c(this)[f?"show":"hide"]()}):this.animate(S("toggle",3),a,b,d);return this},fadeTo:function(a,b,d,e){return this.filter(":hidden").css("opacity",0).show().end().animate({opacity:b},a,d,e)},animate:function(a,b,d,e){var f=c.speed(b,
+d,e);if(c.isEmptyObject(a))return this.each(f.complete);return this[f.queue===false?"each":"queue"](function(){var h=c.extend({},f),l,k=this.nodeType===1,o=k&&c(this).is(":hidden"),x=this;for(l in a){var r=c.camelCase(l);if(l!==r){a[r]=a[l];delete a[l];l=r}if(a[l]==="hide"&&o||a[l]==="show"&&!o)return h.complete.call(this);if(k&&(l==="height"||l==="width")){h.overflow=[this.style.overflow,this.style.overflowX,this.style.overflowY];if(c.css(this,"display")==="inline"&&c.css(this,"float")==="none")if(c.support.inlineBlockNeedsLayout)if(qa(this.nodeName)===
+"inline")this.style.display="inline-block";else{this.style.display="inline";this.style.zoom=1}else this.style.display="inline-block"}if(c.isArray(a[l])){(h.specialEasing=h.specialEasing||{})[l]=a[l][1];a[l]=a[l][0]}}if(h.overflow!=null)this.style.overflow="hidden";h.curAnim=c.extend({},a);c.each(a,function(A,C){var J=new c.fx(x,h,A);if(vb.test(C))J[C==="toggle"?o?"show":"hide":C](a);else{var w=wb.exec(C),I=J.cur()||0;if(w){var L=parseFloat(w[2]),g=w[3]||"px";if(g!=="px"){c.style(x,A,(L||1)+g);I=(L||
+1)/J.cur()*I;c.style(x,A,I+g)}if(w[1])L=(w[1]==="-="?-1:1)*L+I;J.custom(I,L,g)}else J.custom(I,C,"")}});return true})},stop:function(a,b){var d=c.timers;a&&this.queue([]);this.each(function(){for(var e=d.length-1;e>=0;e--)if(d[e].elem===this){b&&d[e](true);d.splice(e,1)}});b||this.dequeue();return this}});c.each({slideDown:S("show",1),slideUp:S("hide",1),slideToggle:S("toggle",1),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"},fadeToggle:{opacity:"toggle"}},function(a,b){c.fn[a]=function(d,e,f){return this.animate(b,
+d,e,f)}});c.extend({speed:function(a,b,d){var e=a&&typeof a==="object"?c.extend({},a):{complete:d||!d&&b||c.isFunction(a)&&a,duration:a,easing:d&&b||b&&!c.isFunction(b)&&b};e.duration=c.fx.off?0:typeof e.duration==="number"?e.duration:e.duration in c.fx.speeds?c.fx.speeds[e.duration]:c.fx.speeds._default;e.old=e.complete;e.complete=function(){e.queue!==false&&c(this).dequeue();c.isFunction(e.old)&&e.old.call(this)};return e},easing:{linear:function(a,b,d,e){return d+e*a},swing:function(a,b,d,e){return(-Math.cos(a*
+Math.PI)/2+0.5)*e+d}},timers:[],fx:function(a,b,d){this.options=b;this.elem=a;this.prop=d;if(!b.orig)b.orig={}}});c.fx.prototype={update:function(){this.options.step&&this.options.step.call(this.elem,this.now,this);(c.fx.step[this.prop]||c.fx.step._default)(this)},cur:function(){if(this.elem[this.prop]!=null&&(!this.elem.style||this.elem.style[this.prop]==null))return this.elem[this.prop];var a=parseFloat(c.css(this.elem,this.prop));return a&&a>-1E4?a:0},custom:function(a,b,d){function e(l){return f.step(l)}
+var f=this,h=c.fx;this.startTime=c.now();this.start=a;this.end=b;this.unit=d||this.unit||"px";this.now=this.start;this.pos=this.state=0;e.elem=this.elem;if(e()&&c.timers.push(e)&&!ba)ba=setInterval(h.tick,h.interval)},show:function(){this.options.orig[this.prop]=c.style(this.elem,this.prop);this.options.show=true;this.custom(this.prop==="width"||this.prop==="height"?1:0,this.cur());c(this.elem).show()},hide:function(){this.options.orig[this.prop]=c.style(this.elem,this.prop);this.options.hide=true;
+this.custom(this.cur(),0)},step:function(a){var b=c.now(),d=true;if(a||b>=this.options.duration+this.startTime){this.now=this.end;this.pos=this.state=1;this.update();this.options.curAnim[this.prop]=true;for(var e in this.options.curAnim)if(this.options.curAnim[e]!==true)d=false;if(d){if(this.options.overflow!=null&&!c.support.shrinkWrapBlocks){var f=this.elem,h=this.options;c.each(["","X","Y"],function(k,o){f.style["overflow"+o]=h.overflow[k]})}this.options.hide&&c(this.elem).hide();if(this.options.hide||
+this.options.show)for(var l in this.options.curAnim)c.style(this.elem,l,this.options.orig[l]);this.options.complete.call(this.elem)}return false}else{a=b-this.startTime;this.state=a/this.options.duration;b=this.options.easing||(c.easing.swing?"swing":"linear");this.pos=c.easing[this.options.specialEasing&&this.options.specialEasing[this.prop]||b](this.state,a,0,1,this.options.duration);this.now=this.start+(this.end-this.start)*this.pos;this.update()}return true}};c.extend(c.fx,{tick:function(){for(var a=
+c.timers,b=0;b<a.length;b++)a[b]()||a.splice(b--,1);a.length||c.fx.stop()},interval:13,stop:function(){clearInterval(ba);ba=null},speeds:{slow:600,fast:200,_default:400},step:{opacity:function(a){c.style(a.elem,"opacity",a.now)},_default:function(a){if(a.elem.style&&a.elem.style[a.prop]!=null)a.elem.style[a.prop]=(a.prop==="width"||a.prop==="height"?Math.max(0,a.now):a.now)+a.unit;else a.elem[a.prop]=a.now}}});if(c.expr&&c.expr.filters)c.expr.filters.animated=function(a){return c.grep(c.timers,function(b){return a===
+b.elem}).length};var xb=/^t(?:able|d|h)$/i,Ia=/^(?:body|html)$/i;c.fn.offset="getBoundingClientRect"in t.documentElement?function(a){var b=this[0],d;if(a)return this.each(function(l){c.offset.setOffset(this,a,l)});if(!b||!b.ownerDocument)return null;if(b===b.ownerDocument.body)return c.offset.bodyOffset(b);try{d=b.getBoundingClientRect()}catch(e){}var f=b.ownerDocument,h=f.documentElement;if(!d||!c.contains(h,b))return d||{top:0,left:0};b=f.body;f=fa(f);return{top:d.top+(f.pageYOffset||c.support.boxModel&&
+h.scrollTop||b.scrollTop)-(h.clientTop||b.clientTop||0),left:d.left+(f.pageXOffset||c.support.boxModel&&h.scrollLeft||b.scrollLeft)-(h.clientLeft||b.clientLeft||0)}}:function(a){var b=this[0];if(a)return this.each(function(x){c.offset.setOffset(this,a,x)});if(!b||!b.ownerDocument)return null;if(b===b.ownerDocument.body)return c.offset.bodyOffset(b);c.offset.initialize();var d,e=b.offsetParent,f=b.ownerDocument,h=f.documentElement,l=f.body;d=(f=f.defaultView)?f.getComputedStyle(b,null):b.currentStyle;
+for(var k=b.offsetTop,o=b.offsetLeft;(b=b.parentNode)&&b!==l&&b!==h;){if(c.offset.supportsFixedPosition&&d.position==="fixed")break;d=f?f.getComputedStyle(b,null):b.currentStyle;k-=b.scrollTop;o-=b.scrollLeft;if(b===e){k+=b.offsetTop;o+=b.offsetLeft;if(c.offset.doesNotAddBorder&&!(c.offset.doesAddBorderForTableAndCells&&xb.test(b.nodeName))){k+=parseFloat(d.borderTopWidth)||0;o+=parseFloat(d.borderLeftWidth)||0}e=b.offsetParent}if(c.offset.subtractsBorderForOverflowNotVisible&&d.overflow!=="visible"){k+=
+parseFloat(d.borderTopWidth)||0;o+=parseFloat(d.borderLeftWidth)||0}d=d}if(d.position==="relative"||d.position==="static"){k+=l.offsetTop;o+=l.offsetLeft}if(c.offset.supportsFixedPosition&&d.position==="fixed"){k+=Math.max(h.scrollTop,l.scrollTop);o+=Math.max(h.scrollLeft,l.scrollLeft)}return{top:k,left:o}};c.offset={initialize:function(){var a=t.body,b=t.createElement("div"),d,e,f,h=parseFloat(c.css(a,"marginTop"))||0;c.extend(b.style,{position:"absolute",top:0,left:0,margin:0,border:0,width:"1px",
+height:"1px",visibility:"hidden"});b.innerHTML="<div style='position:absolute;top:0;left:0;margin:0;border:5px solid #000;padding:0;width:1px;height:1px;'><div></div></div><table style='position:absolute;top:0;left:0;margin:0;border:5px solid #000;padding:0;width:1px;height:1px;' cellpadding='0' cellspacing='0'><tr><td></td></tr></table>";a.insertBefore(b,a.firstChild);d=b.firstChild;e=d.firstChild;f=d.nextSibling.firstChild.firstChild;this.doesNotAddBorder=e.offsetTop!==5;this.doesAddBorderForTableAndCells=
+f.offsetTop===5;e.style.position="fixed";e.style.top="20px";this.supportsFixedPosition=e.offsetTop===20||e.offsetTop===15;e.style.position=e.style.top="";d.style.overflow="hidden";d.style.position="relative";this.subtractsBorderForOverflowNotVisible=e.offsetTop===-5;this.doesNotIncludeMarginInBodyOffset=a.offsetTop!==h;a.removeChild(b);c.offset.initialize=c.noop},bodyOffset:function(a){var b=a.offsetTop,d=a.offsetLeft;c.offset.initialize();if(c.offset.doesNotIncludeMarginInBodyOffset){b+=parseFloat(c.css(a,
+"marginTop"))||0;d+=parseFloat(c.css(a,"marginLeft"))||0}return{top:b,left:d}},setOffset:function(a,b,d){var e=c.css(a,"position");if(e==="static")a.style.position="relative";var f=c(a),h=f.offset(),l=c.css(a,"top"),k=c.css(a,"left"),o=e==="absolute"&&c.inArray("auto",[l,k])>-1;e={};var x={};if(o)x=f.position();l=o?x.top:parseInt(l,10)||0;k=o?x.left:parseInt(k,10)||0;if(c.isFunction(b))b=b.call(a,d,h);if(b.top!=null)e.top=b.top-h.top+l;if(b.left!=null)e.left=b.left-h.left+k;"using"in b?b.using.call(a,
+e):f.css(e)}};c.fn.extend({position:function(){if(!this[0])return null;var a=this[0],b=this.offsetParent(),d=this.offset(),e=Ia.test(b[0].nodeName)?{top:0,left:0}:b.offset();d.top-=parseFloat(c.css(a,"marginTop"))||0;d.left-=parseFloat(c.css(a,"marginLeft"))||0;e.top+=parseFloat(c.css(b[0],"borderTopWidth"))||0;e.left+=parseFloat(c.css(b[0],"borderLeftWidth"))||0;return{top:d.top-e.top,left:d.left-e.left}},offsetParent:function(){return this.map(function(){for(var a=this.offsetParent||t.body;a&&!Ia.test(a.nodeName)&&
+c.css(a,"position")==="static";)a=a.offsetParent;return a})}});c.each(["Left","Top"],function(a,b){var d="scroll"+b;c.fn[d]=function(e){var f=this[0],h;if(!f)return null;if(e!==B)return this.each(function(){if(h=fa(this))h.scrollTo(!a?e:c(h).scrollLeft(),a?e:c(h).scrollTop());else this[d]=e});else return(h=fa(f))?"pageXOffset"in h?h[a?"pageYOffset":"pageXOffset"]:c.support.boxModel&&h.document.documentElement[d]||h.document.body[d]:f[d]}});c.each(["Height","Width"],function(a,b){var d=b.toLowerCase();
+c.fn["inner"+b]=function(){return this[0]?parseFloat(c.css(this[0],d,"padding")):null};c.fn["outer"+b]=function(e){return this[0]?parseFloat(c.css(this[0],d,e?"margin":"border")):null};c.fn[d]=function(e){var f=this[0];if(!f)return e==null?null:this;if(c.isFunction(e))return this.each(function(l){var k=c(this);k[d](e.call(this,l,k[d]()))});if(c.isWindow(f))return f.document.compatMode==="CSS1Compat"&&f.document.documentElement["client"+b]||f.document.body["client"+b];else if(f.nodeType===9)return Math.max(f.documentElement["client"+
+b],f.body["scroll"+b],f.documentElement["scroll"+b],f.body["offset"+b],f.documentElement["offset"+b]);else if(e===B){f=c.css(f,d);var h=parseFloat(f);return c.isNaN(h)?f:h}else return this.css(d,typeof e==="string"?e:e+"px")}})})(window);
diff --git a/js/jquery.contextmenu.js b/js/jquery.contextmenu.js
new file mode 100644 (file)
index 0000000..136c85f
--- /dev/null
@@ -0,0 +1,265 @@
+/**
+ * Copyright (c)2005-2009 Matt Kruse (javascripttoolbox.com)
+ * 
+ * Dual licensed under the MIT and GPL licenses. 
+ * This basically means you can use this code however you want for
+ * free, but don't claim to have written it yourself!
+ * Donations always accepted: http://www.JavascriptToolbox.com/donate/
+ * 
+ * Please do not link to the .js files on javascripttoolbox.com from
+ * your site. Copy the files locally to your server instead.
+ * 
+ */
+/**
+ * jquery.contextmenu.js
+ * jQuery Plugin for Context Menus
+ * http://www.JavascriptToolbox.com/lib/contextmenu/
+ *
+ * Copyright (c) 2008 Matt Kruse (javascripttoolbox.com)
+ * Dual licensed under the MIT and GPL licenses. 
+ *
+ * @version 1.1
+ * @history 1.1 2010-01-25 Fixed a problem with 1.4 which caused undesired show/hide animations
+ * @history 1.0 2008-10-20 Initial Release
+ * @todo slideUp doesn't work in IE - because of iframe?
+ * @todo Hide all other menus when contextmenu is shown?
+ * @todo More themes
+ * @todo Nested context menus
+ */
+;(function($){
+       $.contextMenu = {
+               shadow:true,
+               shadowOffset:0,
+               shadowOffsetX:5,
+               shadowOffsetY:5,
+               shadowWidthAdjust:-3,
+               shadowHeightAdjust:-3,
+               shadowOpacity:.2,
+               shadowClass:'context-menu-shadow',
+               shadowColor:'black',
+
+               offsetX:0,
+               offsetY:0,
+               appendTo:'body',
+               direction:'down',
+               constrainToScreen:true,
+                               
+               showTransition:'show',
+               hideTransition:'hide',
+               showSpeed:null,
+               hideSpeed:null,
+               showCallback:null,
+               hideCallback:null,
+               
+               className:'context-menu',
+               itemClassName:'context-menu-item',
+               itemHoverClassName:'context-menu-item-hover',
+               disabledItemClassName:'context-menu-item-disabled',
+               disabledItemHoverClassName:'context-menu-item-disabled-hover',
+               separatorClassName:'context-menu-separator',
+               innerDivClassName:'context-menu-item-inner',
+               themePrefix:'context-menu-theme-',
+               theme:'default',
+
+               separator:'context-menu-separator', // A specific key to identify a separator
+               target:null, // The target of the context click, to be populated when triggered
+               menu:null, // The jQuery object containing the HTML object that is the menu itself
+               shadowObj:null, // Shadow object
+               bgiframe:null, // The iframe object for IE6
+               shown:false, // Currently being shown?
+               useIframe:/*@cc_on @*//*@if (@_win32) true, @else @*/false,/*@end @*/ // This is a better check than looking at userAgent!
+               
+               // Create the menu instance
+               create: function(menu,opts) {
+                       var cmenu = $.extend({},this,opts); // Clone all default properties to created object
+                       
+                       // If a selector has been passed in, then use that as the menu
+                       if (typeof menu=="string") {
+                               cmenu.menu = $(menu);
+                       } 
+                       // If a function has been passed in, call it each time the menu is shown to create the menu
+                       else if (typeof menu=="function") {
+                               cmenu.menuFunction = menu;
+                       }
+                       // Otherwise parse the Array passed in
+                       else {
+                               cmenu.menu = cmenu.createMenu(menu,cmenu);
+                       }
+                       if (cmenu.menu) {
+                               cmenu.menu.css({display:'none'});
+                               $(cmenu.appendTo).append(cmenu.menu);
+                       }
+                       
+                       // Create the shadow object if shadow is enabled
+                       if (cmenu.shadow) {
+                               cmenu.createShadow(cmenu); // Extracted to method for extensibility
+                               if (cmenu.shadowOffset) { cmenu.shadowOffsetX = cmenu.shadowOffsetY = cmenu.shadowOffset; }
+                       }
+                       $('body').bind('contextmenu',function(){cmenu.hide();}); // If right-clicked somewhere else in the document, hide this menu
+                       return cmenu;
+               },
+               
+               // Create an iframe object to go behind the menu
+               createIframe: function() {
+                   return $('<iframe frameborder="0" tabindex="-1" src="javascript:false" style="display:block;position:absolute;z-index:-1;filter:Alpha(Opacity=0);"/>');
+               },
+               
+               // Accept an Array representing a menu structure and turn it into HTML
+               createMenu: function(menu,cmenu) {
+                       var className = cmenu.className;
+                       $.each(cmenu.theme.split(","),function(i,n){className+=' '+cmenu.themePrefix+n});
+                       var $t = $('<table cellspacing=0 cellpadding=0></table>').click(function(){cmenu.hide(); return false;}); // We wrap a table around it so width can be flexible
+                       var $tr = $('<tr></tr>');
+                       var $td = $('<td></td>');
+                       var $div = $('<div class="'+className+'"></div>');
+                       
+                       // Each menu item is specified as either:
+                       //     title:function
+                       // or  title: { property:value ... }
+                       for (var i=0; i<menu.length; i++) {
+                               var m = menu[i];
+                               if (m==$.contextMenu.separator) {
+                                       $div.append(cmenu.createSeparator());
+                               }
+                               else {
+                                       for (var opt in menu[i]) {
+                                               $div.append(cmenu.createMenuItem(opt,menu[i][opt])); // Extracted to method for extensibility
+                                       }
+                               }
+                       }
+                       if ( cmenu.useIframe ) {
+                               $td.append(cmenu.createIframe());
+                       }
+                       $t.append($tr.append($td.append($div)))
+                       return $t;
+               },
+               
+               // Create an individual menu item
+               createMenuItem: function(label,obj) {
+                       var cmenu = this;
+                       if (typeof obj=="function") { obj={onclick:obj}; } // If passed a simple function, turn it into a property of an object
+                       // Default properties, extended in case properties are passed
+                       var o = $.extend({
+                               onclick:function() { },
+                               className:'',
+                               hoverClassName:cmenu.itemHoverClassName,
+                               icon:'',
+                               disabled:false,
+                               title:'',
+                               hoverItem:cmenu.hoverItem,
+                               hoverItemOut:cmenu.hoverItemOut
+                       },obj);
+                       // If an icon is specified, hard-code the background-image style. Themes that don't show images should take this into account in their CSS
+                       var iconStyle = (o.icon)?'background-image:url('+o.icon+');':'';
+                       var $div = $('<div class="'+cmenu.itemClassName+' '+o.className+((o.disabled)?' '+cmenu.disabledItemClassName:'')+'" title="'+o.title+'"></div>')
+                                                       // If the item is disabled, don't do anything when it is clicked
+                                                       .click(function(e){if(cmenu.isItemDisabled(this)){return false;}else{return o.onclick.call(cmenu.target,this,cmenu,e)}})
+                                                       // Change the class of the item when hovered over
+                                                       .hover( function(){ o.hoverItem.call(this,(cmenu.isItemDisabled(this))?cmenu.disabledItemHoverClassName:o.hoverClassName); }
+                                                                       ,function(){ o.hoverItemOut.call(this,(cmenu.isItemDisabled(this))?cmenu.disabledItemHoverClassName:o.hoverClassName); }
+                                                       );
+                       var $idiv = $('<div class="'+cmenu.innerDivClassName+'" style="'+iconStyle+'">'+label+'</div>');
+                       $div.append($idiv);
+                       return $div;
+               },
+               
+               // Create a separator row
+               createSeparator: function() {
+                       return $('<div class="'+this.separatorClassName+'"></div>');
+               },
+               
+               // Determine if an individual item is currently disabled. This is called each time the item is hovered or clicked because the disabled status may change at any time
+               isItemDisabled: function(item) { return $(item).is('.'+this.disabledItemClassName); },
+               
+               // Functions to fire on hover. Extracted to methods for extensibility
+               hoverItem: function(c) { $(this).addClass(c); },
+               hoverItemOut: function(c) { $(this).removeClass(c); },
+               
+               // Create the shadow object
+               createShadow: function(cmenu) {
+                       cmenu.shadowObj = $('<div class="'+cmenu.shadowClass+'"></div>').css( {display:'none',position:"absolute", zIndex:9998, opacity:cmenu.shadowOpacity, backgroundColor:cmenu.shadowColor } );
+                       $(cmenu.appendTo).append(cmenu.shadowObj);
+               },
+               
+               // Display the shadow object, given the position of the menu itself
+               showShadow: function(x,y,e) {
+                       var cmenu = this;
+                       if (cmenu.shadow) {
+                               cmenu.shadowObj.css( {
+                                       width:(cmenu.menu.width()+cmenu.shadowWidthAdjust)+"px", 
+                                       height:(cmenu.menu.height()+cmenu.shadowHeightAdjust)+"px", 
+                                       top:(y+cmenu.shadowOffsetY)+"px", 
+                                       left:(x+cmenu.shadowOffsetX)+"px"
+                               }).addClass(cmenu.shadowClass)[cmenu.showTransition](cmenu.showSpeed);
+                       }
+               },
+               
+               // A hook to call before the menu is shown, in case special processing needs to be done.
+               // Return false to cancel the default show operation
+               beforeShow: function() { return true; },
+               
+               // Show the context menu
+               show: function(t,e) {
+                       var cmenu=this, x=e.pageX, y=e.pageY;
+                       cmenu.target = t; // Preserve the object that triggered this context menu so menu item click methods can see it
+                       if (cmenu.beforeShow()!==false) {
+                               // If the menu content is a function, call it to populate the menu each time it is displayed
+                               if (cmenu.menuFunction) {
+                                       if (cmenu.menu) { $(cmenu.menu).remove(); }
+                                       cmenu.menu = cmenu.createMenu(cmenu.menuFunction(cmenu,t),cmenu);
+                                       cmenu.menu.css({display:'none'});
+                                       $(cmenu.appendTo).append(cmenu.menu);
+                               }
+                               var $c = cmenu.menu;
+                               x+=cmenu.offsetX; y+=cmenu.offsetY;
+                               var pos = cmenu.getPosition(x,y,cmenu,e); // Extracted to method for extensibility
+                               cmenu.showShadow(pos.x,pos.y,e);
+                               // Resize the iframe if needed
+                               if (cmenu.useIframe) {
+                                       $c.find('iframe').css({width:$c.width()+cmenu.shadowOffsetX+cmenu.shadowWidthAdjust,height:$c.height()+cmenu.shadowOffsetY+cmenu.shadowHeightAdjust});
+                               }
+                               $c.css( {top:pos.y+"px", left:pos.x+"px", position:"absolute",zIndex:9999} )[cmenu.showTransition](cmenu.showSpeed,((cmenu.showCallback)?function(){cmenu.showCallback.call(cmenu);}:null));
+                               cmenu.shown=true;
+                               $(document).one('click',null,function(){cmenu.hide()}); // Handle a single click to the document to hide the menu
+                       }
+               },
+               
+               // Find the position where the menu should appear, given an x,y of the click event
+               getPosition: function(clickX,clickY,cmenu,e) {
+                       var x = clickX+cmenu.offsetX;
+                       var y = clickY+cmenu.offsetY
+                       var h = $(cmenu.menu).height();
+                       var w = $(cmenu.menu).width();
+                       var dir = cmenu.direction;
+                       if (cmenu.constrainToScreen) {
+                               var $w = $(window);
+                               var wh = $w.height();
+                               var ww = $w.width();
+                               if (dir=="down" && (y+h-$w.scrollTop() > wh)) { dir = "up"; }
+                               var maxRight = x+w-$w.scrollLeft();
+                               if (maxRight > ww) { x -= (maxRight-ww); }
+                       }
+                       if (dir=="up") { y -= h; }
+                       return {'x':x,'y':y};
+               },
+               
+               // Hide the menu, of course
+               hide: function() {
+                       var cmenu=this;
+                       if (cmenu.shown) {
+                               if (cmenu.iframe) { $(cmenu.iframe).hide(); }
+                               if (cmenu.menu) { cmenu.menu[cmenu.hideTransition](cmenu.hideSpeed,((cmenu.hideCallback)?function(){cmenu.hideCallback.call(cmenu);}:null)); }
+                               if (cmenu.shadow) { cmenu.shadowObj[cmenu.hideTransition](cmenu.hideSpeed); }
+                       }
+                       cmenu.shown = false;
+               }
+       };
+       
+       // This actually adds the .contextMenu() function to the jQuery namespace
+       $.fn.contextMenu = function(menu,options) {
+               var cmenu = $.contextMenu.create(menu,options);
+               return this.each(function(){
+                       $(this).bind('contextmenu',function(e){cmenu.show(this,e);return false;});
+               });
+       };
+})(jQuery);
diff --git a/js/jquery.thumbhover.js b/js/jquery.thumbhover.js
new file mode 100644 (file)
index 0000000..da16c2a
--- /dev/null
@@ -0,0 +1,120 @@
+// This library is based on jquery.thumbhover.js from unknown author.
+// Far and away modified for using in RackTables.
+// Usage: jquery_object_a.thumbPopup(jquery_object_b, [options])
+//   after that call, object_b will be hidden
+//   object_a, when hovered, will show object_b floating and moving by the cursor.
+//   When clicked on object_a, object_b will stay visible until outside click
+(function($) {
+       $.fn.thumbPopup = function(popup, options)
+       {
+               //Combine the passed in options with the default settings
+               var settings = jQuery.extend({
+                       //popupId: "thumbPopup",
+                       cursorTopOffset: 15,
+                       cursorLeftOffset: 15,
+                       showFreezeHint: true
+               }, options);
+
+               var freezeHint = null;
+               var timeout_id = null;
+               var hintHeight = 0;
+               if (! freezeHint && settings.showFreezeHint) {
+                       freezeHint = $('<div />').html('click to freeze').css('position', 'absolute').css('border', '1px solid black').css('background-color', 'white').appendTo('body');
+                       hintHeight = freezeHint[0].offsetHeight;
+                       freezeHint.hide();
+               }
+               
+               if (! popup.length)
+                       return false;
+               popup.css("position", "absolute").hide();
+               $(this).css("cursor", "pointer");
+               
+               //Attach hover events that manage the popup
+               $(this)
+               .bind('mouseenter', setPopup)
+               .bind('mousemove', updatePopupPosition)
+               .bind('mouseleave', hidePopup)
+               .click(stickPopup);
+               
+               function stickPopup(event) {
+                       popup.data("sticked", true);
+                       if (freezeHint)
+                               freezeHint.hide();
+                       $('body').bind('click', function(event) {
+                               if (event.target == popup[0] || $(event.target).parents().filter(popup).length)
+                                       return false;
+                               popup.data("sticked", false);
+                               popup.hide();
+                               return true;
+                       });
+                       return false;
+               }
+               
+               function ShowFreezeHint() {
+                       freezeHint.show();
+               }
+               
+               function setPopup(event) {
+                       if (popup.data("sticked"))
+                               return;
+                       popup.data("hovered", true);
+                       updatePopupPosition(event);
+                       $(popup).show();
+               }
+               
+               function updatePopupPosition(event) {
+                       var windowSize = getWindowSize();
+                       var popupSize = getPopupSize();
+                       var bPopupShownAbove = windowSize.height + windowSize.scrollTop < event.pageY + popupSize.height + settings.cursorTopOffset;
+                       if (freezeHint) {
+                               var deltaHint = bPopupShownAbove ? 20 :  - 5 - hintHeight;
+                               freezeHint.hide();
+                               freezeHint.css('top', event.pageY + deltaHint).css('left', event.pageX);
+                               clearTimeout(timeout_id);
+                               timeout_id = setTimeout(ShowFreezeHint, 1000);
+                       }
+                       if (popup.data("sticked"))
+                               return;
+                       if (windowSize.width + windowSize.scrollLeft < event.pageX + popupSize.width + settings.cursorLeftOffset){
+                               $(popup).css("left", event.pageX - popupSize.width - settings.cursorLeftOffset);
+                       } else {
+                               $(popup).css("left", event.pageX + settings.cursorLeftOffset);
+                       }
+                       if (bPopupShownAbove) {
+                               $(popup).css("top", event.pageY - popupSize.height - settings.cursorTopOffset);
+                       } else {
+                               $(popup).css("top", event.pageY + settings.cursorTopOffset);
+                       }
+               }
+               
+               function hidePopup(event) {
+                       popup.data("hovered", false);
+                       if (freezeHint) {
+                               freezeHint.hide();
+                               clearTimeout(timeout_id);
+                       }
+                       if (popup.data("sticked"))
+                               return;
+                       $(popup).hide();
+               }
+               
+               function getWindowSize() {
+                       return {
+                               scrollLeft: $(window).scrollLeft(),
+                               scrollTop: $(window).scrollTop(),
+                               width: $(window).width(),
+                               height: $(window).height()
+                       };
+               }
+               
+               function getPopupSize() {
+                       return {
+                               width: $(popup).width(),
+                               height: $(popup).height()
+                       };
+               }
+               
+               //Return original selection for chaining
+               return this;
+       };
+})(jQuery);
diff --git a/js/portinfo.js b/js/portinfo.js
new file mode 100644 (file)
index 0000000..c8962dd
--- /dev/null
@@ -0,0 +1,186 @@
+if (enabled_elements == null)
+       enabled_elements = [];
+enabled_elements_count = enabled_elements.length;
+port_cmenu_items = [];
+wait_count = 0;
+bk_event = null;
+
+(function () {
+       var menu_item_candidates = {
+               link: {'Show links status': {onclick: menuItemClicked, className: 'itemname-link'}},
+               conf: {'Show ports configuration': {onclick: menuItemClicked, className: 'itemname-conf'}},
+               mac: {'Show learned MACs': {onclick: menuItemClicked, className: 'itemname-mac'}}
+       };
+       var pushed = false;
+       for (var i in enabled_elements) {
+               var name = enabled_elements[i];
+               if (menu_item_candidates[name] != null) {
+                       port_cmenu_items.push(menu_item_candidates[name]);
+                       pushed = true;
+               }
+       }
+       if (pushed) {
+               port_cmenu_items.unshift($.contextMenu.separator);
+               port_cmenu_items.unshift({'Show all info': {onclick: showAllClicked, className: 'itemname-all'}});
+       }
+})();
+
+function showAllClicked(menuItem, menu) {
+       for (var i in enabled_elements) {
+               var name = enabled_elements[i];
+               menuItemClicked($('.context-menu-item.itemname-' + name)[0], menu);
+       }
+}
+
+$(document).ready(function () {
+       // create global object port_cmenu
+       if (port_cmenu_items.length) {
+               port_cmenu = $.contextMenu.create(port_cmenu_items, {theme:'vista'});
+               // add popup button after every portname
+               $('.interactive-portname.port-menu').after('<a title="Show info from switch" class="port-popup" href="#">&#133;</a>');
+               $('<div />').hide().addClass('cursor-shadow').css('position', 'absolute').css('width', 16).css('height', 16).css("background-image", "url(pix/ajax-loader.gif").appendTo('body');
+
+               // bind popup menu to every link with class port-popup
+               $('a.port-popup').bind('click', function(e){port_cmenu.show(this,e);return false;});
+               $('body').bind('mouseup', rememberCursorPosition);
+       }
+});
+
+function disableMenuItem(menuItem) {
+       setTimeout (function() {
+               if (! $(menuItem).hasClass($.contextMenu.disabledItemClassName)) {
+                       $(menuItem).addClass($.contextMenu.disabledItemClassName);
+                       if (--enabled_elements_count <= 0) {
+                               $('.context-menu-item.itemname-all').addClass($.contextMenu.disabledItemClassName);
+                       }
+               }
+       }, 50);
+}
+
+function setItemIcon(menuItem, iconName) {
+       var iconURL;
+       if (iconName == 'wait')
+               iconURL = 'pix/ajax-loader.gif';
+       else if (iconName == 'ok')
+               iconURL = 'pix/checkbox_yes.png';
+       $(menuItem).children('.' + $.contextMenu.innerDivClassName).css("background-image", "url(" + iconURL + ")");
+}
+
+function menuItemClicked(menuItem, menu) {
+       // if the item is already disabled, do not react on click
+       if ($(menuItem).hasClass($.contextMenu.disabledItemClassName))
+               return;
+
+       // determine the typename of menuItem ('link', 'mac' or 'conf')
+       var matches = menuItem.className.match(/itemname-([^ ]+)/);
+       if (! matches)
+               return;
+       var type = matches[1];
+       
+       var bSuccessIcon = false;
+       $.ajax({
+               async: true,
+               beforeSend: function(XMLHttpRequest) {
+                       if (++wait_count > 0) {
+                               cursor_shadow = $('.cursor-shadow');
+                               $('body').bind('mousemove', waitCursorMove);
+                               if (bk_event)
+                                       waitCursorMove(bk_event);
+                       }
+                       setItemIcon(menuItem, 'wait');
+               },
+               complete: function(XMLHttpRequest, textStatus) {
+                       if (--wait_count <= 0) {
+                               $('.cursor-shadow').hide();
+                               $('body').unbind('mousemove', waitCursorMove);
+                               $('body').unbind('click', rememberCursorPosition);
+                       }
+                       if (! bSuccessIcon)
+                               setItemIcon(menuItem, '');
+               },
+               type: 'GET',
+               url: 'ajax.php',
+               data: {
+                       'ac': 'get-port-' + type,
+                       'object_id': getQueryString('object_id')
+               },
+               dataType: 'json',
+               success: function(data, textStatus, XMLHttpRequest) {
+                       if (! data)
+                               return;
+                       bSuccessIcon = true;
+                       setItemIcon(menuItem, 'ok');
+                       if (type == 'link')
+                               applyLinkData(data);
+                       else if (type == 'mac')
+                               applyMacData(data);
+                       else if (type == 'conf')
+                               applyConfData(data);
+               }
+       });
+       disableMenuItem(menuItem);
+}
+
+function rememberCursorPosition(event) {
+       bk_event = event;
+}
+
+function waitCursorMove(event) {
+       cursor_shadow.css("left", event.pageX + 15).css("top", event.pageY + 15).show();
+}
+
+function applyLinkData(data) {
+       var seen_portnames = {};
+       $('.interactive-portname').each(function() {
+               var portname = getPortName (this);
+               var item = data[portname];
+               if (item != null) {
+                       var prepended;
+                       if (item['inline'])
+                               prepended = $('<span />').addClass('port-link').html(item['inline']).insertBefore(this);
+                       if (item['popup'] && prepended) {
+                               if (! seen_portnames[portname])
+                                       seen_portnames[portname] = $('<div />').addClass('popup-box').html(item['popup']).appendTo('body');
+                               prepended.thumbPopup(seen_portnames[portname]);
+                       }
+               }
+       });
+}
+
+function applyMacData(data) {
+       var seen_portnames = {};
+       $('.interactive-portname').each(function() {
+               var portname = getPortName (this);
+               var item = data[portname];
+               if (item != null) {
+                       var prepended;
+                       if (item['inline'])
+                               appended = $('<div />').addClass('mac-count').html(item['inline']).appendTo($(this).parent());
+                       if (item['popup'] && appended) {
+                               if (! seen_portnames[portname])
+                                       seen_portnames[portname] = $('<div />').addClass('popup-box mac-list').html(item['popup']).appendTo('body');
+                               appended.thumbPopup(seen_portnames[portname]);
+                       }
+               }
+       });
+}
+
+function applyConfData(data) {
+       var seen_portnames = {};
+       $('.interactive-portname').each(function() {
+               var portname = getPortName (this);
+               var item = data[portname];
+               if (item != null) {
+                       if (! seen_portnames[portname])
+                               seen_portnames[portname] = $('<div />').addClass('popup-box port-config').html(item['popup']).appendTo('body');
+                       $(this).thumbPopup(seen_portnames[portname]);
+               }
+       });
+}
+
+function getPortName (element) {
+       if (element.type == 'text')
+               return $(element).val();
+       else
+               return $(element).html();
+}
index 449204a..8dd05ef 100644 (file)
@@ -171,3 +171,16 @@ function blockToggleColumnOfAtoms (rackId, columnId, numRows) {
                document.getElementById(checkboxId).checked = toSet;
        }
 }
+
+// used by portinfo.js
+function getQueryString(key, default_)
+{
+       if (default_==null) default_="";
+       key = key.replace(/[\[]/,"\\\[").replace(/[\]]/,"\\\]");
+       var regex = new RegExp("[\\?&]"+key+"=([^&#]*)");
+       var qs = regex.exec(window.location.href);
+       if(qs == null)
+               return default_;
+       else
+               return qs[1];
+}
diff --git a/pix/1x1t.gif b/pix/1x1t.gif
new file mode 100644 (file)
index 0000000..66d96ed
Binary files /dev/null and b/pix/1x1t.gif differ
diff --git a/pix/ajax-loader.gif b/pix/ajax-loader.gif
new file mode 100644 (file)
index 0000000..d0bce15
Binary files /dev/null and b/pix/ajax-loader.gif differ
diff --git a/pix/checkbox_yes.png b/pix/checkbox_yes.png
new file mode 100644 (file)
index 0000000..44ed8c2
Binary files /dev/null and b/pix/checkbox_yes.png differ
diff --git a/pix/link-disabled.png b/pix/link-disabled.png
new file mode 100644 (file)
index 0000000..7ec992a
Binary files /dev/null and b/pix/link-disabled.png differ
diff --git a/pix/link-down.png b/pix/link-down.png
new file mode 100644 (file)
index 0000000..fd6fe90
Binary files /dev/null and b/pix/link-down.png differ
diff --git a/pix/link-up.png b/pix/link-up.png
new file mode 100644 (file)
index 0000000..8c30de9
Binary files /dev/null and b/pix/link-up.png differ