summaryrefslogtreecommitdiffstats
path: root/frontends
diff options
context:
space:
mode:
Diffstat (limited to 'frontends')
-rw-r--r--frontends/php/charts.php24
-rw-r--r--frontends/php/css.css3
-rw-r--r--frontends/php/history.php22
-rw-r--r--frontends/php/images/general/bar/arrow_down.gifbin0 -> 826 bytes
-rw-r--r--frontends/php/images/general/bar/arrow_l.gifbin0 -> 864 bytes
-rw-r--r--frontends/php/images/general/bar/arrow_r.gifbin0 -> 862 bytes
-rw-r--r--frontends/php/images/general/bar/arrow_sm.gifbin0 -> 830 bytes
-rw-r--r--frontends/php/images/general/bar/arrow_up.gifbin0 -> 826 bytes
-rw-r--r--frontends/php/images/general/bar/bar_bg.gifbin0 -> 839 bytes
-rw-r--r--frontends/php/images/general/bar/bar_left.gifbin0 -> 826 bytes
-rw-r--r--frontends/php/images/general/bar/bar_middle.gifbin0 -> 873 bytes
-rw-r--r--frontends/php/images/general/bar/bar_right.gifbin0 -> 826 bytes
-rw-r--r--frontends/php/images/general/bar/bg.gifbin0 -> 855 bytes
-rw-r--r--frontends/php/images/general/bar/cal.gifbin0 -> 887 bytes
-rw-r--r--frontends/php/images/general/bar/left.gifbin0 -> 943 bytes
-rw-r--r--frontends/php/images/general/bar/right.gifbin0 -> 941 bytes
-rw-r--r--frontends/php/include/classes/cimg.inc.php1
-rw-r--r--frontends/php/include/config.inc.php171
-rw-r--r--frontends/php/include/graphs.inc.php41
-rw-r--r--frontends/php/include/js.inc.php14
-rw-r--r--frontends/php/include/screens.inc.php7
-rw-r--r--frontends/php/js/common.js58
-rw-r--r--frontends/php/js/gmenu.js954
-rw-r--r--frontends/php/js/prototype.js3278
-rw-r--r--frontends/php/js/sbinit.js113
-rw-r--r--frontends/php/js/scrollbar.js712
-rw-r--r--frontends/php/js/url.js214
-rw-r--r--frontends/php/screens.php29
-rw-r--r--frontends/php/styles/bar.css170
-rw-r--r--frontends/php/styles/gmenu.css384
30 files changed, 6002 insertions, 193 deletions
diff --git a/frontends/php/charts.php b/frontends/php/charts.php
index ed8783e2..da9ae309 100644
--- a/frontends/php/charts.php
+++ b/frontends/php/charts.php
@@ -1,7 +1,7 @@
<?php
/*
** ZABBIX
-** Copyright (C) 2000-2005 SIA Zabbix
+** Copyright (C) 2000-2007 SIA Zabbix
**
** This program is free software; you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
@@ -26,6 +26,7 @@
$page['title'] = 'S_CUSTOM_GRAPHS';
$page['file'] = 'charts.php';
$page['hist_arg'] = array('hostid','grouid','graphid','period','dec','inc','left','right','stime');
+ $page['scripts'] = array('prototype.js','url.js','gmenu.js','scrollbar.js','sbinit.js');
?>
<?php
if(isset($_REQUEST['fullscreen']))
@@ -258,8 +259,8 @@ include_once 'include/page_header.php';
<!--
if(window.innerWidth) width=window.innerWidth;
else width=document.body.clientWidth;
- document.write(\'<img src="chart6.php?graphid='.$_REQUEST['graphid'].url_param('stime').url_param('from').
- '&period='.$effectiveperiod.'" />\');
+ document.write(\'<img id="graph" src="chart6.php?graphid='.$_REQUEST['graphid'].url_param('stime').url_param('from').
+ '&period='.$effectiveperiod.'" /><br /><br />\');
-->
</script>'."\n";
}
@@ -268,8 +269,8 @@ include_once 'include/page_header.php';
<!--
if(window.innerWidth) width=window.innerWidth;
else width=document.body.clientWidth;
- document.write(\'<img src="chart2.php?graphid='.$_REQUEST['graphid'].url_param('stime').url_param('from').
- '&period='.$effectiveperiod.'&width=\'+(width-108)+\'" />\');
+ document.write(\'<img id="graph" src="chart2.php?graphid='.$_REQUEST['graphid'].url_param('stime').url_param('from').
+ '&period='.$effectiveperiod.'&width=\'+(width-108)+\'" /><br /><br />\');
-->
</script>'."\n";
}
@@ -280,7 +281,18 @@ include_once 'include/page_header.php';
if($_REQUEST['graphid'] > 0)
{
- navigation_bar('charts.php',array('groupid','hostid','graphid'));
+ $stime = get_min_itemclock_by_graphid($_REQUEST['graphid']);
+ $bstime = time()-$effectiveperiod;
+ if(isset($_REQUEST['stime'])){
+ $bstime = $_REQUEST['stime'];
+ $bstime = mktime(substr($bstime,8,2),substr($bstime,10,2),0,substr($bstime,4,2),substr($bstime,6,2),substr($bstime,0,4));
+ }
+
+ $script = 'scrollinit(0,0,0,'.$effectiveperiod.','.$stime.',0,'.$bstime.');
+ showgraphmenu("graph");';
+
+ zbx_add_post_js($script);
+// navigation_bar('charts.php',array('groupid','hostid','graphid'));
}
?>
diff --git a/frontends/php/css.css b/frontends/php/css.css
index 39d57cfe..9407df98 100644
--- a/frontends/php/css.css
+++ b/frontends/php/css.css
@@ -6,7 +6,8 @@
@import "styles/ul.css";
@import "styles/p.css";
@import "styles/popupmenu.css";
-
+@import "styles/bar.css";
+@import "styles/gmenu.css";
body{
background-color:#e5e5e5;
diff --git a/frontends/php/history.php b/frontends/php/history.php
index 8e09a988..76a1e343 100644
--- a/frontends/php/history.php
+++ b/frontends/php/history.php
@@ -25,7 +25,8 @@
$page["file"] = "history.php";
$page["title"] = "S_HISTORY";
-
+ $page['scripts'] = array('prototype.js','url.js','gmenu.js','scrollbar.js','sbinit.js');
+
if(isset($_REQUEST['plaintext']) || isset($_REQUEST['fullscreen']))
{
define('ZBX_PAGE_NO_MENU', 1);
@@ -512,9 +513,22 @@ COpt::profiling_stop("history");
if(!isset($_REQUEST["plaintext"]))
{
- if(in_array($_REQUEST["action"],array("showvalues","showgraph")))
- {
- navigation_bar("history.php",$to_save_request);
+ if(in_array($_REQUEST["action"],array("showvalues","showgraph"))){
+
+ $stime = get_min_itemclock_by_itemid($_REQUEST["itemid"]);
+ $bstime = time()-$effectiveperiod;
+
+ if(isset($_REQUEST['stime'])){
+ $bstime = $_REQUEST['stime'];
+ $bstime = mktime(substr($bstime,8,2),substr($bstime,10,2),0,substr($bstime,4,2),substr($bstime,6,2),substr($bstime,0,4));
+ }
+
+ $script = 'scrollinit(0,0,0,'.$effectiveperiod.','.$stime.',0,'.$bstime.');
+ showgraphmenu("graph");';
+
+ zbx_add_post_js($script);
+
+ // navigation_bar("history.php",$to_save_request);
}
}
?>
diff --git a/frontends/php/images/general/bar/arrow_down.gif b/frontends/php/images/general/bar/arrow_down.gif
new file mode 100644
index 00000000..f3e63c93
--- /dev/null
+++ b/frontends/php/images/general/bar/arrow_down.gif
Binary files differ
diff --git a/frontends/php/images/general/bar/arrow_l.gif b/frontends/php/images/general/bar/arrow_l.gif
new file mode 100644
index 00000000..c0ca4181
--- /dev/null
+++ b/frontends/php/images/general/bar/arrow_l.gif
Binary files differ
diff --git a/frontends/php/images/general/bar/arrow_r.gif b/frontends/php/images/general/bar/arrow_r.gif
new file mode 100644
index 00000000..b2a1c655
--- /dev/null
+++ b/frontends/php/images/general/bar/arrow_r.gif
Binary files differ
diff --git a/frontends/php/images/general/bar/arrow_sm.gif b/frontends/php/images/general/bar/arrow_sm.gif
new file mode 100644
index 00000000..df075f2a
--- /dev/null
+++ b/frontends/php/images/general/bar/arrow_sm.gif
Binary files differ
diff --git a/frontends/php/images/general/bar/arrow_up.gif b/frontends/php/images/general/bar/arrow_up.gif
new file mode 100644
index 00000000..9be28750
--- /dev/null
+++ b/frontends/php/images/general/bar/arrow_up.gif
Binary files differ
diff --git a/frontends/php/images/general/bar/bar_bg.gif b/frontends/php/images/general/bar/bar_bg.gif
new file mode 100644
index 00000000..ea96cb5b
--- /dev/null
+++ b/frontends/php/images/general/bar/bar_bg.gif
Binary files differ
diff --git a/frontends/php/images/general/bar/bar_left.gif b/frontends/php/images/general/bar/bar_left.gif
new file mode 100644
index 00000000..8af23b58
--- /dev/null
+++ b/frontends/php/images/general/bar/bar_left.gif
Binary files differ
diff --git a/frontends/php/images/general/bar/bar_middle.gif b/frontends/php/images/general/bar/bar_middle.gif
new file mode 100644
index 00000000..cdf9c794
--- /dev/null
+++ b/frontends/php/images/general/bar/bar_middle.gif
Binary files differ
diff --git a/frontends/php/images/general/bar/bar_right.gif b/frontends/php/images/general/bar/bar_right.gif
new file mode 100644
index 00000000..ae7f13f0
--- /dev/null
+++ b/frontends/php/images/general/bar/bar_right.gif
Binary files differ
diff --git a/frontends/php/images/general/bar/bg.gif b/frontends/php/images/general/bar/bg.gif
new file mode 100644
index 00000000..4058d437
--- /dev/null
+++ b/frontends/php/images/general/bar/bg.gif
Binary files differ
diff --git a/frontends/php/images/general/bar/cal.gif b/frontends/php/images/general/bar/cal.gif
new file mode 100644
index 00000000..4c952ce1
--- /dev/null
+++ b/frontends/php/images/general/bar/cal.gif
Binary files differ
diff --git a/frontends/php/images/general/bar/left.gif b/frontends/php/images/general/bar/left.gif
new file mode 100644
index 00000000..3877f50b
--- /dev/null
+++ b/frontends/php/images/general/bar/left.gif
Binary files differ
diff --git a/frontends/php/images/general/bar/right.gif b/frontends/php/images/general/bar/right.gif
new file mode 100644
index 00000000..4cb55ef4
--- /dev/null
+++ b/frontends/php/images/general/bar/right.gif
Binary files differ
diff --git a/frontends/php/include/classes/cimg.inc.php b/frontends/php/include/classes/cimg.inc.php
index bc1f130b..488c7b91 100644
--- a/frontends/php/include/classes/cimg.inc.php
+++ b/frontends/php/include/classes/cimg.inc.php
@@ -35,6 +35,7 @@
$name="image";
$this->AddOption('border',0);
+ $this->AddOption('alt',$name);
$this->SetName($name);
$this->SetAltText($name);
$this->SetSrc($src);
diff --git a/frontends/php/include/config.inc.php b/frontends/php/include/config.inc.php
index 1e20df98..1f191b0d 100644
--- a/frontends/php/include/config.inc.php
+++ b/frontends/php/include/config.inc.php
@@ -1,7 +1,7 @@
<?php
/*
** ZABBIX
-** Copyright (C) 2000-2005 SIA Zabbix
+** Copyright (C) 2000-2007 SIA Zabbix
**
** This program is free software; you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
@@ -1071,20 +1071,24 @@ function TODO($msg) { echo "TODO: ".$msg.BR; } // DEBUG INFO!!!
$till=date(S_DATE_FORMAT_YMDHMS,time(NULL)-$from*3600);
show_table_header("TILL $till (".($period/3600)." HOURs)");
- echo "<center>";
- echo "<TABLE BORDER=0 WIDTH=100% BGCOLOR=\"#CCCCCC\" cellspacing=1 cellpadding=3>";
- echo "<TR BGCOLOR=#DDDDDD>";
- echo "<TD ALIGN=CENTER>";
-
- insert_sizeable_graph('chart.php?itemid='.$itemid.
- url_param($from,false,'from').
- url_param($stime,false,'stime').
- url_param($period,false,'period'));
-
- echo "</TD>";
- echo "</TR>";
- echo "</TABLE>";
- echo "</center>";
+ $td = new CCol(get_js_sizeable_graph('chart.php?itemid='.$itemid.
+ url_param($from,false,'from').
+ url_param($stime,false,'stime').
+ url_param($period,false,'period')));
+ $td->AddOption('align','center');
+
+ $tr = new CRow($td);
+ $tr->AddOption('bgcolor','$dddddd');
+
+ $table = new CTable();
+ $table->AddOption('width','100%');
+ $table->AddOption('bgcolor','#cccccc');
+ $table->AddOption('cellspacing','1');
+ $table->AddOption('cellpadding','3');
+
+ $table->AddRow($tr);
+
+ $table->Show();
}
@@ -1484,143 +1488,6 @@ function TODO($msg) { echo "TODO: ".$msg.BR; } // DEBUG INFO!!!
}
- function time_navigator($resource="graphid",$id)
- {
- echo "<TABLE BORDER=0 align=center COLS=2 WIDTH=100% BGCOLOR=\"#CCCCCC\" cellspacing=1 cellpadding=1>";
- echo "<TR BGCOLOR=#FFFFFF>";
- echo "<TD ALIGN=LEFT>";
-
- echo "<div align=left>";
- echo "<b>".S_PERIOD.":</b>".SPACE;
-
- $hour=3600;
-
- $a=array(S_1H=>3600,S_2H=>2*3600,S_4H=>4*3600,S_8H=>8*3600,S_12H=>12*3600,
- S_24H=>24*3600,S_WEEK_SMALL=>7*24*3600,S_MONTH_SMALL=>31*24*3600,S_YEAR_SMALL=>365*24*3600);
- foreach($a as $label=>$sec)
- {
- echo "[";
- if($_REQUEST["period"]>$sec)
- {
- $tmp=$_REQUEST["period"]-$sec;
- echo("<A HREF=\"charts.php?period=$tmp".url_param($resource).url_param("stime").url_param("from").url_param("keep").url_param("fullscreen")."\">-</A>");
- }
- else
- {
- echo "-";
- }
-
- echo("<A HREF=\"charts.php?period=$sec".url_param($resource).url_param("stime").url_param("from").url_param("keep").url_param("fullscreen")."\">");
- echo($label."</A>");
-
- $tmp=$_REQUEST["period"]+$sec;
- echo("<A HREF=\"charts.php?period=$tmp".url_param($resource).url_param("stime").url_param("from").url_param("keep").url_param("fullscreen")."\">+</A>");
-
- echo "]".SPACE;
- }
-
- echo("</div>");
-
- echo "</TD>";
- echo "<TD BGCOLOR=#FFFFFF WIDTH=15% ALIGN=RIGHT>";
- echo "<b>".nbsp(S_KEEP_PERIOD).":</b>".SPACE;
- if($_REQUEST["keep"] == 1)
- {
- echo("[<A HREF=\"charts.php?keep=0".url_param($resource).url_param("from").url_param("period").url_param("fullscreen")."\">".S_ON_C."</a>]");
- }
- else
- {
- echo("[<A HREF=\"charts.php?keep=1".url_param($resource).url_param("from").url_param("period").url_param("fullscreen")."\">".S_OFF_C."</a>]");
- }
- echo "</TD>";
- echo "</TR>";
- echo "<TR BGCOLOR=#FFFFFF>";
- echo "<TD>";
- if(isset($_REQUEST["stime"]))
- {
- echo "<div align=left>" ;
- echo "<b>".S_MOVE.":</b>".SPACE;
-
- $day=24;
-// $a already defined
-// $a=array("1h"=>1,"2h"=>2,"4h"=>4,"8h"=>8,"12h"=>12,
-// "24h"=>24,"week"=>7*24,"month"=>31*24,"year"=>365*24);
- foreach($a as $label=>$hours)
- {
- echo "[";
-
- $stime=$_REQUEST["stime"];
- $tmp=mktime(substr($stime,8,2),substr($stime,10,2),0,substr($stime,4,2),substr($stime,6,2),substr($stime,0,4));
- $tmp=$tmp-3600*$hours;
- $tmp=date("YmdHi",$tmp);
- echo("<A HREF=\"charts.php?stime=$tmp".url_param($resource).url_param("period").url_param("keep").url_param("fullscreen")."\">-</A>");
-
- echo($label);
-
- $stime=$_REQUEST["stime"];
- $tmp=mktime(substr($stime,8,2),substr($stime,10,2),0,substr($stime,4,2),substr($stime,6,2),substr($stime,0,4));
- $tmp=$tmp+3600*$hours;
- $tmp=date("YmdHi",$tmp);
- echo("<A HREF=\"charts.php?stime=$tmp".url_param($resource).url_param("period").url_param("keep").url_param("fullscreen")."\">+</A>");
-
- echo "]".SPACE;
- }
- echo("</div>");
- }
- else
- {
- echo "<div align=left>";
- echo "<b>".S_MOVE.":</b>".SPACE;
-
- $day=24;
-// $a already defined
-// $a=array("1h"=>1,"2h"=>2,"4h"=>4,"8h"=>8,"12h"=>12,
-// "24h"=>24,"week"=>7*24,"month"=>31*24,"year"=>365*24);
- foreach($a as $label=>$hours)
- {
- echo "[";
- $tmp=$_REQUEST["from"]+$hours;
- echo("<A HREF=\"charts.php?from=$tmp".url_param($resource).url_param("period").url_param("keep").url_param("fullscreen")."\">-</A>");
-
- echo($label);
-
- if($_REQUEST["from"]>=$hours)
- {
- $tmp=$_REQUEST["from"]-$hours;
- echo("<A HREF=\"charts.php?from=$tmp".url_param($resource).url_param("period").url_param("keep").url_param("fullscreen")."\">+</A>");
- }
- else
- {
- echo "+";
- }
-
- echo "]".SPACE;
- }
- echo("</div>");
- }
- echo "</TD>";
- echo "<TD BGCOLOR=#FFFFFF WIDTH=15% ALIGN=RIGHT>";
-// echo("<div align=left>");
- echo "<form method=\"put\" action=\"charts.php\">";
- echo "<input name=\"graphid\" type=\"hidden\" value=\"".$_REQUEST[$resource]."\" size=12>";
- echo "<input name=\"period\" type=\"hidden\" value=\"".(9*3600)."\" size=12>";
- if(isset($_REQUEST["stime"]))
- {
- echo "<input name=\"stime\" class=\"biginput\" value=\"".$_REQUEST["stime"]."\" size=12>";
- }
- else
- {
- echo "<input name=\"stime\" class=\"biginput\" value=\"yyyymmddhhmm\" size=12>";
- }
- echo SPACE;
- echo "<input class=\"button\" type=\"submit\" name=\"action\" value=\"go\">";
- echo "</form>";
-// echo("</div>");
- echo "</TD>";
- echo "</TR>";
- echo "</TABLE>";
- }
-
function add_mapping_to_valuemap($valuemapid, $mappings)
{
DBexecute("delete from mappings where valuemapid=$valuemapid");
diff --git a/frontends/php/include/graphs.inc.php b/frontends/php/include/graphs.inc.php
index 2797a9c3..df1e621e 100644
--- a/frontends/php/include/graphs.inc.php
+++ b/frontends/php/include/graphs.inc.php
@@ -154,6 +154,47 @@
" order by itemid,drawtype,sortorder,color,yaxisside");
}
+ /*
+ * Function: get_min_itemclock_by_graphid
+ *
+ * Description:
+ * Return the time of the 1st apearance of items included in graph in trends
+ *
+ * Author:
+ * Artem Suharev
+ *
+ */
+ function get_min_itemclock_by_graphid($graphid){
+ $row = DBfetch(DBselect('SELECT MIN(t.clock) as clock '.
+ ' FROM graphs_items gi, trends t '.
+ ' WHERE gi.graphid='.$graphid.
+ ' AND t.itemid = gi.itemid'));
+
+ if(!empty($row) && $row)
+ return $row['clock'];
+ return 0;
+ }
+
+ /*
+ * Function: get_min_itemclock_by_itemid
+ *
+ * Description:
+ * Return the time of the 1st apearance of item in trends
+ *
+ * Author:
+ * Artem Suharev
+ *
+ */
+ function get_min_itemclock_by_itemid($itemid){
+ $row = DBfetch(DBselect('SELECT MIN(t.clock) as clock '.
+ ' FROM trends t '.
+ ' WHERE t.itemid='.$itemid));
+
+ if(!empty($row) && $row)
+ return $row['clock'];
+ return 0;
+ }
+
function get_graphitem_by_gitemid($gitemid)
{
$result=DBselect("SELECT * FROM graphs_items WHERE gitemid=$gitemid");
diff --git a/frontends/php/include/js.inc.php b/frontends/php/include/js.inc.php
index 3e8b9e46..04c04bf0 100644
--- a/frontends/php/include/js.inc.php
+++ b/frontends/php/include/js.inc.php
@@ -53,13 +53,15 @@ function zbx_add_post_js($script)
$ZBX_PAGE_POST_JS[] = $script;
}
-function insert_sizeable_graph($url){
- echo '<script language="JavaScript" type="text/javascript">
- <!--
- insert_sizeable_graph('.zbx_jsvalue($url).');
- -->
- </script>';
+function get_js_sizeable_graph($url){
+return '
+ <script language="JavaScript" type="text/javascript">
+ <!--
+ insert_sizeable_graph('.zbx_jsvalue($url).');
+ -->
+ </script>
+ ';
}
diff --git a/frontends/php/include/screens.inc.php b/frontends/php/include/screens.inc.php
index 9dcd35fb..050f901d 100644
--- a/frontends/php/include/screens.inc.php
+++ b/frontends/php/include/screens.inc.php
@@ -199,8 +199,10 @@
if(!isset($step))
{
- return new CIFrame('screens.php?config=1&fullscreen=2&elementid='.$slideshowid.'&step='.$curr_step.
+ $iframe = new CIFrame('screens.php?config=1&fullscreen=2&elementid='.$slideshowid.'&step='.$curr_step.
'&period='.$effectiveperiod.url_param('stime').url_param('from'));
+
+ return $iframe;
}
$slide_data = DBfetch(DBselect('select sl.screenid,sl.delay,ss.delay as ss_delay from slides sl,slideshows ss '.
@@ -259,6 +261,7 @@
$table = new CTable(
new CLink("No rows in screen ".$row["name"],"screenconf.php?config=0&form=update&screenid=".$screenid),
($editmode == 0 || $editmode == 2) ? "screen_view" : "screen_edit");
+ $table->AddOption('id','iframe');
for($r=0;$r<$row["vsize"];$r++)
{
@@ -271,7 +274,7 @@
$iresult=DBSelect("select * from screens_items".
" where screenid=$screenid and x=$c and y=$r");
- $irow = DBfetch($iresult);
+ $irow = DBfetch($iresult);
if($irow)
{
$screenitemid = $irow["screenitemid"];
diff --git a/frontends/php/js/common.js b/frontends/php/js/common.js
index 4819a096..a13ea971 100644
--- a/frontends/php/js/common.js
+++ b/frontends/php/js/common.js
@@ -19,6 +19,28 @@
var OP = window.opera?true:false;
var IE = ((!OP) && (document.all))?true:false;
+function isset(obj){
+ return (typeof(obj) != 'undefined');
+}
+
+function empty(obj){
+ if(is_null(obj) || !obj) return true;
+ return false;
+}
+
+function is_null(obj){
+ if(obj==null) return true;
+return false;
+}
+
+function is_number(obj){
+ return (typeof(obj) == 'number');
+}
+
+function is_string(obj){
+ return (typeof(obj) == 'string');
+}
+
if (!Array.prototype.forEach)
{
Array.prototype.forEach = function(fun /*, thisp*/)
@@ -226,7 +248,7 @@ function insert_sizeable_graph(url)
if(width) url += "&amp;width=" + (width - 108);
- document.write('<img src="'+url+'" alt="graph">');
+ document.write('<img id="graph" src="'+url+'" alt="graph"><br /><br />');
}
function resizeiframe(id){
@@ -236,10 +258,16 @@ function resizeiframe(id){
if(typeof(indoc) == 'undefined') return;
var height = parseInt(indoc.getElementsByTagName('body')[0].scrollHeight);
var height2 = parseInt(indoc.getElementsByTagName('body')[0].offsetHeight);
+
if(height2 > height){
height = height2;
}
+
iframe.style.height = (height)+'px';
+
+ if(!is_null($('scroll')) && showgraphmenu){
+ showgraphmenu('iframe');
+ }
}
function openWinCentered(loc, winname, iwidth, iheight, params){
@@ -253,19 +281,15 @@ function openWinCentered(loc, winname, iwidth, iheight, params){
WinObjReferer.focus();
}
-function isset(obj){
- return (typeof(obj) != 'undefined');
-}
-
-function empty(obj){
- if(isset(obj) && obj) return true;
- return false;
-}
-
-function is_number(obj){
- return (typeof(obj) == 'number');
-}
-
-function is_string(obj){
- return (typeof(obj) == 'string');
-}
+function getPosition(obj){
+ var pos = {top: 0, left: 0};
+ if (obj.offsetParent) {
+ pos.left = obj.offsetLeft;
+ pos.top = obj.offsetTop;
+ while (obj = obj.offsetParent) {
+ pos.left += obj.offsetLeft;
+ pos.top += obj.offsetTop;
+ }
+ }
+return pos;
+} \ No newline at end of file
diff --git a/frontends/php/js/gmenu.js b/frontends/php/js/gmenu.js
new file mode 100644
index 00000000..837007ce
--- /dev/null
+++ b/frontends/php/js/gmenu.js
@@ -0,0 +1,954 @@
+// JavaScript Document
+/*
+** ZABBIX
+** Copyright (C) 2000-2007 SIA Zabbix
+**
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the GNU General Public License as published by
+** the Free Software Foundation; either version 2 of the License, or
+** (at your option) any later version.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+** GNU General Public License for more details.
+**
+** You should have received a copy of the GNU General Public License
+** along with this program; if not, write to the Free Software
+** Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+**
+*/
+<!--
+
+var G_MENU; //gmenu obj reference
+var _PE_GM = null; // Periodical executer obj reference
+var GMENU_IMG_PATH='images/general/bar';
+//var cal = new calendar();
+
+function gmenuinit(top,left,period,bar_stime){
+
+ gmenucreate(top,left);
+
+ period = period || 3600;
+ bar_stime = bar_stime || 0;
+
+ G_MENU = new gmenu(period,bar_stime);
+
+ G_MENU.gm_value = $('gmenu_period_value');
+ G_MENU.gm_type = $('gmenu_period_type');
+
+ if(is_null(G_MENU.gm_value) || is_null(G_MENU.gm_type)){
+ G_MENU = null;
+ return false;
+ }
+
+ G_MENU.gm_gmenu = $('gmenu');
+
+ G_MENU.gm_minute = $('gmenu_minute');
+ G_MENU.gm_hour = $('gmenu_hour');
+ G_MENU.gm_day = $('gmenu_day');
+ G_MENU.gm_month = $('gmenu_month');
+ G_MENU.gm_year = $('gmenu_year');
+
+ G_MENU.syncBSDateByBSTime();
+
+ G_MENU.calcPeriodAndTypeByUnix(period);
+ G_MENU.setBSDate();
+ G_MENU.setPeriod();
+ G_MENU.setPeriodType();
+
+
+ var gm_gm_msover = function(e){
+ if(!is_null(_PE_SB)){
+ _PE_SB.stop();
+ _PE_SB = null;
+ }
+
+ G_MENU.msover = 1;
+ if(IE){
+ e.cancelBubble = true;
+ }
+ else{
+ e.stopPropagation();
+ }
+ }
+
+ var gm_gm_msout = function(e){
+ if(!IE && (e.eventPhase != 2)){
+ if(IE){
+ e.cancelBubble = true;
+ }
+ else{
+ e.stopPropagation();
+ }
+ return;
+ }
+
+ G_MENU.msover = 0;
+ if(is_null(_PE_GM)){
+ _PE_GM = new PeriodicalExecuter(G_MENU.ongmmsout.bind(G_MENU),0.5);
+ }
+ }
+
+ if(!IE){
+ G_MENU.gm_gmenu.addEventListener('mouseover',gm_gm_msover,true);
+
+ G_MENU.gm_gmenu.addEventListener('mouseout',gm_gm_msout,false);
+
+ $('gmenu_load').addEventListener('click',G_MENU.ongmload.bindAsEventListener(G_MENU),false);
+ $('gmenu_hide').addEventListener('click',G_MENU.gmenuhide.bindAsEventListener(G_MENU),false);
+ }
+ else{
+ G_MENU.gm_gmenu.attachEvent('onmouseover',gm_gm_msover);
+
+ G_MENU.gm_gmenu.attachEvent('onmouseout',gm_gm_msout);
+
+ $('gmenu_load').attachEvent('onclick',G_MENU.ongmload.bindAsEventListener(G_MENU));
+ $('gmenu_hide').attachEvent('onclick',G_MENU.gmenuhide.bindAsEventListener(G_MENU));
+ }
+
+
+
+ $('gmenu_day_up').onclick = G_MENU.dayup.bind(G_MENU);
+ $('gmenu_month_up').onclick = G_MENU.monthup.bind(G_MENU);
+ $('gmenu_year_up').onclick = G_MENU.yearup.bind(G_MENU);
+
+ $('gmenu_hour_up').onclick = G_MENU.hourup.bind(G_MENU);
+ $('gmenu_minute_up').onclick = G_MENU.minuteup.bind(G_MENU);
+
+ $('gmenu_period_v_up').onclick = G_MENU.pvalueup.bind(G_MENU);
+ $('gmenu_period_t_up').onclick = G_MENU.ptypeup.bind(G_MENU);
+
+ $('gmenu_day_down').onclick = G_MENU.daydown.bind(G_MENU);
+ $('gmenu_month_down').onclick = G_MENU.monthdown.bind(G_MENU);
+ $('gmenu_year_down').onclick = G_MENU.yeardown.bind(G_MENU);
+
+ $('gmenu_hour_down').onclick = G_MENU.hourdown.bind(G_MENU);
+ $('gmenu_minute_down').onclick = G_MENU.minutedown.bind(G_MENU);
+
+ $('gmenu_period_v_down').onclick = G_MENU.pvaluedown.bind(G_MENU);
+ $('gmenu_period_t_down').onclick = G_MENU.ptypedown.bind(G_MENU);
+
+// G_MENU.gmenushow();
+// cal.onselect = SCROLL_BAR.movebarbydate.bind(SCROLL_BAR);
+}
+
+
+var gmenu = Class.create();
+
+gmenu.prototype = {
+
+
+dt: new Date(), //Date object on load time
+cdt: new Date(), //Date object of bstime
+
+day: 1, //represents day number
+month: 0, //represents month number
+year: 2007, //represents year
+
+hour: 12, //hours
+minute: 00, //minutes
+
+timestamp: 0, //selected date in unix timestamp
+
+period: 0, //period in seconds
+bstime: 0, //graph starttime in seconds
+
+gmenumsover: 0, // if mouse is over gmenu(how to change it and use it is on your own)
+
+gm_gmenu: null, // represents HTML obj of gmenu
+
+gm_value: null, //html obj
+gm_type: null, //html obj
+
+gm_minute: null, //html obj
+gm_hour: null, //html obj
+gm_day: null, //html obj
+gm_month: null, //html obj
+gm_year: null, //html obj
+
+
+monthname: new Array('January','February','March','April','May','June','July','August','September','October','November','December'), // months
+
+period_value: 1, // period value
+period_type: 0, // period value type
+
+period_typename: new Array('Hours','Days','Weeks','Months','Years'), //period value type
+
+initialize: function(period, bstime){
+ this.bstime = parseInt(bstime); // setting graph starttime
+
+ if(this.bstime < 1000000000){
+ this.bstime = parseInt(this.dt.getTime()/1000) - this.period;
+ }
+
+ this.cdt.setTime(this.bstime*1000);
+},
+
+ongmmsout: function(){
+ if(this.msover == 0){
+ this.gmenumouseout();
+ }
+},
+
+gmenumouseout: function(){ // you may attach any functionto this
+},
+
+ongmload: function(e){
+ if(isset(e)){
+ if(IE){
+ e.cancelBubble = true;
+ e.returnValue = false;
+ }
+ else{
+ e.stopPropagation();
+ e.preventDefault();
+ }
+ }
+ this.gmenuload();
+},
+
+gmenuload: function(){ // bind any func to this
+},
+
+gmenuhide: function(e){
+ if(isset(e)){
+ if(IE){
+ e.cancelBubble = true;
+ e.returnValue = false;
+ }
+ else{
+ e.stopPropagation();
+ e.preventDefault();
+ }
+ }
+
+ if(!is_null(_PE_GM)){
+ _PE_GM.stop();
+ _PE_GM = null;
+ }
+ this.gm_gmenu.hide();
+},
+
+gmenushow: function(period, bstime){
+ if(isset(period) && isset(bstime)){
+ this.initialize(period, bstime);
+
+ this.syncBSDateByBSTime();
+ this.calcPeriodAndTypeByUnix(period);
+ this.setBSDate();
+ this.setPeriod();
+ this.setPeriodType();
+ }
+
+ this.gm_gmenu.show();
+},
+
+minuteup: function(){
+ if((this.bstime+60+this.period)>=parseInt(this.dt.getTime()/1000)){ // max date is date when script has been loaded
+ return;
+ }
+
+ this.minute++;
+
+ if(this.minute > 59){
+ this.minute = 00;
+ this.syncBSTime();
+
+ this.hourup();
+ return;
+ }
+
+ this.syncBSTime();
+ this.setBSDate();
+},
+
+hourup: function(){
+ if((this.bstime+3601+this.period)>=parseInt(this.dt.getTime()/1000)){ // max date is date when script has been loaded
+ return;
+ }
+
+ this.hour++;
+
+ if(this.hour > 23){
+ this.hour = 00;
+ this.syncBSTime();
+
+ this.dayup();
+ return;
+ }
+
+ this.syncBSTime();
+ this.setBSDate();
+},
+
+dayup: function(){
+ if((this.bstime+86400+this.period)>=parseInt(this.dt.getTime()/1000)){ // max date is date when script has been loaded
+ return;
+ }
+
+ this.day++;
+
+ if(this.day > this.daysInMonth(this.month,this.year)){
+ this.day = 1;
+ this.syncBSTime();
+
+ this.monthup();
+ return;
+ }
+
+ this.syncBSTime();
+ this.setBSDate();
+},
+
+monthup: function(){
+ var monthinsec = (86400*this.daysInMonth(this.month,this.year));
+ if((this.bstime+monthinsec+this.period)>=parseInt(this.dt.getTime()/1000)){ // max date is date when script has been loaded
+ return;
+ }
+
+ var monthlastday = (this.day == this.daysInMonth(this.month,this.year));
+ this.month++;
+
+ if(this.month > 11){
+ this.month = 0;
+ this.syncBSTime();
+
+ this.yearup();
+
+ if(monthlastday) this.day = this.daysInMonth(this.month,this.year);
+ this.syncBSTime();
+
+ return;
+ }
+
+ if(monthlastday) this.day = this.daysInMonth(this.month,this.year);
+
+ this.syncBSTime();
+ this.period = this.calcPeriod();
+ this.setBSDate();
+},
+
+yearup: function(){
+
+ var inc = this.calcPeriodIncByYear(1);
+
+ if((this.bstime+inc+this.period) >= parseInt(this.dt.getTime()/1000)){ // max date is date when script has been loaded
+ return ;
+ }
+
+ this.year++;
+ this.syncBSTime();
+ this.period = this.calcPeriod();
+ this.setBSDate();
+},
+
+minutedown: function(){
+ this.minute--;
+
+ if(this.minute < 0){
+ this.minute = 59;
+ this.syncBSTime();
+
+ this.hourdown();
+ return;
+ }
+
+ this.syncBSTime();
+ this.setBSDate();
+},
+
+hourdown: function(){
+ this.hour--;
+
+ if(this.hour < 0){
+ this.hour = 23;
+ this.syncBSTime();
+
+ this.daydown();
+ return;
+ }
+
+ this.syncBSTime();
+ this.setBSDate();
+},
+
+daydown: function(){
+ this.day--;
+
+ if(this.day < 1){
+ this.monthdown();
+
+ this.day = this.daysInMonth(this.month,this.year)
+ this.syncBSTime();
+ }
+
+ this.syncBSTime();
+ this.setBSDate();
+},
+
+monthdown: function(){
+
+ var monthlastday = (this.day == this.daysInMonth(this.month,this.year));
+ this.month--;
+
+ if(this.month < 0){
+ this.month = 11;
+ this.syncBSTime();
+
+ this.yeardown();
+
+ if(monthlastday) this.day = this.daysInMonth(this.month,this.year);
+ this.syncBSTime();
+
+ return;
+ }
+
+ if(monthlastday) this.day = this.daysInMonth(this.month,this.year);
+
+ this.syncBSTime();
+ this.period = this.calcPeriod();
+ this.setBSDate();
+},
+
+yeardown: function(){
+
+ if((this.year-1) < 1971){ // shouldn't be lower
+ return ;
+ }
+
+ this.year--;
+ this.syncBSTime();
+ this.period = this.calcPeriod();
+ this.setBSDate();
+},
+
+pvalueup: function(){
+ this.period_value++;
+ var period = this.calcPeriod();
+ if(period){
+ this.period = period;
+ this.setPeriod();
+ return;
+ }
+ this.period_value--;
+},
+
+ptypeup: function(){
+ if(!isset(this.period_typename[this.period_type+1])){
+ return;
+ }
+ var temp_period_value = this.period_value;
+
+ this.period_type++;
+ this.period_value = 1;
+
+ var period = this.calcPeriod();
+
+ if(period){
+ this.period = period;
+
+ this.setPeriod();
+ this.setPeriodType();
+ return;
+ }
+
+ this.period_type--;
+ this.period_value = temp_period_value;
+},
+
+pvaluedown: function(){
+ if(this.period_value < 2){
+ return;
+ }
+ this.period_value--;
+ var period = this.calcPeriod();
+ if(period){
+ this.period = period;
+ this.setPeriod();
+ return;
+ }
+ this.period_value++;
+},
+
+ptypedown: function(){
+ if(this.period_type < 1){
+ return;
+ }
+
+ var temp_period_value = this.period_value;
+
+ this.period_type--;
+ this.period_value = 1;
+
+ var period = this.calcPeriod();
+
+ if(period){
+ this.period = period;
+
+ this.setPeriod();
+ this.setPeriodType();
+ return;
+ }
+
+ this.period_type++;
+ this.period_value = temp_period_value;
+},
+
+calcPeriod: function(){
+ var inc = 0;
+
+ switch(this.period_type){
+ case 1:
+ inc = this.period_value * 86400; //day
+ break;
+ case 2:
+ inc = this.period_value * 604800; //week
+ break;
+ case 3:
+ inc = this.calcPeriodIncByMonth(this.period_value); //month
+ break;
+ case 4:
+ inc = this.calcPeriodIncByYear(this.period_value); //years
+ break;
+ default:
+ inc = this.period_value * 3600;
+ }
+
+ if((this.bstime + inc) > parseInt(this.dt.getTime()/1000)){
+ return false;
+ }
+
+return inc;
+},
+
+calcPeriodIncByMonth: function(pvalue){
+ var inc = 0;
+ var days = 0;
+ var daysnext = 0;
+ var month = this.month;
+ var nextmonth = 0;
+ var year = this.year;
+ var nextyear = 0;
+ var type_eval = 0;
+ var monthlastday = null;
+
+ for(var i=0; i < pvalue; i++){
+ nextyear = year;
+ nextmonth = month + 1;
+
+ if(nextmonth > 11){
+ nextyear=this.year+1;
+ nextmonth = 0;
+ }
+
+ days = this.daysInMonth(month,year);
+ monthlastday = (this.day == this.daysInMonth(month,year));
+
+ if(monthlastday){
+ days = this.daysInMonth(nextmonth,nextyear);;
+ }
+
+ inc += 86400 * days; //each month
+ month = nextmonth;
+ year = nextyear;
+ }
+return inc;
+},
+
+calcPeriodIncByYear: function(years){
+ return this.calcPeriodIncByMonth(years*12);
+},
+
+setCDT: function(d,m,y,h,i){
+ this.cdt.setMinutes(i);
+ this.cdt.setHours(h);
+ this.cdt.setDate(d);
+ this.cdt.setMonth(m);
+ this.cdt.setFullYear(y);
+},
+
+syncBSDateByBSTime: function(){
+ this.minute = this.cdt.getMinutes();
+ this.hour = this.cdt.getHours();
+ this.day = this.cdt.getDate();
+ this.month = this.cdt.getMonth();
+ this.year = this.cdt.getFullYear();
+},
+
+syncBSTime: function(){
+ this.setCDT(this.day,this.month,this.year,this.hour,this.minute);
+ this.bstime = parseInt(this.cdt.getTime()/1000);
+},
+
+calcPeriodAndTypeByUnix: function(time){
+ if((this.bstime+time) > parseInt(this.dt.getTime()/1000)){
+ time = parseInt(this.dt.getTime()/1000) - this.bstime;
+ }
+
+ var years = parseInt(time / 22204800);
+ var months = parseInt(time / (28*86400));
+ var weeks = parseInt(time / 604800);
+ var days = parseInt(time / 86400);
+ var hours = parseInt(time / 3600);
+
+ this.period_type = 0;
+
+ if((time % 3600) == 0){
+ if(years>0){
+ if(time == this.calcPeriodIncByYear(years)){
+ this.period = time;
+ this.period_value = years;
+ this.period_type = 4;
+ return;
+ }
+ }
+
+ if(months>0){
+ if(time == this.calcPeriodIncByMonth(months)){
+ this.period = time;
+ this.period_value = months;
+ this.period_type = 3;
+ return;
+ }
+ }
+
+ if((weeks>0) && (time == (weeks*604800))){
+ this.period = time;
+ this.period_value = weeks;
+ this.period_type = 2;
+ }
+ else if((days>0) && (time == (days*86400))){
+ this.period = time;
+ this.period_value = days;
+ this.period_type = 1;
+ }
+ else if(hours>0){
+ this.period = time;
+ this.period_value = hours;
+ this.period_type = 0;
+ }
+ else{
+ this.period = 3600;
+ }
+ return;
+ }
+
+ if(years>0){
+ years++;
+ this.period = this.calcPeriodIncByYear(years);
+ this.period_value = years;
+ this.period_type = 4;
+ }
+ else if(months>0){
+ months++;
+ this.period = this.calcPeriodIncByMonth(months);
+ this.period_value = months;
+ this.period_type = 3;
+ }
+ else if(weeks>0){
+ weeks++;
+ this.period = weeks * 604800;
+ this.period_value = weeks;
+ this.period_type = 2;
+ }
+ else if(days>0){
+ days++;
+ this.period = days * 86400;
+ this.period_value = days;
+ this.period_type = 1;
+ }
+ else if(hours>0){
+ hours++;
+ this.period_value = hours;
+ this.period = hours * 3600;
+ }
+ else{
+ this.period = 3600*3;
+ }
+},
+
+setPeriodType: function(){
+ if(IE){
+ this.gm_type.innerText = this.period_typename[this.period_type];
+ }
+ else{
+ this.gm_type.textContent = this.period_typename[this.period_type];
+ }
+},
+
+setPeriod: function(){
+ if(IE){
+ this.gm_value.innerText = this.period_value;
+ }
+ else{
+ this.gm_value.textContent = this.period_value;
+ }
+},
+
+setBSDate: function(){
+ if(IE){
+ this.gm_minute.innerText = this.minute;
+ this.gm_hour.innerText = this.hour;
+ this.gm_day.innerText = this.day;
+ this.gm_month.innerText = this.monthname[this.month];
+ this.gm_year.innerText = this.year;
+ }
+ else{
+ this.gm_minute.textContent = this.minute;
+ this.gm_hour.textContent = this.hour;
+ this.gm_day.textContent = this.day;
+ this.gm_month.textContent = this.monthname[this.month];
+ this.gm_year.textContent = this.year;
+ }
+},
+
+daysInFeb: function(year){
+ // February has 29 days in any year evenly divisible by four,
+ // EXCEPT for centurial years which are not also divisible by 400.
+ return (((year % 4 == 0) && ( (!(year % 100 == 0)) || (year % 400 == 0))) ? 29 : 28 );
+},
+
+daysInMonth: function(m,y){
+ m++;
+ var days = 31;
+ if (m==4 || m==6 || m==9 || m==11){
+ days = 30;
+ }
+ else if(m==2){
+ days = this.daysInFeb(y);
+ }
+
+return days;
+}
+}
+
+
+/*-------------------------------------------------------------------------------------------------*\
+* GMENU CREATION *
+\*-------------------------------------------------------------------------------------------------*/
+function gmenucreate(top,left){
+
+ var div_gmenu = document.createElement('div');
+ document.getElementsByTagName('body')[0].appendChild(div_gmenu);
+
+ Element.extend(div_gmenu);
+ div_gmenu.setAttribute('id','gmenu');
+ div_gmenu.setStyle({top: top+'px', left: left+'px',display: 'none'});
+
+////////////////////////////////////////////// BSDATE
+
+ var div_bsdate = document.createElement('div');
+ div_gmenu.appendChild(div_bsdate);
+
+ div_bsdate.setAttribute('id','gmenu_bsdate');
+
+ var img = document.createElement('img');
+ div_bsdate.appendChild(img);
+
+ img.setAttribute('id','gmenu_day_up');
+ img.setAttribute('src',GMENU_IMG_PATH+'/arrow_up.gif');
+ img.setAttribute('alt','^');
+
+ var img = document.createElement('img');
+ div_bsdate.appendChild(img);
+
+ img.setAttribute('id','gmenu_month_up');
+ img.setAttribute('src',GMENU_IMG_PATH+'/arrow_up.gif');
+ img.setAttribute('alt','^');
+
+ var img = document.createElement('img');
+ div_bsdate.appendChild(img);
+
+ img.setAttribute('id','gmenu_year_up');
+ img.setAttribute('src',GMENU_IMG_PATH+'/arrow_up.gif');
+ img.setAttribute('alt','^');
+
+ var span = document.createElement('span');
+ div_bsdate.appendChild(span);
+
+ span.setAttribute('id','gmenu_day')
+ span.appendChild(document.createTextNode('1'));
+
+ var span = document.createElement('span');
+ div_bsdate.appendChild(span);
+
+ span.setAttribute('id','gmenu_month')
+ span.appendChild(document.createTextNode('January'));
+
+ var span = document.createElement('span');
+ div_bsdate.appendChild(span);
+
+ span.setAttribute('id','gmenu_year')
+ span.appendChild(document.createTextNode('2007'));
+
+ var img = document.createElement('img');
+ div_bsdate.appendChild(img);
+
+ img.setAttribute('id','gmenu_day_down');
+ img.setAttribute('src',GMENU_IMG_PATH+'/arrow_down.gif');
+ img.setAttribute('alt','v');
+
+
+ var img = document.createElement('img');
+ div_bsdate.appendChild(img);
+
+ img.setAttribute('id','gmenu_month_down');
+ img.setAttribute('src',GMENU_IMG_PATH+'/arrow_down.gif');
+ img.setAttribute('alt','v');
+
+
+ var img = document.createElement('img');
+ div_bsdate.appendChild(img);
+
+ img.setAttribute('id','gmenu_year_down');
+ img.setAttribute('src',GMENU_IMG_PATH+'/arrow_down.gif');
+ img.setAttribute('alt','v');
+
+/////////////////////////////////////// HOUR:MINUTE
+
+ var img = document.createElement('img');
+ div_bsdate.appendChild(img);
+
+ img.setAttribute('id','gmenu_hour_up');
+ img.setAttribute('src',GMENU_IMG_PATH+'/arrow_up.gif');
+ img.setAttribute('alt','^');
+
+ var img = document.createElement('img');
+ div_bsdate.appendChild(img);
+
+ img.setAttribute('id','gmenu_minute_up');
+ img.setAttribute('src',GMENU_IMG_PATH+'/arrow_up.gif');
+ img.setAttribute('alt','^');
+
+ var span = document.createElement('span');
+ div_bsdate.appendChild(span);
+
+ span.setAttribute('id','gmenu_hour')
+ span.appendChild(document.createTextNode('12'));
+
+ var span = document.createElement('span');
+ div_bsdate.appendChild(span);
+
+ span.setAttribute('id','gmenu_minute')
+ span.appendChild(document.createTextNode('00'));
+
+ var img = document.createElement('img');
+ div_bsdate.appendChild(img);
+
+ img.setAttribute('id','gmenu_hour_down');
+ img.setAttribute('src',GMENU_IMG_PATH+'/arrow_down.gif');
+ img.setAttribute('alt','v');
+
+ var img = document.createElement('img');
+ div_bsdate.appendChild(img);
+
+ img.setAttribute('id','gmenu_minute_down');
+ img.setAttribute('src',GMENU_IMG_PATH+'/arrow_down.gif');
+ img.setAttribute('alt','v');
+
+//////////////////////////////////////////////////////// PERIOD
+
+ var div_period = document.createElement('div');
+ div_gmenu.appendChild(div_period);
+
+ div_period.setAttribute('id','gmenu_period');
+
+ var img = document.createElement('img');
+ div_period.appendChild(img);
+
+ img.setAttribute('id','gmenu_period_v_up');
+ img.setAttribute('src',GMENU_IMG_PATH+'/arrow_up.gif');
+ img.setAttribute('alt','^');
+
+ var img = document.createElement('img');
+ div_period.appendChild(img);
+
+ img.setAttribute('id','gmenu_period_t_up');
+ img.setAttribute('src',GMENU_IMG_PATH+'/arrow_up.gif');
+ img.setAttribute('alt','^');
+
+ var span = document.createElement('span');
+ div_period.appendChild(span);
+
+ span.setAttribute('id','gmenu_period_desc')
+ span.appendChild(document.createTextNode('Period'));
+
+ var span = document.createElement('span');
+ div_period.appendChild(span);
+
+ span.setAttribute('id','gmenu_period_value')
+ span.appendChild(document.createTextNode('1'));
+
+ var span = document.createElement('span');
+ div_period.appendChild(span);
+
+ span.setAttribute('id','gmenu_period_type')
+ span.appendChild(document.createTextNode('Hours'));
+
+ var img = document.createElement('img');
+ div_period.appendChild(img);
+
+ img.setAttribute('id','gmenu_period_v_down');
+ img.setAttribute('src',GMENU_IMG_PATH+'/arrow_down.gif');
+ img.setAttribute('alt','v');
+
+ var img = document.createElement('img');
+ div_period.appendChild(img);
+
+ img.setAttribute('id','gmenu_period_t_down');
+ img.setAttribute('src',GMENU_IMG_PATH+'/arrow_down.gif');
+ img.setAttribute('alt','v');
+
+///////////////////////////////////////////////////// CONTROL BUTTONS
+
+ var link_load = document.createElement('a');
+ div_gmenu.appendChild(link_load);
+
+ link_load.setAttribute('id','gmenu_load');
+ link_load.setAttribute('href',location.href);
+ link_load.appendChild(document.createTextNode('OK'));
+
+ var link_hide = document.createElement('a');
+ div_gmenu.appendChild(link_hide);
+
+ link_hide.setAttribute('id','gmenu_hide');
+ link_hide.setAttribute('href',location.href);
+
+ link_hide.appendChild(document.createTextNode('Back'));
+
+/*
+<div id="gmenu" style="top: 220px; left:10px;">
+ <div id="gmenu_bsdate">
+ <img id="gmenu_day_up" src="images/general/bar/arrow_up.gif" alt="^" />
+ <img id="gmenu_month_up" src="images/general/bar/arrow_up.gif" alt="^" />
+ <img id="gmenu_year_up" src="images/general/bar/arrow_up.gif" alt="^" />
+
+ <span id="gmenu_day">20</span><span id="gmenu_month">January</span><span id="gmenu_year">2007</span>
+
+ <img id="gmenu_day_down" src="images/general/bar/arrow_down.gif" alt="v" />
+ <img id="gmenu_month_down" src="images/general/bar/arrow_down.gif" alt="v" />
+ <img id="gmenu_year_down" src="images/general/bar/arrow_down.gif" alt="v" />
+
+ <img id="gmenu_hour_up" src="images/general/bar/arrow_up.gif" alt="^" />
+ <img id="gmenu_minute_up" src="images/general/bar/arrow_up.gif" alt="^" />
+
+ <span id="gmenu_hour">12</span><span id="gmenu_minute">00</span>
+
+ <img id="gmenu_hour_down" src="images/general/bar/arrow_down.gif" alt="v" />
+ <img id="gmenu_minute_down" src="images/general/bar/arrow_down.gif" alt="v" />
+ </div>
+ <div id="gmenu_period">
+ <img id="gmenu_period_v_up" src="images/general/bar/arrow_up.gif" alt="^" />
+ <img id="gmenu_period_t_up" src="images/general/bar/arrow_up.gif" alt="^" />
+
+ <span id="gmenu_period_desc">Period</span><span id="gmenu_period_value">10</span><span id="gmenu_period_type">Months</span>
+
+ <img id="gmenu_period_v_down" src="images/general/bar/arrow_down.gif" alt="v" />
+ <img id="gmenu_period_t_down" src="images/general/bar/arrow_down.gif" alt="v" />
+ </div>
+ <a href="javascript: return false;" id="gmenu_load">OK</a>
+ <a href="#1" id="gmenu_hide">Back</a>
+</div>
+//*/
+} \ No newline at end of file
diff --git a/frontends/php/js/prototype.js b/frontends/php/js/prototype.js
new file mode 100644
index 00000000..053bde6a
--- /dev/null
+++ b/frontends/php/js/prototype.js
@@ -0,0 +1,3278 @@
+/* Prototype JavaScript framework, version 1.5.1.1
+ * (c) 2005-2007 Sam Stephenson
+ *
+ * Prototype is freely distributable under the terms of an MIT-style license.
+ * For details, see the Prototype web site: http://www.prototypejs.org/
+ *
+/*--------------------------------------------------------------------------*/
+
+var Prototype = {
+ Version: '1.5.1.1',
+
+ Browser: {
+ IE: !!(window.attachEvent && !window.opera),
+ Opera: !!window.opera,
+ WebKit: navigator.userAgent.indexOf('AppleWebKit/') > -1,
+ Gecko: navigator.userAgent.indexOf('Gecko') > -1 && navigator.userAgent.indexOf('KHTML') == -1
+ },
+
+ BrowserFeatures: {
+ XPath: !!document.evaluate,
+ ElementExtensions: !!window.HTMLElement,
+ SpecificElementExtensions:
+ (document.createElement('div').__proto__ !==
+ document.createElement('form').__proto__)
+ },
+
+ ScriptFragment: '<script[^>]*>([\\S\\s]*?)<\/script>',
+ JSONFilter: /^\/\*-secure-([\s\S]*)\*\/\s*$/,
+
+ emptyFunction: function() { },
+ K: function(x) { return x }
+}
+
+var Class = {
+ create: function() {
+ return function() {
+ this.initialize.apply(this, arguments);
+ }
+ }
+}
+
+var Abstract = new Object();
+
+Object.extend = function(destination, source) {
+ for (var property in source) {
+ destination[property] = source[property];
+ }
+ return destination;
+}
+
+Object.extend(Object, {
+ inspect: function(object) {
+ try {
+ if (object === undefined) return 'undefined';
+ if (object === null) return 'null';
+ return object.inspect ? object.inspect() : object.toString();
+ } catch (e) {
+ if (e instanceof RangeError) return '...';
+ throw e;
+ }
+ },
+
+ toJSON: function(object) {
+ var type = typeof object;
+ switch(type) {
+ case 'undefined':
+ case 'function':
+ case 'unknown': return;
+ case 'boolean': return object.toString();
+ }
+ if (object === null) return 'null';
+ if (object.toJSON) return object.toJSON();
+ if (object.ownerDocument === document) return;
+ var results = [];
+ for (var property in object) {
+ var value = Object.toJSON(object[property]);
+ if (value !== undefined)
+ results.push(property.toJSON() + ': ' + value);
+ }
+ return '{' + results.join(', ') + '}';
+ },
+
+ keys: function(object) {
+ var keys = [];
+ for (var property in object)
+ keys.push(property);
+ return keys;
+ },
+
+ values: function(object) {
+ var values = [];
+ for (var property in object)
+ values.push(object[property]);
+ return values;
+ },
+
+ clone: function(object) {
+ return Object.extend({}, object);
+ }
+});
+
+Function.prototype.bind = function() {
+ var __method = this, args = $A(arguments), object = args.shift();
+ return function() {
+ return __method.apply(object, args.concat($A(arguments)));
+ }
+}
+
+Function.prototype.bindAsEventListener = function(object) {
+ var __method = this, args = $A(arguments), object = args.shift();
+ return function(event) {
+ return __method.apply(object, [event || window.event].concat(args));
+ }
+}
+
+Object.extend(Number.prototype, {
+ toColorPart: function() {
+ return this.toPaddedString(2, 16);
+ },
+
+ succ: function() {
+ return this + 1;
+ },
+
+ times: function(iterator) {
+ $R(0, this, true).each(iterator);
+ return this;
+ },
+
+ toPaddedString: function(length, radix) {
+ var string = this.toString(radix || 10);
+ return '0'.times(length - string.length) + string;
+ },
+
+ toJSON: function() {
+ return isFinite(this) ? this.toString() : 'null';
+ }
+});
+
+Date.prototype.toJSON = function() {
+ return '"' + this.getFullYear() + '-' +
+ (this.getMonth() + 1).toPaddedString(2) + '-' +
+ this.getDate().toPaddedString(2) + 'T' +
+ this.getHours().toPaddedString(2) + ':' +
+ this.getMinutes().toPaddedString(2) + ':' +
+ this.getSeconds().toPaddedString(2) + '"';
+};
+
+var Try = {
+ these: function() {
+ var returnValue;
+
+ for (var i = 0, length = arguments.length; i < length; i++) {
+ var lambda = arguments[i];
+ try {
+ returnValue = lambda();
+ break;
+ } catch (e) {}
+ }
+
+ return returnValue;
+ }
+}
+
+/*--------------------------------------------------------------------------*/
+
+var PeriodicalExecuter = Class.create();
+PeriodicalExecuter.prototype = {
+ initialize: function(callback, frequency) {
+ this.callback = callback;
+ this.frequency = frequency;
+ this.currentlyExecuting = false;
+
+ this.registerCallback();
+ },
+
+ registerCallback: function() {
+ this.timer = setInterval(this.onTimerEvent.bind(this), this.frequency * 1000);
+ },
+
+ stop: function() {
+ if (!this.timer) return;
+ clearInterval(this.timer);
+ this.timer = null;
+ },
+
+ onTimerEvent: function() {
+ if (!this.currentlyExecuting) {
+ try {
+ this.currentlyExecuting = true;
+ this.callback(this);
+ } finally {
+ this.currentlyExecuting = false;
+ }
+ }
+ }
+}
+Object.extend(String, {
+ interpret: function(value) {
+ return value == null ? '' : String(value);
+ },
+ specialChar: {
+ '\b': '\\b',
+ '\t': '\\t',
+ '\n': '\\n',
+ '\f': '\\f',
+ '\r': '\\r',
+ '\\': '\\\\'
+ }
+});
+
+Object.extend(String.prototype, {
+ gsub: function(pattern, replacement) {
+ var result = '', source = this, match;
+ replacement = arguments.callee.prepareReplacement(replacement);
+
+ while (source.length > 0) {
+ if (match = source.match(pattern)) {
+ result += source.slice(0, match.index);
+ result += String.interpret(replacement(match));
+ source = source.slice(match.index + match[0].length);
+ } else {
+ result += source, source = '';
+ }
+ }
+ return result;
+ },
+
+ sub: function(pattern, replacement, count) {
+ replacement = this.gsub.prepareReplacement(replacement);
+ count = count === undefined ? 1 : count;
+
+ return this.gsub(pattern, function(match) {
+ if (--count < 0) return match[0];
+ return replacement(match);
+ });
+ },
+
+ scan: function(pattern, iterator) {
+ this.gsub(pattern, iterator);
+ return this;
+ },
+
+ truncate: function(length, truncation) {
+ length = length || 30;
+ truncation = truncation === undefined ? '...' : truncation;
+ return this.length > length ?
+ this.slice(0, length - truncation.length) + truncation : this;
+ },
+
+ strip: function() {
+ return this.replace(/^\s+/, '').replace(/\s+$/, '');
+ },
+
+ stripTags: function() {
+ return this.replace(/<\/?[^>]+>/gi, '');
+ },
+
+ stripScripts: function() {
+ return this.replace(new RegExp(Prototype.ScriptFragment, 'img'), '');
+ },
+
+ extractScripts: function() {
+ var matchAll = new RegExp(Prototype.ScriptFragment, 'img');
+ var matchOne = new RegExp(Prototype.ScriptFragment, 'im');
+ return (this.match(matchAll) || []).map(function(scriptTag) {
+ return (scriptTag.match(matchOne) || ['', ''])[1];
+ });
+ },
+
+ evalScripts: function() {
+ return this.extractScripts().map(function(script) { return eval(script) });
+ },
+
+ escapeHTML: function() {
+ var self = arguments.callee;
+ self.text.data = this;
+ return self.div.innerHTML;
+ },
+
+ unescapeHTML: function() {
+ var div = document.createElement('div');
+ div.innerHTML = this.stripTags();
+ return div.childNodes[0] ? (div.childNodes.length > 1 ?
+ $A(div.childNodes).inject('', function(memo, node) { return memo+node.nodeValue }) :
+ div.childNodes[0].nodeValue) : '';
+ },
+
+ toQueryParams: function(separator) {
+ var match = this.strip().match(/([^?#]*)(#.*)?$/);
+ if (!match) return {};
+
+ return match[1].split(separator || '&').inject({}, function(hash, pair) {
+ if ((pair = pair.split('='))[0]) {
+ var key = decodeURIComponent(pair.shift());
+ var value = pair.length > 1 ? pair.join('=') : pair[0];
+ if (value != undefined) value = decodeURIComponent(value);
+
+ if (key in hash) {
+ if (hash[key].constructor != Array) hash[key] = [hash[key]];
+ hash[key].push(value);
+ }
+ else hash[key] = value;
+ }
+ return hash;
+ });
+ },
+
+ toArray: function() {
+ return this.split('');
+ },
+
+ succ: function() {
+ return this.slice(0, this.length - 1) +
+ String.fromCharCode(this.charCodeAt(this.length - 1) + 1);
+ },
+
+ times: function(count) {
+ var result = '';
+ for (var i = 0; i < count; i++) result += this;
+ return result;
+ },
+
+ camelize: function() {
+ var parts = this.split('-'), len = parts.length;
+ if (len == 1) return parts[0];
+
+ var camelized = this.charAt(0) == '-'
+ ? parts[0].charAt(0).toUpperCase() + parts[0].substring(1)
+ : parts[0];
+
+ for (var i = 1; i < len; i++)
+ camelized += parts[i].charAt(0).toUpperCase() + parts[i].substring(1);
+
+ return camelized;
+ },
+
+ capitalize: function() {
+ return this.charAt(0).toUpperCase() + this.substring(1).toLowerCase();
+ },
+
+ underscore: function() {
+ return this.gsub(/::/, '/').gsub(/([A-Z]+)([A-Z][a-z])/,'#{1}_#{2}').gsub(/([a-z\d])([A-Z])/,'#{1}_#{2}').gsub(/-/,'_').toLowerCase();
+ },
+
+ dasherize: function() {
+ return this.gsub(/_/,'-');
+ },
+
+ inspect: function(useDoubleQuotes) {
+ var escapedString = this.gsub(/[\x00-\x1f\\]/, function(match) {
+ var character = String.specialChar[match[0]];
+ return character ? character : '\\u00' + match[0].charCodeAt().toPaddedString(2, 16);
+ });
+ if (useDoubleQuotes) return '"' + escapedString.replace(/"/g, '\\"') + '"';
+ return "'" + escapedString.replace(/'/g, '\\\'') + "'";
+ },
+
+ toJSON: function() {
+ return this.inspect(true);
+ },
+
+ unfilterJSON: function(filter) {
+ return this.sub(filter || Prototype.JSONFilter, '#{1}');
+ },
+
+ isJSON: function() {
+ var str = this.replace(/\\./g, '@').replace(/"[^"\\\n\r]*"/g, '');
+ return (/^[,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t]*$/).test(str);
+ },
+
+ evalJSON: function(sanitize) {
+ var json = this.unfilterJSON();
+ try {
+ if (!sanitize || json.isJSON()) return eval('(' + json + ')');
+ } catch (e) { }
+ throw new SyntaxError('Badly formed JSON string: ' + this.inspect());
+ },
+
+ include: function(pattern) {
+ return this.indexOf(pattern) > -1;
+ },
+
+ startsWith: function(pattern) {
+ return this.indexOf(pattern) === 0;
+ },
+
+ endsWith: function(pattern) {
+ var d = this.length - pattern.length;
+ return d >= 0 && this.lastIndexOf(pattern) === d;
+ },
+
+ empty: function() {
+ return this == '';
+ },
+
+ blank: function() {
+ return /^\s*$/.test(this);
+ }
+});
+
+if (Prototype.Browser.WebKit || Prototype.Browser.IE) Object.extend(String.prototype, {
+ escapeHTML: function() {
+ return this.replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;');
+ },
+ unescapeHTML: function() {
+ return this.replace(/&amp;/g,'&').replace(/&lt;/g,'<').replace(/&gt;/g,'>');
+ }
+});
+
+String.prototype.gsub.prepareReplacement = function(replacement) {
+ if (typeof replacement == 'function') return replacement;
+ var template = new Template(replacement);
+ return function(match) { return template.evaluate(match) };
+}
+
+String.prototype.parseQuery = String.prototype.toQueryParams;
+
+Object.extend(String.prototype.escapeHTML, {
+ div: document.createElement('div'),
+ text: document.createTextNode('')
+});
+
+with (String.prototype.escapeHTML) div.appendChild(text);
+
+var Template = Class.create();
+Template.Pattern = /(^|.|\r|\n)(#\{(.*?)\})/;
+Template.prototype = {
+ initialize: function(template, pattern) {
+ this.template = template.toString();
+ this.pattern = pattern || Template.Pattern;
+ },
+
+ evaluate: function(object) {
+ return this.template.gsub(this.pattern, function(match) {
+ var before = match[1];
+ if (before == '\\') return match[2];
+ return before + String.interpret(object[match[3]]);
+ });
+ }
+}
+
+var $break = {}, $continue = new Error('"throw $continue" is deprecated, use "return" instead');
+
+var Enumerable = {
+ each: function(iterator) {
+ var index = 0;
+ try {
+ this._each(function(value) {
+ iterator(value, index++);
+ });
+ } catch (e) {
+ if (e != $break) throw e;
+ }
+ return this;
+ },
+
+ eachSlice: function(number, iterator) {
+ var index = -number, slices = [], array = this.toArray();
+ while ((index += number) < array.length)
+ slices.push(array.slice(index, index+number));
+ return slices.map(iterator);
+ },
+
+ all: function(iterator) {
+ var result = true;
+ this.each(function(value, index) {
+ result = result && !!(iterator || Prototype.K)(value, index);
+ if (!result) throw $break;
+ });
+ return result;
+ },
+
+ any: function(iterator) {
+ var result = false;
+ this.each(function(value, index) {
+ if (result = !!(iterator || Prototype.K)(value, index))
+ throw $break;
+ });
+ return result;
+ },
+
+ collect: function(iterator) {
+ var results = [];
+ this.each(function(value, index) {
+ results.push((iterator || Prototype.K)(value, index));
+ });
+ return results;
+ },
+
+ detect: function(iterator) {
+ var result;
+ this.each(function(value, index) {
+ if (iterator(value, index)) {
+ result = value;
+ throw $break;
+ }
+ });
+ return result;
+ },
+
+ findAll: function(iterator) {
+ var results = [];
+ this.each(function(value, index) {
+ if (iterator(value, index))
+ results.push(value);
+ });
+ return results;
+ },
+
+ grep: function(pattern, iterator) {
+ var results = [];
+ this.each(function(value, index) {
+ var stringValue = value.toString();
+ if (stringValue.match(pattern))
+ results.push((iterator || Prototype.K)(value, index));
+ })
+ return results;
+ },
+
+ include: function(object) {
+ var found = false;
+ this.each(function(value) {
+ if (value == object) {
+ found = true;
+ throw $break;
+ }
+ });
+ return found;
+ },
+
+ inGroupsOf: function(number, fillWith) {
+ fillWith = fillWith === undefined ? null : fillWith;
+ return this.eachSlice(number, function(slice) {
+ while(slice.length < number) slice.push(fillWith);
+ return slice;
+ });
+ },
+
+ inject: function(memo, iterator) {
+ this.each(function(value, index) {
+ memo = iterator(memo, value, index);
+ });
+ return memo;
+ },
+
+ invoke: function(method) {
+ var args = $A(arguments).slice(1);
+ return this.map(function(value) {
+ return value[method].apply(value, args);
+ });
+ },
+
+ max: function(iterator) {
+ var result;
+ this.each(function(value, index) {
+ value = (iterator || Prototype.K)(value, index);
+ if (result == undefined || value >= result)
+ result = value;
+ });
+ return result;
+ },
+
+ min: function(iterator) {
+ var result;
+ this.each(function(value, index) {
+ value = (iterator || Prototype.K)(value, index);
+ if (result == undefined || value < result)
+ result = value;
+ });
+ return result;
+ },
+
+ partition: function(iterator) {
+ var trues = [], falses = [];
+ this.each(function(value, index) {
+ ((iterator || Prototype.K)(value, index) ?
+ trues : falses).push(value);
+ });
+ return [trues, falses];
+ },
+
+ pluck: function(property) {
+ var results = [];
+ this.each(function(value, index) {
+ results.push(value[property]);
+ });
+ return results;
+ },
+
+ reject: function(iterator) {
+ var results = [];
+ this.each(function(value, index) {
+ if (!iterator(value, index))
+ results.push(value);
+ });
+ return results;
+ },
+
+ sortBy: function(iterator) {
+ return this.map(function(value, index) {
+ return {value: value, criteria: iterator(value, index)};
+ }).sort(function(left, right) {
+ var a = left.criteria, b = right.criteria;
+ return a < b ? -1 : a > b ? 1 : 0;
+ }).pluck('value');
+ },
+
+ toArray: function() {
+ return this.map();
+ },
+
+ zip: function() {
+ var iterator = Prototype.K, args = $A(arguments);
+ if (typeof args.last() == 'function')
+ iterator = args.pop();
+
+ var collections = [this].concat(args).map($A);
+ return this.map(function(value, index) {
+ return iterator(collections.pluck(index));
+ });
+ },
+
+ size: function() {
+ return this.toArray().length;
+ },
+
+ inspect: function() {
+ return '#<Enumerable:' + this.toArray().inspect() + '>';
+ }
+}
+
+Object.extend(Enumerable, {
+ map: Enumerable.collect,
+ find: Enumerable.detect,
+ select: Enumerable.findAll,
+ member: Enumerable.include,
+ entries: Enumerable.toArray
+});
+var $A = Array.from = function(iterable) {
+ if (!iterable) return [];
+ if (iterable.toArray) {
+ return iterable.toArray();
+ } else {
+ var results = [];
+ for (var i = 0, length = iterable.length; i < length; i++)
+ results.push(iterable[i]);
+ return results;
+ }
+}
+
+if (Prototype.Browser.WebKit) {
+ $A = Array.from = function(iterable) {
+ if (!iterable) return [];
+ if (!(typeof iterable == 'function' && iterable == '[object NodeList]') &&
+ iterable.toArray) {
+ return iterable.toArray();
+ } else {
+ var results = [];
+ for (var i = 0, length = iterable.length; i < length; i++)
+ results.push(iterable[i]);
+ return results;
+ }
+ }
+}
+
+Object.extend(Array.prototype, Enumerable);
+
+if (!Array.prototype._reverse)
+ Array.prototype._reverse = Array.prototype.reverse;
+
+Object.extend(Array.prototype, {
+ _each: function(iterator) {
+ for (var i = 0, length = this.length; i < length; i++)
+ iterator(this[i]);
+ },
+
+ clear: function() {
+ this.length = 0;
+ return this;
+ },
+
+ first: function() {
+ return this[0];
+ },
+
+ last: function() {
+ return this[this.length - 1];
+ },
+
+ compact: function() {
+ return this.select(function(value) {
+ return value != null;
+ });
+ },
+
+ flatten: function() {
+ return this.inject([], function(array, value) {
+ return array.concat(value && value.constructor == Array ?
+ value.flatten() : [value]);
+ });
+ },
+
+ without: function() {
+ var values = $A(arguments);
+ return this.select(function(value) {
+ return !values.include(value);
+ });
+ },
+
+ indexOf: function(object) {
+ for (var i = 0, length = this.length; i < length; i++)
+ if (this[i] == object) return i;
+ return -1;
+ },
+
+ reverse: function(inline) {
+ return (inline !== false ? this : this.toArray())._reverse();
+ },
+
+ reduce: function() {
+ return this.length > 1 ? this : this[0];
+ },
+
+ uniq: function(sorted) {
+ return this.inject([], function(array, value, index) {
+ if (0 == index || (sorted ? array.last() != value : !array.include(value)))
+ array.push(value);
+ return array;
+ });
+ },
+
+ clone: function() {
+ return [].concat(this);
+ },
+
+ size: function() {
+ return this.length;
+ },
+
+ inspect: function() {
+ return '[' + this.map(Object.inspect).join(', ') + ']';
+ },
+
+ toJSON: function() {
+ var results = [];
+ this.each(function(object) {
+ var value = Object.toJSON(object);
+ if (value !== undefined) results.push(value);
+ });
+ return '[' + results.join(', ') + ']';
+ }
+});
+
+Array.prototype.toArray = Array.prototype.clone;
+
+function $w(string) {
+ string = string.strip();
+ return string ? string.split(/\s+/) : [];
+}
+
+if (Prototype.Browser.Opera){
+ Array.prototype.concat = function() {
+ var array = [];
+ for (var i = 0, length = this.length; i < length; i++) array.push(this[i]);
+ for (var i = 0, length = arguments.length; i < length; i++) {
+ if (arguments[i].constructor == Array) {
+ for (var j = 0, arrayLength = arguments[i].length; j < arrayLength; j++)
+ array.push(arguments[i][j]);
+ } else {
+ array.push(arguments[i]);
+ }
+ }
+ return array;
+ }
+}
+var Hash = function(object) {
+ if (object instanceof Hash) this.merge(object);
+ else Object.extend(this, object || {});
+};
+
+Object.extend(Hash, {
+ toQueryString: function(obj) {
+ var parts = [];
+ parts.add = arguments.callee.addPair;
+
+ this.prototype._each.call(obj, function(pair) {
+ if (!pair.key) return;
+ var value = pair.value;
+
+ if (value && typeof value == 'object') {
+ if (value.constructor == Array) value.each(function(value) {
+ parts.add(pair.key, value);
+ });
+ return;
+ }
+ parts.add(pair.key, value);
+ });
+
+ return parts.join('&');
+ },
+
+ toJSON: function(object) {
+ var results = [];
+ this.prototype._each.call(object, function(pair) {
+ var value = Object.toJSON(pair.value);
+ if (value !== undefined) results.push(pair.key.toJSON() + ': ' + value);
+ });
+ return '{' + results.join(', ') + '}';
+ }
+});
+
+Hash.toQueryString.addPair = function(key, value, prefix) {
+ key = encodeURIComponent(key);
+ if (value === undefined) this.push(key);
+ else this.push(key + '=' + (value == null ? '' : encodeURIComponent(value)));
+}
+
+Object.extend(Hash.prototype, Enumerable);
+Object.extend(Hash.prototype, {
+ _each: function(iterator) {
+ for (var key in this) {
+ var value = this[key];
+ if (value && value == Hash.prototype[key]) continue;
+
+ var pair = [key, value];
+ pair.key = key;
+ pair.value = value;
+ iterator(pair);
+ }
+ },
+
+ keys: function() {
+ return this.pluck('key');
+ },
+
+ values: function() {
+ return this.pluck('value');
+ },
+
+ merge: function(hash) {
+ return $H(hash).inject(this, function(mergedHash, pair) {
+ mergedHash[pair.key] = pair.value;
+ return mergedHash;
+ });
+ },
+
+ remove: function() {
+ var result;
+ for(var i = 0, length = arguments.length; i < length; i++) {
+ var value = this[arguments[i]];
+ if (value !== undefined){
+ if (result === undefined) result = value;
+ else {
+ if (result.constructor != Array) result = [result];
+ result.push(value)
+ }
+ }
+ delete this[arguments[i]];
+ }
+ return result;
+ },
+
+ toQueryString: function() {
+ return Hash.toQueryString(this);
+ },
+
+ inspect: function() {
+ return '#<Hash:{' + this.map(function(pair) {
+ return pair.map(Object.inspect).join(': ');
+ }).join(', ') + '}>';
+ },
+
+ toJSON: function() {
+ return Hash.toJSON(this);
+ }
+});
+
+function $H(object) {
+ if (object instanceof Hash) return object;
+ return new Hash(object);
+};
+
+// Safari iterates over shadowed properties
+if (function() {
+ var i = 0, Test = function(value) { this.key = value };
+ Test.prototype.key = 'foo';
+ for (var property in new Test('bar')) i++;
+ return i > 1;
+}()) Hash.prototype._each = function(iterator) {
+ var cache = [];
+ for (var key in this) {
+ var value = this[key];
+ if ((value && value == Hash.prototype[key]) || cache.include(key)) continue;
+ cache.push(key);
+ var pair = [key, value];
+ pair.key = key;
+ pair.value = value;
+ iterator(pair);
+ }
+};
+ObjectRange = Class.create();
+Object.extend(ObjectRange.prototype, Enumerable);
+Object.extend(ObjectRange.prototype, {
+ initialize: function(start, end, exclusive) {
+ this.start = start;
+ this.end = end;
+ this.exclusive = exclusive;
+ },
+
+ _each: function(iterator) {
+ var value = this.start;
+ while (this.include(value)) {
+ iterator(value);
+ value = value.succ();
+ }
+ },
+
+ include: function(value) {
+ if (value < this.start)
+ return false;
+ if (this.exclusive)
+ return value < this.end;
+ return value <= this.end;
+ }
+});
+
+var $R = function(start, end, exclusive) {
+ return new ObjectRange(start, end, exclusive);
+}
+
+var Ajax = {
+ getTransport: function() {
+ return Try.these(
+ function() {return new XMLHttpRequest()},
+ function() {return new ActiveXObject('Msxml2.XMLHTTP')},
+ function() {return new ActiveXObject('Microsoft.XMLHTTP')}
+ ) || false;
+ },
+
+ activeRequestCount: 0
+}
+
+Ajax.Responders = {
+ responders: [],
+
+ _each: function(iterator) {
+ this.responders._each(iterator);
+ },
+
+ register: function(responder) {
+ if (!this.include(responder))
+ this.responders.push(responder);
+ },
+
+ unregister: function(responder) {
+ this.responders = this.responders.without(responder);
+ },
+
+ dispatch: function(callback, request, transport, json) {
+ this.each(function(responder) {
+ if (typeof responder[callback] == 'function') {
+ try {
+ responder[callback].apply(responder, [request, transport, json]);
+ } catch (e) {}
+ }
+ });
+ }
+};
+
+Object.extend(Ajax.Responders, Enumerable);
+
+Ajax.Responders.register({
+ onCreate: function() {
+ Ajax.activeRequestCount++;
+ },
+ onComplete: function() {
+ Ajax.activeRequestCount--;
+ }
+});
+
+Ajax.Base = function() {};
+Ajax.Base.prototype = {
+ setOptions: function(options) {
+ this.options = {
+ method: 'post',
+ asynchronous: true,
+ contentType: 'application/x-www-form-urlencoded',
+ encoding: 'UTF-8',
+ parameters: ''
+ }
+ Object.extend(this.options, options || {});
+
+ this.options.method = this.options.method.toLowerCase();
+ if (typeof this.options.parameters == 'string')
+ this.options.parameters = this.options.parameters.toQueryParams();
+ }
+}
+
+Ajax.Request = Class.create();
+Ajax.Request.Events =
+ ['Uninitialized', 'Loading', 'Loaded', 'Interactive', 'Complete'];
+
+Ajax.Request.prototype = Object.extend(new Ajax.Base(), {
+ _complete: false,
+
+ initialize: function(url, options) {
+ this.transport = Ajax.getTransport();
+ this.setOptions(options);
+ this.request(url);
+ },
+
+ request: function(url) {
+ this.url = url;
+ this.method = this.options.method;
+ var params = Object.clone(this.options.parameters);
+
+ if (!['get', 'post'].include(this.method)) {
+ // simulate other verbs over post
+ params['_method'] = this.method;
+ this.method = 'post';
+ }
+
+ this.parameters = params;
+
+ if (params = Hash.toQueryString(params)) {
+ // when GET, append parameters to URL
+ if (this.method == 'get')
+ this.url += (this.url.include('?') ? '&' : '?') + params;
+ else if (/Konqueror|Safari|KHTML/.test(navigator.userAgent))
+ params += '&_=';
+ }
+
+ try {
+ if (this.options.onCreate) this.options.onCreate(this.transport);
+ Ajax.Responders.dispatch('onCreate', this, this.transport);
+
+ this.transport.open(this.method.toUpperCase(), this.url,
+ this.options.asynchronous);
+
+ if (this.options.asynchronous)
+ setTimeout(function() { this.respondToReadyState(1) }.bind(this), 10);
+
+ this.transport.onreadystatechange = this.onStateChange.bind(this);
+ this.setRequestHeaders();
+
+ this.body = this.method == 'post' ? (this.options.postBody || params) : null;
+ this.transport.send(this.body);
+
+ /* Force Firefox to handle ready state 4 for synchronous requests */
+ if (!this.options.asynchronous && this.transport.overrideMimeType)
+ this.onStateChange();
+
+ }
+ catch (e) {
+ this.dispatchException(e);
+ }
+ },
+
+ onStateChange: function() {
+ var readyState = this.transport.readyState;
+ if (readyState > 1 && !((readyState == 4) && this._complete))
+ this.respondToReadyState(this.transport.readyState);
+ },
+
+ setRequestHeaders: function() {
+ var headers = {
+ 'X-Requested-With': 'XMLHttpRequest',
+ 'X-Prototype-Version': Prototype.Version,
+ 'Accept': 'text/javascript, text/html, application/xml, text/xml, */*'
+ };
+
+ if (this.method == 'post') {
+ headers['Content-type'] = this.options.contentType +
+ (this.options.encoding ? '; charset=' + this.options.encoding : '');
+
+ /* Force "Connection: close" for older Mozilla browsers to work
+ * around a bug where XMLHttpRequest sends an incorrect
+ * Content-length header. See Mozilla Bugzilla #246651.
+ */
+ if (this.transport.overrideMimeType &&
+ (navigator.userAgent.match(/Gecko\/(\d{4})/) || [0,2005])[1] < 2005)
+ headers['Connection'] = 'close';
+ }
+
+ // user-defined headers
+ if (typeof this.options.requestHeaders == 'object') {
+ var extras = this.options.requestHeaders;
+
+ if (typeof extras.push == 'function')
+ for (var i = 0, length = extras.length; i < length; i += 2)
+ headers[extras[i]] = extras[i+1];
+ else
+ $H(extras).each(function(pair) { headers[pair.key] = pair.value });
+ }
+
+ for (var name in headers)
+ this.transport.setRequestHeader(name, headers[name]);
+ },
+
+ success: function() {
+ return !this.transport.status
+ || (this.transport.status >= 200 && this.transport.status < 300);
+ },
+
+ respondToReadyState: function(readyState) {
+ var state = Ajax.Request.Events[readyState];
+ var transport = this.transport, json = this.evalJSON();
+
+ if (state == 'Complete') {
+ try {
+ this._complete = true;
+ (this.options['on' + this.transport.status]
+ || this.options['on' + (this.success() ? 'Success' : 'Failure')]
+ || Prototype.emptyFunction)(transport, json);
+ } catch (e) {
+ this.dispatchException(e);
+ }
+
+ var contentType = this.getHeader('Content-type');
+ if (contentType && contentType.strip().
+ match(/^(text|application)\/(x-)?(java|ecma)script(;.*)?$/i))
+ this.evalResponse();
+ }
+
+ try {
+ (this.options['on' + state] || Prototype.emptyFunction)(transport, json);
+ Ajax.Responders.dispatch('on' + state, this, transport, json);
+ } catch (e) {
+ this.dispatchException(e);
+ }
+
+ if (state == 'Complete') {
+ // avoid memory leak in MSIE: clean up
+ this.transport.onreadystatechange = Prototype.emptyFunction;
+ }
+ },
+
+ getHeader: function(name) {
+ try {
+ return this.transport.getResponseHeader(name);
+ } catch (e) { return null }
+ },
+
+ evalJSON: function() {
+ try {
+ var json = this.getHeader('X-JSON');
+ return json ? json.evalJSON() : null;
+ } catch (e) { return null }
+ },
+
+ evalResponse: function() {
+ try {
+ return eval((this.transport.responseText || '').unfilterJSON());
+ } catch (e) {
+ this.dispatchException(e);
+ }
+ },
+
+ dispatchException: function(exception) {
+ (this.options.onException || Prototype.emptyFunction)(this, exception);
+ Ajax.Responders.dispatch('onException', this, exception);
+ }
+});
+
+Ajax.Updater = Class.create();
+
+Object.extend(Object.extend(Ajax.Updater.prototype, Ajax.Request.prototype), {
+ initialize: function(container, url, options) {
+ this.container = {
+ success: (container.success || container),
+ failure: (container.failure || (container.success ? null : container))
+ }
+
+ this.transport = Ajax.getTransport();
+ this.setOptions(options);
+
+ var onComplete = this.options.onComplete || Prototype.emptyFunction;
+ this.options.onComplete = (function(transport, param) {
+ this.updateContent();
+ onComplete(transport, param);
+ }).bind(this);
+
+ this.request(url);
+ },
+
+ updateContent: function() {
+ var receiver = this.container[this.success() ? 'success' : 'failure'];
+ var response = this.transport.responseText;
+
+ if (!this.options.evalScripts) response = response.stripScripts();
+
+ if (receiver = $(receiver)) {
+ if (this.options.insertion)
+ new this.options.insertion(receiver, response);
+ else
+ receiver.update(response);
+ }
+
+ if (this.success()) {
+ if (this.onComplete)
+ setTimeout(this.onComplete.bind(this), 10);
+ }
+ }
+});
+
+Ajax.PeriodicalUpdater = Class.create();
+Ajax.PeriodicalUpdater.prototype = Object.extend(new Ajax.Base(), {
+ initialize: function(container, url, options) {
+ this.setOptions(options);
+ this.onComplete = this.options.onComplete;
+
+ this.frequency = (this.options.frequency || 2);
+ this.decay = (this.options.decay || 1);
+
+ this.updater = {};
+ this.container = container;
+ this.url = url;
+
+ this.start();
+ },
+
+ start: function() {
+ this.options.onComplete = this.updateComplete.bind(this);
+ this.onTimerEvent();
+ },
+
+ stop: function() {
+ this.updater.options.onComplete = undefined;
+ clearTimeout(this.timer);
+ (this.onComplete || Prototype.emptyFunction).apply(this, arguments);
+ },
+
+ updateComplete: function(request) {
+ if (this.options.decay) {
+ this.decay = (request.responseText == this.lastText ?
+ this.decay * this.options.decay : 1);
+
+ this.lastText = request.responseText;
+ }
+ this.timer = setTimeout(this.onTimerEvent.bind(this),
+ this.decay * this.frequency * 1000);
+ },
+
+ onTimerEvent: function() {
+ this.updater = new Ajax.Updater(this.container, this.url, this.options);
+ }
+});
+function $(element) {
+ if (arguments.length > 1) {
+ for (var i = 0, elements = [], length = arguments.length; i < length; i++)
+ elements.push($(arguments[i]));
+ return elements;
+ }
+ if (typeof element == 'string')
+ element = document.getElementById(element);
+ return Element.extend(element);
+}
+
+if (Prototype.BrowserFeatures.XPath) {
+ document._getElementsByXPath = function(expression, parentElement) {
+ var results = [];
+ var query = document.evaluate(expression, $(parentElement) || document,
+ null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
+ for (var i = 0, length = query.snapshotLength; i < length; i++)
+ results.push(query.snapshotItem(i));
+ return results;
+ };
+
+ document.getElementsByClassName = function(className, parentElement) {
+ var q = ".//*[contains(concat(' ', @class, ' '), ' " + className + " ')]";
+ return document._getElementsByXPath(q, parentElement);
+ }
+
+} else document.getElementsByClassName = function(className, parentElement) {
+ var children = ($(parentElement) || document.body).getElementsByTagName('*');
+ var elements = [], child, pattern = new RegExp("(^|\\s)" + className + "(\\s|$)");
+ for (var i = 0, length = children.length; i < length; i++) {
+ child = children[i];
+ var elementClassName = child.className;
+ if (elementClassName.length == 0) continue;
+ if (elementClassName == className || elementClassName.match(pattern))
+ elements.push(Element.extend(child));
+ }
+ return elements;
+};
+
+/*--------------------------------------------------------------------------*/
+
+if (!window.Element) var Element = {};
+
+Element.extend = function(element) {
+ var F = Prototype.BrowserFeatures;
+ if (!element || !element.tagName || element.nodeType == 3 ||
+ element._extended || F.SpecificElementExtensions || element == window)
+ return element;
+
+ var methods = {}, tagName = element.tagName, cache = Element.extend.cache,
+ T = Element.Methods.ByTag;
+
+ // extend methods for all tags (Safari doesn't need this)
+ if (!F.ElementExtensions) {
+ Object.extend(methods, Element.Methods),
+ Object.extend(methods, Element.Methods.Simulated);
+ }
+
+ // extend methods for specific tags
+ if (T[tagName]) Object.extend(methods, T[tagName]);
+
+ for (var property in methods) {
+ var value = methods[property];
+ if (typeof value == 'function' && !(property in element))
+ element[property] = cache.findOrStore(value);
+ }
+
+ element._extended = Prototype.emptyFunction;
+ return element;
+};
+
+Element.extend.cache = {
+ findOrStore: function(value) {
+ return this[value] = this[value] || function() {
+ return value.apply(null, [this].concat($A(arguments)));
+ }
+ }
+};
+
+Element.Methods = {
+ visible: function(element) {
+ return $(element).style.display != 'none';
+ },
+
+ toggle: function(element) {
+ element = $(element);
+ Element[Element.visible(element) ? 'hide' : 'show'](element);
+ return element;
+ },
+
+ hide: function(element) {
+ $(element).style.display = 'none';
+ return element;
+
+ },
+
+ show: function(element) {
+ $(element).style.display = '';
+ return element;
+ },
+
+ remove: function(element) {
+ element = $(element);
+ element.parentNode.removeChild(element);
+ return element;
+ },
+
+ update: function(element, html) {
+ html = typeof html == 'undefined' ? '' : html.toString();
+ $(element).innerHTML = html.stripScripts();
+ setTimeout(function() {html.evalScripts()}, 10);
+ return element;
+ },
+
+ replace: function(element, html) {
+ element = $(element);
+ html = typeof html == 'undefined' ? '' : html.toString();
+ if (element.outerHTML) {
+ element.outerHTML = html.stripScripts();
+ } else {
+ var range = element.ownerDocument.createRange();
+ range.selectNodeContents(element);
+ element.parentNode.replaceChild(
+ range.createContextualFragment(html.stripScripts()), element);
+ }
+ setTimeout(function() {html.evalScripts()}, 10);
+ return element;
+ },
+
+ inspect: function(element) {
+ element = $(element);
+ var result = '<' + element.tagName.toLowerCase();
+ $H({'id': 'id', 'className': 'class'}).each(function(pair) {
+ var property = pair.first(), attribute = pair.last();
+ var value = (element[property] || '').toString();
+ if (value) result += ' ' + attribute + '=' + value.inspect(true);
+ });
+ return result + '>';
+ },
+
+ recursivelyCollect: function(element, property) {
+ element = $(element);
+ var elements = [];
+ while (element = element[property])
+ if (element.nodeType == 1)
+ elements.push(Element.extend(element));
+ return elements;
+ },
+
+ ancestors: function(element) {
+ return $(element).recursivelyCollect('parentNode');
+ },
+
+ descendants: function(element) {
+ return $A($(element).getElementsByTagName('*')).each(Element.extend);
+ },
+
+ firstDescendant: function(element) {
+ element = $(element).firstChild;
+ while (element && element.nodeType != 1) element = element.nextSibling;
+ return $(element);
+ },
+
+ immediateDescendants: function(element) {
+ if (!(element = $(element).firstChild)) return [];
+ while (element && element.nodeType != 1) element = element.nextSibling;
+ if (element) return [element].concat($(element).nextSiblings());
+ return [];
+ },
+
+ previousSiblings: function(element) {
+ return $(element).recursivelyCollect('previousSibling');
+ },
+
+ nextSiblings: function(element) {
+ return $(element).recursivelyCollect('nextSibling');
+ },
+
+ siblings: function(element) {
+ element = $(element);
+ return element.previousSiblings().reverse().concat(element.nextSiblings());
+ },
+
+ match: function(element, selector) {
+ if (typeof selector == 'string')
+ selector = new Selector(selector);
+ return selector.match($(element));
+ },
+
+ up: function(element, expression, index) {
+ element = $(element);
+ if (arguments.length == 1) return $(element.parentNode);
+ var ancestors = element.ancestors();
+ return expression ? Selector.findElement(ancestors, expression, index) :
+ ancestors[index || 0];
+ },
+
+ down: function(element, expression, index) {
+ element = $(element);
+ if (arguments.length == 1) return element.firstDescendant();
+ var descendants = element.descendants();
+ return expression ? Selector.findElement(descendants, expression, index) :
+ descendants[index || 0];
+ },
+
+ previous: function(element, expression, index) {
+ element = $(element);
+ if (arguments.length == 1) return $(Selector.handlers.previousElementSibling(element));
+ var previousSiblings = element.previousSiblings();
+ return expression ? Selector.findElement(previousSiblings, expression, index) :
+ previousSiblings[index || 0];
+ },
+
+ next: function(element, expression, index) {
+ element = $(element);
+ if (arguments.length == 1) return $(Selector.handlers.nextElementSibling(element));
+ var nextSiblings = element.nextSiblings();
+ return expression ? Selector.findElement(nextSiblings, expression, index) :
+ nextSiblings[index || 0];
+ },
+
+ getElementsBySelector: function() {
+ var args = $A(arguments), element = $(args.shift());
+ return Selector.findChildElements(element, args);
+ },
+
+ getElementsByClassName: function(element, className) {
+ return document.getElementsByClassName(className, element);
+ },
+
+ readAttribute: function(element, name) {
+ element = $(element);
+ if (Prototype.Browser.IE) {
+ if (!element.attributes) return null;
+ var t = Element._attributeTranslations;
+ if (t.values[name]) return t.values[name](element, name);
+ if (t.names[name]) name = t.names[name];
+ var attribute = element.attributes[name];
+ return attribute ? attribute.nodeValue : null;
+ }
+ return element.getAttribute(name);
+ },
+
+ getHeight: function(element) {
+ return $(element).getDimensions().height;
+ },
+
+ getWidth: function(element) {
+ return $(element).getDimensions().width;
+ },
+
+ classNames: function(element) {
+ return new Element.ClassNames(element);
+ },
+
+ hasClassName: function(element, className) {
+ if (!(element = $(element))) return;
+ var elementClassName = element.className;
+ if (elementClassName.length == 0) return false;
+ if (elementClassName == className ||
+ elementClassName.match(new RegExp("(^|\\s)" + className + "(\\s|$)")))
+ return true;
+ return false;
+ },
+
+ addClassName: function(element, className) {
+ if (!(element = $(element))) return;
+ Element.classNames(element).add(className);
+ return element;
+ },
+
+ removeClassName: function(element, className) {
+ if (!(element = $(element))) return;
+ Element.classNames(element).remove(className);
+ return element;
+ },
+
+ toggleClassName: function(element, className) {
+ if (!(element = $(element))) return;
+ Element.classNames(element)[element.hasClassName(className) ? 'remove' : 'add'](className);
+ return element;
+ },
+
+ observe: function() {
+ Event.observe.apply(Event, arguments);
+ return $A(arguments).first();
+ },
+
+ stopObserving: function() {
+ Event.stopObserving.apply(Event, arguments);
+ return $A(arguments).first();
+ },
+
+ // removes whitespace-only text node children
+ cleanWhitespace: function(element) {
+ element = $(element);
+ var node = element.firstChild;
+ while (node) {
+ var nextNode = node.nextSibling;
+ if (node.nodeType == 3 && !/\S/.test(node.nodeValue))
+ element.removeChild(node);
+ node = nextNode;
+ }
+ return element;
+ },
+
+ empty: function(element) {
+ return $(element).innerHTML.blank();
+ },
+
+ descendantOf: function(element, ancestor) {
+ element = $(element), ancestor = $(ancestor);
+ while (element = element.parentNode)
+ if (element == ancestor) return true;
+ return false;
+ },
+
+ scrollTo: function(element) {
+ element = $(element);
+ var pos = Position.cumulativeOffset(element);
+ window.scrollTo(pos[0], pos[1]);
+ return element;
+ },
+
+ getStyle: function(element, style) {
+ element = $(element);
+ style = style == 'float' ? 'cssFloat' : style.camelize();
+ var value = element.style[style];
+ if (!value) {
+ var css = document.defaultView.getComputedStyle(element, null);
+ value = css ? css[style] : null;
+ }
+ if (style == 'opacity') return value ? parseFloat(value) : 1.0;
+ return value == 'auto' ? null : value;
+ },
+
+ getOpacity: function(element) {
+ return $(element).getStyle('opacity');
+ },
+
+ setStyle: function(element, styles, camelized) {
+ element = $(element);
+ var elementStyle = element.style;
+
+ for (var property in styles)
+ if (property == 'opacity') element.setOpacity(styles[property])
+ else
+ elementStyle[(property == 'float' || property == 'cssFloat') ?
+ (elementStyle.styleFloat === undefined ? 'cssFloat' : 'styleFloat') :
+ (camelized ? property : property.camelize())] = styles[property];
+
+ return element;
+ },
+
+ setOpacity: function(element, value) {
+ element = $(element);
+ element.style.opacity = (value == 1 || value === '') ? '' :
+ (value < 0.00001) ? 0 : value;
+ return element;
+ },
+
+ getDimensions: function(element) {
+ element = $(element);
+ var display = $(element).getStyle('display');
+ if (display != 'none' && display != null) // Safari bug
+ return {width: element.offsetWidth, height: element.offsetHeight};
+
+ // All *Width and *Height properties give 0 on elements with display none,
+ // so enable the element temporarily
+ var els = element.style;
+ var originalVisibility = els.visibility;
+ var originalPosition = els.position;
+ var originalDisplay = els.display;
+ els.visibility = 'hidden';
+ els.position = 'absolute';
+ els.display = 'block';
+ var originalWidth = element.clientWidth;
+ var originalHeight = element.clientHeight;
+ els.display = originalDisplay;
+ els.position = originalPosition;
+ els.visibility = originalVisibility;
+ return {width: originalWidth, height: originalHeight};
+ },
+
+ makePositioned: function(element) {
+ element = $(element);
+ var pos = Element.getStyle(element, 'position');
+ if (pos == 'static' || !pos) {
+ element._madePositioned = true;
+ element.style.position = 'relative';
+ // Opera returns the offset relative to the positioning context, when an
+ // element is position relative but top and left have not been defined
+ if (window.opera) {
+ element.style.top = 0;
+ element.style.left = 0;
+ }
+ }
+ return element;
+ },
+
+ undoPositioned: function(element) {
+ element = $(element);
+ if (element._madePositioned) {
+ element._madePositioned = undefined;
+ element.style.position =
+ element.style.top =
+ element.style.left =
+ element.style.bottom =
+ element.style.right = '';
+ }
+ return element;
+ },
+
+ makeClipping: function(element) {
+ element = $(element);
+ if (element._overflow) return element;
+ element._overflow = element.style.overflow || 'auto';
+ if ((Element.getStyle(element, 'overflow') || 'visible') != 'hidden')
+ element.style.overflow = 'hidden';
+ return element;
+ },
+
+ undoClipping: function(element) {
+ element = $(element);
+ if (!element._overflow) return element;
+ element.style.overflow = element._overflow == 'auto' ? '' : element._overflow;
+ element._overflow = null;
+ return element;
+ }
+};
+
+Object.extend(Element.Methods, {
+ childOf: Element.Methods.descendantOf,
+ childElements: Element.Methods.immediateDescendants
+});
+
+if (Prototype.Browser.Opera) {
+ Element.Methods._getStyle = Element.Methods.getStyle;
+ Element.Methods.getStyle = function(element, style) {
+ switch(style) {
+ case 'left':
+ case 'top':
+ case 'right':
+ case 'bottom':
+ if (Element._getStyle(element, 'position') == 'static') return null;
+ default: return Element._getStyle(element, style);
+ }
+ };
+}
+else if (Prototype.Browser.IE) {
+ Element.Methods.getStyle = function(element, style) {
+ element = $(element);
+ style = (style == 'float' || style == 'cssFloat') ? 'styleFloat' : style.camelize();
+ var value = element.style[style];
+ if (!value && element.currentStyle) value = element.currentStyle[style];
+
+ if (style == 'opacity') {
+ if (value = (element.getStyle('filter') || '').match(/alpha\(opacity=(.*)\)/))
+ if (value[1]) return parseFloat(value[1]) / 100;
+ return 1.0;
+ }
+
+ if (value == 'auto') {
+ if ((style == 'width' || style == 'height') && (element.getStyle('display') != 'none'))
+ return element['offset'+style.capitalize()] + 'px';
+ return null;
+ }
+ return value;
+ };
+
+ Element.Methods.setOpacity = function(element, value) {
+ element = $(element);
+ var filter = element.getStyle('filter'), style = element.style;
+ if (value == 1 || value === '') {
+ style.filter = filter.replace(/alpha\([^\)]*\)/gi,'');
+ return element;
+ } else if (value < 0.00001) value = 0;
+ style.filter = filter.replace(/alpha\([^\)]*\)/gi, '') +
+ 'alpha(opacity=' + (value * 100) + ')';
+ return element;
+ };
+
+ // IE is missing .innerHTML support for TABLE-related elements
+ Element.Methods.update = function(element, html) {
+ element = $(element);
+ html = typeof html == 'undefined' ? '' : html.toString();
+ var tagName = element.tagName.toUpperCase();
+ if (['THEAD','TBODY','TR','TD'].include(tagName)) {
+ var div = document.createElement('div');
+ switch (tagName) {
+ case 'THEAD':
+ case 'TBODY':
+ div.innerHTML = '<table><tbody>' + html.stripScripts() + '</tbody></table>';
+ depth = 2;
+ break;
+ case 'TR':
+ div.innerHTML = '<table><tbody><tr>' + html.stripScripts() + '</tr></tbody></table>';
+ depth = 3;
+ break;
+ case 'TD':
+ div.innerHTML = '<table><tbody><tr><td>' + html.stripScripts() + '</td></tr></tbody></table>';
+ depth = 4;
+ }
+ $A(element.childNodes).each(function(node) { element.removeChild(node) });
+ depth.times(function() { div = div.firstChild });
+ $A(div.childNodes).each(function(node) { element.appendChild(node) });
+ } else {
+ element.innerHTML = html.stripScripts();
+ }
+ setTimeout(function() { html.evalScripts() }, 10);
+ return element;
+ }
+}
+else if (Prototype.Browser.Gecko) {
+ Element.Methods.setOpacity = function(element, value) {
+ element = $(element);
+ element.style.opacity = (value == 1) ? 0.999999 :
+ (value === '') ? '' : (value < 0.00001) ? 0 : value;
+ return element;
+ };
+}
+
+Element._attributeTranslations = {
+ names: {
+ colspan: "colSpan",
+ rowspan: "rowSpan",
+ valign: "vAlign",
+ datetime: "dateTime",
+ accesskey: "accessKey",
+ tabindex: "tabIndex",
+ enctype: "encType",
+ maxlength: "maxLength",
+ readonly: "readOnly",
+ longdesc: "longDesc"
+ },
+ values: {
+ _getAttr: function(element, attribute) {
+ return element.getAttribute(attribute, 2);
+ },
+ _flag: function(element, attribute) {
+ return $(element).hasAttribute(attribute) ? attribute : null;
+ },
+ style: function(element) {
+ return element.style.cssText.toLowerCase();
+ },
+ title: function(element) {
+ var node = element.getAttributeNode('title');
+ return node.specified ? node.nodeValue : null;
+ }
+ }
+};
+
+(function() {
+ Object.extend(this, {
+ href: this._getAttr,
+ src: this._getAttr,
+ type: this._getAttr,
+ disabled: this._flag,
+ checked: this._flag,
+ readonly: this._flag,
+ multiple: this._flag
+ });
+}).call(Element._attributeTranslations.values);
+
+Element.Methods.Simulated = {
+ hasAttribute: function(element, attribute) {
+ var t = Element._attributeTranslations, node;
+ attribute = t.names[attribute] || attribute;
+ node = $(element).getAttributeNode(attribute);
+ return node && node.specified;
+ }
+};
+
+Element.Methods.ByTag = {};
+
+Object.extend(Element, Element.Methods);
+
+if (!Prototype.BrowserFeatures.ElementExtensions &&
+ document.createElement('div').__proto__) {
+ window.HTMLElement = {};
+ window.HTMLElement.prototype = document.createElement('div').__proto__;
+ Prototype.BrowserFeatures.ElementExtensions = true;
+}
+
+Element.hasAttribute = function(element, attribute) {
+ if (element.hasAttribute) return element.hasAttribute(attribute);
+ return Element.Methods.Simulated.hasAttribute(element, attribute);
+};
+
+Element.addMethods = function(methods) {
+ var F = Prototype.BrowserFeatures, T = Element.Methods.ByTag;
+
+ if (!methods) {
+ Object.extend(Form, Form.Methods);
+ Object.extend(Form.Element, Form.Element.Methods);
+ Object.extend(Element.Methods.ByTag, {
+ "FORM": Object.clone(Form.Methods),
+ "INPUT": Object.clone(Form.Element.Methods),
+ "SELECT": Object.clone(Form.Element.Methods),
+ "TEXTAREA": Object.clone(Form.Element.Methods)
+ });
+ }
+
+ if (arguments.length == 2) {
+ var tagName = methods;
+ methods = arguments[1];
+ }
+
+ if (!tagName) Object.extend(Element.Methods, methods || {});
+ else {
+ if (tagName.constructor == Array) tagName.each(extend);
+ else extend(tagName);
+ }
+
+ function extend(tagName) {
+ tagName = tagName.toUpperCase();
+ if (!Element.Methods.ByTag[tagName])
+ Element.Methods.ByTag[tagName] = {};
+ Object.extend(Element.Methods.ByTag[tagName], methods);
+ }
+
+ function copy(methods, destination, onlyIfAbsent) {
+ onlyIfAbsent = onlyIfAbsent || false;
+ var cache = Element.extend.cache;
+ for (var property in methods) {
+ var value = methods[property];
+ if (!onlyIfAbsent || !(property in destination))
+ destination[property] = cache.findOrStore(value);
+ }
+ }
+
+ function findDOMClass(tagName) {
+ var klass;
+ var trans = {
+ "OPTGROUP": "OptGroup", "TEXTAREA": "TextArea", "P": "Paragraph",
+ "FIELDSET": "FieldSet", "UL": "UList", "OL": "OList", "DL": "DList",
+ "DIR": "Directory", "H1": "Heading", "H2": "Heading", "H3": "Heading",
+ "H4": "Heading", "H5": "Heading", "H6": "Heading", "Q": "Quote",
+ "INS": "Mod", "DEL": "Mod", "A": "Anchor", "IMG": "Image", "CAPTION":
+ "TableCaption", "COL": "TableCol", "COLGROUP": "TableCol", "THEAD":
+ "TableSection", "TFOOT": "TableSection", "TBODY": "TableSection", "TR":
+ "TableRow", "TH": "TableCell", "TD": "TableCell", "FRAMESET":
+ "FrameSet", "IFRAME": "IFrame"
+ };
+ if (trans[tagName]) klass = 'HTML' + trans[tagName] + 'Element';
+ if (window[klass]) return window[klass];
+ klass = 'HTML' + tagName + 'Element';
+ if (window[klass]) return window[klass];
+ klass = 'HTML' + tagName.capitalize() + 'Element';
+ if (window[klass]) return window[klass];
+
+ window[klass] = {};
+ window[klass].prototype = document.createElement(tagName).__proto__;
+ return window[klass];
+ }
+
+ if (F.ElementExtensions) {
+ copy(Element.Methods, HTMLElement.prototype);
+ copy(Element.Methods.Simulated, HTMLElement.prototype, true);
+ }
+
+ if (F.SpecificElementExtensions) {
+ for (var tag in Element.Methods.ByTag) {
+ var klass = findDOMClass(tag);
+ if (typeof klass == "undefined") continue;
+ copy(T[tag], klass.prototype);
+ }
+ }
+
+ Object.extend(Element, Element.Methods);
+ delete Element.ByTag;
+};
+
+var Toggle = { display: Element.toggle };
+
+/*--------------------------------------------------------------------------*/
+
+Abstract.Insertion = function(adjacency) {
+ this.adjacency = adjacency;
+}
+
+Abstract.Insertion.prototype = {
+ initialize: function(element, content) {
+ this.element = $(element);
+ this.content = content.stripScripts();
+
+ if (this.adjacency && this.element.insertAdjacentHTML) {
+ try {
+ this.element.insertAdjacentHTML(this.adjacency, this.content);
+ } catch (e) {
+ var tagName = this.element.tagName.toUpperCase();
+ if (['TBODY', 'TR'].include(tagName)) {
+ this.insertContent(this.contentFromAnonymousTable());
+ } else {
+ throw e;
+ }
+ }
+ } else {
+ this.range = this.element.ownerDocument.createRange();
+ if (this.initializeRange) this.initializeRange();
+ this.insertContent([this.range.createContextualFragment(this.content)]);
+ }
+
+ setTimeout(function() {content.evalScripts()}, 10);
+ },
+
+ contentFromAnonymousTable: function() {
+ var div = document.createElement('div');
+ div.innerHTML = '<table><tbody>' + this.content + '</tbody></table>';
+ return $A(div.childNodes[0].childNodes[0].childNodes);
+ }
+}
+
+var Insertion = new Object();
+
+Insertion.Before = Class.create();
+Insertion.Before.prototype = Object.extend(new Abstract.Insertion('beforeBegin'), {
+ initializeRange: function() {
+ this.range.setStartBefore(this.element);
+ },
+
+ insertContent: function(fragments) {
+ fragments.each((function(fragment) {
+ this.element.parentNode.insertBefore(fragment, this.element);
+ }).bind(this));
+ }
+});
+
+Insertion.Top = Class.create();
+Insertion.Top.prototype = Object.extend(new Abstract.Insertion('afterBegin'), {
+ initializeRange: function() {
+ this.range.selectNodeContents(this.element);
+ this.range.collapse(true);
+ },
+
+ insertContent: function(fragments) {
+ fragments.reverse(false).each((function(fragment) {
+ this.element.insertBefore(fragment, this.element.firstChild);
+ }).bind(this));
+ }
+});
+
+Insertion.Bottom = Class.create();
+Insertion.Bottom.prototype = Object.extend(new Abstract.Insertion('beforeEnd'), {
+ initializeRange: function() {
+ this.range.selectNodeContents(this.element);
+ this.range.collapse(this.element);
+ },
+
+ insertContent: function(fragments) {
+ fragments.each((function(fragment) {
+ this.element.appendChild(fragment);
+ }).bind(this));
+ }
+});
+
+Insertion.After = Class.create();
+Insertion.After.prototype = Object.extend(new Abstract.Insertion('afterEnd'), {
+ initializeRange: function() {
+ this.range.setStartAfter(this.element);
+ },
+
+ insertContent: function(fragments) {
+ fragments.each((function(fragment) {
+ this.element.parentNode.insertBefore(fragment,
+ this.element.nextSibling);
+ }).bind(this));
+ }
+});
+
+/*--------------------------------------------------------------------------*/
+
+Element.ClassNames = Class.create();
+Element.ClassNames.prototype = {
+ initialize: function(element) {
+ this.element = $(element);
+ },
+
+ _each: function(iterator) {
+ this.element.className.split(/\s+/).select(function(name) {
+ return name.length > 0;
+ })._each(iterator);
+ },
+
+ set: function(className) {
+ this.element.className = className;
+ },
+
+ add: function(classNameToAdd) {
+ if (this.include(classNameToAdd)) return;
+ this.set($A(this).concat(classNameToAdd).join(' '));
+ },
+
+ remove: function(classNameToRemove) {
+ if (!this.include(classNameToRemove)) return;
+ this.set($A(this).without(classNameToRemove).join(' '));
+ },
+
+ toString: function() {
+ return $A(this).join(' ');
+ }
+};
+
+Object.extend(Element.ClassNames.prototype, Enumerable);
+/* Portions of the Selector class are derived from Jack Slocum’s DomQuery,
+ * part of YUI-Ext version 0.40, distributed under the terms of an MIT-style
+ * license. Please see http://www.yui-ext.com/ for more information. */
+
+var Selector = Class.create();
+
+Selector.prototype = {
+ initialize: function(expression) {
+ this.expression = expression.strip();
+ this.compileMatcher();
+ },
+
+ compileMatcher: function() {
+ // Selectors with namespaced attributes can't use the XPath version
+ if (Prototype.BrowserFeatures.XPath && !(/\[[\w-]*?:/).test(this.expression))
+ return this.compileXPathMatcher();
+
+ var e = this.expression, ps = Selector.patterns, h = Selector.handlers,
+ c = Selector.criteria, le, p, m;
+
+ if (Selector._cache[e]) {
+ this.matcher = Selector._cache[e]; return;
+ }
+ this.matcher = ["this.matcher = function(root) {",
+ "var r = root, h = Selector.handlers, c = false, n;"];
+
+ while (e && le != e && (/\S/).test(e)) {
+ le = e;
+ for (var i in ps) {
+ p = ps[i];
+ if (m = e.match(p)) {
+ this.matcher.push(typeof c[i] == 'function' ? c[i](m) :
+ new Template(c[i]).evaluate(m));
+ e = e.replace(m[0], '');
+ break;
+ }
+ }
+ }
+
+ this.matcher.push("return h.unique(n);\n}");
+ eval(this.matcher.join('\n'));
+ Selector._cache[this.expression] = this.matcher;
+ },
+
+ compileXPathMatcher: function() {
+ var e = this.expression, ps = Selector.patterns,
+ x = Selector.xpath, le, m;
+
+ if (Selector._cache[e]) {
+ this.xpath = Selector._cache[e]; return;
+ }
+
+ this.matcher = ['.//*'];
+ while (e && le != e && (/\S/).test(e)) {
+ le = e;
+ for (var i in ps) {
+ if (m = e.match(ps[i])) {
+ this.matcher.push(typeof x[i] == 'function' ? x[i](m) :
+ new Template(x[i]).evaluate(m));
+ e = e.replace(m[0], '');
+ break;
+ }
+ }
+ }
+
+ this.xpath = this.matcher.join('');
+ Selector._cache[this.expression] = this.xpath;
+ },
+
+ findElements: function(root) {
+ root = root || document;
+ if (this.xpath) return document._getElementsByXPath(this.xpath, root);
+ return this.matcher(root);
+ },
+
+ match: function(element) {
+ return this.findElements(document).include(element);
+ },
+
+ toString: function() {
+ return this.expression;
+ },
+
+ inspect: function() {
+ return "#<Selector:" + this.expression.inspect() + ">";
+ }
+};
+
+Object.extend(Selector, {
+ _cache: {},
+
+ xpath: {
+ descendant: "//*",
+ child: "/*",
+ adjacent: "/following-sibling::*[1]",
+ laterSibling: '/following-sibling::*',
+ tagName: function(m) {
+ if (m[1] == '*') return '';
+ return "[local-name()='" + m[1].toLowerCase() +
+ "' or local-name()='" + m[1].toUpperCase() + "']";
+ },
+ className: "[contains(concat(' ', @class, ' '), ' #{1} ')]",
+ id: "[@id='#{1}']",
+ attrPresence: "[@#{1}]",
+ attr: function(m) {
+ m[3] = m[5] || m[6];
+ return new Template(Selector.xpath.operators[m[2]]).evaluate(m);
+ },
+ pseudo: function(m) {
+ var h = Selector.xpath.pseudos[m[1]];
+ if (!h) return '';
+ if (typeof h === 'function') return h(m);
+ return new Template(Selector.xpath.pseudos[m[1]]).evaluate(m);
+ },
+ operators: {
+ '=': "[@#{1}='#{3}']",
+ '!=': "[@#{1}!='#{3}']",
+ '^=': "[starts-with(@#{1}, '#{3}')]",
+ '$=': "[substring(@#{1}, (string-length(@#{1}) - string-length('#{3}') + 1))='#{3}']",
+ '*=': "[contains(@#{1}, '#{3}')]",
+ '~=': "[contains(concat(' ', @#{1}, ' '), ' #{3} ')]",
+ '|=': "[contains(concat('-', @#{1}, '-'), '-#{3}-')]"
+ },
+ pseudos: {
+ 'first-child': '[not(preceding-sibling::*)]',
+ 'last-child': '[not(following-sibling::*)]',
+ 'only-child': '[not(preceding-sibling::* or following-sibling::*)]',
+ 'empty': "[count(*) = 0 and (count(text()) = 0 or translate(text(), ' \t\r\n', '') = '')]",
+ 'checked': "[@checked]",
+ 'disabled': "[@disabled]",
+ 'enabled': "[not(@disabled)]",
+ 'not': function(m) {
+ var e = m[6], p = Selector.patterns,
+ x = Selector.xpath, le, m, v;
+
+ var exclusion = [];
+ while (e && le != e && (/\S/).test(e)) {
+ le = e;
+ for (var i in p) {
+ if (m = e.match(p[i])) {
+ v = typeof x[i] == 'function' ? x[i](m) : new Template(x[i]).evaluate(m);
+ exclusion.push("(" + v.substring(1, v.length - 1) + ")");
+ e = e.replace(m[0], '');
+ break;
+ }
+ }
+ }
+ return "[not(" + exclusion.join(" and ") + ")]";
+ },
+ 'nth-child': function(m) {
+ return Selector.xpath.pseudos.nth("(count(./preceding-sibling::*) + 1) ", m);
+ },
+ 'nth-last-child': function(m) {
+ return Selector.xpath.pseudos.nth("(count(./following-sibling::*) + 1) ", m);
+ },
+ 'nth-of-type': function(m) {
+ return Selector.xpath.pseudos.nth("position() ", m);
+ },
+ 'nth-last-of-type': function(m) {
+ return Selector.xpath.pseudos.nth("(last() + 1 - position()) ", m);
+ },
+ 'first-of-type': function(m) {
+ m[6] = "1"; return Selector.xpath.pseudos['nth-of-type'](m);
+ },
+ 'last-of-type': function(m) {
+ m[6] = "1"; return Selector.xpath.pseudos['nth-last-of-type'](m);
+ },
+ 'only-of-type': function(m) {
+ var p = Selector.xpath.pseudos; return p['first-of-type'](m) + p['last-of-type'](m);
+ },
+ nth: function(fragment, m) {
+ var mm, formula = m[6], predicate;
+ if (formula == 'even') formula = '2n+0';
+ if (formula == 'odd') formula = '2n+1';
+ if (mm = formula.match(/^(\d+)$/)) // digit only
+ return '[' + fragment + "= " + mm[1] + ']';
+ if (mm = formula.match(/^(-?\d*)?n(([+-])(\d+))?/)) { // an+b
+ if (mm[1] == "-") mm[1] = -1;
+ var a = mm[1] ? Number(mm[1]) : 1;
+ var b = mm[2] ? Number(mm[2]) : 0;
+ predicate = "[((#{fragment} - #{b}) mod #{a} = 0) and " +
+ "((#{fragment} - #{b}) div #{a} >= 0)]";
+ return new Template(predicate).evaluate({
+ fragment: fragment, a: a, b: b });
+ }
+ }
+ }
+ },
+
+ criteria: {
+ tagName: 'n = h.tagName(n, r, "#{1}", c); c = false;',
+ className: 'n = h.className(n, r, "#{1}", c); c = false;',
+ id: 'n = h.id(n, r, "#{1}", c); c = false;',
+ attrPresence: 'n = h.attrPresence(n, r, "#{1}"); c = false;',
+ attr: function(m) {
+ m[3] = (m[5] || m[6]);
+ return new Template('n = h.attr(n, r, "#{1}", "#{3}", "#{2}"); c = false;').evaluate(m);
+ },
+ pseudo: function(m) {
+ if (m[6]) m[6] = m[6].replace(/"/g, '\\"');
+ return new Template('n = h.pseudo(n, "#{1}", "#{6}", r, c); c = false;').evaluate(m);
+ },
+ descendant: 'c = "descendant";',
+ child: 'c = "child";',
+ adjacent: 'c = "adjacent";',
+ laterSibling: 'c = "laterSibling";'
+ },
+
+ patterns: {
+ // combinators must be listed first
+ // (and descendant needs to be last combinator)
+ laterSibling: /^\s*~\s*/,
+ child: /^\s*>\s*/,
+ adjacent: /^\s*\+\s*/,
+ descendant: /^\s/,
+
+ // selectors follow
+ tagName: /^\s*(\*|[\w\-]+)(\b|$)?/,
+ id: /^#([\w\-\*]+)(\b|$)/,
+ className: /^\.([\w\-\*]+)(\b|$)/,
+ pseudo: /^:((first|last|nth|nth-last|only)(-child|-of-type)|empty|checked|(en|dis)abled|not)(\((.*?)\))?(\b|$|\s|(?=:))/,
+ attrPresence: /^\[([\w]+)\]/,
+ attr: /\[((?:[\w-]*:)?[\w-]+)\s*(?:([!^$*~|]?=)\s*((['"])([^\]]*?)\4|([^'"][^\]]*?)))?\]/ //"
+ },
+
+ handlers: {
+ // UTILITY FUNCTIONS
+ // joins two collections
+ concat: function(a, b) {
+ for (var i = 0, node; node = b[i]; i++)
+ a.push(node);
+ return a;
+ },
+
+ // marks an array of nodes for counting
+ mark: function(nodes) {
+ for (var i = 0, node; node = nodes[i]; i++)
+ node._counted = true;
+ return nodes;
+ },
+
+ unmark: function(nodes) {
+ for (var i = 0, node; node = nodes[i]; i++)
+ node._counted = undefined;
+ return nodes;
+ },
+
+ // mark each child node with its position (for nth calls)
+ // "ofType" flag indicates whether we're indexing for nth-of-type
+ // rather than nth-child
+ index: function(parentNode, reverse, ofType) {
+ parentNode._counted = true;
+ if (reverse) {
+ for (var nodes = parentNode.childNodes, i = nodes.length - 1, j = 1; i >= 0; i--) {
+ node = nodes[i];
+ if (node.nodeType == 1 && (!ofType || node._counted)) node.nodeIndex = j++;
+ }
+ } else {
+ for (var i = 0, j = 1, nodes = parentNode.childNodes; node = nodes[i]; i++)
+ if (node.nodeType == 1 && (!ofType || node._counted)) node.nodeIndex = j++;
+ }
+ },
+
+ // filters out duplicates and extends all nodes
+ unique: function(nodes) {
+ if (nodes.length == 0) return nodes;
+ var results = [], n;
+ for (var i = 0, l = nodes.length; i < l; i++)
+ if (!(n = nodes[i])._counted) {
+ n._counted = true;
+ results.push(Element.extend(n));
+ }
+ return Selector.handlers.unmark(results);
+ },
+
+ // COMBINATOR FUNCTIONS
+ descendant: function(nodes) {
+ var h = Selector.handlers;
+ for (var i = 0, results = [], node; node = nodes[i]; i++)
+ h.concat(results, node.getElementsByTagName('*'));
+ return results;
+ },
+
+ child: function(nodes) {
+ var h = Selector.handlers;
+ for (var i = 0, results = [], node; node = nodes[i]; i++) {
+ for (var j = 0, children = [], child; child = node.childNodes[j]; j++)
+ if (child.nodeType == 1 && child.tagName != '!') results.push(child);
+ }
+ return results;
+ },
+
+ adjacent: function(nodes) {
+ for (var i = 0, results = [], node; node = nodes[i]; i++) {
+ var next = this.nextElementSibling(node);
+ if (next) results.push(next);
+ }
+ return results;
+ },
+
+ laterSibling: function(nodes) {
+ var h = Selector.handlers;
+ for (var i = 0, results = [], node; node = nodes[i]; i++)
+ h.concat(results, Element.nextSiblings(node));
+ return results;
+ },
+
+ nextElementSibling: function(node) {
+ while (node = node.nextSibling)
+ if (node.nodeType == 1) return node;
+ return null;
+ },
+
+ previousElementSibling: function(node) {
+ while (node = node.previousSibling)
+ if (node.nodeType == 1) return node;
+ return null;
+ },
+
+ // TOKEN FUNCTIONS
+ tagName: function(nodes, root, tagName, combinator) {
+ tagName = tagName.toUpperCase();
+ var results = [], h = Selector.handlers;
+ if (nodes) {
+ if (combinator) {
+ // fastlane for ordinary descendant combinators
+ if (combinator == "descendant") {
+ for (var i = 0, node; node = nodes[i]; i++)
+ h.concat(results, node.getElementsByTagName(tagName));
+ return results;
+ } else nodes = this[combinator](nodes);
+ if (tagName == "*") return nodes;
+ }
+ for (var i = 0, node; node = nodes[i]; i++)
+ if (node.tagName.toUpperCase() == tagName) results.push(node);
+ return results;
+ } else return root.getElementsByTagName(tagName);
+ },
+
+ id: function(nodes, root, id, combinator) {
+ var targetNode = $(id), h = Selector.handlers;
+ if (!nodes && root == document) return targetNode ? [targetNode] : [];
+ if (nodes) {
+ if (combinator) {
+ if (combinator == 'child') {
+ for (var i = 0, node; node = nodes[i]; i++)
+ if (targetNode.parentNode == node) return [targetNode];
+ } else if (combinator == 'descendant') {
+ for (var i = 0, node; node = nodes[i]; i++)
+ if (Element.descendantOf(targetNode, node)) return [targetNode];
+ } else if (combinator == 'adjacent') {
+ for (var i = 0, node; node = nodes[i]; i++)
+ if (Selector.handlers.previousElementSibling(targetNode) == node)
+ return [targetNode];
+ } else nodes = h[combinator](nodes);
+ }
+ for (var i = 0, node; node = nodes[i]; i++)
+ if (node == targetNode) return [targetNode];
+ return [];
+ }
+ return (targetNode && Element.descendantOf(targetNode, root)) ? [targetNode] : [];
+ },
+
+ className: function(nodes, root, className, combinator) {
+ if (nodes && combinator) nodes = this[combinator](nodes);
+ return Selector.handlers.byClassName(nodes, root, className);
+ },
+
+ byClassName: function(nodes, root, className) {
+ if (!nodes) nodes = Selector.handlers.descendant([root]);
+ var needle = ' ' + className + ' ';
+ for (var i = 0, results = [], node, nodeClassName; node = nodes[i]; i++) {
+ nodeClassName = node.className;
+ if (nodeClassName.length == 0) continue;
+ if (nodeClassName == className || (' ' + nodeClassName + ' ').include(needle))
+ results.push(node);
+ }
+ return results;
+ },
+
+ attrPresence: function(nodes, root, attr) {
+ var results = [];
+ for (var i = 0, node; node = nodes[i]; i++)
+ if (Element.hasAttribute(node, attr)) results.push(node);
+ return results;
+ },
+
+ attr: function(nodes, root, attr, value, operator) {
+ if (!nodes) nodes = root.getElementsByTagName("*");
+ var handler = Selector.operators[operator], results = [];
+ for (var i = 0, node; node = nodes[i]; i++) {
+ var nodeValue = Element.readAttribute(node, attr);
+ if (nodeValue === null) continue;
+ if (handler(nodeValue, value)) results.push(node);
+ }
+ return results;
+ },
+
+ pseudo: function(nodes, name, value, root, combinator) {
+ if (nodes && combinator) nodes = this[combinator](nodes);
+ if (!nodes) nodes = root.getElementsByTagName("*");
+ return Selector.pseudos[name](nodes, value, root);
+ }
+ },
+
+ pseudos: {
+ 'first-child': function(nodes, value, root) {
+ for (var i = 0, results = [], node; node = nodes[i]; i++) {
+ if (Selector.handlers.previousElementSibling(node)) continue;
+ results.push(node);
+ }
+ return results;
+ },
+ 'last-child': function(nodes, value, root) {
+ for (var i = 0, results = [], node; node = nodes[i]; i++) {
+ if (Selector.handlers.nextElementSibling(node)) continue;
+ results.push(node);
+ }
+ return results;
+ },
+ 'only-child': function(nodes, value, root) {
+ var h = Selector.handlers;
+ for (var i = 0, results = [], node; node = nodes[i]; i++)
+ if (!h.previousElementSibling(node) && !h.nextElementSibling(node))
+ results.push(node);
+ return results;
+ },
+ 'nth-child': function(nodes, formula, root) {
+ return Selector.pseudos.nth(nodes, formula, root);
+ },
+ 'nth-last-child': function(nodes, formula, root) {
+ return Selector.pseudos.nth(nodes, formula, root, true);
+ },
+ 'nth-of-type': function(nodes, formula, root) {
+ return Selector.pseudos.nth(nodes, formula, root, false, true);
+ },
+ 'nth-last-of-type': function(nodes, formula, root) {
+ return Selector.pseudos.nth(nodes, formula, root, true, true);
+ },
+ 'first-of-type': function(nodes, formula, root) {
+ return Selector.pseudos.nth(nodes, "1", root, false, true);
+ },
+ 'last-of-type': function(nodes, formula, root) {
+ return Selector.pseudos.nth(nodes, "1", root, true, true);
+ },
+ 'only-of-type': function(nodes, formula, root) {
+ var p = Selector.pseudos;
+ return p['last-of-type'](p['first-of-type'](nodes, formula, root), formula, root);
+ },
+
+ // handles the an+b logic
+ getIndices: function(a, b, total) {
+ if (a == 0) return b > 0 ? [b] : [];
+ return $R(1, total).inject([], function(memo, i) {
+ if (0 == (i - b) % a && (i - b) / a >= 0) memo.push(i);
+ return memo;
+ });
+ },
+
+ // handles nth(-last)-child, nth(-last)-of-type, and (first|last)-of-type
+ nth: function(nodes, formula, root, reverse, ofType) {
+ if (nodes.length == 0) return [];
+ if (formula == 'even') formula = '2n+0';
+ if (formula == 'odd') formula = '2n+1';
+ var h = Selector.handlers, results = [], indexed = [], m;
+ h.mark(nodes);
+ for (var i = 0, node; node = nodes[i]; i++) {
+ if (!node.parentNode._counted) {
+ h.index(node.parentNode, reverse, ofType);
+ indexed.push(node.parentNode);
+ }
+ }
+ if (formula.match(/^\d+$/)) { // just a number
+ formula = Number(formula);
+ for (var i = 0, node; node = nodes[i]; i++)
+ if (node.nodeIndex == formula) results.push(node);
+ } else if (m = formula.match(/^(-?\d*)?n(([+-])(\d+))?/)) { // an+b
+ if (m[1] == "-") m[1] = -1;
+ var a = m[1] ? Number(m[1]) : 1;
+ var b = m[2] ? Number(m[2]) : 0;
+ var indices = Selector.pseudos.getIndices(a, b, nodes.length);
+ for (var i = 0, node, l = indices.length; node = nodes[i]; i++) {
+ for (var j = 0; j < l; j++)
+ if (node.nodeIndex == indices[j]) results.push(node);
+ }
+ }
+ h.unmark(nodes);
+ h.unmark(indexed);
+ return results;
+ },
+
+ 'empty': function(nodes, value, root) {
+ for (var i = 0, results = [], node; node = nodes[i]; i++) {
+ // IE treats comments as element nodes
+ if (node.tagName == '!' || (node.firstChild && !node.innerHTML.match(/^\s*$/))) continue;
+ results.push(node);
+ }
+ return results;
+ },
+
+ 'not': function(nodes, selector, root) {
+ var h = Selector.handlers, selectorType, m;
+ var exclusions = new Selector(selector).findElements(root);
+ h.mark(exclusions);
+ for (var i = 0, results = [], node; node = nodes[i]; i++)
+ if (!node._counted) results.push(node);
+ h.unmark(exclusions);
+ return results;
+ },
+
+ 'enabled': function(nodes, value, root) {
+ for (var i = 0, results = [], node; node = nodes[i]; i++)
+ if (!node.disabled) results.push(node);
+ return results;
+ },
+
+ 'disabled': function(nodes, value, root) {
+ for (var i = 0, results = [], node; node = nodes[i]; i++)
+ if (node.disabled) results.push(node);
+ return results;
+ },
+
+ 'checked': function(nodes, value, root) {
+ for (var i = 0, results = [], node; node = nodes[i]; i++)
+ if (node.checked) results.push(node);
+ return results;
+ }
+ },
+
+ operators: {
+ '=': function(nv, v) { return nv == v; },
+ '!=': function(nv, v) { return nv != v; },
+ '^=': function(nv, v) { return nv.startsWith(v); },
+ '$=': function(nv, v) { return nv.endsWith(v); },
+ '*=': function(nv, v) { return nv.include(v); },
+ '~=': function(nv, v) { return (' ' + nv + ' ').include(' ' + v + ' '); },
+ '|=': function(nv, v) { return ('-' + nv.toUpperCase() + '-').include('-' + v.toUpperCase() + '-'); }
+ },
+
+ matchElements: function(elements, expression) {
+ var matches = new Selector(expression).findElements(), h = Selector.handlers;
+ h.mark(matches);
+ for (var i = 0, results = [], element; element = elements[i]; i++)
+ if (element._counted) results.push(element);
+ h.unmark(matches);
+ return results;
+ },
+
+ findElement: function(elements, expression, index) {
+ if (typeof expression == 'number') {
+ index = expression; expression = false;
+ }
+ return Selector.matchElements(elements, expression || '*')[index || 0];
+ },
+
+ findChildElements: function(element, expressions) {
+ var exprs = expressions.join(','), expressions = [];
+ exprs.scan(/(([\w#:.~>+()\s-]+|\*|\[.*?\])+)\s*(,|$)/, function(m) {
+ expressions.push(m[1].strip());
+ });
+ var results = [], h = Selector.handlers;
+ for (var i = 0, l = expressions.length, selector; i < l; i++) {
+ selector = new Selector(expressions[i].strip());
+ h.concat(results, selector.findElements(element));
+ }
+ return (l > 1) ? h.unique(results) : results;
+ }
+});
+
+function $$() {
+ return Selector.findChildElements(document, $A(arguments));
+}
+var Form = {
+ reset: function(form) {
+ $(form).reset();
+ return form;
+ },
+
+ serializeElements: function(elements, getHash) {
+ var data = elements.inject({}, function(result, element) {
+ if (!element.disabled && element.name) {
+ var key = element.name, value = $(element).getValue();
+ if (value != null) {
+ if (key in result) {
+ if (result[key].constructor != Array) result[key] = [result[key]];
+ result[key].push(value);
+ }
+ else result[key] = value;
+ }
+ }
+ return result;
+ });
+
+ return getHash ? data : Hash.toQueryString(data);
+ }
+};
+
+Form.Methods = {
+ serialize: function(form, getHash) {
+ return Form.serializeElements(Form.getElements(form), getHash);
+ },
+
+ getElements: function(form) {
+ return $A($(form).getElementsByTagName('*')).inject([],
+ function(elements, child) {
+ if (Form.Element.Serializers[child.tagName.toLowerCase()])
+ elements.push(Element.extend(child));
+ return elements;
+ }
+ );
+ },
+
+ getInputs: function(form, typeName, name) {
+ form = $(form);
+ var inputs = form.getElementsByTagName('input');
+
+ if (!typeName && !name) return $A(inputs).map(Element.extend);
+
+ for (var i = 0, matchingInputs = [], length = inputs.length; i < length; i++) {
+ var input = inputs[i];
+ if ((typeName && input.type != typeName) || (name && input.name != name))
+ continue;
+ matchingInputs.push(Element.extend(input));
+ }
+
+ return matchingInputs;
+ },
+
+ disable: function(form) {
+ form = $(form);
+ Form.getElements(form).invoke('disable');
+ return form;
+ },
+
+ enable: function(form) {
+ form = $(form);
+ Form.getElements(form).invoke('enable');
+ return form;
+ },
+
+ findFirstElement: function(form) {
+ return $(form).getElements().find(function(element) {
+ return element.type != 'hidden' && !element.disabled &&
+ ['input', 'select', 'textarea'].include(element.tagName.toLowerCase());
+ });
+ },
+
+ focusFirstElement: function(form) {
+ form = $(form);
+ form.findFirstElement().activate();
+ return form;
+ },
+
+ request: function(form, options) {
+ form = $(form), options = Object.clone(options || {});
+
+ var params = options.parameters;
+ options.parameters = form.serialize(true);
+
+ if (params) {
+ if (typeof params == 'string') params = params.toQueryParams();
+ Object.extend(options.parameters, params);
+ }
+
+ if (form.hasAttribute('method') && !options.method)
+ options.method = form.method;
+
+ return new Ajax.Request(form.readAttribute('action'), options);
+ }
+}
+
+/*--------------------------------------------------------------------------*/
+
+Form.Element = {
+ focus: function(element) {
+ $(element).focus();
+ return element;
+ },
+
+ select: function(element) {
+ $(element).select();
+ return element;
+ }
+}
+
+Form.Element.Methods = {
+ serialize: function(element) {
+ element = $(element);
+ if (!element.disabled && element.name) {
+ var value = element.getValue();
+ if (value != undefined) {
+ var pair = {};
+ pair[element.name] = value;
+ return Hash.toQueryString(pair);
+ }
+ }
+ return '';
+ },
+
+ getValue: function(element) {
+ element = $(element);
+ var method = element.tagName.toLowerCase();
+ return Form.Element.Serializers[method](element);
+ },
+
+ clear: function(element) {
+ $(element).value = '';
+ return element;
+ },
+
+ present: function(element) {
+ return $(element).value != '';
+ },
+
+ activate: function(element) {
+ element = $(element);
+ try {
+ element.focus();
+ if (element.select && (element.tagName.toLowerCase() != 'input' ||
+ !['button', 'reset', 'submit'].include(element.type)))
+ element.select();
+ } catch (e) {}
+ return element;
+ },
+
+ disable: function(element) {
+ element = $(element);
+ element.blur();
+ element.disabled = true;
+ return element;
+ },
+
+ enable: function(element) {
+ element = $(element);
+ element.disabled = false;
+ return element;
+ }
+}
+
+/*--------------------------------------------------------------------------*/
+
+var Field = Form.Element;
+var $F = Form.Element.Methods.getValue;
+
+/*--------------------------------------------------------------------------*/
+
+Form.Element.Serializers = {
+ input: function(element) {
+ switch (element.type.toLowerCase()) {
+ case 'checkbox':
+ case 'radio':
+ return Form.Element.Serializers.inputSelector(element);
+ default:
+ return Form.Element.Serializers.textarea(element);
+ }
+ },
+
+ inputSelector: function(element) {
+ return element.checked ? element.value : null;
+ },
+
+ textarea: function(element) {
+ return element.value;
+ },
+
+ select: function(element) {
+ return this[element.type == 'select-one' ?
+ 'selectOne' : 'selectMany'](element);
+ },
+
+ selectOne: function(element) {
+ var index = element.selectedIndex;
+ return index >= 0 ? this.optionValue(element.options[index]) : null;
+ },
+
+ selectMany: function(element) {
+ var values, length = element.length;
+ if (!length) return null;
+
+ for (var i = 0, values = []; i < length; i++) {
+ var opt = element.options[i];
+ if (opt.selected) values.push(this.optionValue(opt));
+ }
+ return values;
+ },
+
+ optionValue: function(opt) {
+ // extend element because hasAttribute may not be native
+ return Element.extend(opt).hasAttribute('value') ? opt.value : opt.text;
+ }
+}
+
+/*--------------------------------------------------------------------------*/
+
+Abstract.TimedObserver = function() {}
+Abstract.TimedObserver.prototype = {
+ initialize: function(element, frequency, callback) {
+ this.frequency = frequency;
+ this.element = $(element);
+ this.callback = callback;
+
+ this.lastValue = this.getValue();
+ this.registerCallback();
+ },
+
+ registerCallback: function() {
+ setInterval(this.onTimerEvent.bind(this), this.frequency * 1000);
+ },
+
+ onTimerEvent: function() {
+ var value = this.getValue();
+ var changed = ('string' == typeof this.lastValue && 'string' == typeof value
+ ? this.lastValue != value : String(this.lastValue) != String(value));
+ if (changed) {
+ this.callback(this.element, value);
+ this.lastValue = value;
+ }
+ }
+}
+
+Form.Element.Observer = Class.create();
+Form.Element.Observer.prototype = Object.extend(new Abstract.TimedObserver(), {
+ getValue: function() {
+ return Form.Element.getValue(this.element);
+ }
+});
+
+Form.Observer = Class.create();
+Form.Observer.prototype = Object.extend(new Abstract.TimedObserver(), {
+ getValue: function() {
+ return Form.serialize(this.element);
+ }
+});
+
+/*--------------------------------------------------------------------------*/
+
+Abstract.EventObserver = function() {}
+Abstract.EventObserver.prototype = {
+ initialize: function(element, callback) {
+ this.element = $(element);
+ this.callback = callback;
+
+ this.lastValue = this.getValue();
+ if (this.element.tagName.toLowerCase() == 'form')
+ this.registerFormCallbacks();
+ else
+ this.registerCallback(this.element);
+ },
+
+ onElementEvent: function() {
+ var value = this.getValue();
+ if (this.lastValue != value) {
+ this.callback(this.element, value);
+ this.lastValue = value;
+ }
+ },
+
+ registerFormCallbacks: function() {
+ Form.getElements(this.element).each(this.registerCallback.bind(this));
+ },
+
+ registerCallback: function(element) {
+ if (element.type) {
+ switch (element.type.toLowerCase()) {
+ case 'checkbox':
+ case 'radio':
+ Event.observe(element, 'click', this.onElementEvent.bind(this));
+ break;
+ default:
+ Event.observe(element, 'change', this.onElementEvent.bind(this));
+ break;
+ }
+ }
+ }
+}
+
+Form.Element.EventObserver = Class.create();
+Form.Element.EventObserver.prototype = Object.extend(new Abstract.EventObserver(), {
+ getValue: function() {
+ return Form.Element.getValue(this.element);
+ }
+});
+
+Form.EventObserver = Class.create();
+Form.EventObserver.prototype = Object.extend(new Abstract.EventObserver(), {
+ getValue: function() {
+ return Form.serialize(this.element);
+ }
+});
+if (!window.Event) {
+ var Event = new Object();
+}
+
+Object.extend(Event, {
+ KEY_BACKSPACE: 8,
+ KEY_TAB: 9,
+ KEY_RETURN: 13,
+ KEY_ESC: 27,
+ KEY_LEFT: 37,
+ KEY_UP: 38,
+ KEY_RIGHT: 39,
+ KEY_DOWN: 40,
+ KEY_DELETE: 46,
+ KEY_HOME: 36,
+ KEY_END: 35,
+ KEY_PAGEUP: 33,
+ KEY_PAGEDOWN: 34,
+
+ element: function(event) {
+ return $(event.target || event.srcElement);
+ },
+
+ isLeftClick: function(event) {
+ return (((event.which) && (event.which == 1)) ||
+ ((event.button) && (event.button == 1)));
+ },
+
+ pointerX: function(event) {
+ return event.pageX || (event.clientX +
+ (document.documentElement.scrollLeft || document.body.scrollLeft));
+ },
+
+ pointerY: function(event) {
+ return event.pageY || (event.clientY +
+ (document.documentElement.scrollTop || document.body.scrollTop));
+ },
+
+ stop: function(event) {
+ if (event.preventDefault) {
+ event.preventDefault();
+ event.stopPropagation();
+ } else {
+ event.returnValue = false;
+ event.cancelBubble = true;
+ }
+ },
+
+ // find the first node with the given tagName, starting from the
+ // node the event was triggered on; traverses the DOM upwards
+ findElement: function(event, tagName) {
+ var element = Event.element(event);
+ while (element.parentNode && (!element.tagName ||
+ (element.tagName.toUpperCase() != tagName.toUpperCase())))
+ element = element.parentNode;
+ return element;
+ },
+
+ observers: false,
+
+ _observeAndCache: function(element, name, observer, useCapture) {
+ if (!this.observers) this.observers = [];
+ if (element.addEventListener) {
+ this.observers.push([element, name, observer, useCapture]);
+ element.addEventListener(name, observer, useCapture);
+ } else if (element.attachEvent) {
+ this.observers.push([element, name, observer, useCapture]);
+ element.attachEvent('on' + name, observer);
+ }
+ },
+
+ unloadCache: function() {
+ if (!Event.observers) return;
+ for (var i = 0, length = Event.observers.length; i < length; i++) {
+ Event.stopObserving.apply(this, Event.observers[i]);
+ Event.observers[i][0] = null;
+ }
+ Event.observers = false;
+ },
+
+ observe: function(element, name, observer, useCapture) {
+ element = $(element);
+ useCapture = useCapture || false;
+
+ if (name == 'keypress' &&
+ (Prototype.Browser.WebKit || element.attachEvent))
+ name = 'keydown';
+
+ Event._observeAndCache(element, name, observer, useCapture);
+ },
+
+ stopObserving: function(element, name, observer, useCapture) {
+ element = $(element);
+ useCapture = useCapture || false;
+
+ if (name == 'keypress' &&
+ (Prototype.Browser.WebKit || element.attachEvent))
+ name = 'keydown';
+
+ if (element.removeEventListener) {
+ element.removeEventListener(name, observer, useCapture);
+ } else if (element.detachEvent) {
+ try {
+ element.detachEvent('on' + name, observer);
+ } catch (e) {}
+ }
+ }
+});
+
+/* prevent memory leaks in IE */
+if (Prototype.Browser.IE)
+ Event.observe(window, 'unload', Event.unloadCache, false);
+var Position = {
+ // set to true if needed, warning: firefox performance problems
+ // NOT neeeded for page scrolling, only if draggable contained in
+ // scrollable elements
+ includeScrollOffsets: false,
+
+ // must be called before calling withinIncludingScrolloffset, every time the
+ // page is scrolled
+ prepare: function() {
+ this.deltaX = window.pageXOffset
+ || document.documentElement.scrollLeft
+ || document.body.scrollLeft
+ || 0;
+ this.deltaY = window.pageYOffset
+ || document.documentElement.scrollTop
+ || document.body.scrollTop
+ || 0;
+ },
+
+ realOffset: function(element) {
+ var valueT = 0, valueL = 0;
+ do {
+ valueT += element.scrollTop || 0;
+ valueL += element.scrollLeft || 0;
+ element = element.parentNode;
+ } while (element);
+ return [valueL, valueT];
+ },
+
+ cumulativeOffset: function(element) {
+ var valueT = 0, valueL = 0;
+ do {
+ valueT += element.offsetTop || 0;
+ valueL += element.offsetLeft || 0;
+ element = element.offsetParent;
+ } while (element);
+ return [valueL, valueT];
+ },
+
+ positionedOffset: function(element) {
+ var valueT = 0, valueL = 0;
+ do {
+ valueT += element.offsetTop || 0;
+ valueL += element.offsetLeft || 0;
+ element = element.offsetParent;
+ if (element) {
+ if(element.tagName=='BODY') break;
+ var p = Element.getStyle(element, 'position');
+ if (p == 'relative' || p == 'absolute') break;
+ }
+ } while (element);
+ return [valueL, valueT];
+ },
+
+ offsetParent: function(element) {
+ if (element.offsetParent) return element.offsetParent;
+ if (element == document.body) return element;
+
+ while ((element = element.parentNode) && element != document.body)
+ if (Element.getStyle(element, 'position') != 'static')
+ return element;
+
+ return document.body;
+ },
+
+ // caches x/y coordinate pair to use with overlap
+ within: function(element, x, y) {
+ if (this.includeScrollOffsets)
+ return this.withinIncludingScrolloffsets(element, x, y);
+ this.xcomp = x;
+ this.ycomp = y;
+ this.offset = this.cumulativeOffset(element);
+
+ return (y >= this.offset[1] &&
+ y < this.offset[1] + element.offsetHeight &&
+ x >= this.offset[0] &&
+ x < this.offset[0] + element.offsetWidth);
+ },
+
+ withinIncludingScrolloffsets: function(element, x, y) {
+ var offsetcache = this.realOffset(element);
+
+ this.xcomp = x + offsetcache[0] - this.deltaX;
+ this.ycomp = y + offsetcache[1] - this.deltaY;
+ this.offset = this.cumulativeOffset(element);
+
+ return (this.ycomp >= this.offset[1] &&
+ this.ycomp < this.offset[1] + element.offsetHeight &&
+ this.xcomp >= this.offset[0] &&
+ this.xcomp < this.offset[0] + element.offsetWidth);
+ },
+
+ // within must be called directly before
+ overlap: function(mode, element) {
+ if (!mode) return 0;
+ if (mode == 'vertical')
+ return ((this.offset[1] + element.offsetHeight) - this.ycomp) /
+ element.offsetHeight;
+ if (mode == 'horizontal')
+ return ((this.offset[0] + element.offsetWidth) - this.xcomp) /
+ element.offsetWidth;
+ },
+
+ page: function(forElement) {
+ var valueT = 0, valueL = 0;
+
+ var element = forElement;
+ do {
+ valueT += element.offsetTop || 0;
+ valueL += element.offsetLeft || 0;
+
+ // Safari fix
+ if (element.offsetParent == document.body)
+ if (Element.getStyle(element,'position')=='absolute') break;
+
+ } while (element = element.offsetParent);
+
+ element = forElement;
+ do {
+ if (!window.opera || element.tagName=='BODY') {
+ valueT -= element.scrollTop || 0;
+ valueL -= element.scrollLeft || 0;
+ }
+ } while (element = element.parentNode);
+
+ return [valueL, valueT];
+ },
+
+ clone: function(source, target) {
+ var options = Object.extend({
+ setLeft: true,
+ setTop: true,
+ setWidth: true,
+ setHeight: true,
+ offsetTop: 0,
+ offsetLeft: 0
+ }, arguments[2] || {})
+
+ // find page position of source
+ source = $(source);
+ var p = Position.page(source);
+
+ // find coordinate system to use
+ target = $(target);
+ var delta = [0, 0];
+ var parent = null;
+ // delta [0,0] will do fine with position: fixed elements,
+ // position:absolute needs offsetParent deltas
+ if (Element.getStyle(target,'position') == 'absolute') {
+ parent = Position.offsetParent(target);
+ delta = Position.page(parent);
+ }
+
+ // correct by body offsets (fixes Safari)
+ if (parent == document.body) {
+ delta[0] -= document.body.offsetLeft;
+ delta[1] -= document.body.offsetTop;
+ }
+
+ // set position
+ if(options.setLeft) target.style.left = (p[0] - delta[0] + options.offsetLeft) + 'px';
+ if(options.setTop) target.style.top = (p[1] - delta[1] + options.offsetTop) + 'px';
+ if(options.setWidth) target.style.width = source.offsetWidth + 'px';
+ if(options.setHeight) target.style.height = source.offsetHeight + 'px';
+ },
+
+ absolutize: function(element) {
+ element = $(element);
+ if (element.style.position == 'absolute') return;
+ Position.prepare();
+
+ var offsets = Position.positionedOffset(element);
+ var top = offsets[1];
+ var left = offsets[0];
+ var width = element.clientWidth;
+ var height = element.clientHeight;
+
+ element._originalLeft = left - parseFloat(element.style.left || 0);
+ element._originalTop = top - parseFloat(element.style.top || 0);
+ element._originalWidth = element.style.width;
+ element._originalHeight = element.style.height;
+
+ element.style.position = 'absolute';
+ element.style.top = top + 'px';
+ element.style.left = left + 'px';
+ element.style.width = width + 'px';
+ element.style.height = height + 'px';
+ },
+
+ relativize: function(element) {
+ element = $(element);
+ if (element.style.position == 'relative') return;
+ Position.prepare();
+
+ element.style.position = 'relative';
+ var top = parseFloat(element.style.top || 0) - (element._originalTop || 0);
+ var left = parseFloat(element.style.left || 0) - (element._originalLeft || 0);
+
+ element.style.top = top + 'px';
+ element.style.left = left + 'px';
+ element.style.height = element._originalHeight;
+ element.style.width = element._originalWidth;
+ }
+}
+
+// Safari returns margins on body which is incorrect if the child is absolutely
+// positioned. For performance reasons, redefine Position.cumulativeOffset for
+// KHTML/WebKit only.
+if (Prototype.Browser.WebKit) {
+ Position.cumulativeOffset = function(element) {
+ var valueT = 0, valueL = 0;
+ do {
+ valueT += element.offsetTop || 0;
+ valueL += element.offsetLeft || 0;
+ if (element.offsetParent == document.body)
+ if (Element.getStyle(element, 'position') == 'absolute') break;
+
+ element = element.offsetParent;
+ } while (element);
+
+ return [valueL, valueT];
+ }
+}
+
+Element.addMethods(); \ No newline at end of file
diff --git a/frontends/php/js/sbinit.js b/frontends/php/js/sbinit.js
new file mode 100644
index 00000000..dcd6ca10
--- /dev/null
+++ b/frontends/php/js/sbinit.js
@@ -0,0 +1,113 @@
+// JavaScript Document
+var _PE_SB = null;
+
+function hidegraphmenu(pe){
+ if(is_null(_PE_SB)) return;
+ _PE_SB.stop();
+ _PE_SB = null;
+
+ if((G_MENU.gmenumsover == 0 ) && (SCROLL_BAR.barmsdown == 0) && (SCROLL_BAR.arrowmsdown == 0)){
+ graphsubmit();
+ }
+}
+
+function showgraphmenu(obj_id){
+
+ var obj = $(obj_id);
+ if(!isset(obj)) return false;
+
+ var pos = getPosition(obj);
+ pos.top+=obj.offsetHeight+18;
+
+ var scrl = $('scroll');
+ scrl.style.top = pos.top+"px";
+ scrl.style.left = 1+"px";
+
+ G_MENU.gm_gmenu.style.top = (pos.top-108)+"px" // 110 = G_MENU height
+ G_MENU.gm_gmenu.style.left = 1+"px"
+
+ SCROLL_BAR.onchange = function(){
+ if(is_null(_PE_SB)){
+ _PE_SB = new PeriodicalExecuter(hidegraphmenu,2);
+ }
+ }
+
+ SCROLL_BAR.barmousedown = function(){
+ G_MENU.gmenuhide();
+
+ if(is_null(_PE_SB)) return;
+ _PE_SB.stop();
+ _PE_SB = null;
+ }
+
+ G_MENU.gmenuload = gmenuload;
+// G_MENU.gmenumouseout = function(){G_MENU.gmenuhide(); }
+
+ var gmshow = function(){
+ if(SCROLL_BAR.changed == 1){
+ G_MENU.gmenushow(SCROLL_BAR.period,SCROLL_BAR.getsTimeInUnix());
+ }
+ else{
+ G_MENU.gmenushow();
+ }
+ }
+ if(!IE){
+ $('scroll_calendar').addEventListener('click',gmshow,false);
+ }
+ else{
+ $('scroll_calendar').attachEvent('onclick',gmshow);
+ }
+
+ var date = datetoarray(G_MENU.bstime);
+
+ SCROLL_BAR.tabinfoleft.innerHTML = SCROLL_BAR.FormatStampbyDHM(SCROLL_BAR.period)+" | "+date[0]+'.'+date[1]+'.'+date[2]+' '+date[3]+':'+date[4]+':'+date[5];
+
+ date = datetoarray(G_MENU.bstime+SCROLL_BAR.period);
+ SCROLL_BAR.tabinforight.innerHTML = date[0]+'.'+date[1]+'.'+date[2]+' '+date[3]+':'+date[4]+':'+date[5];
+
+
+ scrl.style.visibility = 'visible';
+}
+
+function graphsubmit(){
+ var scrl = $('scroll');
+
+ scrl.style.display = 'none';
+ var uri = new url(location.href);
+
+ uri.setArgument('stime', SCROLL_BAR.getsTime());
+ uri.setArgument('period', SCROLL_BAR.getPeriod());
+ location.href = uri.getUrl();
+}
+
+function gmenuload(){
+
+ var date = datetoarray(G_MENU.bstime);
+
+ var stime = ''+date[2]+date[1]+date[0]+date[3]+date[4];
+ var uri = new url(location.href);
+
+ uri.setArgument('stime', stime);
+ uri.setArgument('period', G_MENU.period);
+
+ location.href = uri.getUrl();
+}
+
+function datetoarray(unixtime){
+
+ var date = new Date();
+ date.setTime(unixtime*1000);
+
+ var thedate = new Array();
+ thedate[0] = date.getDate();
+ thedate[1] = date.getMonth()+1;
+ thedate[2] = date.getFullYear();
+ thedate[3] = date.getHours();
+ thedate[4] = date.getMinutes();
+ thedate[5] = date.getSeconds();
+
+ for(i = 0; i < thedate.length; i++){
+ if((thedate[i]+'').length < 2) thedate[i] = '0'+thedate[i];
+ }
+return thedate;
+} \ No newline at end of file
diff --git a/frontends/php/js/scrollbar.js b/frontends/php/js/scrollbar.js
new file mode 100644
index 00000000..5fa554f1
--- /dev/null
+++ b/frontends/php/js/scrollbar.js
@@ -0,0 +1,712 @@
+// JavaScript Document
+/*
+** ZABBIX
+** Copyright (C) 2000-2007 SIA Zabbix
+**
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the GNU General Public License as published by
+** the Free Software Foundation; either version 2 of the License, or
+** (at your option) any later version.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+** GNU General Public License for more details.
+**
+** You should have received a copy of the GNU General Public License
+** along with this program; if not, write to the Free Software
+** Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+**
+*/
+<!--
+
+var SCROLL_BAR;
+var IMG_PATH='images/general/bar';
+//var cal = new calendar();
+
+function scrollinit(x,y,w,period,stime,timel,bar_stime){
+ if((typeof(x) == 'undefined') && (typeof(y) == 'undefined')){
+ alert("Parametrs haven't been sent properly");
+ return false;
+ }
+ w = w | 0;
+ if(w == 0){
+ var w = parseInt(document.body.scrollWidth) - 36;
+ var w2 = parseInt(document.body.offsetWidth) - 36;
+
+ w = (w2 > w)?w2:w;
+ }
+ scrollcreate(x,y,w);
+
+ period = period || 3600;
+
+ stime = stime || 0;
+ timel = timel || 0;
+
+ bar_stime = bar_stime || stime;
+
+ gmenuinit(y,x,period,bar_stime);
+
+ SCROLL_BAR = new scrollbar(stime,timel,period,bar_stime);
+
+ var scroll_x = $('scroll');
+ var arrow_l = $('arrow_l');
+ var arrow_r = $('arrow_r');
+
+ arrow_l.onmousedown = SCROLL_BAR.arrowmousedown.bind(SCROLL_BAR);
+ arrow_r.onmousedown = SCROLL_BAR.arrowmousedown.bind(SCROLL_BAR);
+
+ scroll_x.onmouseover= SCROLL_BAR.arrowmouseover.bind(SCROLL_BAR);
+ scroll_x.onmouseout = SCROLL_BAR.arrowmouseout.bind(SCROLL_BAR);
+
+ $('scroll_left').onclick = SCROLL_BAR.scrollmoveleft.bind(SCROLL_BAR);
+ $('scroll_right').onclick = SCROLL_BAR.scrollmoveright.bind(SCROLL_BAR);
+
+ $('scroll_bar').onmousedown = SCROLL_BAR.mousedown.bind(SCROLL_BAR);
+ document.onmouseup = SCROLL_BAR.mouseup.bind(SCROLL_BAR);
+
+// cal.onselect = SCROLL_BAR.movebarbydate.bind(SCROLL_BAR);
+}
+
+
+var scrollbar = Class.create();
+
+scrollbar.prototype = {
+
+dt : new Date(), // Date object
+starttime:0 , // time in seconds, for scrollbar
+timelength: 0, // starttime+timelength = endtime
+
+bar : '', // bar object
+barX: 0, // bar location on x-axis relativ to scrollbar
+barW: 8+4+4, // bar width
+minbarW: 16, // min allowed value for barW due to period > 3600
+scrollbarX: 0, // scrollbar location
+scrollbarW: 0, // length of scroll where bar can move
+maxX: 8+4+4+12, // max movement range for bar
+mouseX: 0, // mouse location
+barmsdown: 0, // if mousedown on bar = 1, else = 0
+
+arrow: '', // pressed arrow (l/r)
+arrowleft: '', // left arrow
+arrowright:'', // right arrow
+arrowX: 0, // arrow position
+arrowmsdown: 0, // if mousedown on arrow = 1, else = 0
+arrowmsX: 0, // mouse location when dragging arrows
+
+barbgl:26, // size of left side +6 of bar
+barbgr:26, // size of right side +6 of bar
+
+period: 3600, // viewable period (1h,2h etc.)
+
+pxtime: 0, // 1px = some time
+
+tabinfoleft: '', // html object(div) where view info (left)
+tabinforight: '', // html object(div) where view info (right)
+
+scrollmsover: 0, // if mouse over scrollbar then = 1, out = 0
+
+changed: 0, // switches to 1, when scrollbar been moved or period changed
+
+xp: 0, // exponential of time length
+
+initialize: function(stime,timel,period,bar_stime){ // where to put bar on start(time on graph)
+ try{
+ this.tabinfoleft = $('scrolltableft');
+ this.tabinforight = $('scrolltabright');
+
+ this.arrowleft = $('arrow_l');
+ this.arrowright = $('arrow_r');
+ this.arrowX = this.barX;
+
+ this.bar = $('scroll_bar');
+
+ this.barbgl = $('bar_bg_l');
+ this.barbgr = $('bar_bg_r');
+
+ this.period = parseInt(period);
+
+/************************************************************************
+* Do not change till you fully understand what you are doing. *
+************************************************************************/
+
+ if(stime < 10000000){
+ this.timelength = (timel < this.period)?(3*this.period):timel;
+ this.starttime = parseInt(this.dt.getTime()/1000 - this.timelength);
+ }
+ else{
+ this.starttime = stime;
+ this.timelength = (timel < this.period)?((this.dt.getTime()/1000) - stime):timel;
+
+ if(this.timelength < (2*this.period)){
+ this.timelength = 3*this.period;
+ this.starttime = parseInt(this.dt.getTime()/1000 - this.timelength);
+ }
+ }
+
+ this.endtime = this.dt.getTime()/1000;
+ this.maxX = parseInt($('scroll_middle').style.width);
+
+ this.settabinfo(this.barX);
+
+ this.xp = Math.log(this.timelength) / this.maxX;
+
+ this.minbarW = this.time2px(3600);
+ this.period2bar(this.period);
+
+ this.scrollbarW = parseInt(this.maxX) - this.barW;
+ this.calcpx2time();
+
+ if(typeof(bar_stime) != 'undefined') this.movebarbydate(bar_stime);
+
+ this.changed = 0; // we need to reset this attribute, becouse generaly we may already performe a movement.
+ } catch(e){
+ alert("Needed params haven't been initialized properly");
+ return false;
+ }
+},
+
+onbarchange: function(){
+ this.changed = 1;
+// SDI(this.timelength+' : '+this.maxX+' : '+this.barW+' : '+this.barX);
+ this.onchange();
+},
+
+scrollmouseout: function(){ // U may use this func to attach some function on mouseout from scroll method
+},
+
+scrollmouseover: function(){ // U may use this func to attach some function on mouseover from scroll method
+},
+
+onchange: function(){ // executed every time the bar period or bar time is changed(mouse button released)
+},
+
+
+/*--------------------------------------------------------------------------
+------------------------------ ARROW CONTROLS ------------------------------
+--------------------------------------------------------------------------*/
+
+arrowmouseover: function(){
+ this.arrowmovetoX(this.arrowX);
+ var arrowflag = false;
+ if(this.barX > 12){
+ this.arrowleft.setStyle({display: 'inline'});
+ arrowflag = true;
+ }
+
+ if((this.barX+this.barW) < (this.maxX-12)){
+ this.arrowright.setStyle({display: 'inline'});
+ arrowflag = true;
+ }
+ if(!arrowflag) this.arrowright.setStyle({display: 'inline'});
+
+ this.scrollmsover = 1;
+
+ try{
+ this.scrollmouseover();
+ }
+ catch(e){
+ }
+},
+
+arrowmouseout: function(){
+
+ this.arrowleft.setStyle({display: 'none'});
+ this.arrowright.setStyle({display: 'none'});
+ this.scrollmsover = 0;
+
+ try{
+ this.scrollmouseout();
+ }
+ catch(e){
+
+ }
+},
+
+arrowmousedown: function(e){
+ e = e || window.event;
+
+ this.deselectall();
+
+ this.arrow = e.originalTarget || e.srcElement;
+ this.arrowmsX = parseInt(this.getmousexy(e).x);
+
+ if((this.arrow.id != 'arrow_l') && (this.arrow.id != 'arrow_r')) return false;
+
+ this.arrowmsdown = 1;
+ this.barmousedown();
+
+ document.onmousemove = this.arrowmousemove.bind(this);
+},
+
+arrowmousemove: function(e){
+ e = e || window.event;
+
+ if(this.arrow.id == 'arrow_l'){
+ this.arrowmousemove_L(e);
+ }
+ else{
+ this.arrowmousemove_R(e);
+ }
+
+ this.calcpx2time();
+ this.period = this.calcperiod(this.barW);
+ this.settabinfo(this.barX);
+},
+
+arrowmousemove_L: function(e){
+ var mousexy = this.getmousexy(e);
+
+ var mouseXdiff = parseInt(mousexy.x) - parseInt(this.arrowmsX);
+ var barXr = this.barX+this.barW;
+
+ if((this.barW < this.minbarW) && ( mouseXdiff > 0)) return false;
+
+ var barWtemp = parseInt(this.barW) - parseInt(mouseXdiff);
+ var barXtemp = barXr - barWtemp;
+
+ if(barXtemp < 0) return barWtemp;
+ barWtemp = this.checkbarW(barWtemp, this.checkbarX(barXtemp, mousexy.x), mousexy.x);
+
+ if((barWtemp > this.minbarW) && (barWtemp != this.barW) && ((this.barX + mouseXdiff) > -1)){
+ this.barW = barWtemp;
+ this.barX = this.checkbarX(barXtemp, mousexy.x);
+ }
+
+ this.barchangeW(this.barW);
+ this.barmovetoX(this.barX);
+ this.arrowmovelefttoX(this.barX);
+},
+
+arrowmousemove_R: function(e){
+ var mousexy = this.getmousexy(e);
+ var mouseXdiff = parseInt(mousexy.x) - parseInt(this.arrowmsX);
+
+ var barWtemp = parseInt(this.barW) + parseInt(mouseXdiff);
+
+ barWtemp = this.checkbarW(barWtemp, this.barX, mousexy.x);
+
+ if((barWtemp > this.minbarW) && (barWtemp != this.barW)){
+ this.barW = barWtemp;
+ }
+
+ this.barchangeW(this.barW);
+ this.arrowmoverighttoX(this.barX);
+},
+
+arrowmouseup: function(e){
+ this.period = this.calcperiod(this.barW);
+ document.onmousemove = null;
+ this.arrowmsdown = 0;
+ this.onbarchange();
+},
+//-------------------------------
+
+
+/*------------------------------------------------------------------------
+------------------------------ BAR CONTROLS ------------------------------
+------------------------------------------------------------------------*/
+mousedown: function(e){
+ e = e || window.event;
+ this.deselectall();
+
+ this.scrollbarX = Position.cumulativeOffset(this.bar.parentNode)[0];
+ this.barX = Position.cumulativeOffset(this.bar)[0] - this.scrollbarX;
+ this.mouseX = parseInt(this.getmousexy(e).x);
+
+ this.barmsdown = 1;
+ this.barmousedown();
+ document.onmousemove = this.mousemove.bind(this);
+},
+
+mousebardown: function(e){
+
+},
+
+mousebarup: function(e){
+ document.onmousemove = null;
+ this.barmsdown = 0;
+ this.onbarchange();
+},
+
+mouseup: function(e){
+ e = e || window.event;
+ if( this.barmsdown == 1){
+ this.mousebarup(e);
+ }
+ else if(this.arrowmsdown == 1){
+ this.arrowmouseup(e);
+ }
+},
+
+mousemove: function(e){
+ e = e || window.event;
+
+ var mousexy = this.getmousexy(e);
+ var mouseXdiff = parseInt(mousexy.x) - parseInt(this.mouseX);
+
+ this.barX = parseInt(this.barX) + parseInt(mouseXdiff);
+ this.barX = this.checkbarX(this.barX, mousexy.x);
+
+ this.barmovetoX(this.barX);
+ this.arrowmovetoX(this.barX);
+},
+//-------------------------------
+
+/*-----------------------------------------------------------------------
+------------------------------ FUNC IN USE ------------------------------
+-----------------------------------------------------------------------*/
+//---arrow
+arrowmovelefttoX: function(x){
+ this.arrowleft.setStyle({left: (x+17-12)+'px'});
+},
+
+arrowmoverighttoX: function(x){
+ x += parseInt(this.barW)+17;
+ this.arrowright.setStyle({left: x+'px'});
+},
+//-------------------------------
+
+//---bar
+checkbarW: function(barWtemp,barXtemp,msx){
+ if(barWtemp < this.minbarW){
+ return this.minbarW;
+ }
+// SDI(barXtemp+' : '+this.arrowmsX+' : '+msx+'<br />'+barWtemp+' : '+this.barW);
+
+ if(barWtemp < 16){
+ return 16;
+ }
+ else if((barWtemp + barXtemp) > this.maxX){
+ return this.maxX - barXtemp;
+ }
+ else{
+ this.arrowmsX = parseInt(msx);
+ return barWtemp;
+ }
+},
+
+checkbarX: function(barXtemp,msx){
+ if(barXtemp < 0){
+ return 0;
+ }
+ else if((barXtemp + this.barW) > this.maxX){
+ return this.scrollbarW;
+ }
+ else{
+ this.mouseX = parseInt(msx);
+ return barXtemp;
+ }
+},
+
+barchangeW: function(w){
+ this.scrollbarW = parseInt(this.maxX - w);
+
+ w -=12;
+ var wl = Math.round(w/2);
+ var wr = w - wl;
+ this.barbgl.setStyle({width: wl +'px'});
+ this.barbgr.setStyle({width: wr +'px'});
+},
+
+barmovetoX: function(x){
+ this.arrowX = x;
+ this.bar.setStyle({left: (x+17) +'px'});
+
+ this.settabinfo(x);
+},
+//-------------------------------
+
+calcpx2time: function(){
+ if( this.scrollbarW > 0){
+ this.pxtime = parseInt((this.timelength - this.period) / this.scrollbarW);
+ }
+ else{
+ this.pxtime = parseInt(this.timelength - this.period);
+ }
+},
+
+time2px: function(time){
+ var px = time/this.pxtime;
+ if(px == 'Infinity'){
+ var c = (Math.log(time) / this.xp)
+ var cor = this.maxX/1.1 - c;
+ px = Math.round(c - cor);
+ }
+return Math.round(px);
+},
+
+px2time: function(px){
+ var cor = (this.maxX/1.1 - px)/2;
+ cor = (cor > 0)?cor:0;
+
+ var c = Math.round(px+cor);
+ var time = Math.round(Math.exp(c*this.xp));
+return parseInt(time);
+},
+
+getmousexy: function(e){
+ if(e.pageX || e.pageY){
+ return {x:e.pageX, y:e.pageY};
+ }
+ return {
+ x:e.clientX + document.body.scrollLeft - document.body.clientLeft,
+ y:e.clientY + document.body.scrollTop - document.body.clientTop
+ };
+},
+
+formatdate: function(x,adjust){
+
+ adjust = adjust || 0;
+ this.dt.setTime(Math.round((this.starttime+(x*this.pxtime) + adjust) * 1000));
+
+ var date = new Array();
+ date[0] = this.dt.getDate();
+ date[1] = this.dt.getMonth()+1;
+ date[2] = this.dt.getFullYear();
+ date[3] = this.dt.getHours();
+ date[4] = this.dt.getMinutes();
+ date[5] = this.dt.getSeconds();
+
+ for(i = 0; i < date.length; i++){
+ if((date[i]+'').length < 2) date[i] = '0'+date[i];
+ }
+
+return date;
+},
+
+deselectall: function(){
+ if(IE){
+ document.selection.empty();
+ }
+ else{
+ var sel = window.getSelection();
+ sel.removeAllRanges();
+ }
+},
+
+/*---------------------------------------------------------------------
+------------------------------ FUNC USES ------------------------------
+---------------------------------------------------------------------*/
+//---arrow
+arrowmovetoX: function(x){
+ this.arrowmovelefttoX(x);
+ this.arrowmoverighttoX(x);
+},
+//-------------------------------
+
+//---bar
+period2bar: function(period){
+ var barW = this.time2px(period);
+ this.barW = this.checkbarW(barW);
+
+ this.barchangeW(this.barW);
+},
+//-------------------------------
+
+//--- scrollmoves
+scrollmoveleft: function(){
+ this.movescroll(this.barX-1);
+},
+scrollmoveright: function(){
+ this.movescroll(this.barX+1);
+},
+//-------------------------------
+
+movebarbydate: function(timestamp){
+ timestamp = parseInt(timestamp - this.starttime);
+ this.movescroll(this.time2px(timestamp));
+},
+
+movescroll: function(x){
+ this.barX = this.checkbarX(x,0);
+ this.barmovetoX(this.barX);
+ this.arrowmovetoX(this.barX);
+ this.settabinfo(this.barX);
+ this.onbarchange();
+},
+
+settabinfo: function(x){
+
+ var date = this.formatdate(x);
+ this.tabinfoleft.innerHTML = this.FormatStampbyDHM(this.period)+" | "+date[0]+'.'+date[1]+'.'+date[2]+' '+date[3]+':'+date[4]+':'+date[5];
+
+ date = this.formatdate(x,this.period);
+ this.tabinforight.innerHTML = date[0]+'.'+date[1]+'.'+date[2]+' '+date[3]+':'+date[4]+':'+date[5];
+},
+
+calcperiod: function(barW){
+ var period = this.px2time(barW)
+ period = (period > this.timelength)?(this.timelength):(period);
+ this.getPeriod();
+return period;
+},
+
+getsTimeInUnix: function(){
+
+ return Math.round((this.starttime+(this.barX*this.pxtime)));
+},
+
+getsTime: function(){
+ var date = this.formatdate(this.barX);
+return date[2]+date[1]+date[0]+date[3]+date[4];
+},
+
+
+getPeriod: function(){
+return this.period;
+},
+
+FormatStampbyDHM: function(timestamp){
+ timestamp = timestamp || 0;
+ var days = parseInt(timestamp/86400);
+ var hours = parseInt((timestamp - days*86400)/3600);
+ var minutes = parseInt((timestamp -days*86400 - hours*3600)/60);
+
+ var str = (days==0)?(''):(days+'d ');
+ str+=hours+'h '+minutes+'m ';
+
+return str;
+}
+}
+
+
+/*-------------------------------------------------------------------------------------------------*\
+* SCROLL CREATION *
+\*-------------------------------------------------------------------------------------------------*/
+function scrollcreate(x,y,w){
+ var div_scroll = document.createElement('div');
+ document.getElementsByTagName('body')[0].appendChild(div_scroll);
+
+ Element.extend(div_scroll);
+ div_scroll.setAttribute('id','scroll');
+ div_scroll.setStyle({top: y+'px', left: x+'px',width: (17*2+w)+'px',visibility: 'hidden'});
+
+
+ var div = document.createElement('div');
+ div_scroll.appendChild(div);
+
+ Element.extend(div);
+ div.setAttribute('id','scrolltableft');
+ div.appendChild(document.createTextNode('0'));
+
+ var img = document.createElement('img');
+ div_scroll.appendChild(img);
+
+ img.setAttribute('src',IMG_PATH+'/cal.gif');
+ img.setAttribute('width','16');
+ img.setAttribute('height','12');
+ img.setAttribute('border','0');
+ img.setAttribute('alt','cal');
+ img.setAttribute('id','scroll_calendar');
+
+ var div = document.createElement('div');
+ div_scroll.appendChild(div);
+
+ Element.extend(div);
+ div.setAttribute('id','scrolltabright');
+ div.appendChild(document.createTextNode('0'));
+
+
+ var div = document.createElement('div');
+ div_scroll.appendChild(div);
+
+ Element.extend(div);
+ div.setAttribute('id','arrow_l');
+
+
+ var div = document.createElement('div');
+ div_scroll.appendChild(div);
+
+ Element.extend(div);
+ div.setAttribute('id','arrow_r');
+
+
+ var div = document.createElement('div');
+ div_scroll.appendChild(div);
+
+ Element.extend(div);
+ div.setAttribute('id','scroll_left');
+
+
+ var div_mid = document.createElement('div');
+ div_scroll.appendChild(div_mid);
+
+ Element.extend(div_mid);
+ div_mid.setAttribute('id','scroll_middle');
+ div_mid.setStyle({width: w+'px'});
+
+ var div_bar = document.createElement('div');
+ div_mid.appendChild(div_bar);
+
+ Element.extend(div_bar);
+ div_bar.setAttribute('id','scroll_bar');
+
+
+ var div = document.createElement('div');
+ div_bar.appendChild(div);
+
+ Element.extend(div);
+ div.setAttribute('id','bar_left');
+
+
+ var div = document.createElement('div');
+ div_bar.appendChild(div);
+
+ Element.extend(div);
+ div.setAttribute('id','bar_bg_l');
+
+
+ var div = document.createElement('div');
+ div_bar.appendChild(div);
+
+ Element.extend(div);
+ div.setAttribute('id','bar_middle');
+ div.setAttribute('align','middle');
+
+
+ var div = document.createElement('div');
+ div_bar.appendChild(div);
+
+ Element.extend(div);
+ div.setAttribute('id','bar_bg_r');
+
+
+ var div = document.createElement('div');
+ div_bar.appendChild(div);
+
+ Element.extend(div);
+ div.setAttribute('id','bar_right');
+
+
+ var div = document.createElement('div');
+ div_scroll.appendChild(div);
+
+ Element.extend(div);
+ div.setAttribute('id','scroll_right');
+
+/*
+<div id="scroll">
+ <img id="scroll_calendar" src="img/cal.gif" width="16" height="12" border="0" alt="GM" />
+
+ <div id="scrolltableft">0</div>
+ <div id="scrolltabright">0</div>
+
+ <div id="arrow_l"></div>
+ <div id="arrow_r"></div>
+
+ <div id="scroll_left"></div>
+ <div id="scroll_middle">
+ <div id="scroll_bar">
+ <div id="bar_left"></div>
+ <div id="bar_bg_l"></div>
+ <div id="bar_middle" align="center"></div>
+ <div id="bar_bg_r"></div>
+ <div id="bar_right"></div>
+ </div>
+ </div>
+ <div id="scroll_right"></div>
+</div>
+*/
+}
+--> \ No newline at end of file
diff --git a/frontends/php/js/url.js b/frontends/php/js/url.js
new file mode 100644
index 00000000..7a501bb0
--- /dev/null
+++ b/frontends/php/js/url.js
@@ -0,0 +1,214 @@
+// JavaScript Document
+var url = Class.create();
+
+url.prototype = {
+url: '', // actually, it's depricated/private variable
+port: -1,
+host: '',
+protocol: '',
+username: '',
+password: '',
+filr: '',
+reference: '',
+path: '',
+query: '',
+arguments: new Array(),
+
+initialize: function(url){
+ this.url=unescape(url);
+
+ this.query=(this.url.indexOf('?')>=0)?this.url.substring(this.url.indexOf('?')+1):'';
+ if(this.query.indexOf('#')>=0) this.query=this.query.substring(0,this.query.indexOf('#'));
+
+ var protocolSepIndex=this.url.indexOf('://');
+ if(protocolSepIndex>=0){
+ this.protocol=this.url.substring(0,protocolSepIndex).toLowerCase();
+ this.host=this.url.substring(protocolSepIndex+3);
+ if(this.host.indexOf('/')>=0) this.host=this.host.substring(0,this.host.indexOf('/'));
+ var atIndex=this.host.indexOf('@');
+ if(atIndex>=0){
+ var credentials=this.host.substring(0,atIndex);
+ var colonIndex=credentials.indexOf(':');
+ if(colonIndex>=0){
+ this.username=credentials.substring(0,colonIndex);
+ this.password=credentials.substring(colonIndex);
+ }else{
+ this.username=credentials;
+ }
+ this.host=this.host.substring(atIndex+1);
+ }
+ var portColonIndex=this.host.indexOf(':');
+ if(portColonIndex>=0){
+ this.port=this.host.substring(portColonIndex);
+ this.host=this.host.substring(0,portColonIndex);
+ }
+ this.file=this.url.substring(protocolSepIndex+3);
+ this.file=this.file.substring(this.file.indexOf('/'));
+ }else{
+ this.file=this.url;
+ }
+ if(this.file.indexOf('?')>=0) this.file=this.file.substring(0, this.file.indexOf('?'));
+
+ var refSepIndex=url.indexOf('#');
+ if(refSepIndex>=0){
+ this.file=this.file.substring(0,refSepIndex);
+ this.reference=this.url.substring(this.url.indexOf('#'));
+ }
+ this.path=this.file;
+ if(this.query.length>0) this.file+='?'+this.query;
+ if(this.reference.length>0) this.file+='#'+this.reference;
+
+ this.getArguments();
+},
+
+getArguments: function(){
+ var args=this.query.split('&');
+ var keyval='';
+
+ if(args.length<1) return;
+
+ for(i=0;i<args.length;i++){
+ keyval=args[i].split('=');
+ this.arguments[i] = new Array(keyval[0],(keyval.length==1)?keyval[0]:keyval[1]);
+ }
+},
+
+getArgumentValue: function(key){
+ if(key.length<1) return '';
+ for(i=0; i < this.arguments.length; i++){
+ if(this.arguments[i][0] == key) return this.arguments[i][1];
+ }
+
+return '';
+},
+
+getArgumentValues: function(){
+ var a=new Array();
+ var b=this.query.split('&');
+ var c='';
+ if(b.length<1) return a;
+ for(i=0;i<b.length;i++){
+ c=b[i].split('=');
+ a[i]=new Array(c[0],((c.length==1)?c[0]:c[1]));
+ }
+return a;
+},
+
+getUrl: function(){
+ var uri = (this.protocol.length > 0)?(this.protocol+'://'):'';
+ uri += (this.username.length > 0)?(this.username):'';
+ uri += (this.password.length > 0)?(':'+this.password):'';
+ uri += (this.host.length > 0)?(this.host):'';
+ uri += (this.path.length > 0)?(this.path):'';
+ uri += (this.query.length > 0)?('?'+this.query):'';
+ uri += (this.reference.length > 0)?('#'+this.reference):'';
+return encodeURI(uri);
+},
+
+setArgument: function(key,value){
+
+ var valueisset = false;
+ if(typeof(key) == 'undefined') throw 'Invalid argument past for setArgument';
+ value = value || '';
+
+ for(i=0; i < this.arguments.length; i++){
+ if(this.arguments[i][0] == key){
+ valueisset = true;
+ this.arguments[i][1] = value;
+ };
+ }
+ if(!valueisset) this.arguments[this.arguments.length] = new Array(key,value);
+ this.formatQuery();
+},
+
+formatQuery: function(){
+ if(this.arguments.lenght < 1) return;
+
+ var query = '';
+ for(i=0; i < this.arguments.length; i++){
+ query+=this.arguments[i][0]+'='+this.arguments[i][1]+'&';
+ }
+ this.query = query.substring(0,query.length-1);
+},
+
+getPort: function(){
+ return this.port;
+},
+
+setPort: function(port){
+ this.port = port;
+},
+
+getQuery: function(){
+ return this.query;
+},
+
+setQuery: function(query){
+ this.query = query;
+ this.getArgumentValues();
+ this.formatQuery();
+},
+
+/* Returns the protocol of this URL, i.e. 'http' in the url 'http://server/' */
+getProtocol: function(){
+ return this.protocol;
+},
+
+setProtocol: function(protocol){
+ this.protocol = protocol;
+},
+/* Returns the host name of this URL, i.e. 'server.com' in the url 'http://server.com/' */
+getHost: function(){
+ return this.host;
+},
+
+setHost: function(set){
+ this.host = host;
+},
+
+/* Returns the user name part of this URL, i.e. 'joe' in the url 'http://joe@server.com/' */
+getUserName: function(){
+ return this.username;
+},
+
+setUserName: function(username){
+ this.username = username;
+},
+
+/* Returns the password part of this url, i.e. 'secret' in the url 'http://joe:secret@server.com/' */
+getPassword: function(){
+ return this.password;
+},
+
+setPassword: function(password){
+ this.password = password;
+},
+
+/* Returns the file part of this url, i.e. everything after the host name. */
+getFile: function(){
+ return this.file = file;
+},
+
+setFile: function(file){
+ this.file = file;
+},
+
+/* Returns the reference of this url, i.e. 'bookmark' in the url 'http://server/file.html#bookmark' */
+getReference: function(){
+ return this.reference;
+},
+
+setReference: function(reference){
+ this.reference = reference;
+},
+
+/* Returns the file path of this url, i.e. '/dir/file.html' in the url 'http://server/dir/file.html' */
+getPath: function(){
+ return this.path;
+},
+
+setPath: function(path){
+ this.path = path;
+}
+
+} \ No newline at end of file
diff --git a/frontends/php/screens.php b/frontends/php/screens.php
index 0d06440a..2456f2d8 100644
--- a/frontends/php/screens.php
+++ b/frontends/php/screens.php
@@ -1,7 +1,7 @@
<?php
/*
** ZABBIX
-** Copyright (C) 2000-2005 SIA Zabbix
+** Copyright (C) 2000-2007 SIA Zabbix
**
** This program is free software; you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
@@ -27,6 +27,7 @@
$page["title"] = "S_CUSTOM_SCREENS";
$page["file"] = "screens.php";
$page['hist_arg'] = array('config','elementid');
+ $page['scripts'] = array('prototype.js','url.js','gmenu.js','scrollbar.js','sbinit.js'); //do not change order!!!
$_REQUEST["fullscreen"] = get_request("fullscreen", 0);
@@ -197,16 +198,34 @@ include_once "include/page_header.php";
else
{
$element = get_slideshow($elementid, get_request('step', null), $effectiveperiod);
- zbx_add_post_js('if(typeof(parent) != "undefined") parent.resizeiframe("iframe");
+ zbx_add_post_js('if(isset(parent)) parent.resizeiframe("iframe");
else resizeiframe("iframe");
');
}
- if($element) $element->Show();
+ if($element){
+ $element->Show();
+ }
$_REQUEST['elementid'] = $elementid;
- if( 2 != $_REQUEST["fullscreen"] )
- navigation_bar("screens.php",array('config','elementid'));
+ if( 2 != $_REQUEST["fullscreen"] ){
+
+ $stime = time() - (31536000); // 1year
+ $bstime = time()-$effectiveperiod;
+
+ if(isset($_REQUEST['stime'])){
+ $bstime = $_REQUEST['stime'];
+ $bstime = mktime(substr($bstime,8,2),substr($bstime,10,2),0,substr($bstime,4,2),substr($bstime,6,2),substr($bstime,0,4));
+ }
+
+ $script = 'scrollinit(0,0,0,'.$effectiveperiod.','.$stime.',0,'.$bstime.');
+ showgraphmenu("iframe");';
+
+ zbx_add_post_js($script);
+ $img = new CImg('images/general/tree/O.gif','space','20','20');
+ $img->Show();
+// navigation_bar("screens.php",array('config','elementid'));
+ }
}
else
{
diff --git a/frontends/php/styles/bar.css b/frontends/php/styles/bar.css
new file mode 100644
index 00000000..058693d0
--- /dev/null
+++ b/frontends/php/styles/bar.css
@@ -0,0 +1,170 @@
+/* CSS Document */
+/*
+** ZABBIX
+** Copyright (C) 2000-2007 SIA Zabbix
+**
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the GNU General Public License as published by
+** the Free Software Foundation; either version 2 of the License, or
+** (at your option) any later version.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+** GNU General Public License for more details.
+**
+** You should have received a copy of the GNU General Public License
+** along with this program; if not, write to the Free Software
+** Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+**
+*/
+div.scrollx{
+ overflow:auto;
+ height:18px;
+}
+
+div.scrolly{
+ overflow:auto;
+ width:20px;
+}
+
+div.sdi{
+ position:absolute;
+ right: 2px;
+ top: 2px;
+ width: 200px;
+ height: 100px;
+ border: red 1px solid;
+ overflow:auto;
+}
+
+img.bar_arrow{
+ display: none;
+ position: relative;
+ z-index: 10;
+}
+
+div#scroll{
+ position:absolute;
+/* display:none; */
+ height:17px;
+}
+
+img#scroll_calendar{
+ position:absolute;
+ top: -12px;
+ left: 0px;
+}
+
+img#scroll_calendar:hover{
+ cursor: pointer;
+ position:absolute;
+ top: -12px;
+ left: 0px;
+}
+
+div#scrolltableft{
+ position:absolute;
+ top: -12px;
+ left: 18px;
+ font-family:Verdana, Arial, Helvetica, sans-serif;
+ font-size:10px;
+ font-weight:bold;
+/* background-color:#FFF; */
+}
+
+div#scrolltabright{
+ position:absolute;
+ top: -12px;
+ right: 0px;
+ font-family:Verdana, Arial, Helvetica, sans-serif;
+ font-size:10px;
+ font-weight:bold;
+/* background-color:#FFF; */
+}
+
+div#scroll_left{
+ background-image: url(../images/general/bar/left.gif);
+ background-repeat:no-repeat;
+ width:17px;
+ height: 17px;
+ float: left;
+}
+
+div#scroll_right{
+ background-image: url(../images/general/bar/right.gif);
+ background-repeat:no-repeat;
+ width:17px;
+ height: 17px;
+ float: left;
+}
+
+div#scroll_middle{
+ background-image: url(../images/general/bar/bg.gif);
+ height: 17px;
+ float: left;
+}
+
+div#scroll_bar{
+ position: absolute;
+ bottom: 0px;
+ left: 17px;
+}
+
+div#arrow_l{
+ position:absolute;
+ bottom: 0px;
+ display:none;
+ background-image:url(../images/general/bar/arrow_l.gif);
+ background-repeat:no-repeat;
+ width: 12px;
+ height:17px;
+}
+
+div#arrow_r{
+ position:absolute;
+ bottom: 0px;
+ display:none;
+ background-image:url(../images/general/bar/arrow_r.gif);
+ background-repeat:no-repeat;
+ width: 12px;
+ height:17px;
+}
+
+div#bar_left{
+ background-image: url(../images/general/bar/bar_left.gif);
+ background-repeat:no-repeat;
+ width:2px;
+ height: 17px;
+ float: left;
+}
+
+div#bar_bg_l{
+ background-image: url(../images/general/bar/bar_bg.gif);
+ width:26px;
+ height: 17px;
+ float: left;
+}
+
+div#bar_middle{
+ background-image: url(../images/general/bar/bar_middle.gif);
+ background-repeat:no-repeat;
+ width:8px;
+ height: 17px;
+ float: left;
+}
+
+div#bar_bg_r{
+ background-image: url(../images/general/bar/bar_bg.gif);
+ width:26px;
+ height: 17px;
+ float: left;
+}
+
+div#bar_right{
+ background-image: url(../images/general/bar/bar_right.gif);
+ background-repeat:no-repeat;
+ width:2px;
+ height: 17px;
+ float: left;
+} \ No newline at end of file
diff --git a/frontends/php/styles/gmenu.css b/frontends/php/styles/gmenu.css
new file mode 100644
index 00000000..d4c192e4
--- /dev/null
+++ b/frontends/php/styles/gmenu.css
@@ -0,0 +1,384 @@
+@charset "utf-8";
+/* CSS Document */
+img{
+ border: 0px;
+}
+
+img#gmenu_day_up{
+ position:absolute;
+ text-align:center;
+ top: 10px;
+ left: 28px;
+}
+img#gmenu_day_up:hover{
+ cursor:pointer;
+}
+
+img#gmenu_month_up{
+ position:absolute;
+ text-align:center;
+ top: 10px;
+ left: 100px;
+}
+img#gmenu_month_up:hover{
+ cursor:pointer;
+}
+
+
+img#gmenu_year_up{
+ position:absolute;
+ text-align:center;
+ top: 10px;
+ left: 152px;
+}
+img#gmenu_year_up:hover{
+ cursor:pointer;
+}
+
+
+img#gmenu_day_down{
+ position:absolute;
+ text-align:center;
+ top: 23px;
+ left: 28px;
+}
+
+img#gmenu_day_down:hover{
+ cursor:pointer;
+}
+
+img#gmenu_month_down{
+ position:absolute;
+ text-align:center;
+ top: 23px;
+ left: 100px;
+}
+img#gmenu_month_down:hover{
+ cursor:pointer;
+}
+
+img#gmenu_year_down{
+ position:absolute;
+ text-align:center;
+ top: 23px;
+ left: 152px;
+}
+img#gmenu_year_down:hover{
+ cursor:pointer;
+}
+
+img#gmenu_hour_up{
+ position:absolute;
+ text-align:center;
+ top: 10px;
+ left: 196px;
+}
+img#gmenu_hour_up:hover{
+ cursor:pointer;
+}
+
+img#gmenu_minute_up{
+ position:absolute;
+ text-align:center;
+ top: 10px;
+ left: 230px;
+}
+img#gmenu_minute_up:hover{
+ cursor:pointer;
+}
+
+img#gmenu_hour_down{
+ position:absolute;
+ text-align:center;
+ top: 23px;
+ left: 196px;
+}
+img#gmenu_hour_down:hover{
+ cursor:pointer;
+}
+
+img#gmenu_minute_down{
+ position:absolute;
+ text-align:center;
+ top: 23px;
+ left: 230px;
+}
+img#gmenu_minute_down:hover{
+ cursor:pointer;
+}
+
+img#gmenu_period_v_up{
+ position:absolute;
+ text-align:center;
+ top: 10px;
+ left: 82px;
+}
+img#gmenu_period_v_up:hover{
+ cursor:pointer;
+}
+
+img#gmenu_period_t_up{
+ position:absolute;
+ text-align:center;
+ top: 10px;
+ left: 154px;
+}
+img#gmenu_period_t_up:hover{
+ cursor:pointer;
+}
+
+img#gmenu_period_v_down{
+ position:absolute;
+ text-align:center;
+ top: 23px;
+ left: 82px;
+}
+img#gmenu_period_v_down:hover{
+ cursor:pointer;
+}
+
+img#gmenu_period_t_down{
+ position:absolute;
+ text-align:center;
+ top: 23px;
+ left: 154px;
+}
+img#gmenu_period_t_down:hover{
+ cursor:pointer;
+}
+
+a#gmenu_load:link{
+ position:absolute;
+ border:#666666 1px solid;
+ background-color:#FFFFFF;
+ text-align:center;
+ text-decoration:none;
+ color:#333333;
+ font-family:Arial, Helvetica, sans-serif;
+ font-size: 9px;
+ font-weight:bold;
+ top: 50px;
+ left: 175px;
+ width: 72px;
+}
+
+a#gmenu_load:visited{
+ position:absolute;
+ border:#666666 1px solid;
+ background-color:#FFFFFF;
+ text-align:center;
+ text-decoration:none;
+ color:#333333;
+ font-family:Arial, Helvetica, sans-serif;
+ font-size: 11px;
+ font-weight:bold;
+ top: 50px;
+ left: 175px;
+ width: 72px;
+}
+
+a#gmenu_load:hover{
+ position:absolute;
+ border:#666666 1px solid;
+ background-color:#CFCFCF;
+ text-align:center;
+ text-decoration:none;
+ color:#333333;
+ font-family:Arial, Helvetica, sans-serif;
+ font-size: 11px;
+ font-weight:bold;
+ top: 50px;
+ left: 175px;
+ width: 72px;
+}
+
+a#gmenu_load:active{
+ position:absolute;
+ border:#666666 1px solid;
+ background-color:#FFFFFF;
+ text-align:center;
+ text-decoration:none;
+ color:#333333;
+ font-family:Arial, Helvetica, sans-serif;
+ font-size: 11px;
+ font-weight:bold;
+ top: 50px;
+ left: 175px;
+ width: 72px;
+}
+
+a#gmenu_hide:link{
+ position:absolute;
+ border:#666666 1px solid;
+ background-color:#FFFFFF;
+ text-align:center;
+ text-decoration:none;
+ color:#333333;
+ font-family:Arial, Helvetica, sans-serif;
+ font-size: 11px;
+ font-weight:bold;
+ top: 72px;
+ left: 175px;
+ width: 72px;
+}
+
+a#gmenu_hide:visited{
+ position:absolute;
+ border:#666666 1px solid;
+ background-color:#FFFFFF;
+ text-align:center;
+ text-decoration:none;
+ color:#333333;
+ font-family:Arial, Helvetica, sans-serif;
+ font-size: 11px;
+ font-weight:bold;
+ top: 72px;
+ left: 175px;
+ width: 72px;
+}
+
+a#gmenu_hide:hover{
+ position:absolute;
+ border:#666666 1px solid;
+ background-color:#CFCFCF;
+ text-align:center;
+ text-decoration:none;
+ color:#333333;
+ font-family:Arial, Helvetica, sans-serif;
+ font-size: 11px;
+ font-weight:bold;
+ top: 72px;
+ left: 175px;
+ width: 72px;
+}
+
+a#gmenu_hide:active{
+ position:absolute;
+ border:#666666 1px solid;
+ background-color:#FFFFFF;
+ text-align:center;
+ text-decoration:none;
+ color:#333333;
+ font-family:Arial, Helvetica, sans-serif;
+ font-size: 11px;
+ font-weight:bold;
+ top: 72px;
+ left: 175px;
+ width: 72px;
+}
+
+div#gmenu{
+ position:absolute;
+ background-color:#EFEFFF;
+ border:#3333FF 1px solid;
+ width: 254px;
+ height: 94px;
+}
+
+
+div#gmenu_bsdate{
+ position: absolute;
+ border:1px #888888 dashed;
+ top: 3px;
+ left: 4px;
+ height: 38px;
+ width: 244px;
+}
+
+div#gmenu_period{
+ position: absolute;
+ border:1px #888888 dashed;
+ top: 50px;
+ left: 4px;
+ height: 38px;
+ width: 166px;
+}
+
+span#gmenu_day{
+ position:absolute;
+ text-align:center;;
+ font-family:Arial, Helvetica, sans-serif;
+ font-size: 11px;
+ border:#666666 1px solid;
+ top: 10px;
+ left: 6px;
+ width: 20px;
+}
+
+span#gmenu_month{
+ position:absolute;
+ text-align:center;
+ font-family:Arial, Helvetica, sans-serif;
+ font-size: 11px;
+ border:#666666 1px solid;
+ top: 10px;
+ left: 38px;
+ width: 60px;
+}
+
+span#gmenu_year{
+ position:absolute;
+ text-align:center;
+ font-family:Arial, Helvetica, sans-serif;
+ font-size: 11px;
+ border:#666666 1px solid;
+ top: 10px;
+ left: 110px;
+ width: 40px;
+}
+
+span#gmenu_hour{
+ position:absolute;
+ text-align:center;
+ font-family:Arial, Helvetica, sans-serif;
+ font-size: 11px;
+ border:#666666 1px solid;
+ top: 10px;
+ left: 174px;
+ width: 20px;
+}
+
+span#gmenu_minute{
+ position:absolute;
+ text-align:center;
+ font-family:Arial, Helvetica, sans-serif;
+ font-size: 11px;
+ border:#666666 1px solid;
+ top: 10px;
+ left: 208px;
+ width: 20px;
+}
+
+span#gmenu_period_desc{
+ position:absolute;
+ text-align:left;
+ font-weight:bold;
+ font-family:Arial, Helvetica, sans-serif;
+ font-size: 13px;
+ color:#3F3F3F;
+ top: 10px;
+ left: 6px;
+ width: 48px;
+}
+
+span#gmenu_period_value{
+ position:absolute;
+ text-align:center;
+ font-family:Arial, Helvetica, sans-serif;
+ font-size: 11px;
+ border:#666666 1px solid;
+ top: 10px;
+ left: 60px;
+ width: 20px;
+}
+
+span#gmenu_period_type{
+ position:absolute;
+ text-align:center;
+ font-family:Arial, Helvetica, sans-serif;
+ font-size: 11px;
+ border:#666666 1px solid;
+ top: 10px;
+ left: 100px;
+ width: 52px;
+} \ No newline at end of file