diff options
Diffstat (limited to 'frontends')
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 Binary files differnew file mode 100644 index 00000000..f3e63c93 --- /dev/null +++ b/frontends/php/images/general/bar/arrow_down.gif diff --git a/frontends/php/images/general/bar/arrow_l.gif b/frontends/php/images/general/bar/arrow_l.gif Binary files differnew file mode 100644 index 00000000..c0ca4181 --- /dev/null +++ b/frontends/php/images/general/bar/arrow_l.gif diff --git a/frontends/php/images/general/bar/arrow_r.gif b/frontends/php/images/general/bar/arrow_r.gif Binary files differnew file mode 100644 index 00000000..b2a1c655 --- /dev/null +++ b/frontends/php/images/general/bar/arrow_r.gif diff --git a/frontends/php/images/general/bar/arrow_sm.gif b/frontends/php/images/general/bar/arrow_sm.gif Binary files differnew file mode 100644 index 00000000..df075f2a --- /dev/null +++ b/frontends/php/images/general/bar/arrow_sm.gif diff --git a/frontends/php/images/general/bar/arrow_up.gif b/frontends/php/images/general/bar/arrow_up.gif Binary files differnew file mode 100644 index 00000000..9be28750 --- /dev/null +++ b/frontends/php/images/general/bar/arrow_up.gif diff --git a/frontends/php/images/general/bar/bar_bg.gif b/frontends/php/images/general/bar/bar_bg.gif Binary files differnew file mode 100644 index 00000000..ea96cb5b --- /dev/null +++ b/frontends/php/images/general/bar/bar_bg.gif diff --git a/frontends/php/images/general/bar/bar_left.gif b/frontends/php/images/general/bar/bar_left.gif Binary files differnew file mode 100644 index 00000000..8af23b58 --- /dev/null +++ b/frontends/php/images/general/bar/bar_left.gif diff --git a/frontends/php/images/general/bar/bar_middle.gif b/frontends/php/images/general/bar/bar_middle.gif Binary files differnew file mode 100644 index 00000000..cdf9c794 --- /dev/null +++ b/frontends/php/images/general/bar/bar_middle.gif diff --git a/frontends/php/images/general/bar/bar_right.gif b/frontends/php/images/general/bar/bar_right.gif Binary files differnew file mode 100644 index 00000000..ae7f13f0 --- /dev/null +++ b/frontends/php/images/general/bar/bar_right.gif diff --git a/frontends/php/images/general/bar/bg.gif b/frontends/php/images/general/bar/bg.gif Binary files differnew file mode 100644 index 00000000..4058d437 --- /dev/null +++ b/frontends/php/images/general/bar/bg.gif diff --git a/frontends/php/images/general/bar/cal.gif b/frontends/php/images/general/bar/cal.gif Binary files differnew file mode 100644 index 00000000..4c952ce1 --- /dev/null +++ b/frontends/php/images/general/bar/cal.gif diff --git a/frontends/php/images/general/bar/left.gif b/frontends/php/images/general/bar/left.gif Binary files differnew file mode 100644 index 00000000..3877f50b --- /dev/null +++ b/frontends/php/images/general/bar/left.gif diff --git a/frontends/php/images/general/bar/right.gif b/frontends/php/images/general/bar/right.gif Binary files differnew file mode 100644 index 00000000..4cb55ef4 --- /dev/null +++ b/frontends/php/images/general/bar/right.gif 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 += "&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,'&').replace(/</g,'<').replace(/>/g,'>'); + }, + unescapeHTML: function() { + return this.replace(/&/g,'&').replace(/</g,'<').replace(/>/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 |