diff options
Diffstat (limited to 'frontends')
45 files changed, 4140 insertions, 1507 deletions
diff --git a/frontends/php/chart3.php b/frontends/php/chart3.php index 5152fabc..54d69938 100644 --- a/frontends/php/chart3.php +++ b/frontends/php/chart3.php @@ -40,7 +40,7 @@ include_once "include/page_header.php"; "name"=> array(T_ZBX_STR, O_OPT, NULL, null, null), "width"=> array(T_ZBX_INT, O_OPT, NULL, BETWEEN(0,65535), null), "height"=> array(T_ZBX_INT, O_OPT, NULL, BETWEEN(0,65535), null), - "yaxistype"=> array(T_ZBX_INT, O_OPT, NULL, IN("0,1"), null), + "yaxistype"=> array(T_ZBX_INT, O_OPT, NULL, IN("0,1,2"), null), "graphtype"=> array(T_ZBX_INT, O_OPT, NULL, IN("0,1"), null), "yaxismin"=> array(T_ZBX_DBL, O_OPT, NULL, BETWEEN(-65535,65535), null), "yaxismax"=> array(T_ZBX_DBL, O_OPT, NULL, null, null), diff --git a/frontends/php/chart7.php b/frontends/php/chart7.php index 78ff629d..d048adbc 100644 --- a/frontends/php/chart7.php +++ b/frontends/php/chart7.php @@ -98,7 +98,7 @@ include_once "include/page_header.php"; $gitem["periods_cnt"] ); - unset($items[$id]); +// unset($items[$id]); } $graph->Draw(); ?> diff --git a/frontends/php/charts.php b/frontends/php/charts.php index 9d3be1e8..45bb6dea 100644 --- a/frontends/php/charts.php +++ b/frontends/php/charts.php @@ -120,7 +120,7 @@ include_once 'include/page_header.php'; update_profile('web.charts.graphid',0); access_deny(); } - array_push($h1, new CLink($row['name'], '?graphid='.$_REQUEST['graphid'].(isset($_REQUEST['fullscreen']) ? '&fullscreen=1' : ''))); + array_push($h1, new CLink($row['name'], '?graphid='.$_REQUEST['graphid'].(isset($_REQUEST['fullscreen']) ? '' : '&fullscreen=1'))); } else { @@ -368,13 +368,15 @@ include_once 'include/page_header.php'; if(($graphtype == GRAPH_TYPE_PIE) || ($graphtype == GRAPH_TYPE_EXPLODED)){ $row = "\n".'<script language="javascript" type="text/javascript"> <!-- - var ZBX_G_WIDTH; - if(window.innerWidth) ZBX_G_WIDTH=window.innerWidth; - else ZBX_G_WIDTH=document.body.clientWidth; + A_SBOX["'.$dom_graph_id.'"] = new Object; + A_SBOX["'.$dom_graph_id.'"].shiftT = 17; + A_SBOX["'.$dom_graph_id.'"].shiftL = '.$shiftXleft.'; + + var ZBX_G_WIDTH = get_bodywidth(); + ZBX_G_WIDTH-= parseInt('.($shiftXleft+$shiftXright).'+parseInt((SF)?10:10)); - ZBX_G_WIDTH-='.($shiftXleft+$shiftXright+10).'; document.write(\'<img id="'.$dom_graph_id.'" src="chart6.php?graphid='.$_REQUEST['graphid'].url_param('stime'). - '&period='.$effectiveperiod.'&width=\'+ZBX_G_WIDTH+\'" /><br /><br />\'); + '&period='.$effectiveperiod.'&width=\'+ZBX_G_WIDTH+\'" /><br />\'); --> </script>'."\n"; } diff --git a/frontends/php/dashboard.php b/frontends/php/dashboard.php new file mode 100644 index 00000000..cae72970 --- /dev/null +++ b/frontends/php/dashboard.php @@ -0,0 +1,345 @@ +<?php +/* +** ZABBIX +** Copyright (C) 2000-2005 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. +**/ + +require_once "include/config.inc.php"; +require_once "include/hosts.inc.php"; +require_once "include/triggers.inc.php"; +require_once "include/items.inc.php"; +require_once "include/html.inc.php"; +require_once "include/blocks.inc.php"; + +$page["title"] = "S_DASHBOARD"; +$page["file"] = "dashboard.php"; +$page['hist_arg'] = array(); +$page['scripts'] = array('prototype.js','json.js','dashboard.js'); + + +$page['type'] = detect_page_type(PAGE_TYPE_HTML); + +if(PAGE_TYPE_HTML == $page['type']) + define('ZBX_PAGE_DO_REFRESH', 1); + + +include_once "include/page_header.php"; + +// VAR TYPE OPTIONAL FLAGS VALIDATION EXCEPTION + $fields=array( + 'groupid'=> array(T_ZBX_INT, O_OPT, P_SYS, DB_ID, NULL), + 'view_style'=> array(T_ZBX_INT, O_OPT, P_SYS, IN('0,1'), NULL), + 'type'=> array(T_ZBX_INT, O_OPT, P_SYS, IN('0,1'), NULL), + + 'output'=> array(T_ZBX_STR, O_OPT, P_ACT, NULL, NULL), + 'jsscriptid'=> array(T_ZBX_STR, O_OPT, P_ACT, NULL, NULL), + +//ajax + 'favobj'=> array(T_ZBX_STR, O_OPT, P_ACT, NULL, NULL), + 'favid'=> array(T_ZBX_STR, O_OPT, P_ACT, NOT_EMPTY, 'isset({favobj})'), + 'favcnt'=> array(T_ZBX_INT, O_OPT, null, null, null), + + 'action'=> array(T_ZBX_STR, O_OPT, P_ACT, NOT_EMPTY, NULL), + 'state'=> array(T_ZBX_STR, O_OPT, P_ACT, NOT_EMPTY, 'isset({favobj}) && ("hat"=={favobj})'), + ); + + check_fields($fields); + + $available_hosts = get_accessible_hosts_by_user($USER_DETAILS,PERM_READ_ONLY, null, null, get_current_nodeid()); + +// ACTION ///////////////////////////////////////////////////////////////////////////// + + if(isset($_REQUEST['favobj'])){ + if($_REQUEST['favobj'] == 'hat'){ +// echo 'alert("'.$_REQUEST['favid'].' : '.$_REQUEST['state'].'");'; + update_profile('web.dashboard.hats.'.$_REQUEST['favid'].'.state',$_REQUEST['state']); + } +//SDI() + if(in_array($_REQUEST['favobj'],array('simple_graph','graphs'))){ + $result = false; + if($_REQUEST['action'] == 'add'){ + $graphids = get_profile('web.favorite.graphids',array()); + $graph_rsrc = get_profile('web.favorite.graph_rsrc',array()); + + $graphids[] = $_REQUEST['favid']; + $graph_rsrc[] = ($_REQUEST['favobj'] == 'graphs')?'graphs':'simple_graph'; + + $result = update_profile('web.favorite.graphids',$graphids); + $result &= update_profile('web.favorite.graph_rsrc',$graph_rsrc); + } + else if($_REQUEST['action'] == 'remove'){ + $graphids = get_profile('web.favorite.graphids',array()); + $graph_rsrc = get_profile('web.favorite.graph_rsrc',array()); + + $favcnt = (isset($_REQUEST['favcnt']))?$_REQUEST['favcnt']:0; + foreach($graphids as $key => $value){ + if(($_REQUEST['favid'] == $value) && ($graph_rsrc[$key] == $_REQUEST['favobj'])){ + if(0 == $favcnt){ + unset($graphids[$key]); + unset($graph_rsrc[$key]); + break; + } + } + $favcnt--; + } + + $result = update_profile('web.favorite.graphids',$graphids); + $result &= update_profile('web.favorite.graph_rsrc',$graph_rsrc); + } + + + if((PAGE_TYPE_JS == $page['type']) && $result){ + $innerHTML = make_favorite_graphs($available_hosts); + $innerHTML = $innerHTML->toString(); + echo '$("hat_favgrph").update('.zbx_jsvalue($innerHTML).');'; + + $menu = array(); + $submenu = array(); + echo 'dashboard_submenu["menu_graphs"] = '.zbx_jsvalue(make_graph_submenu()).';'; + } + } + if('sysmaps' == $_REQUEST['favobj']){ + $result = false; + if($_REQUEST['action'] == 'add'){ + $sysmapids = get_profile('web.favorite.sysmapids',array()); + $sysmapids[] = $_REQUEST['favid']; + + $result = update_profile('web.favorite.sysmapids',$sysmapids); + } + else if($_REQUEST['action'] == 'remove'){ + $sysmapids = get_profile('web.favorite.sysmapids',array()); + + $favcnt = (isset($_REQUEST['favcnt']))?$_REQUEST['favcnt']:0; + foreach($sysmapids as $key => $value){ + if($_REQUEST['favid'] == $value){ + if(0 == $favcnt){ + unset($sysmapids[$key]); + break; + } + } + $favcnt--; + } + $result = update_profile('web.favorite.sysmapids',$sysmapids); + } + + + if((PAGE_TYPE_JS == $page['type']) && $result){ + $innerHTML = make_favorite_maps(); + $innerHTML = $innerHTML->toString(); + echo '$("hat_favmap").update('.zbx_jsvalue($innerHTML).');'; + + $menu = array(); + $submenu = array(); + echo 'dashboard_submenu["menu_sysmaps"] = '.zbx_jsvalue(make_sysmap_submenu()).';'; + } + } + if(in_array($_REQUEST['favobj'],array('screens','slides'))){ + $result = false; + if($_REQUEST['action'] == 'add'){ + $perm = ('screens' == $_REQUEST['favobj'])? + screen_accessiable($_REQUEST['favid'], PERM_READ_ONLY): + slideshow_accessiable($_REQUEST['favid'], PERM_READ_ONLY); + + if($perm){ + $screenids = get_profile('web.favorite.screenids',array()); + $screen_rsrc = get_profile('web.favorite.screen_rsrc',array()); + + $screenids[] = $_REQUEST['favid']; + $screen_rsrc[] = $_REQUEST['favobj']; + + $result = update_profile('web.favorite.screenids',$screenids); + $result &= update_profile('web.favorite.screen_rsrc',$screen_rsrc); + } + } + else if($_REQUEST['action'] == 'remove'){ + $screenids = get_profile('web.favorite.screenids',array()); + $screen_rsrc = get_profile('web.favorite.screen_rsrc',array()); + + $favcnt = (isset($_REQUEST['favcnt']))?$_REQUEST['favcnt']:0; + foreach($graphids as $key => $value){ + if(($_REQUEST['favid'] == $value) && ($graph_rsrc[$key] == $_REQUEST['favobj'])){ + if(0 == $favcnt){ + unset($screenids[$key]); + unset($screen_rsrc[$key]); + break; + } + } + $favcnt--; + } + + $result = update_profile('web.favorite.screenids',$screenids); + $result &= update_profile('web.favorite.screen_rsrc',$screen_rsrc); + } + + if(PAGE_TYPE_JS == $page['type']){ + $innerHTML = make_favorite_screens(); + $innerHTML = $innerHTML->toString(); + echo '$("hat_favscr").update('.zbx_jsvalue($innerHTML).');'; + + $menu = array(); + $submenu = array(); + echo 'dashboard_submenu["menu_screens"] = '.zbx_jsvalue(make_screen_submenu()).';'; + } + } + } + + if(isset($_REQUEST['output'])){ + if('json2' == $_REQUEST['output']){ + echo 'try{'. + 'json.callBack("sdt"); '. + 'json.removeScript("'.$_REQUEST['jsscriptid'].'");'. + ' }catch(e){ '. + 'alert("Warning: incorrect JSON return.");'. + 'json.removeScript("'.$_REQUEST['jsscriptid'].'");'. + ' }'; + } + } + + + + if((PAGE_TYPE_JS == $page['type']) || (PAGE_TYPE_HTML_BLOCK == $page['type'])){ + exit(); + } + +// validate_group(PERM_READ_ONLY,array("allow_all_hosts","monitored_hosts","with_monitored_items")); + show_table_header(SPACE.S_DASHBOARD_BIG.SPACE.date("[H:i:s]",time()),SPACE); + + $left_tab = new CTable(); + $left_tab->SetCellPadding(5); + $left_tab->SetCellSpacing(5); + + $left_tab->AddOption('border',0); + + $menu = array(); + $submenu = array(); + +// js menu arrays + make_graph_menu($menu,$submenu); + make_sysmap_menu($menu,$submenu); + make_screen_menu($menu,$submenu); + + insert_js('var dashboard_menu='.zbx_jsvalue($menu)."\n". + 'var dashboard_submenu='.zbx_jsvalue($submenu)."\n" + ); + +// -------------- + + $graph_menu = new CDiv(SPACE,'menuplus'); + $graph_menu->AddAction('onclick','javascript: create_menu(event,"graphs");'); + + $left_tab->AddRow(create_hat( + S_FAVORITE.SPACE.S_GRAPHS, + make_favorite_graphs($available_hosts), + array($graph_menu), + 'hat_favgrph', + get_profile('web.dashboard.hats.hat_favgrph.state') + )); + + $sysmap_menu = new CDiv(SPACE,'menuplus'); + $sysmap_menu->AddAction('onclick','javascript: create_menu(event,"sysmaps");'); + + $left_tab->AddRow(create_hat( + S_FAVORITE.SPACE.S_MAPS, + make_favorite_maps(), + array($sysmap_menu), + 'hat_favmap', + get_profile('web.dashboard.hats.hat_favmap.state') + )); + + $screen_menu = new CDiv(SPACE,'menuplus'); + $screen_menu->AddAction('onclick','javascript: create_menu(event,"screens");'); + + $left_tab->AddRow(create_hat( + S_FAVORITE.SPACE.S_SCREENS, + make_favorite_screens(), + array($screen_menu), + 'hat_favscr', + get_profile('web.dashboard.hats.hat_favscr.state') + )); + $left_tab->AddRow(SPACE); + + $right_tab = new CTable(); + $right_tab->SetCellPadding(5); + $right_tab->SetCellSpacing(5); + + $right_tab->AddOption('border',0); + +// $right_td_l = new CCol(); +// $right_td_l->Addoption('valign','top'); + + $right_tab->AddRow(create_hat( + S_SYSTEM_STATUS, + make_system_summary($available_hosts), + null, + 'hat_syssum', + get_profile('web.dashboard.hats.hat_syssum.state') + )); + $right_tab->AddRow(create_hat( + S_STATUS_OF_ZABBIX, + make_status_of_zbx(), + null, + 'hat_stszbx', + get_profile('web.dashboard.hats.hat_stszbx.state') + )); + $right_tab->AddRow(create_hat(S_LATEST_ISSUES, + make_latest_issues($available_hosts), + null, + 'hat_lastiss', + get_profile('web.dashboard.hats.hat_lastiss.state') + )); + $right_tab->AddRow(create_hat( + S_WEB_MONITORING, + make_webmon_overview(), + null, + 'hat_webovr', + get_profile('web.dashboard.hats.hat_webovr.state') + )); + + $td_l = new CCol($left_tab); + $td_l->AddOption('valign','top'); + + $td_r = new CCol($right_tab); + $td_r->AddOption('valign','top'); + + $outer_table = new CTable(); + $outer_table->AddOption('border',0); + $outer_table->SetCellPadding(1); + $outer_table->SetCellSpacing(1); + $outer_table->AddRow(array($td_l,$td_r)); + + $outer_table->Show(); + + $fav_form = new CForm(); + $fav_form->AddOption('name','fav_form'); + $fav_form->AddOption('id','fav_form'); + $fav_form->AddOption('style','display: inline; margin: 0px;'); + $fav_form->AddVar('favobj',''); + $fav_form->AddVar('favid',''); + $fav_form->AddVar('resource',''); + $fav_form->Show(); + + $jsmenu = new CPUMenu(null,170); + $jsmenu->InsertJavaScript(); + +// $link = new CLink('Click Me','javascript: callJSON();','highlight'); +// $link->Show(); +?> +<?php + +include_once "include/page_footer.php"; + +?>
\ No newline at end of file diff --git a/frontends/php/graphs.php b/frontends/php/graphs.php index 270d4db8..dfecc265 100644 --- a/frontends/php/graphs.php +++ b/frontends/php/graphs.php @@ -48,7 +48,7 @@ include_once "include/page_header.php"; "name"=> array(T_ZBX_STR, O_OPT, NULL, NOT_EMPTY, 'isset({save})'), "width"=> array(T_ZBX_INT, O_OPT, NULL, BETWEEN(0,65535), 'isset({save})'), "height"=> array(T_ZBX_INT, O_OPT, NULL, BETWEEN(0,65535), 'isset({save})'), - "yaxistype"=> array(T_ZBX_INT, O_OPT, NULL, IN("0,1"), 'isset({save})&&(({graphtype} == 0) || ({graphtype} == 1))'), + "yaxistype"=> array(T_ZBX_INT, O_OPT, NULL, IN("0,1,2"), 'isset({save})&&(({graphtype} == 0) || ({graphtype} == 1))'), "graphtype"=> array(T_ZBX_INT, O_OPT, NULL, IN("0,1,2,3"), 'isset({save})'), "yaxismin"=> array(T_ZBX_DBL, O_OPT, NULL, null, 'isset({save})&&(({graphtype} == 0) || ({graphtype} == 1))'), @@ -85,9 +85,9 @@ include_once "include/page_header.php"; check_fields($fields); validate_sort_and_sortorder(); - - validate_group_with_host(PERM_READ_WRITE,array("allow_all_hosts","always_select_first_host","only_current_node"), - 'web.last.conf.groupid', 'web.last.conf.hostid'); + + $options = array("allow_all_hosts","monitored_hosts","with_monitored_items","always_select_first_host","only_current_node"); + validate_group_with_host(PERM_READ_WRITE,$options,'web.last.conf.groupid', 'web.last.conf.hostid'); ?> <?php diff --git a/frontends/php/images/general/bttn/arrowdown.png b/frontends/php/images/general/bttn/arrowdown.png Binary files differnew file mode 100644 index 00000000..a251bbb6 --- /dev/null +++ b/frontends/php/images/general/bttn/arrowdown.png diff --git a/frontends/php/images/general/bttn/arrowdown_bb.png b/frontends/php/images/general/bttn/arrowdown_bb.png Binary files differnew file mode 100644 index 00000000..cbac0113 --- /dev/null +++ b/frontends/php/images/general/bttn/arrowdown_bb.png diff --git a/frontends/php/images/general/bttn/arrowup.png b/frontends/php/images/general/bttn/arrowup.png Binary files differnew file mode 100644 index 00000000..8c5577dc --- /dev/null +++ b/frontends/php/images/general/bttn/arrowup.png diff --git a/frontends/php/images/general/bttn/arrowup_bb.png b/frontends/php/images/general/bttn/arrowup_bb.png Binary files differnew file mode 100644 index 00000000..bbf78157 --- /dev/null +++ b/frontends/php/images/general/bttn/arrowup_bb.png diff --git a/frontends/php/images/general/bttn/plus.png b/frontends/php/images/general/bttn/plus.png Binary files differnew file mode 100644 index 00000000..61ad0cd6 --- /dev/null +++ b/frontends/php/images/general/bttn/plus.png diff --git a/frontends/php/images/general/bttn/plus_bb.png b/frontends/php/images/general/bttn/plus_bb.png Binary files differnew file mode 100644 index 00000000..d68efcfa --- /dev/null +++ b/frontends/php/images/general/bttn/plus_bb.png diff --git a/frontends/php/images/general/chart.png b/frontends/php/images/general/chart.png Binary files differnew file mode 100644 index 00000000..45e1449c --- /dev/null +++ b/frontends/php/images/general/chart.png diff --git a/frontends/php/images/general/trigg_dep.png b/frontends/php/images/general/trigg_dep.png Binary files differnew file mode 100644 index 00000000..4ad4b8fc --- /dev/null +++ b/frontends/php/images/general/trigg_dep.png diff --git a/frontends/php/include/blocks.inc.php b/frontends/php/include/blocks.inc.php new file mode 100644 index 00000000..6272cc3b --- /dev/null +++ b/frontends/php/include/blocks.inc.php @@ -0,0 +1,719 @@ +<?php +/* +** ZABBIX +** Copyright (C) 2000-2008 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. +**/ +?> +<?php +require_once "include/screens.inc.php"; + +// Author: Aly +function make_system_summary($available_hosts=false){ + global $USER_DETAILS; + + if(!$available_hosts){ + $available_hosts = get_accessible_hosts_by_user($USER_DETAILS,PERM_READ_ONLY, null, null, get_current_nodeid()); + } + + $table = new CTableInfo(); + $table->SetHeader(array( + is_show_subnodes() ? S_NODE : null, + S_HOST_GROUPS, + S_DISASTER, + S_HIGH, + S_AVERAGE, + S_WARNING, + S_INFORMATION, + S_NOT_CLASSIFIED + )); + + $gr_result=DBselect('SELECT DISTINCT g.groupid,g.name '. + ' FROM groups g, hosts_groups hg, hosts h, items i, functions f, triggers t '. + ' WHERE h.hostid in ('.$available_hosts.') '. + ' AND hg.groupid=g.groupid '. + ' AND h.status='.HOST_STATUS_MONITORED. + ' AND h.hostid=i.hostid '. + ' AND hg.hostid=h.hostid '. + ' AND i.status='.ITEM_STATUS_ACTIVE. + ' AND i.itemid=f.itemid '. + ' AND t.triggerid=f.triggerid '. + ' AND t.status='.TRIGGER_STATUS_ENABLED. + ' ORDER BY g.name'); + + while($group = DBFetch($gr_result)){ + $group_row = new CRow(); + if(is_show_subnodes()) + $group_row->AddItem(get_node_name_by_elid($group['groupid'])); + + $group_row->AddItem($group['name']); + + $tab_priority[TRIGGER_SEVERITY_DISASTER] = 0; + $tab_priority[TRIGGER_SEVERITY_HIGH] = 0; + $tab_priority[TRIGGER_SEVERITY_AVERAGE] = 0; + $tab_priority[TRIGGER_SEVERITY_WARNING] = 0; + $tab_priority[TRIGGER_SEVERITY_INFORMATION] = 0; + $tab_priority[TRIGGER_SEVERITY_NOT_CLASSIFIED] = 0; + + $sql='SELECT count(DISTINCT t.triggerid) as tr_cnt,t.priority '. + ' FROM hosts h,items i,hosts_groups hg, functions f, triggers t '. + ' WHERE h.status='.HOST_STATUS_MONITORED. + ' AND h.hostid=i.hostid '. + ' AND hg.groupid='.$group['groupid']. + ' AND hg.hostid=h.hostid'. + ' AND i.status='.ITEM_STATUS_ACTIVE. + ' AND i.itemid=f.itemid '. + ' AND t.triggerid=f.triggerid '. + ' AND t.value='.TRIGGER_VALUE_TRUE. + ' AND t.status='.TRIGGER_STATUS_ENABLED. + ' AND h.hostid in ('.$available_hosts.') '. + ' GROUP BY t.priority'; + + $tr_result = DBSelect($sql); + while($group_stat = DBFetch($tr_result)){ + $tab_priority[$group_stat['priority']] = $group_stat['tr_cnt']; + } + + foreach($tab_priority as $key => $value){ + $group_row->AddItem(new CCol($value,get_severity_style($key,$value))); + } + $table->AddRow($group_row); + } +return $table; +} + +// Author: Aly +function make_status_of_zbx(){ + $table = new CTableInfo(); + + $table->SetHeader(array( + S_PARAMETER, + S_VALUE, + S_DETAILS + )); + + $status=get_status(); + + $table->AddRow(array(S_ZABBIX_SERVER_IS_RUNNING,new CSpan($status['zabbix_server'], ($status['zabbix_server'] == S_YES ? 'off' : 'on')),' - ')); +// $table->AddRow(array(S_VALUES_STORED,$status['history_count']));$table->AddRow(array(S_TRENDS_STORED,$status['trends_count'])); + $table->AddRow(array(S_NUMBER_OF_HOSTS,$status['hosts_count'], + array( + new CSpan($status['hosts_count_monitored'],'off'),' / ', + new CSpan($status['hosts_count_not_monitored'],'on'),' / ', + new CSpan($status['hosts_count_template'],'unknown'),' / ', + $status['hosts_count_deleted'] + ) + )); + $table->AddRow(array(S_NUMBER_OF_ITEMS,$status['items_count'], + array( + new CSpan($status['items_count_monitored'],'off'),' / ', + new CSpan($status['items_count_disabled'],'on'),' / ', + new CSpan($status['items_count_not_supported'],'unknown'), + SPACE.SPACE.'['.$status['items_count_trapper'].']' + ) + )); + $table->AddRow(array(S_NUMBER_OF_TRIGGERS,$status['triggers_count'], + array( + $status['triggers_count_enabled'],' / ', + $status['triggers_count_disabled'].SPACE.SPACE.'[', + new CSpan($status['triggers_count_on'],'on'),' / ', + new CSpan($status['triggers_count_unknown'],'unknown'),' / ', + new CSpan($status['triggers_count_off'],'off'),']' + ) + )); + $table->AddRow(array(S_NUMBER_OF_EVENTS,$status['events_count'],' - ')); + $table->AddRow(array(S_NUMBER_OF_ALERTS,$status['alerts_count'],' - ')); + +//Log Out 10min + $sql = 'SELECT DISTINCT u.userid, s.lastaccess, u.autologout '. + ' FROM users u '. + ' LEFT JOIN sessions s ON s.userid=u.userid'; + + $db_users = DBSelect($sql); + $usr_cnt = 0; + $online_cnt = 0; + while($user=DBFetch($db_users)){ + $online_time = (($user['autologout'] == 0) || (ZBX_USER_ONLINE_TIME<$user['autologout']))?ZBX_USER_ONLINE_TIME:$user['autologout']; + if(!is_null($user['lastaccess']) && (($user['lastaccess']+$online_time)>=time())) $online_cnt++; + $usr_cnt++; + } + + $table->AddRow(array(S_NUMBER_OF_USERS,$usr_cnt,new CSpan($online_cnt,'green'))); + +return $table; +} + +// Author: Aly +function make_favorite_graphs($available_hosts=false){ + global $USER_DETAILS; + + if(!$available_hosts){ + $available_hosts = get_accessible_hosts_by_user($USER_DETAILS,PERM_READ_ONLY, null, null, get_current_nodeid()); + } + + $table = new CTableInfo(); + + $graphids = get_profile('web.favorite.graphids',array()); + $graph_rsrc = get_profile('web.favorite.graph_rsrc',array()); + + foreach($graphids as $key => $resourceid){ + if('simple_graph' == $graph_rsrc[$key]){ + if(!$item = get_item_by_itemid($resourceid)) continue; + + $host = get_host_by_itemid($resourceid); + $item["description"] = item_description($item["description"],$item["key_"]); + + $capt = new CSpan(new CLink($host['host'].':'.$item['description'],'history.php?action=showgraph&itemid='.$resourceid)); + $capt->AddOption('style','line-height: 14px; vertical-align: middle;'); + + $icon = new CLink(new CImg('images/general/chart.png','chart',18,18,'borderless'),'history.php?action=showgraph&itemid='.$resourceid.'&fullscreen=1'); + $icon->SetTarget('blank'); + } + else{ + if(!$graph = get_graph_by_graphid($resourceid)) continue; + + $result = get_hosts_by_graphid($resourceid); + $ghost = DBFetch($result); + + $capt = new CSpan(new CLink($ghost['host'].':'.$graph['name'],'charts.php?graphid='.$resourceid)); + $capt->AddOption('style','line-height: 14px; vertical-align: middle;'); + + $icon = new CLink(new CImg('images/general/chart.png','chart',18,18,'borderless'),'charts.php?graphid='.$resourceid.'&fullscreen=1'); + $icon->SetTarget('blank'); + } + + $table->AddRow(new CCol(array( + $icon, + SPACE, + $capt) + )); + } + +return $table; +} + +// Author: Aly +function make_favorite_screens(){ + $table = new CTableInfo(); + + $screenids = get_profile('web.favorite.screenids',array()); + $screen_rsrc = get_profile('web.favorite.screen_rsrc',array()); + + foreach($screenids as $key => $resourceid){ + if('slides' == $screen_rsrc[$key]){ + if(!$slide = get_slideshow_by_slideshowid($resourceid)) continue; + + $capt = new CSpan(new CLink($slide['name'],'screens.php?config=1&elementid='.$resourceid)); + $capt->AddOption('style','line-height: 14px; vertical-align: middle;'); + + $icon = new CLink(new CImg('images/general/chart.png','screen',18,18,'borderless'),'screens.php?config=1&elementid='.$resourceid.'&fullscreen=1'); + $icon->SetTarget('blank'); + } + else{ + if(!$screen = get_screen_by_screenid($resourceid)) continue; + + $capt = new CSpan(new CLink($screen['name'],'screens.php?resourceid='.$resourceid)); + $capt->AddOption('style','line-height: 14px; vertical-align: middle;'); + + $icon = new CLink(new CImg('images/general/chart.png','screen',18,18,'borderless'),'screens.php?resourceid='.$resourceid.'&fullscreen=1'); + $icon->SetTarget('blank'); + } + + $table->AddRow(new CCol(array( + $icon, + SPACE, + $capt) + )); + } + +return $table; +} + +// Author: Aly +function make_favorite_maps(){ + $table = new CTableInfo(); + + $sysmapids = get_profile('web.favorite.sysmapids',array()); + foreach($sysmapids as $key => $sysmapid){ + if(!$sysmap = get_sysmap_by_sysmapid($sysmapid)) continue; + + $capt = new CSpan(new CLink($sysmap['name'],'maps.php?sysmapid='.$sysmapid)); + $capt->AddOption('style','line-height: 14px; vertical-align: middle;'); + + $icon = new CLink(new CImg('images/general/chart.png','map',18,18,'borderless'),'maps.php?sysmapid='.$sysmapid.'&fullscreen=1'); + $icon->SetTarget('blank'); + + $table->AddRow(new CCol(array( + $icon, + SPACE, + $capt) + )); + } + +return $table; +} + +// author Aly +function make_latest_issues($available_hosts=false){ + global $USER_DETAILS; + + if(!$available_hosts){ + $available_hosts = get_accessible_hosts_by_user($USER_DETAILS,PERM_READ_ONLY, null, null, get_current_nodeid()); + } + $scripts_by_hosts = get_accessible_scripts_by_hosts(explode(',',$available_hosts)); + $config=select_config(); + + $table = new CTableInfo(); + $table->SetHeader(array( + is_show_subnodes() ? S_NODE : null, + S_HOST, + S_ISSUE, + S_LAST_CHANGE, + S_AGE, + ($config['event_ack_enable'])? S_ACK : NULL, + )); + + $sql = 'SELECT DISTINCT t.triggerid,t.status,t.description, t.priority, t.lastchange,t.value,h.host,h.hostid '. + ' FROM triggers t,hosts h,items i,functions f, hosts_groups hg '. + ' WHERE f.itemid=i.itemid AND h.hostid=i.hostid '. + ' AND hg.hostid=h.hostid '. + ' AND t.triggerid=f.triggerid AND t.status='.TRIGGER_STATUS_ENABLED. + ' AND i.status='.ITEM_STATUS_ACTIVE.' AND '.DBin_node('t.triggerid'). + ' AND h.hostid in ('.$available_hosts.') '. + ' AND h.status='.HOST_STATUS_MONITORED. + ' AND t.value='.TRIGGER_VALUE_TRUE. + 'ORDER BY t.lastchange DESC'; + $result = DBselect($sql); + + while($row=DBfetch($result)){ +// Check for dependencies + if(trigger_dependent($row["triggerid"])) continue; + + $host = null; + + $menus = ''; + + $host_nodeid = id2nodeid($row['hostid']); + foreach($scripts_by_hosts[$row['hostid']] as $id => $script){ + $script_nodeid = id2nodeid($script['scriptid']); + if( (bccomp($host_nodeid ,$script_nodeid ) == 0)) + $menus.= "['".$script['name']."',\"javascript: openWinCentered('scripts_exec.php?execute=1&hostid=".$row['hostid']."&scriptid=".$script['scriptid']."','".S_TOOLS."',760,540,'titlebar=no, resizable=yes, scrollbars=yes, dialog=no');\", null,{'outer' : ['pum_o_item'],'inner' : ['pum_i_item']}],"; + } + + $menus = trim($menus,','); + if(!empty($menus)) $menus="show_popup_menu(event,[[".zbx_jsvalue(S_TOOLS).",null,null,{'outer' : ['pum_oheader'],'inner' : ['pum_iheader']}],".$menus."],180);"; + + $host = new CSpan($row['host']); + $host->AddOption('onclick','javascript: '.$menus); + $host->AddOption('onmouseover',"javascript: this.style.cursor = 'pointer';"); + + $event_sql = 'SELECT e.eventid, e.value, e.clock, e.objectid as triggerid, e.acknowledged, t.type '. + ' FROM events e, triggers t '. + ' WHERE e.object=0 AND e.objectid='.$row['triggerid']. + ' AND t.triggerid=e.objectid '. + ' AND e.value='.TRIGGER_VALUE_TRUE. + ' ORDER by e.object DESC, e.objectid DESC, e.eventid DESC'; + + $res_events = DBSelect($event_sql,1); + + while($row_event=DBfetch($res_events)){ + if($config['event_ack_enable']){ + if($row_event['acknowledged'] == 1){ + $ack=new CLink(S_YES,'acknow.php?eventid='.$row_event['eventid'],'action'); + } + else{ + $ack= new CLink(S_NO,'acknow.php?eventid='.$row_event['eventid'],'on'); + } + } + + $description = expand_trigger_description_by_data( + array_merge($row, array("clock"=>$row_event["clock"])), + ZBX_FLAG_EVENT); + + $table->AddRow(array( + get_node_name_by_elid($row['triggerid']), + $host, + new CCol($description,get_severity_style($row["priority"])), + new CLink(zbx_date2str(S_DATE_FORMAT_YMDHMS,$row_event['clock']),"tr_events.php?triggerid=".$row["triggerid"],"action"), + zbx_date2age($row_event['clock']), + ($config['event_ack_enable'])?(new CCol($ack,"center")):NULL, + )); + } + unset($row,$description, $actions); + } +return $table; +} + +// author Aly +function make_webmon_overview($available_hosts=false){ + global $USER_DETAILS; + + if(!$available_hosts){ + $available_hosts = get_accessible_hosts_by_user($USER_DETAILS,PERM_READ_ONLY, null, null, get_current_nodeid()); + } + + + $table = new CTableInfo(); + $table->SetHeader(array( + is_show_subnodes() ? S_NODE : null, + S_HOST_GROUP, + S_OK, + S_FAILED, + S_IN_PROGRESS, + S_UNKNOWN + )); + + $sql = 'SELECT DISTINCT g.groupid, g.name '. + ' FROM httptest ht, applications a, hosts h, groups g, hosts_groups hg '. + ' WHERE hg.hostid in ('.$available_hosts.') '. + ' AND hg.hostid=a.hostid '. + ' AND g.groupid=hg.groupid '. + ' AND a.applicationid=ht.applicationid '. + ' AND ht.status='.HTTPTEST_STATUS_ACTIVE. + ' ORDER BY g.name'; + $host_groups = DBSelect($sql); + + while($group = DBFetch($host_groups)){ + + $apps['ok'] = 0; + $apps['failed'] = 0; + $apps[HTTPTEST_STATE_BUSY] = 0; + $apps[HTTPTEST_STATE_UNKNOWN] = 0; + + $sql = 'SELECT DISTINCT ht.httptestid, ht.curstate, ht.lastfailedstep '. + ' FROM httptest ht, applications a, hosts_groups hg, groups g '. + ' WHERE g.groupid='.$group['groupid']. + ' AND hg.groupid=g.groupid '. + ' AND a.hostid=hg.hostid '. + ' AND ht.applicationid=a.applicationid '. + ' AND ht.status='.HTTPTEST_STATUS_ACTIVE; + + $db_httptests = DBselect($sql); + + while($httptest_data = DBfetch($db_httptests)){ + + if( HTTPTEST_STATE_BUSY == $httptest_data['curstate'] ){ + $apps[HTTPTEST_STATE_BUSY]++; + } + else if( HTTPTEST_STATE_IDLE == $httptest_data['curstate'] ){ + if($httptest_data['lastfailedstep'] > 0){ + $apps['failed']++; + } + else{ + $apps['ok']++; + } + } + else{ + $apps[HTTPTEST_STATE_UNKNOWN]++; + } + } + + $table->AddRow(array( + is_show_subnodes() ? get_node_name_by_elid($group['groupid']) : null, + $group['name'], + new CSpan($apps['ok'],'off'), + new CSpan($apps['failed'],$apps['failed']?'on':'off'), + new CSpan($apps[HTTPTEST_STATE_BUSY],$apps[HTTPTEST_STATE_BUSY]?'orange':'off'), + new CSpan($apps[HTTPTEST_STATE_UNKNOWN],'unknown') + )); + } +return $table; +} + +function make_latest_data($available_hosts=false){ + global $USER_DETAILS; + + if(!$available_hosts){ + $available_hosts = get_accessible_hosts_by_user($USER_DETAILS,PERM_READ_ONLY, null, null, get_current_nodeid()); + } + + while($db_app = DBfetch($db_applications)){ + $db_items = DBselect('SELECT DISTINCT i.* '. + ' FROM items i,items_applications ia'. + ' WHERE ia.applicationid='.$db_app['applicationid']. + ' AND i.itemid=ia.itemid'. + ' AND i.status='.ITEM_STATUS_ACTIVE. + order_by('i.description,i.itemid,i.lastclock')); + + $app_rows = array(); + $item_cnt = 0; + while($db_item = DBfetch($db_items)){ + $description = item_description($db_item["description"],$db_item["key_"]); + + if( '' != $_REQUEST["select"] && !zbx_stristr($description, $_REQUEST["select"]) ) continue; + + ++$item_cnt; + if(!uint_in_array($db_app["applicationid"],$_REQUEST["applications"]) && !isset($show_all_apps)) continue; + + if(isset($db_item["lastclock"])) + $lastclock=date(S_DATE_FORMAT_YMDHMS,$db_item["lastclock"]); + else + $lastclock = new CCol('-', 'center'); + + $lastvalue=format_lastvalue($db_item); + + if( isset($db_item["lastvalue"]) && isset($db_item["prevvalue"]) && + ($db_item["value_type"] == 0) && ($db_item["lastvalue"]-$db_item["prevvalue"] != 0) ) + { + if($db_item["lastvalue"]-$db_item["prevvalue"]<0){ + $change=convert_units($db_item["lastvalue"]-$db_item["prevvalue"],$db_item["units"]); + } + else{ + $change="+".convert_units($db_item["lastvalue"]-$db_item["prevvalue"],$db_item["units"]); + } + $change=nbsp($change); + } + else{ + $change=new CCol("-","center"); + } + if(($db_item["value_type"]==ITEM_VALUE_TYPE_FLOAT) ||($db_item["value_type"]==ITEM_VALUE_TYPE_UINT64)){ + $actions=new CLink(S_GRAPH,"history.php?action=showgraph&itemid=".$db_item["itemid"],"action"); + } + else{ + $actions=new CLink(S_HISTORY,"history.php?action=showvalues&period=3600&itemid=".$db_item["itemid"],"action"); + } + array_push($app_rows, new CRow(array( + is_show_subnodes() ? SPACE : null, + $_REQUEST["hostid"] > 0 ? NULL : SPACE, + str_repeat(SPACE,6).$description, + $lastclock, + new CCol($lastvalue, $lastvalue=='-' ? 'center' : null), + $change, + $actions + ))); + } + + if($item_cnt > 0){ + if(uint_in_array($db_app["applicationid"],$_REQUEST["applications"]) || isset($show_all_apps)){ + $link = new CLink(new CImg("images/general/opened.gif"), + "?close=1&applicationid=".$db_app["applicationid"]. + url_param("groupid").url_param("hostid").url_param("applications"). + url_param("select")); + } + else{ + $link = new CLink(new CImg("images/general/closed.gif"), + "?open=1&applicationid=".$db_app["applicationid"]. + url_param("groupid").url_param("hostid").url_param("applications"). + url_param("select")); + } + + $col = new CCol(array($link,SPACE,bold($db_app["name"]), + SPACE."(".$item_cnt.SPACE.S_ITEMS.")")); + $col->SetColSpan(5); + + $table->ShowRow(array( + get_node_name_by_elid($db_app['hostid']), + $_REQUEST["hostid"] > 0 ? NULL : $db_app["host"], + $col + )); + + $any_app_exist = true; + + foreach($app_rows as $row) $table->ShowRow($row); + } + } +} + +function make_graph_menu(&$menu,&$submenu){ + + $menu['menu_graphs'][] = array( + S_FAVORITE.SPACE.S_GRAPHS, + null, + null, + array('outer'=> array('pum_oheader'), 'inner'=>array('pum_iheader')) + ); + $menu['menu_graphs'][] = array( + S_ADD.SPACE.S_GRAPH, + 'javascript: '. + "PopUp('popup.php?srctbl=graphs&". + 'reference=dashboard&'. + 'dstfrm=fav_form&'. + 'dstfld1=favobj&'. + 'dstfld2=favid&'. + 'srcfld1=description&'. + "srcfld2=graphid',800,450);". + "void(0);", + null, + array('outer' => 'pum_o_submenu', 'inner'=>array('pum_i_submenu')) + ); + $menu['menu_graphs'][] = array( + S_ADD.SPACE.S_SIMPLE_GRAPH, + 'javascript: '. + "PopUp('popup.php?srctbl=simple_graph&". + 'reference=dashboard&'. + 'dstfrm=fav_form&'. + 'dstfld1=favobj&'. + 'dstfld2=favid&'. + 'srcfld1=description&'. + "srcfld2=itemid',800,450);". + "void(0);", + null, + array('outer' => 'pum_o_submenu', 'inner'=>array('pum_i_submenu')) + ); + $menu['menu_graphs'][] = array( + S_REMOVE, + null, + null, + array('outer' => 'pum_o_submenu', 'inner'=>array('pum_i_submenu')) + ); + $submenu['menu_graphs'] = make_graph_submenu(); +} + +function make_graph_submenu(){ + $graphids = array(); + + $fav_graphids = get_profile('web.favorite.graphids',array()); + $graph_rsrc = get_profile('web.favorite.graph_rsrc',array()); + + foreach($fav_graphids as $key => $resourceid){ + if('simple_graph' == $graph_rsrc[$key]){ + if(!$item = get_item_by_itemid($resourceid)) continue; + + $host = get_host_by_itemid($resourceid); + $item["description"] = item_description($item["description"],$item["key_"]); + + $graphids[] = array( + 'name' => $host['host'].':'.$item['description'], + 'favobj'=> 'simple_graph', + 'favid' => $resourceid, + 'action'=> 'remove' + ); + } + else{ + if(!$graph = get_graph_by_graphid($resourceid)) continue; + + $result = get_hosts_by_graphid($resourceid); + $ghost = DBFetch($result); + + $graphids[] = array( + 'name' => $ghost['host'].':'.$graph['name'], + 'favobj'=> 'graphs', + 'favid' => $resourceid, + 'action'=> 'remove' + ); + } + } + +return $graphids; +} + +function make_sysmap_menu(&$menu,&$submenu){ + + $menu['menu_sysmaps'][] = array(S_FAVORITE.SPACE.S_MAPS, null, null, array('outer'=> array('pum_oheader'), 'inner'=>array('pum_iheader'))); + $menu['menu_sysmaps'][] = array( + S_ADD.SPACE.S_MAP, + 'javascript: '. + "PopUp('popup.php?srctbl=sysmaps&". + 'reference=dashboard&'. + 'dstfrm=fav_form&'. + 'dstfld1=favobj&'. + 'dstfld2=favid&'. + 'srcfld1=name&'. + "srcfld2=sysmapid',800,450);". + "void(0);", + null, + array('outer' => 'pum_o_submenu', 'inner'=>array('pum_i_submenu') + )); + $menu['menu_sysmaps'][] = array(S_REMOVE, null, null, array('outer' => 'pum_o_submenu', 'inner'=>array('pum_i_submenu'))); + $submenu['menu_sysmaps'] = make_sysmap_submenu(); +} + +function make_sysmap_submenu(){ + $sysmapids = array(); + $fav_sysmaps = get_profile('web.favorite.sysmapids',array()); + + foreach($fav_sysmaps as $key => $sysmapid){ + if(!$sysmap = get_sysmap_by_sysmapid($sysmapid)) continue; + + $sysmapids[] = array( + 'name' => $sysmap['name'], + 'favobj'=> 'sysmaps', + 'favid' => $sysmapid, + 'action'=> 'remove' + ); + } + +return $sysmapids; +} + +function make_screen_menu(&$menu,&$submenu){ + + $menu['menu_screens'][] = array(S_FAVORITE.SPACE.S_SCREENS, null, null, array('outer'=> array('pum_oheader'), 'inner'=>array('pum_iheader'))); + $menu['menu_screens'][] = array( + S_ADD.SPACE.S_SCREEN, + 'javascript: '. + "PopUp('popup.php?srctbl=screens&". + 'reference=dashboard&'. + 'dstfrm=fav_form&'. + 'dstfld1=favobj&'. + 'dstfld2=favid&'. + 'srcfld1=name&'. + "srcfld2=screenid',800,450);". + "void(0);", + null, + array('outer' => 'pum_o_submenu', 'inner'=>array('pum_i_submenu') + )); + $menu['menu_screens'][] = array( + S_ADD.SPACE.S_SLIDESHOW, + 'javascript: '. + "PopUp('popup.php?srctbl=slides&". + 'reference=dashboard&'. + 'dstfrm=fav_form&'. + 'dstfld1=favobj&'. + 'dstfld2=favid&'. + 'srcfld1=name&'. + "srcfld2=slideshowid',800,450);". + "void(0);", + null, + array('outer' => 'pum_o_submenu', 'inner'=>array('pum_i_submenu') + )); + $menu['menu_screens'][] = array(S_REMOVE, null, null, array('outer' => 'pum_o_submenu', 'inner'=>array('pum_i_submenu'))); + $submenu['menu_screens'] = make_screen_submenu(); +} + +function make_screen_submenu(){ + $screenids = array(); + + $fav_screens = get_profile('web.favorite.screenids',array()); + $screen_rsrc = get_profile('web.favorite.screen_rsrc',array()); + + foreach($fav_screens as $key => $resourceid){ + if('slides' == $screen_rsrc[$key]){ + if(!$slide = get_slideshow_by_slideshowid($resourceid)) continue; + + $screenids[] = array( + 'name' => $slide['name'], + 'favobj'=> 'slides', + 'favid' => $resourceid, + 'action'=> 'remove' + ); + + } + else{ + if(!$screen = get_screen_by_screenid($resourceid)) continue; + + $screenids[] = array( + 'name' => $screen['name'], + 'favobj'=> 'screens', + 'favid' => $resourceid, + 'action'=> 'remove' + ); + } + } + +return $screenids; +} +?>
\ No newline at end of file diff --git a/frontends/php/include/classes/chart.inc.php b/frontends/php/include/classes/chart.inc.php index 8fb74055..4a6668fa 100644 --- a/frontends/php/include/classes/chart.inc.php +++ b/frontends/php/include/classes/chart.inc.php @@ -504,8 +504,9 @@ class Chart extends Graph{ function calculateMinY($side){ if($this->yaxistype==GRAPH_YAXIS_TYPE_FIXED){ return $this->yaxismin; - } - else{ + } else if ($this->yaxistype==GRAPH_YAXIS_TYPE_CALCULATED_0_MIN) { + return 0; + } else{ unset($minY); for($i=0;$i<$this->num;$i++){ @@ -1102,4 +1103,4 @@ class Chart extends Graph{ ImageOut($this->im); } } -?>
\ No newline at end of file +?> diff --git a/frontends/php/include/classes/graph.inc.php b/frontends/php/include/classes/graph.inc.php index c6b6f2d0..0cc74dc2 100644 --- a/frontends/php/include/classes/graph.inc.php +++ b/frontends/php/include/classes/graph.inc.php @@ -24,6 +24,7 @@ require_once "include/hosts.inc.php"; define("GRAPH_YAXIS_TYPE_CALCULATED",0); define("GRAPH_YAXIS_TYPE_FIXED",1); +define("GRAPH_YAXIS_TYPE_CALCULATED_0_MIN",2); define("GRAPH_YAXIS_SIDE_LEFT",0); define("GRAPH_YAXIS_SIDE_RIGHT",1); diff --git a/frontends/php/include/config.inc.php b/frontends/php/include/config.inc.php index 325a9e0a..8b196474 100644 --- a/frontends/php/include/config.inc.php +++ b/frontends/php/include/config.inc.php @@ -324,6 +324,23 @@ function TODO($msg) { echo "TODO: ".$msg.SBR; } // DEBUG INFO!!! include_once "include/page_footer.php"; } + function detect_page_type($default=PAGE_TYPE_HTML){ + if(isset($_REQUEST['output'])){ + switch($_REQUEST['output']){ + case 'ajax': + return PAGE_TYPE_JS; + break; + case 'json': + return PAGE_TYPE_JS; + break; + case 'html': + return PAGE_TYPE_HTML_BLOCK; + break; + } + } + return $default; + } + function zbx_strlen(&$str){ if(!$strlen = strlen($str)) return $strlen; @@ -1087,9 +1104,14 @@ function TODO($msg) { echo "TODO: ".$msg.SBR; } // DEBUG INFO!!! } $table = new CTable(NULL,"header"); +// $table->AddOption('border',1); $table->SetCellSpacing(0); $table->SetCellPadding(1); - $table->AddRow(array(new CCol($col1,"header_l"), new CCol($col2,"header_r"))); + + $td_r = new CCol($col2,"header_r"); + $td_r->AddOption('align','right'); + + $table->AddRow(array(new CCol($col1,"header_l"), $td_r)); return $table; } @@ -1371,69 +1393,68 @@ function TODO($msg) { echo "TODO: ".$msg.SBR; } // DEBUG INFO!!! function get_profile($idx,$default_value=null,$type=PROFILE_TYPE_UNKNOWN){ global $USER_DETAILS; - $result = $default_value; - if($USER_DETAILS["alias"]!=ZBX_GUEST_USER) - { - $db_profiles = DBselect("select * from profiles where userid=".$USER_DETAILS["userid"]." and idx=".zbx_dbstr($idx)); - $profile=DBfetch($db_profiles); + $result = array(); +// $result = $default_value; - if($profile) - { - if($type==PROFILE_TYPE_UNKNOWN) - $type = $profile["valuetype"]; + if($USER_DETAILS["alias"]!=ZBX_GUEST_USER){ + $db_profiles = DBselect('SELECT * FROM profiles WHERE userid='.$USER_DETAILS["userid"].' AND idx='.zbx_dbstr($idx)); + + while($profile=DBfetch($db_profiles)){ + if($type==PROFILE_TYPE_UNKNOWN) $type = $profile["valuetype"]; - $result = $profile["value"]; + switch($type){ + case PROFILE_TYPE_INT: + $result[] = intval($profile["value"]); + break; + case PROFILE_TYPE_STR: + default: + $result[] = strval($profile["value"]); + } } } - switch($type) - { - case PROFILE_TYPE_ARRAY: $result = explode(";", $result); break; - case PROFILE_TYPE_INT: $result = intval($result); break; - case PROFILE_TYPE_STR: $result = strval($result); break; - } - if(is_array($result)) - { - $result = array_filter($result, "not_empty"); - } - return $result; + $result = array_filter($result, "not_empty"); + + if(isset($result[0]) && (PROFILE_TYPE_ARRAY != $type)) $result = $result[0]; + if(empty($result)) $result = $default_value; + + return $result; } //----------- ADD/EDIT USERPROFILE ------------- - function update_profile($idx,$value,$type=PROFILE_TYPE_UNKNOWN) - { - + function update_profile($idx,$value,$type=PROFILE_TYPE_UNKNOWN){ global $USER_DETAILS; - if($USER_DETAILS["alias"]==ZBX_GUEST_USER) - { - return; + if($USER_DETAILS["alias"]==ZBX_GUEST_USER){ + return false; } - + if($type==PROFILE_TYPE_UNKNOWN && is_array($value)) $type = PROFILE_TYPE_ARRAY; if($type==PROFILE_TYPE_ARRAY && !is_array($value)) $value = array($value); - switch($type) - { - case PROFILE_TYPE_ARRAY: $value = implode(";", $value); break; - default: $value = strval($value); - } - - $row = DBfetch(DBselect("select value from profiles where userid=".$USER_DETAILS["userid"]." and idx=".zbx_dbstr($idx))); + $sql='DELETE FROM profiles WHERE userid='.$USER_DETAILS["userid"].' and idx='.zbx_dbstr($idx); + DBExecute($sql); - if(!$row) - { - $profileid = get_dbid('profiles', 'profileid'); - $sql="insert into profiles (profileid,userid,idx,value,valuetype)". - " values (".$profileid.",".$USER_DETAILS["userid"].",".zbx_dbstr($idx).",".zbx_dbstr($value).",".$type.")"; - DBexecute($sql); + insert_profile($idx,$value,$type); + + return true; + } + + function insert_profile($idx,$value,$type=PROFILE_TYPE_UNKNOWN){ + global $USER_DETAILS; + + if(is_array($value)){ + foreach($value as $key => $val){ + insert_profile($idx,$val,$type); // recursion!!! + } } - else - { - $sql="update profiles set value=".zbx_dbstr($value).",valuetype=".$type. - " where userid=".$USER_DETAILS["userid"]." and idx=".zbx_dbstr($idx); + else{ + $profileid = get_dbid('profiles', 'profileid'); + $sql='INSERT INTO profiles (profileid,userid,idx,value,valuetype)'. + ' VALUES ('.$profileid.','.$USER_DETAILS["userid"].','.zbx_dbstr($idx).','.zbx_dbstr($value).','.$type.')'; DBexecute($sql); } + } /***********************************/ @@ -1464,7 +1485,7 @@ function TODO($msg) { echo "TODO: ".$msg.SBR; } // DEBUG INFO!!! } $url = ''; - foreach($page['hist_arg'] as $arg){ + foreach($page['hist_arg'] as $key => $arg){ if(isset($_REQUEST[$arg]) && !empty($_REQUEST[$arg])){ $url.=((empty($url))?('?'):('&')).$arg.'='.$_REQUEST[$arg]; } @@ -1777,6 +1798,33 @@ function TODO($msg) { echo "TODO: ".$msg.SBR; } // DEBUG INFO!!! { return ($timestamp==0)?S_NEVER:date($format,$timestamp); } + + /* function: + * zbx_date2age + * + * description: + * Calculate and convert timestamp to string representation. + * + * author: Aly + */ + function zbx_date2age($start_date,$end_date=0){ + + $start_date=date('U',$start_date); + if($end_date) + $end_date=date('U',$end_date); + else + $end_date = time(); + + $time = abs($end_date-$start_date); + +//SDI($start_date.' - '.$end_date.' = '.$time); + + $days = (int) ($time / 86400); + $hours = (int) (($time - $days*86400) / 3600); + $minutes = (int) ((($time - $days*86400) - ($hours*3600)) / 60); + $str = (($days)?$days.'d ':'').(($hours)?$hours.'h ':'').$minutes.'m'; + return $str; + } function encode_log($data) { diff --git a/frontends/php/include/defines.inc.php b/frontends/php/include/defines.inc.php index de3710b0..e2969831 100644 --- a/frontends/php/include/defines.inc.php +++ b/frontends/php/include/defines.inc.php @@ -41,9 +41,11 @@ define('XML_TAG_SCREEN_ELEMENT', 'screen_element'); define('XML_TAG_SCREEN_ELEMENTS', 'screen_elements'); - define('PAGE_TYPE_HTML', 0); - define('PAGE_TYPE_IMAGE', 1); - define('PAGE_TYPE_XML', 2); + define('PAGE_TYPE_HTML', 0); + define('PAGE_TYPE_IMAGE', 1); + define('PAGE_TYPE_XML', 2); + define('PAGE_TYPE_JS', 3); //javascript + define('PAGE_TYPE_HTML_BLOCK', 4); //simple block of html (as text) define('T_ZBX_STR', 0); define('T_ZBX_INT', 1); @@ -488,6 +490,7 @@ if((ini_get('mbstring.func_overload') > 5)){ define('ZBX_HISTORY_COUNT',5); + define('ZBX_USER_ONLINE_TIME',600); // 10min define('ZBX_GUEST_USER','guest'); define('ZBX_DEFAULT_CSS','default.css'); diff --git a/frontends/php/include/forms.inc.php b/frontends/php/include/forms.inc.php index 64f2ee99..ba346f19 100644 --- a/frontends/php/include/forms.inc.php +++ b/frontends/php/include/forms.inc.php @@ -2545,7 +2545,9 @@ $cmbYType = new CComboBox("yaxistype",$yaxistype,"graphs.submit(this)"); $cmbYType->AddItem(GRAPH_YAXIS_TYPE_CALCULATED,S_CALCULATED); + $cmbYType->AddItem(GRAPH_YAXIS_TYPE_CALCULATED_0_MIN,S_CALCULATED_0_MIN); $cmbYType->AddItem(GRAPH_YAXIS_TYPE_FIXED,S_FIXED); + $frmGraph->AddRow(S_YAXIS_TYPE,$cmbYType); if($yaxistype == GRAPH_YAXIS_TYPE_FIXED){ @@ -5154,7 +5156,7 @@ include_once 'include/discovery.inc.php'; $message = ""; } $frmResult->AddRow(S_RESULT,new CTextArea("message",$message,100,25,'yes')); - $frmResult->AddItemToBottomRow(new CButton('close',S_CLOSE,'close_window();')); + $frmResult->AddItemToBottomRow(new CButton('close',S_CLOSE,'window.close();')); $frmResult->Show(); } diff --git a/frontends/php/include/graphs.inc.php b/frontends/php/include/graphs.inc.php index c348b59c..a666b5e4 100644 --- a/frontends/php/include/graphs.inc.php +++ b/frontends/php/include/graphs.inc.php @@ -127,13 +127,13 @@ } - function &get_graphs_by_hostid($hostid) + function get_graphs_by_hostid($hostid) { return DBselect("SELECT distinct g.* FROM graphs g, graphs_items gi, items i". " WHERE g.graphid=gi.graphid and gi.itemid=i.itemid and i.hostid=$hostid"); } - function &get_realhosts_by_graphid($graphid) + function get_realhosts_by_graphid($graphid) { $graph = get_graph_by_graphid($graphid); if($graph["templateid"] != 0) @@ -142,13 +142,13 @@ return get_hosts_by_graphid($graphid); } - function &get_hosts_by_graphid($graphid) + function get_hosts_by_graphid($graphid) { return DBselect("SELECT distinct h.* FROM graphs_items gi, items i, hosts h". " WHERE h.hostid=i.hostid and gi.itemid=i.itemid and gi.graphid=$graphid"); } - function &get_graphitems_by_graphid($graphid) + function get_graphitems_by_graphid($graphid) { return DBselect("SELECT * FROM graphs_items WHERE graphid=$graphid". " order by itemid,drawtype,sortorder,color,yaxisside"); diff --git a/frontends/php/include/html.inc.php b/frontends/php/include/html.inc.php index 719ce7de..6946ecd4 100644 --- a/frontends/php/include/html.inc.php +++ b/frontends/php/include/html.inc.php @@ -106,4 +106,44 @@ function BR(){ return new CTag('br','no'); } -?> + + function create_hat($caption,$items,$addicons=null,$id=null,$state=1){ + + if(is_null($id)){ + list($usec, $sec) = explode(' ',microtime()); + $id = 'hat_'.((int)($sec % 10)).((int)($usec * 1000)); + } + + $td_l = new CCol(SPACE); + $td_l->AddOption('width','100%'); + + $icons_row = array($td_l); + if(!is_null($addicons)){ + if(!is_array($addicons)) $addicons = array($addicons); + foreach($addicons as $value) $icons_row[] = $value; + } + + $icon = new CDiv(SPACE,($state)?'arrowup':'arrowdown'); + $icon->AddAction('onclick',new CScript("javascript: change_hat_state(this,'".$id."');")); + + $icons_row[] = $icon; + + $icon_tab = new CTable(); + $icon_tab->AddOption('width','100%'); + + $icon_tab->AddRow($icons_row); + + $table = new CTable(); + $table->AddOption('width','100%'); + $table->SetCellPadding(0); + $table->SetCellSpacing(0); + $table->AddRow(get_table_header($caption,$icon_tab)); + + $div = new CDiv($items); + $div->AddOption('id',$id); + if(!$state) $div->AddOption('style','display: none;'); + + $table->AddRow($div); + return $table; + } +?>
\ No newline at end of file diff --git a/frontends/php/include/items.inc.php b/frontends/php/include/items.inc.php index e859f8c7..dc0c5394 100644 --- a/frontends/php/include/items.inc.php +++ b/frontends/php/include/items.inc.php @@ -913,7 +913,7 @@ COpt::profiling_start('prepare data'); while($row = DBfetch($result)) { $row['host'] = get_node_name_by_elid($row['hostid']).$row['host']; - $hosts[$row['host']] = $row['host']; + $hosts[strtolower($row['host'])] = $row['host']; $items[item_description($row["description"],$row["key_"])][$row['host']] = array( 'itemid' => $row['itemid'], 'value_type' => $row['value_type'], @@ -931,7 +931,7 @@ COpt::profiling_start('prepare data'); return $table; } - sort($hosts); + ksort($hosts); COpt::profiling_stop('prepare data'); COpt::profiling_start('prepare table'); diff --git a/frontends/php/include/locales/en_gb.inc.php b/frontends/php/include/locales/en_gb.inc.php index 4191c860..b8614521 100644 --- a/frontends/php/include/locales/en_gb.inc.php +++ b/frontends/php/include/locales/en_gb.inc.php @@ -93,6 +93,7 @@ 'S_IN_CHECK'=> 'In check', 'S_IDLE_TILL'=> 'Idle till', 'S_FAILED_ON'=> 'Failed on', + 'S_FAILED'=> 'Failed', // httpmon.php 'S_STATUS_OF_WEB_MONITORING'=> 'Status of Web monitoring', @@ -555,6 +556,7 @@ 'S_YAXIS_MIN_VALUE'=> 'Y axis MIN value', 'S_YAXIS_MAX_VALUE'=> 'Y axis MAX value', 'S_CALCULATED'=> 'Calculated', + 'S_CALCULATED_0_MIN'=> 'Calculated [Min=0]', 'S_FIXED'=> 'Fixed', 'S_CREATE_GRAPH'=> 'Create Graph', 'S_SHOW_WORKING_TIME'=> 'Show working time', @@ -925,6 +927,17 @@ 'S_MENU_AUDIT'=> 'AUDIT', 'S_SWITCH_NODE'=> 'Switch node', +// dashbord.php + 'S_DASHBOARD'=> 'Dashboard', + 'S_DASHBOARD_BIG'=> 'PERSONAL DASHBOARD', + 'S_SWITCH_VIEW'=> 'Switch view', + 'S_AGE'=> 'Age', + 'S_ISSUE'=> 'Issue', + 'S_ISSUES'=> 'Issues', + 'S_SYSTEM_STATUS'=> 'System status', + 'S_LATEST_ISSUES'=> 'Latest issues', + 'S_FAVORITE'=> 'Favorite', + // overview.php 'S_SELECT_GROUP_DOT_DOT_DOT'=> 'Select group ...', 'S_OVERVIEW'=> 'Overview', diff --git a/frontends/php/include/page_header.php b/frontends/php/include/page_header.php index d5805886..628a5447 100644 --- a/frontends/php/include/page_header.php +++ b/frontends/php/include/page_header.php @@ -52,6 +52,14 @@ COpt::profiling_start("page"); header('Content-Disposition: attachment; filename="'.$page['file'].'"'); define('ZBX_PAGE_NO_MENU', 1); break; + case PAGE_TYPE_JS: + header('Content-Type: application/javascript; charset=UTF-8'); + define('ZBX_PAGE_NO_MENU', 1); + break; + case PAGE_TYPE_HTML_BLOCK: + header('Content-Type: text/plain; charset=UTF-8'); + define('ZBX_PAGE_NO_MENU', 1); + break; case PAGE_TYPE_HTML: default: if(!isset($page['encoding'])) @@ -63,18 +71,17 @@ COpt::profiling_start("page"); if(!isset($page['title'])) $page['title'] = 'ZABBIX'; - if(defined('ZBX_DISTRIBUTED')) - { + if(defined('ZBX_DISTRIBUTED')){ if($curr_node_data = DBfetch(DBselect('select * from nodes where nodeid='.get_current_nodeid(false)))) $page['title'] .= ' ('.$curr_node_data['name'].')'; } - if(defined('ZBX_PAGE_DO_REFRESH') && $USER_DETAILS["refresh"]) - { + + if(defined('ZBX_PAGE_DO_REFRESH') && $USER_DETAILS["refresh"]){ $page['title'] .= ' [refreshed every '.$USER_DETAILS['refresh'].' sec]'; - /* header('Refresh: '.$USER_DETAILS["refresh"]); */ /* is not part of the official HTTP specification */ } - break; /* case PAGE_TYPE_HTML */ - } /* switch($page["type"]) */ + break; + } + /* switch($page["type"]) */ /* NOTE - menu array format: first level: @@ -87,14 +94,15 @@ COpt::profiling_start("page"); 'url' = real url for this page 'label' = submenu title, if missed menu skipped, but remmembed as last visited page. 'sub_pages' = collection of pages for displaying but dont remember as last visited. - */ + $ZBX_MENU = array( "view"=>array( "label" => S_MONITORING, "node_perm" => PERM_READ_LIST, "default_page_id" => 0, "pages"=>array( + array("url"=>"dashboard.php" ,"label"=>S_DASHBOARD ), array("url"=>"overview.php" ,"label"=>S_OVERVIEW ), array("url"=>"httpmon.php" ,"label"=>S_WEB , "sub_pages"=>array("httpdetails.php") diff --git a/frontends/php/include/services.inc.php b/frontends/php/include/services.inc.php index 6ae9e821..44f67ffb 100644 --- a/frontends/php/include/services.inc.php +++ b/frontends/php/include/services.inc.php @@ -139,7 +139,7 @@ * retrive true status * * Author: - * Artem Suharev + * Aly * * Comments: * @@ -208,7 +208,7 @@ * removes any links between trigger and service if service is not leaf (treenode) * * Author: - * Artem Suharev + * Aly * * Comments: * diff --git a/frontends/php/include/setup.inc.php b/frontends/php/include/setup.inc.php index b697622b..c43ef973 100644 --- a/frontends/php/include/setup.inc.php +++ b/frontends/php/include/setup.inc.php @@ -328,9 +328,9 @@ $final_result = array( new CSpan(S_FAIL,'fail'), - BR, BR, + BR(), BR(), 'Please correct all issuse and press "Retry" button', - BR, BR, + BR(), BR(), new CButton('retry', S_RETRY) ); } diff --git a/frontends/php/include/triggers.inc.php b/frontends/php/include/triggers.inc.php index 1be995d4..9bec6e0e 100644 --- a/frontends/php/include/triggers.inc.php +++ b/frontends/php/include/triggers.inc.php @@ -181,20 +181,31 @@ * convert severity constant in to the CSS style name * * Author: - * Eugene Grigorjev (eugene.grigorjev@zabbix.com) + * Aly * * Comments: * */ - function get_severity_style($severity) - { - if($severity == TRIGGER_SEVERITY_INFORMATION) return 'information'; - elseif($severity == TRIGGER_SEVERITY_WARNING) return 'warning'; - elseif($severity == TRIGGER_SEVERITY_AVERAGE) return 'average'; - elseif($severity == TRIGGER_SEVERITY_HIGH) return 'high'; - elseif($severity == TRIGGER_SEVERITY_DISASTER) return 'disaster'; - - return ''; + function get_severity_style($severity,$type=true){ + switch($severity){ + case TRIGGER_SEVERITY_DISASTER: + $style='disaster'; + break; + case TRIGGER_SEVERITY_HIGH: + $style='high'; + break; + case TRIGGER_SEVERITY_AVERAGE: + $style='average'; + break; + case TRIGGER_SEVERITY_WARNING: + $style='warning'; + break; + case TRIGGER_SEVERITY_INFORMATION: + default: + $style='information'; + } + if(!$type) $style='normal';//$style.='_empty'; + return $style; } /* @@ -1780,7 +1791,7 @@ $row['host'] = get_node_name_by_elid($row['hostid']).$row['host']; $row['description'] = expand_trigger_description_constants($row['description'], $row); - $hosts[$row['host']] = $row['host']; + $hosts[strtolower($row['host'])] = $row['host']; $triggers[$row['description']][$row['host']] = array( 'hostid' => $row['hostid'], 'triggerid' => $row['triggerid'], @@ -1792,7 +1803,8 @@ { return $table; } - sort($hosts); + ksort($hosts); + if($view_style == STYLE_TOP){ $header=array(new CCol(S_TRIGGERS,'center')); foreach($hosts as $hostname) diff --git a/frontends/php/js/common.js b/frontends/php/js/common.js index 2b3bc433..7b22bf27 100644 --- a/frontends/php/js/common.js +++ b/frontends/php/js/common.js @@ -57,10 +57,13 @@ function is_string(obj){ } function is_array(obj) { - if (obj.constructor.toString().indexOf("Array") == -1) - return false; - else - return true; + if(obj.constructor == Array) + return true; + + if(obj.constructor.toString().indexOf("Array") == -1) + return false; + else + return true; } if (!Array.prototype.forEach) @@ -80,8 +83,7 @@ if (!Array.prototype.forEach) }; } -function SDI(msg) -{ +function SDI(msg){ alert("DEBUG INFO: " + msg); } @@ -199,6 +201,39 @@ function Confirm(msg){ return false; } +function ShowHide(obj,style){ + if(!isset(style)) + var style = 'inline'; + if(is_string(obj)) + obj = document.getElementById(obj); + if(!obj) return false; + + if(obj.style.display != 'none'){ + obj.style.display = 'none'; + return 0; + } + else{ + obj.style.display = style; + return 1; + } +return false; +} + +function switchElementsClass(obj,class1,class2){ + obj = $(obj); + if(!obj) return false; + + if(obj.className == class1){ + obj.className = class2; + return class2; + } + else{ + obj.className = class1; + return class1; + } +return false; +} + function PopUp(url,width,height,form_name){ if(!width) width = 600; if(!height) height = 450; @@ -255,22 +290,31 @@ function getPosition(obj){ return pos; } -function cancelEvent(event){ - event = event || window.event; +function cancelEvent(e){ + if (!e) var e = window.event; +//SDI(e); + if(e){ + if(IE){ + e.cancelBubble = true; + e.returnValue = false; + } + else{ + e.stopPropagation(); + e.preventDefault(); + } + } +return false; +} -//SDI(event); +function deselectAll(){ if(IE){ - event.cancelBubble = true; - event.returnValue = false; + document.selection.empty(); } - else{ - event.stopPropagation(); - event.preventDefault(); + else if(!KQ){ + var sel = window.getSelection(); + sel.removeAllRanges(); } -return false; } - - /************************************************************************************/ /* Pages stuff */ /************************************************************************************/ diff --git a/frontends/php/js/dashboard.js b/frontends/php/js/dashboard.js new file mode 100644 index 00000000..280bcd9c --- /dev/null +++ b/frontends/php/js/dashboard.js @@ -0,0 +1,110 @@ +// JavaScript Document + +function add2favorites(){ + + var fav_form = document.getElementById('fav_form'); + if(!fav_form) throw "Object not found."; + + var favobj = fav_form.favobj.value; + var favid = fav_form.favid.value;; + + if(empty(favid)) return; + + var params = { + 'favobj': favobj, + 'favid': favid, + 'action': 'add' + } + + new Ajax.Request("dashboard.php?output=ajax", + { + 'method': 'post', + 'parameters':params, + 'onSuccess': function(resp){ },//alert(resp.responseText); + 'onFailure': function(){ document.location = 'dashboard.php?'+Object.toQueryString(params); } + } + ); +// json.onetime('dashboard.php?output=json&'+Object.toQueryString(params)); +} + +function rm4favorites(favobj,favid,menu_rowid){ +// alert(favobj+','+favid+','+menu_rowid); + + if(!isset(favobj) || !isset(favid)) throw "No agruments sent to function [rm4favorites()]."; +/* + var id='menu_'+favobj; + + var tmp_menu = new Array(); + for(var i=0; i < dashboard_submenu[id].length; i++){ + if(isset(dashboard_submenu[id][i]) && (i!=menu_rowid)){ + tmp_menu.push(dashboard_submenu[id][i]); + + } + } + dashboard_submenu[id] = tmp_menu; +*/ + var params = { + 'favobj': favobj, + 'favid': favid, + 'favcnt': menu_rowid, + 'action': 'remove' + } + + new Ajax.Request("dashboard.php?output=ajax", + { + 'method': 'post', + 'parameters':params, + 'onSuccess': function(resp){ }, + 'onFailure': function(){ document.location = 'dashboard.php?'+Object.toQueryString(params); } + } + ); + +// json.onetime('dashboard.php?output=json&'+Object.toQueryString(params)); +} + +function change_hat_state(icon, divid){ + if(!isset(icon) || !isset(divid)) throw "Function [change_hat_state()] awaits exactly 2 arguments."; + + deselectAll(); + var hat_state = ShowHide(divid); + switchElementsClass(icon,"arrowup","arrowdown"); + + if(false === hat_state) return false; + + var params = { + 'favobj': 'hat', + 'favid': divid, + 'state': hat_state + } + + new Ajax.Request("dashboard.php?output=ajax", + { + 'method': 'post', + 'parameters': params, + 'onFailure': function(){ document.location = 'dashboard.php?'+Object.toQueryString(params);} + } + ); +} + +function create_menu(e,id){ + if (!e) var e = window.event; + id='menu_'+id; + + var dbrd_menu = new Array(); + +//to create a copy of array, but not references!!!! + for(var i=0; i < dashboard_menu[id].length; i++){ + if(isset(dashboard_menu[id][i]) && !empty(dashboard_menu[id][i])) + dbrd_menu[i] = dashboard_menu[id][i].clone(); + } + + for(var i=0; i < dashboard_submenu[id].length; i++){ + if(isset(dashboard_submenu[id][i]) && !empty(dashboard_submenu[id][i])){ + var row = dashboard_submenu[id][i]; + var menu_row = new Array(row.name,"javascript: rm4favorites('"+row.favobj+"','"+row.favid+"','"+i+"');"); + dbrd_menu[dbrd_menu.length-1].push(menu_row); + } + } +//alert(dashboard_menu[id]); + show_popup_menu(e,dbrd_menu,280);// JavaScript Document +}
\ No newline at end of file diff --git a/frontends/php/js/json.js b/frontends/php/js/json.js new file mode 100644 index 00000000..797e314c --- /dev/null +++ b/frontends/php/js/json.js @@ -0,0 +1,105 @@ +// JavaScript Document +function callJSON(){ +// json.clean(); + json.createScript('dashboard.php?output=json'); + json.buildAll(); + json.addAll(); +} + +var json = { +scripts: new Array(), // array of existing scripts id's +nextId: 1, // id of next script tag + +head: '', // DOM Head obj + +initialize: function(){ + this.head = document.getElementsByTagName("head").item(0); +}, + +callBack: function(){ + if(this.callBack.arguments.length > 0) + alert(this.callBack.arguments[0]) + else + alert('callBack!'); +}, + +onetime: function(url){ + var onetimeid; + onetimeid = this.createScript(url); + this.buildScript(onetimeid); + this.addScript(onetimeid); +}, + +createScript: function(url){ + this.scripts[this.nextId] = { + 'id': this.nextId, + 'fullurl': url+'&jsscriptid='+this.nextId, + 'noCacheIE': '&noCacheIE=' + (new Date()).getTime(), + 'scriptId': 'JscriptId' + this.nextId, + 'status': 1 + }; +//SDI('create:' + this.nextId); + this.nextId++; +return (this.nextId-1); +}, + +buildScript: function(id){ + if(isset(id)){ + if(isset(this.scripts[id]) && !empty(this.scripts[id]) && (this.scripts[id].status == 1)){ + var scriptObj = document.createElement("script"); + + // Add script object attributes + scriptObj.setAttribute("type", "text/javascript"); + scriptObj.setAttribute("charset", "utf-8"); + + scriptObj.setAttribute("src", this.scripts[id].fullurl+this.scripts[id].noCacheIE); + + scriptObj.setAttribute("id", this.scripts[id].scriptId); + + this.scripts[id].scriptObj = scriptObj; + this.scripts[id].status = 2; + } + } +}, + +buildAll: function() { + for(var i=1; i < this.nextId; i++){ + this.buildScript(i); + } +}, + +addScript: function(id){ + if(isset(id)){ + if(isset(this.scripts[id]) && !empty(this.scripts[id]) && (this.scripts[id].status == 2)){ + this.head.appendChild(this.scripts[id].scriptObj); + this.scripts[id].status = 3; + } + } +}, + +addAll: function(){ + for(var i=1; i < this.nextId; i++){ + this.addScript(i); + } +}, + +removeScript: function(id){ + if(isset(id)){ + if(isset(this.scripts[id]) && !empty(this.scripts[id]) && (this.scripts[id].status == 3)){ +//SDI('remove:'+this.scripts[id].scriptId); + this.head.removeChild(this.scripts[id].scriptObj); + this.scripts[id] = null; + } + } +}, + +clean: function(){ + for(var i=1; i < this.nextId; i++){ + this.removeScript(i); + } + this.scripts = new Array(); + this.nextId = 1; +} +} + +json.initialize();
\ No newline at end of file diff --git a/frontends/php/js/menu.js b/frontends/php/js/menu.js index a6ec0d2c..8c0abc6f 100644 --- a/frontends/php/js/menu.js +++ b/frontends/php/js/menu.js @@ -431,8 +431,8 @@ function menu_item (o_parent, n_order) { new menu_item(this, n_order); } -function A_MENUS_onclick(){ return A_MENUS[this.o_root_n_id].onclick(this.this_n_id); } -function A_MENUS_onmouseout(){ return A_MENUS[this.o_root_n_id].onmouseout(this.this_n_id); } +function A_MENUS_onclick(){ return A_MENUS[this.o_root_n_id].onclick(this.this_n_id); } +function A_MENUS_onmouseout(){ return A_MENUS[this.o_root_n_id].onmouseout(this.this_n_id); }//false;}// function A_MENUS_onmouseover(){ return A_MENUS[this.o_root_n_id].onmouseover(this.this_n_id); } function A_MENUS_onmousedown(){ return A_MENUS[this.o_root_n_id].onmousedown(this.this_n_id); } diff --git a/frontends/php/js/prototype.js b/frontends/php/js/prototype.js index 053bde6a..93023a3e 100644 --- a/frontends/php/js/prototype.js +++ b/frontends/php/js/prototype.js @@ -1,27 +1,29 @@ -/* Prototype JavaScript framework, version 1.5.1.1 - * (c) 2005-2007 Sam Stephenson +/* Prototype JavaScript framework, version 1.6.0.2 + * (c) 2005-2008 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', + Version: '1.6.0.2', 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 + Gecko: navigator.userAgent.indexOf('Gecko') > -1 && navigator.userAgent.indexOf('KHTML') == -1, + MobileSafari: !!navigator.userAgent.match(/Apple.*Mobile.*Safari/) }, BrowserFeatures: { XPath: !!document.evaluate, ElementExtensions: !!window.HTMLElement, SpecificElementExtensions: - (document.createElement('div').__proto__ !== - document.createElement('form').__proto__) + document.createElement('div').__proto__ && + document.createElement('div').__proto__ !== + document.createElement('form').__proto__ }, ScriptFragment: '<script[^>]*>([\\S\\s]*?)<\/script>', @@ -29,31 +31,86 @@ var Prototype = { emptyFunction: function() { }, K: function(x) { return x } -} +}; + +if (Prototype.Browser.MobileSafari) + Prototype.BrowserFeatures.SpecificElementExtensions = false; + +/* Based on Alex Arnell's inheritance implementation. */ var Class = { create: function() { - return function() { + var parent = null, properties = $A(arguments); + if (Object.isFunction(properties[0])) + parent = properties.shift(); + + function klass() { this.initialize.apply(this, arguments); } + + Object.extend(klass, Class.Methods); + klass.superclass = parent; + klass.subclasses = []; + + if (parent) { + var subclass = function() { }; + subclass.prototype = parent.prototype; + klass.prototype = new subclass; + parent.subclasses.push(klass); + } + + for (var i = 0; i < properties.length; i++) + klass.addMethods(properties[i]); + + if (!klass.prototype.initialize) + klass.prototype.initialize = Prototype.emptyFunction; + + klass.prototype.constructor = klass; + + return klass; } -} +}; -var Abstract = new Object(); +Class.Methods = { + addMethods: function(source) { + var ancestor = this.superclass && this.superclass.prototype; + var properties = Object.keys(source); + + if (!Object.keys({ toString: true }).length) + properties.push("toString", "valueOf"); + + for (var i = 0, length = properties.length; i < length; i++) { + var property = properties[i], value = source[property]; + if (ancestor && Object.isFunction(value) && + value.argumentNames().first() == "$super") { + var method = value, value = Object.extend((function(m) { + return function() { return ancestor[m].apply(this, arguments) }; + })(property).wrap(method), { + valueOf: function() { return method }, + toString: function() { return method.toString() } + }); + } + this.prototype[property] = value; + } + + return this; + } +}; + +var Abstract = { }; Object.extend = function(destination, source) { - for (var property in 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.isUndefined(object)) return 'undefined'; if (object === null) return 'null'; - return object.inspect ? object.inspect() : object.toString(); + return object.inspect ? object.inspect() : String(object); } catch (e) { if (e instanceof RangeError) return '...'; throw e; @@ -62,24 +119,35 @@ Object.extend(Object, { toJSON: function(object) { var type = typeof object; - switch(type) { + 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; + if (Object.isElement(object)) return; + var results = []; for (var property in object) { var value = Object.toJSON(object[property]); - if (value !== undefined) + if (!Object.isUndefined(value)) results.push(property.toJSON() + ': ' + value); } + return '{' + results.join(', ') + '}'; }, + toQueryString: function(object) { + return $H(object).toQueryString(); + }, + + toHTML: function(object) { + return object && object.toHTML ? object.toHTML() : String.interpret(object); + }, + keys: function(object) { var keys = []; for (var property in object) @@ -95,55 +163,100 @@ Object.extend(Object, { }, clone: function(object) { - return Object.extend({}, object); + return Object.extend({ }, object); + }, + + isElement: function(object) { + return object && object.nodeType == 1; + }, + + isArray: function(object) { + return object != null && typeof object == "object" && + 'splice' in object && 'join' in object; + }, + + isHash: function(object) { + return object instanceof Hash; + }, + + isFunction: function(object) { + return typeof object == "function"; + }, + + isString: function(object) { + return typeof object == "string"; + }, + + isNumber: function(object) { + return typeof object == "number"; + }, + + isUndefined: function(object) { + return typeof object == "undefined"; } }); -Function.prototype.bind = function() { - var __method = this, args = $A(arguments), object = args.shift(); - return function() { - return __method.apply(object, args.concat($A(arguments))); - } -} +Object.extend(Function.prototype, { + argumentNames: function() { + var names = this.toString().match(/^[\s\(]*function[^(]*\((.*?)\)/)[1].split(",").invoke("strip"); + return names.length == 1 && !names[0] ? [] : names; + }, -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)); - } -} + bind: function() { + if (arguments.length < 2 && Object.isUndefined(arguments[0])) return this; + var __method = this, args = $A(arguments), object = args.shift(); + return function() { + return __method.apply(object, args.concat($A(arguments))); + } + }, -Object.extend(Number.prototype, { - toColorPart: function() { - return this.toPaddedString(2, 16); + bindAsEventListener: function() { + var __method = this, args = $A(arguments), object = args.shift(); + return function(event) { + return __method.apply(object, [event || window.event].concat(args)); + } }, - succ: function() { - return this + 1; + curry: function() { + if (!arguments.length) return this; + var __method = this, args = $A(arguments); + return function() { + return __method.apply(this, args.concat($A(arguments))); + } }, - times: function(iterator) { - $R(0, this, true).each(iterator); - return this; + delay: function() { + var __method = this, args = $A(arguments), timeout = args.shift() * 1000; + return window.setTimeout(function() { + return __method.apply(__method, args); + }, timeout); }, - toPaddedString: function(length, radix) { - var string = this.toString(radix || 10); - return '0'.times(length - string.length) + string; + wrap: function(wrapper) { + var __method = this; + return function() { + return wrapper.apply(this, [__method.bind(this)].concat($A(arguments))); + } }, - toJSON: function() { - return isFinite(this) ? this.toString() : 'null'; + methodize: function() { + if (this._methodized) return this._methodized; + var __method = this; + return this._methodized = function() { + return __method.apply(null, [this].concat($A(arguments))); + }; } }); +Function.prototype.defer = Function.prototype.delay.curry(0.01); + 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) + '"'; + return '"' + this.getUTCFullYear() + '-' + + (this.getUTCMonth() + 1).toPaddedString(2) + '-' + + this.getUTCDate().toPaddedString(2) + 'T' + + this.getUTCHours().toPaddedString(2) + ':' + + this.getUTCMinutes().toPaddedString(2) + ':' + + this.getUTCSeconds().toPaddedString(2) + 'Z"'; }; var Try = { @@ -155,17 +268,22 @@ var Try = { try { returnValue = lambda(); break; - } catch (e) {} + } catch (e) { } } return returnValue; } -} +}; + +RegExp.prototype.match = RegExp.prototype.test; + +RegExp.escape = function(str) { + return String(str).replace(/([.*+?^=!:${}()|[\]\/\\])/g, '\\$1'); +}; /*--------------------------------------------------------------------------*/ -var PeriodicalExecuter = Class.create(); -PeriodicalExecuter.prototype = { +var PeriodicalExecuter = Class.create({ initialize: function(callback, frequency) { this.callback = callback; this.frequency = frequency; @@ -178,6 +296,10 @@ PeriodicalExecuter.prototype = { this.timer = setInterval(this.onTimerEvent.bind(this), this.frequency * 1000); }, + execute: function() { + this.callback(this); + }, + stop: function() { if (!this.timer) return; clearInterval(this.timer); @@ -188,13 +310,13 @@ PeriodicalExecuter.prototype = { if (!this.currentlyExecuting) { try { this.currentlyExecuting = true; - this.callback(this); + this.execute(); } finally { this.currentlyExecuting = false; } } } -} +}); Object.extend(String, { interpret: function(value) { return value == null ? '' : String(value); @@ -228,7 +350,7 @@ Object.extend(String.prototype, { sub: function(pattern, replacement, count) { replacement = this.gsub.prepareReplacement(replacement); - count = count === undefined ? 1 : count; + count = Object.isUndefined(count) ? 1 : count; return this.gsub(pattern, function(match) { if (--count < 0) return match[0]; @@ -238,14 +360,14 @@ Object.extend(String.prototype, { scan: function(pattern, iterator) { this.gsub(pattern, iterator); - return this; + return String(this); }, truncate: function(length, truncation) { length = length || 30; - truncation = truncation === undefined ? '...' : truncation; + truncation = Object.isUndefined(truncation) ? '...' : truncation; return this.length > length ? - this.slice(0, length - truncation.length) + truncation : this; + this.slice(0, length - truncation.length) + truncation : String(this); }, strip: function() { @@ -279,7 +401,7 @@ Object.extend(String.prototype, { }, unescapeHTML: function() { - var div = document.createElement('div'); + var div = new Element('div'); div.innerHTML = this.stripTags(); return div.childNodes[0] ? (div.childNodes.length > 1 ? $A(div.childNodes).inject('', function(memo, node) { return memo+node.nodeValue }) : @@ -288,16 +410,16 @@ Object.extend(String.prototype, { toQueryParams: function(separator) { var match = this.strip().match(/([^?#]*)(#.*)?$/); - if (!match) return {}; + if (!match) return { }; - return match[1].split(separator || '&').inject({}, function(hash, pair) { + 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]]; + if (!Object.isArray(hash[key])) hash[key] = [hash[key]]; hash[key].push(value); } else hash[key] = value; @@ -316,9 +438,7 @@ Object.extend(String.prototype, { }, times: function(count) { - var result = ''; - for (var i = 0; i < count; i++) result += this; - return result; + return count < 1 ? '' : new Array(count + 1).join(this); }, camelize: function() { @@ -365,7 +485,9 @@ Object.extend(String.prototype, { }, isJSON: function() { - var str = this.replace(/\\./g, '@').replace(/"[^"\\\n\r]*"/g, ''); + var str = this; + if (str.blank()) return false; + str = this.replace(/\\./g, '@').replace(/"[^"\\\n\r]*"/g, ''); return (/^[,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t]*$/).test(str); }, @@ -396,6 +518,10 @@ Object.extend(String.prototype, { blank: function() { return /^\s*$/.test(this); + }, + + interpolate: function(object, pattern) { + return new Template(this, pattern).evaluate(object); } }); @@ -409,10 +535,10 @@ if (Prototype.Browser.WebKit || Prototype.Browser.IE) Object.extend(String.proto }); String.prototype.gsub.prepareReplacement = function(replacement) { - if (typeof replacement == 'function') return replacement; + if (Object.isFunction(replacement)) return replacement; var template = new Template(replacement); return function(match) { return template.evaluate(match) }; -} +}; String.prototype.parseQuery = String.prototype.toQueryParams; @@ -423,28 +549,47 @@ Object.extend(String.prototype.escapeHTML, { with (String.prototype.escapeHTML) div.appendChild(text); -var Template = Class.create(); -Template.Pattern = /(^|.|\r|\n)(#\{(.*?)\})/; -Template.prototype = { +var Template = Class.create({ initialize: function(template, pattern) { this.template = template.toString(); - this.pattern = pattern || Template.Pattern; + this.pattern = pattern || Template.Pattern; }, evaluate: function(object) { + if (Object.isFunction(object.toTemplateReplacements)) + object = object.toTemplateReplacements(); + return this.template.gsub(this.pattern, function(match) { - var before = match[1]; + if (object == null) return ''; + + var before = match[1] || ''; if (before == '\\') return match[2]; - return before + String.interpret(object[match[3]]); + + var ctx = object, expr = match[3]; + var pattern = /^([^.[]+|\[((?:.*?[^\\])?)\])(\.|\[|$)/; + match = pattern.exec(expr); + if (match == null) return before; + + while (match != null) { + var comp = match[1].startsWith('[') ? match[2].gsub('\\\\]', ']') : match[1]; + ctx = ctx[comp]; + if (null == ctx || '' == match[3]) break; + expr = expr.substring('[' == match[3] ? match[1].length : match[0].length); + match = pattern.exec(expr); + } + + return before + String.interpret(ctx); }); } -} +}); +Template.Pattern = /(^|.|\r|\n)(#\{(.*?)\})/; -var $break = {}, $continue = new Error('"throw $continue" is deprecated, use "return" instead'); +var $break = { }; var Enumerable = { - each: function(iterator) { + each: function(iterator, context) { var index = 0; + iterator = iterator.bind(context); try { this._each(function(value) { iterator(value, index++); @@ -455,40 +600,45 @@ var Enumerable = { return this; }, - eachSlice: function(number, iterator) { + eachSlice: function(number, iterator, context) { + iterator = iterator ? iterator.bind(context) : Prototype.K; var index = -number, slices = [], array = this.toArray(); while ((index += number) < array.length) slices.push(array.slice(index, index+number)); - return slices.map(iterator); + return slices.collect(iterator, context); }, - all: function(iterator) { + all: function(iterator, context) { + iterator = iterator ? iterator.bind(context) : Prototype.K; var result = true; this.each(function(value, index) { - result = result && !!(iterator || Prototype.K)(value, index); + result = result && !!iterator(value, index); if (!result) throw $break; }); return result; }, - any: function(iterator) { + any: function(iterator, context) { + iterator = iterator ? iterator.bind(context) : Prototype.K; var result = false; this.each(function(value, index) { - if (result = !!(iterator || Prototype.K)(value, index)) + if (result = !!iterator(value, index)) throw $break; }); return result; }, - collect: function(iterator) { + collect: function(iterator, context) { + iterator = iterator ? iterator.bind(context) : Prototype.K; var results = []; this.each(function(value, index) { - results.push((iterator || Prototype.K)(value, index)); + results.push(iterator(value, index)); }); return results; }, - detect: function(iterator) { + detect: function(iterator, context) { + iterator = iterator.bind(context); var result; this.each(function(value, index) { if (iterator(value, index)) { @@ -499,7 +649,8 @@ var Enumerable = { return result; }, - findAll: function(iterator) { + findAll: function(iterator, context) { + iterator = iterator.bind(context); var results = []; this.each(function(value, index) { if (iterator(value, index)) @@ -508,17 +659,24 @@ var Enumerable = { return results; }, - grep: function(pattern, iterator) { + grep: function(filter, iterator, context) { + iterator = iterator ? iterator.bind(context) : Prototype.K; var results = []; + + if (Object.isString(filter)) + filter = new RegExp(filter); + this.each(function(value, index) { - var stringValue = value.toString(); - if (stringValue.match(pattern)) - results.push((iterator || Prototype.K)(value, index)); - }) + if (filter.match(value)) + results.push(iterator(value, index)); + }); return results; }, include: function(object) { + if (Object.isFunction(this.indexOf)) + if (this.indexOf(object) != -1) return true; + var found = false; this.each(function(value) { if (value == object) { @@ -530,14 +688,15 @@ var Enumerable = { }, inGroupsOf: function(number, fillWith) { - fillWith = fillWith === undefined ? null : fillWith; + fillWith = Object.isUndefined(fillWith) ? null : fillWith; return this.eachSlice(number, function(slice) { while(slice.length < number) slice.push(fillWith); return slice; }); }, - inject: function(memo, iterator) { + inject: function(memo, iterator, context) { + iterator = iterator.bind(context); this.each(function(value, index) { memo = iterator(memo, value, index); }); @@ -551,30 +710,33 @@ var Enumerable = { }); }, - max: function(iterator) { + max: function(iterator, context) { + iterator = iterator ? iterator.bind(context) : Prototype.K; var result; this.each(function(value, index) { - value = (iterator || Prototype.K)(value, index); - if (result == undefined || value >= result) + value = iterator(value, index); + if (result == null || value >= result) result = value; }); return result; }, - min: function(iterator) { + min: function(iterator, context) { + iterator = iterator ? iterator.bind(context) : Prototype.K; var result; this.each(function(value, index) { - value = (iterator || Prototype.K)(value, index); - if (result == undefined || value < result) + value = iterator(value, index); + if (result == null || value < result) result = value; }); return result; }, - partition: function(iterator) { + partition: function(iterator, context) { + iterator = iterator ? iterator.bind(context) : Prototype.K; var trues = [], falses = []; this.each(function(value, index) { - ((iterator || Prototype.K)(value, index) ? + (iterator(value, index) ? trues : falses).push(value); }); return [trues, falses]; @@ -582,13 +744,14 @@ var Enumerable = { pluck: function(property) { var results = []; - this.each(function(value, index) { + this.each(function(value) { results.push(value[property]); }); return results; }, - reject: function(iterator) { + reject: function(iterator, context) { + iterator = iterator.bind(context); var results = []; this.each(function(value, index) { if (!iterator(value, index)) @@ -597,7 +760,8 @@ var Enumerable = { return results; }, - sortBy: function(iterator) { + sortBy: function(iterator, context) { + iterator = iterator.bind(context); return this.map(function(value, index) { return {value: value, criteria: iterator(value, index)}; }).sort(function(left, right) { @@ -612,7 +776,7 @@ var Enumerable = { zip: function() { var iterator = Prototype.K, args = $A(arguments); - if (typeof args.last() == 'function') + if (Object.isFunction(args.last())) iterator = args.pop(); var collections = [this].concat(args).map($A); @@ -628,46 +792,42 @@ var Enumerable = { inspect: function() { return '#<Enumerable:' + this.toArray().inspect() + '>'; } -} +}; Object.extend(Enumerable, { map: Enumerable.collect, find: Enumerable.detect, select: Enumerable.findAll, + filter: Enumerable.findAll, member: Enumerable.include, - entries: Enumerable.toArray + entries: Enumerable.toArray, + every: Enumerable.all, + some: Enumerable.any }); -var $A = Array.from = function(iterable) { +function $A(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 (iterable.toArray) return iterable.toArray(); + var length = iterable.length || 0, results = new Array(length); + while (length--) results[length] = iterable[length]; + return results; } if (Prototype.Browser.WebKit) { - $A = Array.from = function(iterable) { + $A = 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; - } - } + if (!(Object.isFunction(iterable) && iterable == '[object NodeList]') && + iterable.toArray) return iterable.toArray(); + var length = iterable.length || 0, results = new Array(length); + while (length--) results[length] = iterable[length]; + return results; + }; } +Array.from = $A; + Object.extend(Array.prototype, Enumerable); -if (!Array.prototype._reverse) - Array.prototype._reverse = Array.prototype.reverse; +if (!Array.prototype._reverse) Array.prototype._reverse = Array.prototype.reverse; Object.extend(Array.prototype, { _each: function(iterator) { @@ -696,7 +856,7 @@ Object.extend(Array.prototype, { flatten: function() { return this.inject([], function(array, value) { - return array.concat(value && value.constructor == Array ? + return array.concat(Object.isArray(value) ? value.flatten() : [value]); }); }, @@ -708,12 +868,6 @@ Object.extend(Array.prototype, { }); }, - 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(); }, @@ -730,6 +884,12 @@ Object.extend(Array.prototype, { }); }, + intersect: function(array) { + return this.uniq().findAll(function(item) { + return array.detect(function(value) { return item === value }); + }); + }, + clone: function() { return [].concat(this); }, @@ -746,15 +906,35 @@ Object.extend(Array.prototype, { var results = []; this.each(function(object) { var value = Object.toJSON(object); - if (value !== undefined) results.push(value); + if (!Object.isUndefined(value)) results.push(value); }); return '[' + results.join(', ') + ']'; } }); +// use native browser JS 1.6 implementation if available +if (Object.isFunction(Array.prototype.forEach)) + Array.prototype._each = Array.prototype.forEach; + +if (!Array.prototype.indexOf) Array.prototype.indexOf = function(item, i) { + i || (i = 0); + var length = this.length; + if (i < 0) i = length + i; + for (; i < length; i++) + if (this[i] === item) return i; + return -1; +}; + +if (!Array.prototype.lastIndexOf) Array.prototype.lastIndexOf = function(item, i) { + i = isNaN(i) ? this.length : (i < 0 ? this.length + i : i) + 1; + var n = this.slice(0, i).reverse().indexOf(item); + return (n < 0) ? n : i - n - 1; +}; + Array.prototype.toArray = Array.prototype.clone; function $w(string) { + if (!Object.isString(string)) return []; string = string.strip(); return string ? string.split(/\s+/) : []; } @@ -764,7 +944,7 @@ if (Prototype.Browser.Opera){ 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) { + if (Object.isArray(arguments[i])) { for (var j = 0, arrayLength = arguments[i].length; j < arrayLength; j++) array.push(arguments[i][j]); } else { @@ -772,136 +952,135 @@ if (Prototype.Browser.Opera){ } } 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; +Object.extend(Number.prototype, { + toColorPart: function() { + return this.toPaddedString(2, 16); + }, - this.prototype._each.call(obj, function(pair) { - if (!pair.key) return; - var value = pair.value; + succ: function() { + return this + 1; + }, - if (value && typeof value == 'object') { - if (value.constructor == Array) value.each(function(value) { - parts.add(pair.key, value); - }); - return; - } - parts.add(pair.key, value); - }); + times: function(iterator) { + $R(0, this, true).each(iterator); + return this; + }, - return parts.join('&'); + toPaddedString: function(length, radix) { + var string = this.toString(radix || 10); + return '0'.times(length - string.length) + string; }, - 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(', ') + '}'; + toJSON: function() { + return isFinite(this) ? this.toString() : 'null'; } }); -Hash.toQueryString.addPair = function(key, value, prefix) { - key = encodeURIComponent(key); - if (value === undefined) this.push(key); - else this.push(key + '=' + (value == null ? '' : encodeURIComponent(value))); -} +$w('abs round ceil floor').each(function(method){ + Number.prototype[method] = Math[method].methodize(); +}); +function $H(object) { + return new Hash(object); +}; -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 Hash = Class.create(Enumerable, (function() { - var pair = [key, value]; - pair.key = key; - pair.value = value; - iterator(pair); - } - }, + function toQueryPair(key, value) { + if (Object.isUndefined(value)) return key; + return key + '=' + encodeURIComponent(String.interpret(value)); + } - keys: function() { - return this.pluck('key'); - }, + return { + initialize: function(object) { + this._object = Object.isHash(object) ? object.toObject() : Object.clone(object); + }, - values: function() { - return this.pluck('value'); - }, + _each: function(iterator) { + for (var key in this._object) { + var value = this._object[key], pair = [key, value]; + pair.key = key; + pair.value = value; + iterator(pair); + } + }, - merge: function(hash) { - return $H(hash).inject(this, function(mergedHash, pair) { - mergedHash[pair.key] = pair.value; - return mergedHash; - }); - }, + set: function(key, value) { + return this._object[key] = value; + }, - 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; - }, + get: function(key) { + return this._object[key]; + }, - toQueryString: function() { - return Hash.toQueryString(this); - }, + unset: function(key) { + var value = this._object[key]; + delete this._object[key]; + return value; + }, - inspect: function() { - return '#<Hash:{' + this.map(function(pair) { - return pair.map(Object.inspect).join(': '); - }).join(', ') + '}>'; - }, + toObject: function() { + return Object.clone(this._object); + }, - toJSON: function() { - return Hash.toJSON(this); - } -}); + keys: function() { + return this.pluck('key'); + }, -function $H(object) { - if (object instanceof Hash) return object; - return new Hash(object); -}; + values: function() { + return this.pluck('value'); + }, + + index: function(value) { + var match = this.detect(function(pair) { + return pair.value === value; + }); + return match && match.key; + }, + + merge: function(object) { + return this.clone().update(object); + }, + + update: function(object) { + return new Hash(object).inject(this, function(result, pair) { + result.set(pair.key, pair.value); + return result; + }); + }, + + toQueryString: function() { + return this.map(function(pair) { + var key = encodeURIComponent(pair.key), values = pair.value; + + if (values && typeof values == 'object') { + if (Object.isArray(values)) + return values.map(toQueryPair.curry(key)).join('&'); + } + return toQueryPair(key, values); + }).join('&'); + }, + + inspect: function() { + return '#<Hash:{' + this.map(function(pair) { + return pair.map(Object.inspect).join(': '); + }).join(', ') + '}>'; + }, -// 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); + toJSON: function() { + return Object.toJSON(this.toObject()); + }, + + clone: function() { + return new Hash(this); + } } -}; -ObjectRange = Class.create(); -Object.extend(ObjectRange.prototype, Enumerable); -Object.extend(ObjectRange.prototype, { +})()); + +Hash.prototype.toTemplateReplacements = Hash.prototype.toObject; +Hash.from = $H; +var ObjectRange = Class.create(Enumerable, { initialize: function(start, end, exclusive) { this.start = start; this.end = end; @@ -927,7 +1106,7 @@ Object.extend(ObjectRange.prototype, { var $R = function(start, end, exclusive) { return new ObjectRange(start, end, exclusive); -} +}; var Ajax = { getTransport: function() { @@ -939,7 +1118,7 @@ var Ajax = { }, activeRequestCount: 0 -} +}; Ajax.Responders = { responders: [], @@ -959,10 +1138,10 @@ Ajax.Responders = { dispatch: function(callback, request, transport, json) { this.each(function(responder) { - if (typeof responder[callback] == 'function') { + if (Object.isFunction(responder[callback])) { try { responder[callback].apply(responder, [request, transport, json]); - } catch (e) {} + } catch (e) { } } }); } @@ -971,42 +1150,38 @@ Ajax.Responders = { Object.extend(Ajax.Responders, Enumerable); Ajax.Responders.register({ - onCreate: function() { - Ajax.activeRequestCount++; - }, - onComplete: function() { - Ajax.activeRequestCount--; - } + onCreate: function() { Ajax.activeRequestCount++ }, + onComplete: function() { Ajax.activeRequestCount-- } }); -Ajax.Base = function() {}; -Ajax.Base.prototype = { - setOptions: function(options) { +Ajax.Base = Class.create({ + initialize: function(options) { this.options = { method: 'post', asynchronous: true, contentType: 'application/x-www-form-urlencoded', encoding: 'UTF-8', - parameters: '' - } - Object.extend(this.options, options || {}); + parameters: '', + evalJSON: true, + evalJS: true + }; + Object.extend(this.options, options || { }); this.options.method = this.options.method.toLowerCase(); - if (typeof this.options.parameters == 'string') + + if (Object.isString(this.options.parameters)) this.options.parameters = this.options.parameters.toQueryParams(); + else if (Object.isHash(this.options.parameters)) + this.options.parameters = this.options.parameters.toObject(); } -} - -Ajax.Request = Class.create(); -Ajax.Request.Events = - ['Uninitialized', 'Loading', 'Loaded', 'Interactive', 'Complete']; +}); -Ajax.Request.prototype = Object.extend(new Ajax.Base(), { +Ajax.Request = Class.create(Ajax.Base, { _complete: false, - initialize: function(url, options) { + initialize: function($super, url, options) { + $super(options); this.transport = Ajax.getTransport(); - this.setOptions(options); this.request(url); }, @@ -1023,7 +1198,7 @@ Ajax.Request.prototype = Object.extend(new Ajax.Base(), { this.parameters = params; - if (params = Hash.toQueryString(params)) { + if (params = Object.toQueryString(params)) { // when GET, append parameters to URL if (this.method == 'get') this.url += (this.url.include('?') ? '&' : '?') + params; @@ -1032,14 +1207,14 @@ Ajax.Request.prototype = Object.extend(new Ajax.Base(), { } try { - if (this.options.onCreate) this.options.onCreate(this.transport); - Ajax.Responders.dispatch('onCreate', this, this.transport); + var response = new Ajax.Response(this); + if (this.options.onCreate) this.options.onCreate(response); + Ajax.Responders.dispatch('onCreate', this, response); this.transport.open(this.method.toUpperCase(), this.url, this.options.asynchronous); - if (this.options.asynchronous) - setTimeout(function() { this.respondToReadyState(1) }.bind(this), 10); + if (this.options.asynchronous) this.respondToReadyState.bind(this).defer(1); this.transport.onreadystatechange = this.onStateChange.bind(this); this.setRequestHeaders(); @@ -1087,7 +1262,7 @@ Ajax.Request.prototype = Object.extend(new Ajax.Base(), { if (typeof this.options.requestHeaders == 'object') { var extras = this.options.requestHeaders; - if (typeof extras.push == 'function') + if (Object.isFunction(extras.push)) for (var i = 0, length = extras.length; i < length; i += 2) headers[extras[i]] = extras[i+1]; else @@ -1099,33 +1274,39 @@ Ajax.Request.prototype = Object.extend(new Ajax.Base(), { }, success: function() { - return !this.transport.status - || (this.transport.status >= 200 && this.transport.status < 300); + var status = this.getStatus(); + return !status || (status >= 200 && status < 300); + }, + + getStatus: function() { + try { + return this.transport.status || 0; + } catch (e) { return 0 } }, respondToReadyState: function(readyState) { - var state = Ajax.Request.Events[readyState]; - var transport = this.transport, json = this.evalJSON(); + var state = Ajax.Request.Events[readyState], response = new Ajax.Response(this); if (state == 'Complete') { try { this._complete = true; - (this.options['on' + this.transport.status] + (this.options['on' + response.status] || this.options['on' + (this.success() ? 'Success' : 'Failure')] - || Prototype.emptyFunction)(transport, json); + || Prototype.emptyFunction)(response, response.headerJSON); } 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(); + var contentType = response.getHeader('Content-type'); + if (this.options.evalJS == 'force' + || (this.options.evalJS && this.isSameOrigin() && contentType + && contentType.match(/^\s*(text|application)\/(x-)?(java|ecma)script(;.*)?\s*$/i))) + this.evalResponse(); } try { - (this.options['on' + state] || Prototype.emptyFunction)(transport, json); - Ajax.Responders.dispatch('on' + state, this, transport, json); + (this.options['on' + state] || Prototype.emptyFunction)(response, response.headerJSON); + Ajax.Responders.dispatch('on' + state, this, response, response.headerJSON); } catch (e) { this.dispatchException(e); } @@ -1136,16 +1317,18 @@ Ajax.Request.prototype = Object.extend(new Ajax.Base(), { } }, - getHeader: function(name) { - try { - return this.transport.getResponseHeader(name); - } catch (e) { return null } + isSameOrigin: function() { + var m = this.url.match(/^\s*https?:\/\/[^\/]*/); + return !m || (m[0] == '#{protocol}//#{domain}#{port}'.interpolate({ + protocol: location.protocol, + domain: document.domain, + port: location.port ? ':' + location.port : '' + })); }, - evalJSON: function() { + getHeader: function(name) { try { - var json = this.getHeader('X-JSON'); - return json ? json.evalJSON() : null; + return this.transport.getResponseHeader(name) || null; } catch (e) { return null } }, @@ -1163,57 +1346,128 @@ Ajax.Request.prototype = Object.extend(new Ajax.Base(), { } }); -Ajax.Updater = Class.create(); +Ajax.Request.Events = + ['Uninitialized', 'Loading', 'Loaded', 'Interactive', 'Complete']; + +Ajax.Response = Class.create({ + initialize: function(request){ + this.request = request; + var transport = this.transport = request.transport, + readyState = this.readyState = transport.readyState; + + if((readyState > 2 && !Prototype.Browser.IE) || readyState == 4) { + this.status = this.getStatus(); + this.statusText = this.getStatusText(); + this.responseText = String.interpret(transport.responseText); + this.headerJSON = this._getHeaderJSON(); + } + + if(readyState == 4) { + var xml = transport.responseXML; + this.responseXML = Object.isUndefined(xml) ? null : xml; + this.responseJSON = this._getResponseJSON(); + } + }, + + status: 0, + statusText: '', + + getStatus: Ajax.Request.prototype.getStatus, + + getStatusText: function() { + try { + return this.transport.statusText || ''; + } catch (e) { return '' } + }, + + getHeader: Ajax.Request.prototype.getHeader, + + getAllHeaders: function() { + try { + return this.getAllResponseHeaders(); + } catch (e) { return null } + }, + + getResponseHeader: function(name) { + return this.transport.getResponseHeader(name); + }, + + getAllResponseHeaders: function() { + return this.transport.getAllResponseHeaders(); + }, + + _getHeaderJSON: function() { + var json = this.getHeader('X-JSON'); + if (!json) return null; + json = decodeURIComponent(escape(json)); + try { + return json.evalJSON(this.request.options.sanitizeJSON || + !this.request.isSameOrigin()); + } catch (e) { + this.request.dispatchException(e); + } + }, + + _getResponseJSON: function() { + var options = this.request.options; + if (!options.evalJSON || (options.evalJSON != 'force' && + !(this.getHeader('Content-type') || '').include('application/json')) || + this.responseText.blank()) + return null; + try { + return this.responseText.evalJSON(options.sanitizeJSON || + !this.request.isSameOrigin()); + } catch (e) { + this.request.dispatchException(e); + } + } +}); -Object.extend(Object.extend(Ajax.Updater.prototype, Ajax.Request.prototype), { - initialize: function(container, url, options) { +Ajax.Updater = Class.create(Ajax.Request, { + initialize: function($super, 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); + options = Object.clone(options); + var onComplete = options.onComplete; + options.onComplete = (function(response, json) { + this.updateContent(response.responseText); + if (Object.isFunction(onComplete)) onComplete(response, json); }).bind(this); - this.request(url); + $super(url, options); }, - updateContent: function() { - var receiver = this.container[this.success() ? 'success' : 'failure']; - var response = this.transport.responseText; + updateContent: function(responseText) { + var receiver = this.container[this.success() ? 'success' : 'failure'], + options = this.options; - if (!this.options.evalScripts) response = response.stripScripts(); + if (!options.evalScripts) responseText = responseText.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); + if (options.insertion) { + if (Object.isString(options.insertion)) { + var insertion = { }; insertion[options.insertion] = responseText; + receiver.insert(insertion); + } + else options.insertion(receiver, responseText); + } + else receiver.update(responseText); } } }); -Ajax.PeriodicalUpdater = Class.create(); -Ajax.PeriodicalUpdater.prototype = Object.extend(new Ajax.Base(), { - initialize: function(container, url, options) { - this.setOptions(options); +Ajax.PeriodicalUpdater = Class.create(Ajax.Base, { + initialize: function($super, container, url, options) { + $super(options); this.onComplete = this.options.onComplete; this.frequency = (this.options.frequency || 2); this.decay = (this.options.decay || 1); - this.updater = {}; + this.updater = { }; this.container = container; this.url = url; @@ -1231,15 +1485,14 @@ Ajax.PeriodicalUpdater.prototype = Object.extend(new Ajax.Base(), { (this.onComplete || Prototype.emptyFunction).apply(this, arguments); }, - updateComplete: function(request) { + updateComplete: function(response) { if (this.options.decay) { - this.decay = (request.responseText == this.lastText ? + this.decay = (response.responseText == this.lastText ? this.decay * this.options.decay : 1); - this.lastText = request.responseText; + this.lastText = response.responseText; } - this.timer = setTimeout(this.onTimerEvent.bind(this), - this.decay * this.frequency * 1000); + this.timer = this.onTimerEvent.bind(this).delay(this.decay * this.frequency); }, onTimerEvent: function() { @@ -1252,7 +1505,7 @@ function $(element) { elements.push($(arguments[i])); return elements; } - if (typeof element == 'string') + if (Object.isString(element)) element = document.getElementById(element); return Element.extend(element); } @@ -1263,67 +1516,51 @@ if (Prototype.BrowserFeatures.XPath) { 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)); + results.push(Element.extend(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; -}; +if (!window.Node) var Node = { }; + +if (!Node.ELEMENT_NODE) { + // DOM level 2 ECMAScript Language Binding + Object.extend(Node, { + ELEMENT_NODE: 1, + ATTRIBUTE_NODE: 2, + TEXT_NODE: 3, + CDATA_SECTION_NODE: 4, + ENTITY_REFERENCE_NODE: 5, + ENTITY_NODE: 6, + PROCESSING_INSTRUCTION_NODE: 7, + COMMENT_NODE: 8, + DOCUMENT_NODE: 9, + DOCUMENT_TYPE_NODE: 10, + DOCUMENT_FRAGMENT_NODE: 11, + NOTATION_NODE: 12 + }); +} -Element.extend.cache = { - findOrStore: function(value) { - return this[value] = this[value] || function() { - return value.apply(null, [this].concat($A(arguments))); +(function() { + var element = this.Element; + this.Element = function(tagName, attributes) { + attributes = attributes || { }; + tagName = tagName.toLowerCase(); + var cache = Element.cache; + if (Prototype.Browser.IE && attributes.name) { + tagName = '<' + tagName + ' name="' + attributes.name + '">'; + delete attributes.name; + return Element.writeAttribute(document.createElement(tagName), attributes); } - } -}; + if (!cache[tagName]) cache[tagName] = Element.extend(document.createElement(tagName)); + return Element.writeAttribute(cache[tagName].cloneNode(false), attributes); + }; + Object.extend(this.Element, element || { }); +}).call(window); + +Element.cache = { }; Element.Methods = { visible: function(element) { @@ -1339,7 +1576,6 @@ Element.Methods = { hide: function(element) { $(element).style.display = 'none'; return element; - }, show: function(element) { @@ -1353,28 +1589,78 @@ Element.Methods = { return element; }, - update: function(element, html) { - html = typeof html == 'undefined' ? '' : html.toString(); - $(element).innerHTML = html.stripScripts(); - setTimeout(function() {html.evalScripts()}, 10); + update: function(element, content) { + element = $(element); + if (content && content.toElement) content = content.toElement(); + if (Object.isElement(content)) return element.update().insert(content); + content = Object.toHTML(content); + element.innerHTML = content.stripScripts(); + content.evalScripts.bind(content).defer(); return element; }, - replace: function(element, html) { + replace: function(element, content) { element = $(element); - html = typeof html == 'undefined' ? '' : html.toString(); - if (element.outerHTML) { - element.outerHTML = html.stripScripts(); - } else { + if (content && content.toElement) content = content.toElement(); + else if (!Object.isElement(content)) { + content = Object.toHTML(content); var range = element.ownerDocument.createRange(); - range.selectNodeContents(element); - element.parentNode.replaceChild( - range.createContextualFragment(html.stripScripts()), element); + range.selectNode(element); + content.evalScripts.bind(content).defer(); + content = range.createContextualFragment(content.stripScripts()); + } + element.parentNode.replaceChild(content, element); + return element; + }, + + insert: function(element, insertions) { + element = $(element); + + if (Object.isString(insertions) || Object.isNumber(insertions) || + Object.isElement(insertions) || (insertions && (insertions.toElement || insertions.toHTML))) + insertions = {bottom:insertions}; + + var content, insert, tagName, childNodes; + + for (var position in insertions) { + content = insertions[position]; + position = position.toLowerCase(); + insert = Element._insertionTranslations[position]; + + if (content && content.toElement) content = content.toElement(); + if (Object.isElement(content)) { + insert(element, content); + continue; + } + + content = Object.toHTML(content); + + tagName = ((position == 'before' || position == 'after') + ? element.parentNode : element).tagName.toUpperCase(); + + childNodes = Element._getContentFromAnonymousElement(tagName, content.stripScripts()); + + if (position == 'top' || position == 'after') childNodes.reverse(); + childNodes.each(insert.curry(element)); + + content.evalScripts.bind(content).defer(); } - setTimeout(function() {html.evalScripts()}, 10); + return element; }, + wrap: function(element, wrapper, attributes) { + element = $(element); + if (Object.isElement(wrapper)) + $(wrapper).writeAttribute(attributes || { }); + else if (Object.isString(wrapper)) wrapper = new Element(wrapper, attributes); + else wrapper = new Element('div', wrapper); + if (element.parentNode) + element.parentNode.replaceChild(wrapper, element); + wrapper.appendChild(element); + return wrapper; + }, + inspect: function(element) { element = $(element); var result = '<' + element.tagName.toLowerCase(); @@ -1400,7 +1686,7 @@ Element.Methods = { }, descendants: function(element) { - return $A($(element).getElementsByTagName('*')).each(Element.extend); + return $(element).select("*"); }, firstDescendant: function(element) { @@ -1430,7 +1716,7 @@ Element.Methods = { }, match: function(element, selector) { - if (typeof selector == 'string') + if (Object.isString(selector)) selector = new Selector(selector); return selector.match($(element)); }, @@ -1439,56 +1725,86 @@ Element.Methods = { element = $(element); if (arguments.length == 1) return $(element.parentNode); var ancestors = element.ancestors(); - return expression ? Selector.findElement(ancestors, expression, index) : - ancestors[index || 0]; + return Object.isNumber(expression) ? ancestors[expression] : + Selector.findElement(ancestors, expression, index); }, 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]; + return Object.isNumber(expression) ? element.descendants()[expression] : + element.select(expression)[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]; + return Object.isNumber(expression) ? previousSiblings[expression] : + Selector.findElement(previousSiblings, expression, index); }, 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]; + return Object.isNumber(expression) ? nextSiblings[expression] : + Selector.findElement(nextSiblings, expression, index); }, - getElementsBySelector: function() { + select: function() { var args = $A(arguments), element = $(args.shift()); return Selector.findChildElements(element, args); }, - getElementsByClassName: function(element, className) { - return document.getElementsByClassName(className, element); + adjacent: function() { + var args = $A(arguments), element = $(args.shift()); + return Selector.findChildElements(element.parentNode, args).without(element); + }, + + identify: function(element) { + element = $(element); + var id = element.readAttribute('id'), self = arguments.callee; + if (id) return id; + do { id = 'anonymous_element_' + self.counter++ } while ($(id)); + element.writeAttribute('id', id); + return id; }, readAttribute: function(element, name) { element = $(element); if (Prototype.Browser.IE) { - if (!element.attributes) return null; - var t = Element._attributeTranslations; + var t = Element._attributeTranslations.read; 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; + if (t.names[name]) name = t.names[name]; + if (name.include(':')) { + return (!element.attributes || !element.attributes[name]) ? null : + element.attributes[name].value; + } } return element.getAttribute(name); }, + writeAttribute: function(element, name, value) { + element = $(element); + var attributes = { }, t = Element._attributeTranslations.write; + + if (typeof name == 'object') attributes = name; + else attributes[name] = Object.isUndefined(value) ? true : value; + + for (var attr in attributes) { + name = t.names[attr] || attr; + value = attributes[attr]; + if (t.values[attr]) name = t.values[attr](element, value); + if (value === false || value === null) + element.removeAttribute(name); + else if (value === true) + element.setAttribute(name, name); + else element.setAttribute(name, value); + } + return element; + }, + getHeight: function(element) { return $(element).getDimensions().height; }, @@ -1504,39 +1820,28 @@ Element.Methods = { 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; + return (elementClassName.length > 0 && (elementClassName == className || + new RegExp("(^|\\s)" + className + "(\\s|$)").test(elementClassName))); }, addClassName: function(element, className) { if (!(element = $(element))) return; - Element.classNames(element).add(className); + if (!element.hasClassName(className)) + element.className += (element.className ? ' ' : '') + className; return element; }, removeClassName: function(element, className) { if (!(element = $(element))) return; - Element.classNames(element).remove(className); + element.className = element.className.replace( + new RegExp("(^|\\s+)" + className + "(\\s+|$)"), ' ').strip(); 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(); + return element[element.hasClassName(className) ? + 'removeClassName' : 'addClassName'](className); }, // removes whitespace-only text node children @@ -1558,14 +1863,30 @@ Element.Methods = { descendantOf: function(element, ancestor) { element = $(element), ancestor = $(ancestor); + var originalAncestor = ancestor; + + if (element.compareDocumentPosition) + return (element.compareDocumentPosition(ancestor) & 8) === 8; + + if (element.sourceIndex && !Prototype.Browser.Opera) { + var e = element.sourceIndex, a = ancestor.sourceIndex, + nextAncestor = ancestor.nextSibling; + if (!nextAncestor) { + do { ancestor = ancestor.parentNode; } + while (!(nextAncestor = ancestor.nextSibling) && ancestor.parentNode); + } + if (nextAncestor && nextAncestor.sourceIndex) + return (e > a && e < nextAncestor.sourceIndex); + } + while (element = element.parentNode) - if (element == ancestor) return true; + if (element == originalAncestor) return true; return false; }, scrollTo: function(element) { element = $(element); - var pos = Position.cumulativeOffset(element); + var pos = element.cumulativeOffset(); window.scrollTo(pos[0], pos[1]); return element; }, @@ -1586,16 +1907,20 @@ Element.Methods = { return $(element).getStyle('opacity'); }, - setStyle: function(element, styles, camelized) { + setStyle: function(element, styles) { element = $(element); - var elementStyle = element.style; - + var elementStyle = element.style, match; + if (Object.isString(styles)) { + element.style.cssText += ';' + styles; + return styles.include('opacity') ? + element.setOpacity(styles.match(/opacity:\s*(\d?\.?\d*)/)[1]) : element; + } for (var property in styles) - if (property == 'opacity') element.setOpacity(styles[property]) + if (property == 'opacity') element.setOpacity(styles[property]); else elementStyle[(property == 'float' || property == 'cssFloat') ? - (elementStyle.styleFloat === undefined ? 'cssFloat' : 'styleFloat') : - (camelized ? property : property.camelize())] = styles[property]; + (Object.isUndefined(elementStyle.styleFloat) ? 'cssFloat' : 'styleFloat') : + property] = styles[property]; return element; }, @@ -1662,8 +1987,8 @@ Element.Methods = { makeClipping: function(element) { element = $(element); if (element._overflow) return element; - element._overflow = element.style.overflow || 'auto'; - if ((Element.getStyle(element, 'overflow') || 'visible') != 'hidden') + element._overflow = Element.getStyle(element, 'overflow') || 'auto'; + if (element._overflow !== 'hidden') element.style.overflow = 'hidden'; return element; }, @@ -1674,28 +1999,253 @@ Element.Methods = { element.style.overflow = element._overflow == 'auto' ? '' : element._overflow; element._overflow = null; return element; + }, + + cumulativeOffset: function(element) { + var valueT = 0, valueL = 0; + do { + valueT += element.offsetTop || 0; + valueL += element.offsetLeft || 0; + element = element.offsetParent; + } while (element); + return Element._returnOffset(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 !== 'static') break; + } + } while (element); + return Element._returnOffset(valueL, valueT); + }, + + absolutize: function(element) { + element = $(element); + if (element.getStyle('position') == 'absolute') return; + // Position.prepare(); // To be done manually by Scripty when it needs it. + + var offsets = element.positionedOffset(); + 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'; + return element; + }, + + relativize: function(element) { + element = $(element); + if (element.getStyle('position') == 'relative') return; + // Position.prepare(); // To be done manually by Scripty when it needs it. + + 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; + return element; + }, + + cumulativeScrollOffset: function(element) { + var valueT = 0, valueL = 0; + do { + valueT += element.scrollTop || 0; + valueL += element.scrollLeft || 0; + element = element.parentNode; + } while (element); + return Element._returnOffset(valueL, valueT); + }, + + getOffsetParent: 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); + }, + + viewportOffset: 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 && + Element.getStyle(element, 'position') == 'absolute') break; + + } while (element = element.offsetParent); + + element = forElement; + do { + if (!Prototype.Browser.Opera || element.tagName == 'BODY') { + valueT -= element.scrollTop || 0; + valueL -= element.scrollLeft || 0; + } + } while (element = element.parentNode); + + return Element._returnOffset(valueL, valueT); + }, + + clonePosition: function(element, source) { + 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 = source.viewportOffset(); + + // find coordinate system to use + element = $(element); + 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(element, 'position') == 'absolute') { + parent = element.getOffsetParent(); + delta = parent.viewportOffset(); + } + + // 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) element.style.left = (p[0] - delta[0] + options.offsetLeft) + 'px'; + if (options.setTop) element.style.top = (p[1] - delta[1] + options.offsetTop) + 'px'; + if (options.setWidth) element.style.width = source.offsetWidth + 'px'; + if (options.setHeight) element.style.height = source.offsetHeight + 'px'; + return element; } }; +Element.Methods.identify.counter = 1; + Object.extend(Element.Methods, { - childOf: Element.Methods.descendantOf, + getElementsBySelector: Element.Methods.select, childElements: Element.Methods.immediateDescendants }); +Element._attributeTranslations = { + write: { + names: { + className: 'class', + htmlFor: 'for' + }, + values: { } + } +}; + 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); + Element.Methods.getStyle = Element.Methods.getStyle.wrap( + function(proceed, element, style) { + switch (style) { + case 'left': case 'top': case 'right': case 'bottom': + if (proceed(element, 'position') === 'static') return null; + case 'height': case 'width': + // returns '0px' for hidden elements; we want it to return null + if (!Element.visible(element)) return null; + + // returns the border-box dimensions rather than the content-box + // dimensions, so we subtract padding and borders from the value + var dim = parseInt(proceed(element, style), 10); + + if (dim !== element['offset' + style.capitalize()]) + return dim + 'px'; + + var properties; + if (style === 'height') { + properties = ['border-top-width', 'padding-top', + 'padding-bottom', 'border-bottom-width']; + } + else { + properties = ['border-left-width', 'padding-left', + 'padding-right', 'border-right-width']; + } + return properties.inject(dim, function(memo, property) { + var val = proceed(element, property); + return val === null ? memo : memo - parseInt(val, 10); + }) + 'px'; + default: return proceed(element, style); + } } - }; + ); + + Element.Methods.readAttribute = Element.Methods.readAttribute.wrap( + function(proceed, element, attribute) { + if (attribute === 'title') return element.title; + return proceed(element, attribute); + } + ); } + else if (Prototype.Browser.IE) { + // IE doesn't report offsets correctly for static elements, so we change them + // to "relative" to get the values, then change them back. + Element.Methods.getOffsetParent = Element.Methods.getOffsetParent.wrap( + function(proceed, element) { + element = $(element); + var position = element.getStyle('position'); + if (position !== 'static') return proceed(element); + element.setStyle({ position: 'relative' }); + var value = proceed(element); + element.setStyle({ position: position }); + return value; + } + ); + + $w('positionedOffset viewportOffset').each(function(method) { + Element.Methods[method] = Element.Methods[method].wrap( + function(proceed, element) { + element = $(element); + var position = element.getStyle('position'); + if (position !== 'static') return proceed(element); + // Trigger hasLayout on the offset parent so that IE6 reports + // accurate offsetTop and offsetLeft values for position: fixed. + var offsetParent = element.getOffsetParent(); + if (offsetParent && offsetParent.getStyle('position') === 'fixed') + offsetParent.setStyle({ zoom: 1 }); + element.setStyle({ position: 'relative' }); + var value = proceed(element); + element.setStyle({ position: position }); + return value; + } + ); + }); + Element.Methods.getStyle = function(element, style) { element = $(element); style = (style == 'float' || style == 'cssFloat') ? 'styleFloat' : style.camelize(); @@ -1710,56 +2260,121 @@ else if (Prototype.Browser.IE) { if (value == 'auto') { if ((style == 'width' || style == 'height') && (element.getStyle('display') != 'none')) - return element['offset'+style.capitalize()] + 'px'; + return element['offset' + style.capitalize()] + 'px'; return null; } return value; }; Element.Methods.setOpacity = function(element, value) { + function stripAlpha(filter){ + return filter.replace(/alpha\([^\)]*\)/gi,''); + } element = $(element); + var currentStyle = element.currentStyle; + if ((currentStyle && !currentStyle.hasLayout) || + (!currentStyle && element.style.zoom == 'normal')) + element.style.zoom = 1; + var filter = element.getStyle('filter'), style = element.style; if (value == 1 || value === '') { - style.filter = filter.replace(/alpha\([^\)]*\)/gi,''); + (filter = stripAlpha(filter)) ? + style.filter = filter : style.removeAttribute('filter'); return element; } else if (value < 0.00001) value = 0; - style.filter = filter.replace(/alpha\([^\)]*\)/gi, '') + + style.filter = stripAlpha(filter) + '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; + Element._attributeTranslations = { + read: { + names: { + 'class': 'className', + 'for': 'htmlFor' + }, + values: { + _getAttr: function(element, attribute) { + return element.getAttribute(attribute, 2); + }, + _getAttrNode: function(element, attribute) { + var node = element.getAttributeNode(attribute); + return node ? node.value : ""; + }, + _getEv: function(element, attribute) { + attribute = element.getAttribute(attribute); + return attribute ? attribute.toString().slice(23, -2) : null; + }, + _flag: function(element, attribute) { + return $(element).hasAttribute(attribute) ? attribute : null; + }, + style: function(element) { + return element.style.cssText.toLowerCase(); + }, + title: function(element) { + return element.title; + } } - $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; - } + }; + + Element._attributeTranslations.write = { + names: Object.extend({ + cellpadding: 'cellPadding', + cellspacing: 'cellSpacing' + }, Element._attributeTranslations.read.names), + values: { + checked: function(element, value) { + element.checked = !!value; + }, + + style: function(element, value) { + element.style.cssText = value ? value : ''; + } + } + }; + + Element._attributeTranslations.has = {}; + + $w('colSpan rowSpan vAlign dateTime accessKey tabIndex ' + + 'encType maxLength readOnly longDesc').each(function(attr) { + Element._attributeTranslations.write.names[attr.toLowerCase()] = attr; + Element._attributeTranslations.has[attr.toLowerCase()] = attr; + }); + + (function(v) { + Object.extend(v, { + href: v._getAttr, + src: v._getAttr, + type: v._getAttr, + action: v._getAttrNode, + disabled: v._flag, + checked: v._flag, + readonly: v._flag, + multiple: v._flag, + onload: v._getEv, + onunload: v._getEv, + onclick: v._getEv, + ondblclick: v._getEv, + onmousedown: v._getEv, + onmouseup: v._getEv, + onmouseover: v._getEv, + onmousemove: v._getEv, + onmouseout: v._getEv, + onfocus: v._getEv, + onblur: v._getEv, + onkeypress: v._getEv, + onkeydown: v._getEv, + onkeyup: v._getEv, + onsubmit: v._getEv, + onreset: v._getEv, + onselect: v._getEv, + onchange: v._getEv + }); + })(Element._attributeTranslations.read.values); } -else if (Prototype.Browser.Gecko) { + +else if (Prototype.Browser.Gecko && /rv:1\.8\.0/.test(navigator.userAgent)) { Element.Methods.setOpacity = function(element, value) { element = $(element); element.style.opacity = (value == 1) ? 0.999999 : @@ -1768,68 +2383,198 @@ else if (Prototype.Browser.Gecko) { }; } -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; +else if (Prototype.Browser.WebKit) { + Element.Methods.setOpacity = function(element, value) { + element = $(element); + element.style.opacity = (value == 1 || value === '') ? '' : + (value < 0.00001) ? 0 : value; + + if (value == 1) + if(element.tagName == 'IMG' && element.width) { + element.width++; element.width--; + } else try { + var n = document.createTextNode(' '); + element.appendChild(n); + element.removeChild(n); + } catch (e) { } + + return element; + }; + + // Safari returns margins on body which is incorrect if the child is absolutely + // positioned. For performance reasons, redefine Element#cumulativeOffset for + // KHTML/WebKit only. + Element.Methods.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 Element._returnOffset(valueL, valueT); + }; +} + +if (Prototype.Browser.IE || Prototype.Browser.Opera) { + // IE and Opera are missing .innerHTML support for TABLE-related and SELECT elements + Element.Methods.update = function(element, content) { + element = $(element); + + if (content && content.toElement) content = content.toElement(); + if (Object.isElement(content)) return element.update().insert(content); + + content = Object.toHTML(content); + var tagName = element.tagName.toUpperCase(); + + if (tagName in Element._insertionTranslations.tags) { + $A(element.childNodes).each(function(node) { element.removeChild(node) }); + Element._getContentFromAnonymousElement(tagName, content.stripScripts()) + .each(function(node) { element.appendChild(node) }); + } + else element.innerHTML = content.stripScripts(); + + content.evalScripts.bind(content).defer(); + return element; + }; +} + +if ('outerHTML' in document.createElement('div')) { + Element.Methods.replace = function(element, content) { + element = $(element); + + if (content && content.toElement) content = content.toElement(); + if (Object.isElement(content)) { + element.parentNode.replaceChild(content, element); + return element; } + + content = Object.toHTML(content); + var parent = element.parentNode, tagName = parent.tagName.toUpperCase(); + + if (Element._insertionTranslations.tags[tagName]) { + var nextSibling = element.next(); + var fragments = Element._getContentFromAnonymousElement(tagName, content.stripScripts()); + parent.removeChild(element); + if (nextSibling) + fragments.each(function(node) { parent.insertBefore(node, nextSibling) }); + else + fragments.each(function(node) { parent.appendChild(node) }); + } + else element.outerHTML = content.stripScripts(); + + content.evalScripts.bind(content).defer(); + return element; + }; +} + +Element._returnOffset = function(l, t) { + var result = [l, t]; + result.left = l; + result.top = t; + return result; +}; + +Element._getContentFromAnonymousElement = function(tagName, html) { + var div = new Element('div'), t = Element._insertionTranslations.tags[tagName]; + if (t) { + div.innerHTML = t[0] + html + t[1]; + t[2].times(function() { div = div.firstChild }); + } else div.innerHTML = html; + return $A(div.childNodes); +}; + +Element._insertionTranslations = { + before: function(element, node) { + element.parentNode.insertBefore(node, element); + }, + top: function(element, node) { + element.insertBefore(node, element.firstChild); + }, + bottom: function(element, node) { + element.appendChild(node); + }, + after: function(element, node) { + element.parentNode.insertBefore(node, element.nextSibling); + }, + tags: { + TABLE: ['<table>', '</table>', 1], + TBODY: ['<table><tbody>', '</tbody></table>', 2], + TR: ['<table><tbody><tr>', '</tr></tbody></table>', 3], + TD: ['<table><tbody><tr><td>', '</td></tr></tbody></table>', 4], + SELECT: ['<select>', '</select>', 1] } }; (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 + Object.extend(this.tags, { + THEAD: this.tags.TBODY, + TFOOT: this.tags.TBODY, + TH: this.tags.TD }); -}).call(Element._attributeTranslations.values); +}).call(Element._insertionTranslations); Element.Methods.Simulated = { hasAttribute: function(element, attribute) { - var t = Element._attributeTranslations, node; - attribute = t.names[attribute] || attribute; - node = $(element).getAttributeNode(attribute); + attribute = Element._attributeTranslations.has[attribute] || attribute; + var node = $(element).getAttributeNode(attribute); return node && node.specified; } }; -Element.Methods.ByTag = {}; +Element.Methods.ByTag = { }; Object.extend(Element, Element.Methods); if (!Prototype.BrowserFeatures.ElementExtensions && - document.createElement('div').__proto__) { - window.HTMLElement = {}; + document.createElement('div').__proto__) { + window.HTMLElement = { }; window.HTMLElement.prototype = document.createElement('div').__proto__; Prototype.BrowserFeatures.ElementExtensions = true; } +Element.extend = (function() { + if (Prototype.BrowserFeatures.SpecificElementExtensions) + return Prototype.K; + + var Methods = { }, ByTag = Element.Methods.ByTag; + + var extend = Object.extend(function(element) { + if (!element || element._extendedByPrototype || + element.nodeType != 1 || element == window) return element; + + var methods = Object.clone(Methods), + tagName = element.tagName, property, value; + + // extend methods for specific tags + if (ByTag[tagName]) Object.extend(methods, ByTag[tagName]); + + for (property in methods) { + value = methods[property]; + if (Object.isFunction(value) && !(property in element)) + element[property] = value.methodize(); + } + + element._extendedByPrototype = Prototype.emptyFunction; + return element; + + }, { + refresh: function() { + // extend methods for all tags (Safari doesn't need this) + if (!Prototype.BrowserFeatures.ElementExtensions) { + Object.extend(Methods, Element.Methods); + Object.extend(Methods, Element.Methods.Simulated); + } + } + }); + + extend.refresh(); + return extend; +})(); + Element.hasAttribute = function(element, attribute) { if (element.hasAttribute) return element.hasAttribute(attribute); return Element.Methods.Simulated.hasAttribute(element, attribute); @@ -1854,26 +2599,26 @@ Element.addMethods = function(methods) { methods = arguments[1]; } - if (!tagName) Object.extend(Element.Methods, methods || {}); + if (!tagName) Object.extend(Element.Methods, methods || { }); else { - if (tagName.constructor == Array) tagName.each(extend); + if (Object.isArray(tagName)) tagName.each(extend); else extend(tagName); } function extend(tagName) { tagName = tagName.toUpperCase(); if (!Element.Methods.ByTag[tagName]) - 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 (!Object.isFunction(value)) continue; if (!onlyIfAbsent || !(property in destination)) - destination[property] = cache.findOrStore(value); + destination[property] = value.methodize(); } } @@ -1897,7 +2642,7 @@ Element.addMethods = function(methods) { klass = 'HTML' + tagName.capitalize() + 'Element'; if (window[klass]) return window[klass]; - window[klass] = {}; + window[klass] = { }; window[klass].prototype = document.createElement(tagName).__proto__; return window[klass]; } @@ -1910,169 +2655,84 @@ Element.addMethods = function(methods) { if (F.SpecificElementExtensions) { for (var tag in Element.Methods.ByTag) { var klass = findDOMClass(tag); - if (typeof klass == "undefined") continue; + if (Object.isUndefined(klass)) 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); - }, + if (Element.extend.refresh) Element.extend.refresh(); + Element.cache = { }; +}; - set: function(className) { - this.element.className = className; +document.viewport = { + getDimensions: function() { + var dimensions = { }; + var B = Prototype.Browser; + $w('width height').each(function(d) { + var D = d.capitalize(); + dimensions[d] = (B.WebKit && !document.evaluate) ? self['inner' + D] : + (B.Opera) ? document.body['client' + D] : document.documentElement['client' + D]; + }); + return dimensions; }, - add: function(classNameToAdd) { - if (this.include(classNameToAdd)) return; - this.set($A(this).concat(classNameToAdd).join(' ')); + getWidth: function() { + return this.getDimensions().width; }, - remove: function(classNameToRemove) { - if (!this.include(classNameToRemove)) return; - this.set($A(this).without(classNameToRemove).join(' ')); + getHeight: function() { + return this.getDimensions().height; }, - toString: function() { - return $A(this).join(' '); + getScrollOffsets: function() { + return Element._returnOffset( + window.pageXOffset || document.documentElement.scrollLeft || document.body.scrollLeft, + window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop); } }; - -Object.extend(Element.ClassNames.prototype, Enumerable); -/* Portions of the Selector class are derived from Jack Slocum’s DomQuery, +/* 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 = { +var Selector = Class.create({ initialize: function(expression) { this.expression = expression.strip(); this.compileMatcher(); }, + shouldUseXPath: function() { + if (!Prototype.BrowserFeatures.XPath) return false; + + var e = this.expression; + + // Safari 3 chokes on :*-of-type and :empty + if (Prototype.Browser.WebKit && + (e.include("-of-type") || e.include(":empty"))) + return false; + + // XPath can't do namespaced attributes, nor can it read + // the "checked" property from DOM nodes + if ((/(\[[\w-]*?:|:checked)/).test(this.expression)) + return false; + + return true; + }, + compileMatcher: function() { - // Selectors with namespaced attributes can't use the XPath version - if (Prototype.BrowserFeatures.XPath && !(/\[[\w-]*?:/).test(this.expression)) + if (this.shouldUseXPath()) 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 = Selector._cache[e]; + return; } + this.matcher = ["this.matcher = function(root) {", "var r = root, h = Selector.handlers, c = false, n;"]; @@ -2081,7 +2741,7 @@ Selector.prototype = { for (var i in ps) { p = ps[i]; if (m = e.match(p)) { - this.matcher.push(typeof c[i] == 'function' ? c[i](m) : + this.matcher.push(Object.isFunction(c[i]) ? c[i](m) : new Template(c[i]).evaluate(m)); e = e.replace(m[0], ''); break; @@ -2096,7 +2756,7 @@ Selector.prototype = { compileXPathMatcher: function() { var e = this.expression, ps = Selector.patterns, - x = Selector.xpath, le, m; + x = Selector.xpath, le, m; if (Selector._cache[e]) { this.xpath = Selector._cache[e]; return; @@ -2107,7 +2767,7 @@ Selector.prototype = { le = e; for (var i in ps) { if (m = e.match(ps[i])) { - this.matcher.push(typeof x[i] == 'function' ? x[i](m) : + this.matcher.push(Object.isFunction(x[i]) ? x[i](m) : new Template(x[i]).evaluate(m)); e = e.replace(m[0], ''); break; @@ -2126,7 +2786,39 @@ Selector.prototype = { }, match: function(element) { - return this.findElements(document).include(element); + this.tokens = []; + + var e = this.expression, ps = Selector.patterns, as = Selector.assertions; + var le, p, m; + + while (e && le !== e && (/\S/).test(e)) { + le = e; + for (var i in ps) { + p = ps[i]; + if (m = e.match(p)) { + // use the Selector.assertions methods unless the selector + // is too complex. + if (as[i]) { + this.tokens.push([i, Object.clone(m)]); + e = e.replace(m[0], ''); + } else { + // reluctantly do a document-wide search + // and look for a match in the array + return this.findElements(document).include(element); + } + } + } + } + + var match = true, name, matches; + for (var i = 0, token; token = this.tokens[i]; i++) { + name = token[0], matches = token[1]; + if (!Selector.assertions[name](element, matches)) { + match = false; break; + } + } + + return match; }, toString: function() { @@ -2136,10 +2828,10 @@ Selector.prototype = { inspect: function() { return "#<Selector:" + this.expression.inspect() + ">"; } -}; +}); Object.extend(Selector, { - _cache: {}, + _cache: { }, xpath: { descendant: "//*", @@ -2153,15 +2845,19 @@ Object.extend(Selector, { }, className: "[contains(concat(' ', @class, ' '), ' #{1} ')]", id: "[@id='#{1}']", - attrPresence: "[@#{1}]", + attrPresence: function(m) { + m[1] = m[1].toLowerCase(); + return new Template("[@#{1}]").evaluate(m); + }, attr: function(m) { + m[1] = m[1].toLowerCase(); 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); + if (Object.isFunction(h)) return h(m); return new Template(Selector.xpath.pseudos[m[1]]).evaluate(m); }, operators: { @@ -2183,14 +2879,14 @@ Object.extend(Selector, { 'enabled': "[not(@disabled)]", 'not': function(m) { var e = m[6], p = Selector.patterns, - x = Selector.xpath, le, m, v; + x = Selector.xpath, le, 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); + v = Object.isFunction(x[i]) ? x[i](m) : new Template(x[i]).evaluate(m); exclusion.push("(" + v.substring(1, v.length - 1) + ")"); e = e.replace(m[0], ''); break; @@ -2240,15 +2936,15 @@ Object.extend(Selector, { }, 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;', + 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); 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); + return new Template('n = h.attr(n, r, "#{1}", "#{3}", "#{2}", c); c = false;').evaluate(m); }, - pseudo: function(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); }, @@ -2270,9 +2966,34 @@ Object.extend(Selector, { 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|(?=:))/, + 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|([^'"][^\]]*?)))?\]/ //" + attr: /\[((?:[\w-]*:)?[\w-]+)\s*(?:([!^$*~|]?=)\s*((['"])([^\4]*?)\4|([^'"][^\]]*?)))?\]/ //" + }, + + // for Selector.match and Element#match + assertions: { + tagName: function(element, matches) { + return matches[1].toUpperCase() == element.tagName.toUpperCase(); + }, + + className: function(element, matches) { + return Element.hasClassName(element, matches[1]); + }, + + id: function(element, matches) { + return element.id === matches[1]; + }, + + attrPresence: function(element, matches) { + return Element.hasAttribute(element, matches[1]); + }, + + attr: function(element, matches) { + var nodeValue = Element.readAttribute(element, matches[1]); + return nodeValue && Selector.operators[matches[2]](nodeValue, matches[5] || matches[6]); + } }, handlers: { @@ -2286,14 +3007,15 @@ Object.extend(Selector, { // marks an array of nodes for counting mark: function(nodes) { + var _true = Prototype.emptyFunction; for (var i = 0, node; node = nodes[i]; i++) - node._counted = true; + node._countedByPrototype = _true; return nodes; }, unmark: function(nodes) { for (var i = 0, node; node = nodes[i]; i++) - node._counted = undefined; + node._countedByPrototype = undefined; return nodes; }, @@ -2301,15 +3023,15 @@ Object.extend(Selector, { // "ofType" flag indicates whether we're indexing for nth-of-type // rather than nth-child index: function(parentNode, reverse, ofType) { - parentNode._counted = true; + parentNode._countedByPrototype = Prototype.emptyFunction; 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++; + var node = nodes[i]; + if (node.nodeType == 1 && (!ofType || node._countedByPrototype)) 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++; + if (node.nodeType == 1 && (!ofType || node._countedByPrototype)) node.nodeIndex = j++; } }, @@ -2318,8 +3040,8 @@ Object.extend(Selector, { 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; + if (!(n = nodes[i])._countedByPrototype) { + n._countedByPrototype = Prototype.emptyFunction; results.push(Element.extend(n)); } return Selector.handlers.unmark(results); @@ -2336,7 +3058,7 @@ Object.extend(Selector, { 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++) + for (var j = 0, child; child = node.childNodes[j]; j++) if (child.nodeType == 1 && child.tagName != '!') results.push(child); } return results; @@ -2371,7 +3093,7 @@ Object.extend(Selector, { // TOKEN FUNCTIONS tagName: function(nodes, root, tagName, combinator) { - tagName = tagName.toUpperCase(); + var uTagName = tagName.toUpperCase(); var results = [], h = Selector.handlers; if (nodes) { if (combinator) { @@ -2384,14 +3106,15 @@ Object.extend(Selector, { if (tagName == "*") return nodes; } for (var i = 0, node; node = nodes[i]; i++) - if (node.tagName.toUpperCase() == tagName) results.push(node); + if (node.tagName.toUpperCase() === uTagName) 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 (!targetNode) return []; + if (!nodes && root == document) return [targetNode]; if (nodes) { if (combinator) { if (combinator == 'child') { @@ -2430,15 +3153,18 @@ Object.extend(Selector, { return results; }, - attrPresence: function(nodes, root, attr) { + attrPresence: function(nodes, root, attr, combinator) { + if (!nodes) nodes = root.getElementsByTagName("*"); + if (nodes && combinator) nodes = this[combinator](nodes); 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) { + attr: function(nodes, root, attr, value, operator, combinator) { if (!nodes) nodes = root.getElementsByTagName("*"); + if (nodes && combinator) nodes = this[combinator](nodes); var handler = Selector.operators[operator], results = []; for (var i = 0, node; node = nodes[i]; i++) { var nodeValue = Element.readAttribute(node, attr); @@ -2517,7 +3243,7 @@ Object.extend(Selector, { var h = Selector.handlers, results = [], indexed = [], m; h.mark(nodes); for (var i = 0, node; node = nodes[i]; i++) { - if (!node.parentNode._counted) { + if (!node.parentNode._countedByPrototype) { h.index(node.parentNode, reverse, ofType); indexed.push(node.parentNode); } @@ -2555,7 +3281,7 @@ Object.extend(Selector, { 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); + if (!node._countedByPrototype) results.push(node); h.unmark(exclusions); return results; }, @@ -2589,27 +3315,32 @@ Object.extend(Selector, { '|=': function(nv, v) { return ('-' + nv.toUpperCase() + '-').include('-' + v.toUpperCase() + '-'); } }, + split: function(expression) { + var expressions = []; + expression.scan(/(([\w#:.~>+()\s-]+|\*|\[.*?\])+)\s*(,|$)/, function(m) { + expressions.push(m[1].strip()); + }); + return expressions; + }, + matchElements: function(elements, expression) { - var matches = new Selector(expression).findElements(), h = Selector.handlers; + var matches = $$(expression), h = Selector.handlers; h.mark(matches); for (var i = 0, results = [], element; element = elements[i]; i++) - if (element._counted) results.push(element); + if (element._countedByPrototype) results.push(element); h.unmark(matches); return results; }, findElement: function(elements, expression, index) { - if (typeof expression == 'number') { + if (Object.isNumber(expression)) { 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()); - }); + expressions = Selector.split(expressions.join(',')); var results = [], h = Selector.handlers; for (var i = 0, l = expressions.length, selector; i < l; i++) { selector = new Selector(expressions[i].strip()); @@ -2619,6 +3350,25 @@ Object.extend(Selector, { } }); +if (Prototype.Browser.IE) { + Object.extend(Selector.handlers, { + // IE returns comment nodes on getElementsByTagName("*"). + // Filter them out. + concat: function(a, b) { + for (var i = 0, node; node = b[i]; i++) + if (node.tagName !== "!") a.push(node); + return a; + }, + + // IE improperly serializes _countedByPrototype in (inner|outer)HTML. + unmark: function(nodes) { + for (var i = 0, node; node = nodes[i]; i++) + node.removeAttribute('_countedByPrototype'); + return nodes; + } + }); +} + function $$() { return Selector.findChildElements(document, $A(arguments)); } @@ -2628,13 +3378,19 @@ var Form = { return form; }, - serializeElements: function(elements, getHash) { - var data = elements.inject({}, function(result, element) { + serializeElements: function(elements, options) { + if (typeof options != 'object') options = { hash: !!options }; + else if (Object.isUndefined(options.hash)) options.hash = true; + var key, value, submitted = false, submit = options.submit; + + 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]]; + key = element.name; value = $(element).getValue(); + if (value != null && (element.type != 'submit' || (!submitted && + submit !== false && (!submit || key == submit) && (submitted = true)))) { + if (key in result) { + // a key is already present; construct an array of values + if (!Object.isArray(result[key])) result[key] = [result[key]]; result[key].push(value); } else result[key] = value; @@ -2643,13 +3399,13 @@ var Form = { return result; }); - return getHash ? data : Hash.toQueryString(data); + return options.hash ? data : Object.toQueryString(data); } }; Form.Methods = { - serialize: function(form, getHash) { - return Form.serializeElements(Form.getElements(form), getHash); + serialize: function(form, options) { + return Form.serializeElements(Form.getElements(form), options); }, getElements: function(form) { @@ -2691,9 +3447,15 @@ Form.Methods = { }, findFirstElement: function(form) { - return $(form).getElements().find(function(element) { - return element.type != 'hidden' && !element.disabled && - ['input', 'select', 'textarea'].include(element.tagName.toLowerCase()); + var elements = $(form).getElements().findAll(function(element) { + return 'hidden' != element.type && !element.disabled; + }); + var firstByIndex = elements.findAll(function(element) { + return element.hasAttribute('tabIndex') && element.tabIndex >= 0; + }).sortBy(function(element) { return element.tabIndex }).first(); + + return firstByIndex ? firstByIndex : elements.find(function(element) { + return ['input', 'select', 'textarea'].include(element.tagName.toLowerCase()); }); }, @@ -2704,22 +3466,23 @@ Form.Methods = { }, request: function(form, options) { - form = $(form), options = Object.clone(options || {}); + form = $(form), options = Object.clone(options || { }); - var params = options.parameters; + var params = options.parameters, action = form.readAttribute('action') || ''; + if (action.blank()) action = window.location.href; options.parameters = form.serialize(true); if (params) { - if (typeof params == 'string') params = params.toQueryParams(); + if (Object.isString(params)) 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); + return new Ajax.Request(action, options); } -} +}; /*--------------------------------------------------------------------------*/ @@ -2733,7 +3496,7 @@ Form.Element = { $(element).select(); return element; } -} +}; Form.Element.Methods = { serialize: function(element) { @@ -2741,9 +3504,9 @@ Form.Element.Methods = { if (!element.disabled && element.name) { var value = element.getValue(); if (value != undefined) { - var pair = {}; + var pair = { }; pair[element.name] = value; - return Hash.toQueryString(pair); + return Object.toQueryString(pair); } } return ''; @@ -2755,6 +3518,13 @@ Form.Element.Methods = { return Form.Element.Serializers[method](element); }, + setValue: function(element, value) { + element = $(element); + var method = element.tagName.toLowerCase(); + Form.Element.Serializers[method](element, value); + return element; + }, + clear: function(element) { $(element).value = ''; return element; @@ -2769,9 +3539,9 @@ Form.Element.Methods = { try { element.focus(); if (element.select && (element.tagName.toLowerCase() != 'input' || - !['button', 'reset', 'submit'].include(element.type))) + !['button', 'reset', 'submit'].include(element.type))) element.select(); - } catch (e) {} + } catch (e) { } return element; }, @@ -2787,7 +3557,7 @@ Form.Element.Methods = { element.disabled = false; return element; } -} +}; /*--------------------------------------------------------------------------*/ @@ -2797,27 +3567,44 @@ var $F = Form.Element.Methods.getValue; /*--------------------------------------------------------------------------*/ Form.Element.Serializers = { - input: function(element) { + input: function(element, value) { switch (element.type.toLowerCase()) { case 'checkbox': case 'radio': - return Form.Element.Serializers.inputSelector(element); + return Form.Element.Serializers.inputSelector(element, value); default: - return Form.Element.Serializers.textarea(element); + return Form.Element.Serializers.textarea(element, value); } }, - inputSelector: function(element) { - return element.checked ? element.value : null; + inputSelector: function(element, value) { + if (Object.isUndefined(value)) return element.checked ? element.value : null; + else element.checked = !!value; }, - textarea: function(element) { - return element.value; + textarea: function(element, value) { + if (Object.isUndefined(value)) return element.value; + else element.value = value; }, - select: function(element) { - return this[element.type == 'select-one' ? - 'selectOne' : 'selectMany'](element); + select: function(element, index) { + if (Object.isUndefined(index)) + return this[element.type == 'select-one' ? + 'selectOne' : 'selectMany'](element); + else { + var opt, value, single = !Object.isArray(index); + for (var i = 0, length = element.length; i < length; i++) { + opt = element.options[i]; + value = this.optionValue(opt); + if (single) { + if (value == index) { + opt.selected = true; + return; + } + } + else opt.selected = index.include(value); + } + } }, selectOne: function(element) { @@ -2840,45 +3627,34 @@ Form.Element.Serializers = { // 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; +Abstract.TimedObserver = Class.create(PeriodicalExecuter, { + initialize: function($super, element, frequency, callback) { + $super(callback, 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() { + execute: function() { var value = this.getValue(); - var changed = ('string' == typeof this.lastValue && 'string' == typeof value - ? this.lastValue != value : String(this.lastValue) != String(value)); - if (changed) { + if (Object.isString(this.lastValue) && Object.isString(value) ? + this.lastValue != value : String(this.lastValue) != String(value)) { this.callback(this.element, value); this.lastValue = value; } } -} +}); -Form.Element.Observer = Class.create(); -Form.Element.Observer.prototype = Object.extend(new Abstract.TimedObserver(), { +Form.Element.Observer = Class.create(Abstract.TimedObserver, { getValue: function() { return Form.Element.getValue(this.element); } }); -Form.Observer = Class.create(); -Form.Observer.prototype = Object.extend(new Abstract.TimedObserver(), { +Form.Observer = Class.create(Abstract.TimedObserver, { getValue: function() { return Form.serialize(this.element); } @@ -2886,8 +3662,7 @@ Form.Observer.prototype = Object.extend(new Abstract.TimedObserver(), { /*--------------------------------------------------------------------------*/ -Abstract.EventObserver = function() {} -Abstract.EventObserver.prototype = { +Abstract.EventObserver = Class.create({ initialize: function(element, callback) { this.element = $(element); this.callback = callback; @@ -2908,7 +3683,7 @@ Abstract.EventObserver.prototype = { }, registerFormCallbacks: function() { - Form.getElements(this.element).each(this.registerCallback.bind(this)); + Form.getElements(this.element).each(this.registerCallback, this); }, registerCallback: function(element) { @@ -2924,24 +3699,20 @@ Abstract.EventObserver.prototype = { } } } -} +}); -Form.Element.EventObserver = Class.create(); -Form.Element.EventObserver.prototype = Object.extend(new Abstract.EventObserver(), { +Form.Element.EventObserver = Class.create(Abstract.EventObserver, { getValue: function() { return Form.Element.getValue(this.element); } }); -Form.EventObserver = Class.create(); -Form.EventObserver.prototype = Object.extend(new Abstract.EventObserver(), { +Form.EventObserver = Class.create(Abstract.EventObserver, { getValue: function() { return Form.serialize(this.element); } }); -if (!window.Event) { - var Event = new Object(); -} +if (!window.Event) var Event = { }; Object.extend(Event, { KEY_BACKSPACE: 8, @@ -2957,100 +3728,339 @@ Object.extend(Event, { KEY_END: 35, KEY_PAGEUP: 33, KEY_PAGEDOWN: 34, + KEY_INSERT: 45, - element: function(event) { - return $(event.target || event.srcElement); - }, + cache: { }, - isLeftClick: function(event) { - return (((event.which) && (event.which == 1)) || - ((event.button) && (event.button == 1))); - }, + relatedTarget: function(event) { + var element; + switch(event.type) { + case 'mouseover': element = event.fromElement; break; + case 'mouseout': element = event.toElement; break; + default: return null; + } + return Element.extend(element); + } +}); - pointerX: function(event) { - return event.pageX || (event.clientX + - (document.documentElement.scrollLeft || document.body.scrollLeft)); - }, +Event.Methods = (function() { + var isButton; - pointerY: function(event) { - return event.pageY || (event.clientY + - (document.documentElement.scrollTop || document.body.scrollTop)); - }, + if (Prototype.Browser.IE) { + var buttonMap = { 0: 1, 1: 4, 2: 2 }; + isButton = function(event, code) { + return event.button == buttonMap[code]; + }; + + } else if (Prototype.Browser.WebKit) { + isButton = function(event, code) { + switch (code) { + case 0: return event.which == 1 && !event.metaKey; + case 1: return event.which == 1 && event.metaKey; + default: return false; + } + }; + + } else { + isButton = function(event, code) { + return event.which ? (event.which === code + 1) : (event.button === code); + }; + } + + return { + isLeftClick: function(event) { return isButton(event, 0) }, + isMiddleClick: function(event) { return isButton(event, 1) }, + isRightClick: function(event) { return isButton(event, 2) }, + + element: function(event) { + var node = Event.extend(event).target; + return Element.extend(node.nodeType == Node.TEXT_NODE ? node.parentNode : node); + }, + + findElement: function(event, expression) { + var element = Event.element(event); + if (!expression) return element; + var elements = [element].concat(element.ancestors()); + return Selector.findElement(elements, expression, 0); + }, + + pointer: function(event) { + return { + x: event.pageX || (event.clientX + + (document.documentElement.scrollLeft || document.body.scrollLeft)), + y: event.pageY || (event.clientY + + (document.documentElement.scrollTop || document.body.scrollTop)) + }; + }, + + pointerX: function(event) { return Event.pointer(event).x }, + pointerY: function(event) { return Event.pointer(event).y }, - stop: function(event) { - if (event.preventDefault) { + stop: function(event) { + Event.extend(event); event.preventDefault(); event.stopPropagation(); - } else { - event.returnValue = false; - event.cancelBubble = true; + event.stopped = 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; - }, +Event.extend = (function() { + var methods = Object.keys(Event.Methods).inject({ }, function(m, name) { + m[name] = Event.Methods[name].methodize(); + return m; + }); + + if (Prototype.Browser.IE) { + Object.extend(methods, { + stopPropagation: function() { this.cancelBubble = true }, + preventDefault: function() { this.returnValue = false }, + inspect: function() { return "[object Event]" } + }); + + return function(event) { + if (!event) return false; + if (event._extendedByPrototype) return event; + + event._extendedByPrototype = Prototype.emptyFunction; + var pointer = Event.pointer(event); + Object.extend(event, { + target: event.srcElement, + relatedTarget: Event.relatedTarget(event), + pageX: pointer.x, + pageY: pointer.y + }); + return Object.extend(event, methods); + }; + + } else { + Event.prototype = Event.prototype || document.createEvent("HTMLEvents").__proto__; + Object.extend(Event.prototype, methods); + return Prototype.K; + } +})(); + +Object.extend(Event, (function() { + var cache = Event.cache; + + function getEventID(element) { + if (element._prototypeEventID) return element._prototypeEventID[0]; + arguments.callee.id = arguments.callee.id || 1; + return element._prototypeEventID = [++arguments.callee.id]; + } + + function getDOMEventName(eventName) { + if (eventName && eventName.include(':')) return "dataavailable"; + return eventName; + } + + function getCacheForID(id) { + return cache[id] = cache[id] || { }; + } + + function getWrappersForEventName(id, eventName) { + var c = getCacheForID(id); + return c[eventName] = c[eventName] || []; + } + + function createWrapper(element, eventName, handler) { + var id = getEventID(element); + var c = getWrappersForEventName(id, eventName); + if (c.pluck("handler").include(handler)) return false; + + var wrapper = function(event) { + if (!Event || !Event.extend || + (event.eventName && event.eventName != eventName)) + return false; + + Event.extend(event); + handler.call(element, event); + }; + + wrapper.handler = handler; + c.push(wrapper); + return wrapper; + } + + function findWrapper(id, eventName, handler) { + var c = getWrappersForEventName(id, eventName); + return c.find(function(wrapper) { return wrapper.handler == handler }); + } + + function destroyWrapper(id, eventName, handler) { + var c = getCacheForID(id); + if (!c[eventName]) return false; + c[eventName] = c[eventName].without(findWrapper(id, eventName, handler)); + } + + function destroyCache() { + for (var id in cache) + for (var eventName in cache[id]) + cache[id][eventName] = null; + } + + if (window.attachEvent) { + window.attachEvent("onunload", destroyCache); + } + + return { + observe: function(element, eventName, handler) { + element = $(element); + var name = getDOMEventName(eventName); + + var wrapper = createWrapper(element, eventName, handler); + if (!wrapper) return element; + + if (element.addEventListener) { + element.addEventListener(name, wrapper, false); + } else { + element.attachEvent("on" + name, wrapper); + } + + return element; + }, + + stopObserving: function(element, eventName, handler) { + element = $(element); + var id = getEventID(element), name = getDOMEventName(eventName); + + if (!handler && eventName) { + getWrappersForEventName(id, eventName).each(function(wrapper) { + element.stopObserving(eventName, wrapper.handler); + }); + return element; + + } else if (!eventName) { + Object.keys(getCacheForID(id)).each(function(eventName) { + element.stopObserving(eventName); + }); + return element; + } + + var wrapper = findWrapper(id, eventName, handler); + if (!wrapper) return element; + + if (element.removeEventListener) { + element.removeEventListener(name, wrapper, false); + } else { + element.detachEvent("on" + name, wrapper); + } + + destroyWrapper(id, eventName, handler); + + return element; + }, - observers: false, + fire: function(element, eventName, memo) { + element = $(element); + if (element == document && document.createEvent && !element.dispatchEvent) + element = document.documentElement; - _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); + var event; + if (document.createEvent) { + event = document.createEvent("HTMLEvents"); + event.initEvent("dataavailable", true, true); + } else { + event = document.createEventObject(); + event.eventType = "ondataavailable"; + } + + event.eventName = eventName; + event.memo = memo || { }; + + if (document.createEvent) { + element.dispatchEvent(event); + } else { + element.fireEvent(event.eventType, event); + } + + return Event.extend(event); } - }, + }; +})()); + +Object.extend(Event, Event.Methods); + +Element.addMethods({ + fire: Event.fire, + observe: Event.observe, + stopObserving: Event.stopObserving +}); + +Object.extend(document, { + fire: Element.Methods.fire.methodize(), + observe: Element.Methods.observe.methodize(), + stopObserving: Element.Methods.stopObserving.methodize(), + loaded: false +}); + +(function() { + /* Support for the DOMContentLoaded event is based on work by Dan Webb, + Matthias Miller, Dean Edwards and John Resig. */ - 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; + var timer; + + function fireContentLoadedEvent() { + if (document.loaded) return; + if (timer) window.clearInterval(timer); + document.fire("dom:loaded"); + document.loaded = true; + } + + if (document.addEventListener) { + if (Prototype.Browser.WebKit) { + timer = window.setInterval(function() { + if (/loaded|complete/.test(document.readyState)) + fireContentLoadedEvent(); + }, 0); + + Event.observe(window, "load", fireContentLoadedEvent); + + } else { + document.addEventListener("DOMContentLoaded", + fireContentLoadedEvent, false); } - Event.observers = false; - }, - observe: function(element, name, observer, useCapture) { - element = $(element); - useCapture = useCapture || false; + } else { + document.write("<script id=__onDOMContentLoaded defer src=//:><\/script>"); + $("__onDOMContentLoaded").onreadystatechange = function() { + if (this.readyState == "complete") { + this.onreadystatechange = null; + fireContentLoadedEvent(); + } + }; + } +})(); +/*------------------------------- DEPRECATED -------------------------------*/ - if (name == 'keypress' && - (Prototype.Browser.WebKit || element.attachEvent)) - name = 'keydown'; +Hash.toQueryString = Object.toQueryString; - Event._observeAndCache(element, name, observer, useCapture); +var Toggle = { display: Element.toggle }; + +Element.Methods.childOf = Element.Methods.descendantOf; + +var Insertion = { + Before: function(element, content) { + return Element.insert(element, {before:content}); }, - stopObserving: function(element, name, observer, useCapture) { - element = $(element); - useCapture = useCapture || false; + Top: function(element, content) { + return Element.insert(element, {top:content}); + }, - if (name == 'keypress' && - (Prototype.Browser.WebKit || element.attachEvent)) - name = 'keydown'; + Bottom: function(element, content) { + return Element.insert(element, {bottom:content}); + }, - if (element.removeEventListener) { - element.removeEventListener(name, observer, useCapture); - } else if (element.detachEvent) { - try { - element.detachEvent('on' + name, observer); - } catch (e) {} - } + After: function(element, content) { + return Element.insert(element, {after:content}); } -}); +}; -/* prevent memory leaks in IE */ -if (Prototype.Browser.IE) - Event.observe(window, 'unload', Event.unloadCache, false); +var $continue = new Error('"throw $continue" is deprecated, use "return" instead'); + +// This should be moved to script.aculo.us; notice the deprecated methods +// further below, that map to the newer Element methods. var Position = { // set to true if needed, warning: firefox performance problems // NOT neeeded for page scrolling, only if draggable contained in @@ -3070,59 +4080,13 @@ var Position = { || 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); + this.offset = Element.cumulativeOffset(element); return (y >= this.offset[1] && y < this.offset[1] + element.offsetHeight && @@ -3131,11 +4095,11 @@ var Position = { }, withinIncludingScrolloffsets: function(element, x, y) { - var offsetcache = this.realOffset(element); + var offsetcache = Element.cumulativeScrollOffset(element); this.xcomp = x + offsetcache[0] - this.deltaX; this.ycomp = y + offsetcache[1] - this.deltaY; - this.offset = this.cumulativeOffset(element); + this.offset = Element.cumulativeOffset(element); return (this.ycomp >= this.offset[1] && this.ycomp < this.offset[1] + element.offsetHeight && @@ -3154,125 +4118,104 @@ var Position = { element.offsetWidth; }, - page: function(forElement) { - var valueT = 0, valueL = 0; - - var element = forElement; - do { - valueT += element.offsetTop || 0; - valueL += element.offsetLeft || 0; + // Deprecation layer -- use newer Element methods now (1.5.2). - // Safari fix - if (element.offsetParent == document.body) - if (Element.getStyle(element,'position')=='absolute') break; + cumulativeOffset: Element.Methods.cumulativeOffset, - } while (element = element.offsetParent); + positionedOffset: Element.Methods.positionedOffset, - element = forElement; - do { - if (!window.opera || element.tagName=='BODY') { - valueT -= element.scrollTop || 0; - valueL -= element.scrollLeft || 0; - } - } while (element = element.parentNode); + absolutize: function(element) { + Position.prepare(); + return Element.absolutize(element); + }, - return [valueL, valueT]; + relativize: function(element) { + Position.prepare(); + return Element.relativize(element); }, - clone: function(source, target) { - var options = Object.extend({ - setLeft: true, - setTop: true, - setWidth: true, - setHeight: true, - offsetTop: 0, - offsetLeft: 0 - }, arguments[2] || {}) + realOffset: Element.Methods.cumulativeScrollOffset, - // find page position of source - source = $(source); - var p = Position.page(source); + offsetParent: Element.Methods.getOffsetParent, - // 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); - } + page: Element.Methods.viewportOffset, - // correct by body offsets (fixes Safari) - if (parent == document.body) { - delta[0] -= document.body.offsetLeft; - delta[1] -= document.body.offsetTop; + clone: function(source, target, options) { + options = options || { }; + return Element.clonePosition(target, source, options); + } +}; + +/*--------------------------------------------------------------------------*/ + +if (!document.getElementsByClassName) document.getElementsByClassName = function(instanceMethods){ + function iter(name) { + return name.blank() ? null : "[contains(concat(' ', @class, ' '), ' " + name + " ')]"; + } + + instanceMethods.getElementsByClassName = Prototype.BrowserFeatures.XPath ? + function(element, className) { + className = className.toString().strip(); + var cond = /\s/.test(className) ? $w(className).map(iter).join('') : iter(className); + return cond ? document._getElementsByXPath('.//*' + cond, element) : []; + } : function(element, className) { + className = className.toString().strip(); + var elements = [], classNames = (/\s/.test(className) ? $w(className) : null); + if (!classNames && !className) return elements; + + var nodes = $(element).getElementsByTagName('*'); + className = ' ' + className + ' '; + + for (var i = 0, child, cn; child = nodes[i]; i++) { + if (child.className && (cn = ' ' + child.className + ' ') && (cn.include(className) || + (classNames && classNames.all(function(name) { + return !name.toString().blank() && cn.include(' ' + name + ' '); + })))) + elements.push(Element.extend(child)); } + return elements; + }; - // 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'; - }, + return function(className, parentElement) { + return $(parentElement || document.body).getElementsByClassName(className); + }; +}(Element.Methods); - 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.ClassNames = Class.create(); +Element.ClassNames.prototype = { + initialize: function(element) { + this.element = $(element); + }, - 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; + _each: function(iterator) { + this.element.className.split(/\s+/).select(function(name) { + return name.length > 0; + })._each(iterator); + }, - element.style.position = 'absolute'; - element.style.top = top + 'px'; - element.style.left = left + 'px'; - element.style.width = width + 'px'; - element.style.height = height + 'px'; + set: function(className) { + this.element.className = className; }, - relativize: function(element) { - element = $(element); - if (element.style.position == 'relative') return; - Position.prepare(); + add: function(classNameToAdd) { + if (this.include(classNameToAdd)) return; + this.set($A(this).concat(classNameToAdd).join(' ')); + }, - element.style.position = 'relative'; - var top = parseFloat(element.style.top || 0) - (element._originalTop || 0); - var left = parseFloat(element.style.left || 0) - (element._originalLeft || 0); + remove: function(classNameToRemove) { + if (!this.include(classNameToRemove)) return; + this.set($A(this).without(classNameToRemove).join(' ')); + }, - element.style.top = top + 'px'; - element.style.left = left + 'px'; - element.style.height = element._originalHeight; - element.style.width = element._originalWidth; + toString: function() { + return $A(this).join(' '); } -} - -// 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); +Object.extend(Element.ClassNames.prototype, Enumerable); - 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 index 345b4a13..0ae173c8 100644 --- a/frontends/php/js/sbinit.js +++ b/frontends/php/js/sbinit.js @@ -122,7 +122,7 @@ function graph_zoom_init(graph_id,stime,period,width,height){ A_SBOX[graph_id].sbox = sbox_init(stime,period); A_SBOX[graph_id].sbox.sbox_id = graph_id; - + var igraph = $(graph_id); var posxy = getPosition(igraph); diff --git a/frontends/php/js/url.js b/frontends/php/js/url.js index dea32cb8..c50f178a 100644 --- a/frontends/php/js/url.js +++ b/frontends/php/js/url.js @@ -70,7 +70,7 @@ initialize: function(url){ var portColonIndex=host_less.indexOf(':'); if(portColonIndex>=0){ - this.port=host_less.substring(portColonIndex); + this.port=host_less.substring(portColonIndex+1); this.host=this.host.substring(0,host_ipv6); } } @@ -78,7 +78,7 @@ initialize: function(url){ else{ var portColonIndex=this.host.indexOf(':'); if(portColonIndex>=0){ - this.port=this.host.substring(portColonIndex); + this.port=this.host.substring(portColonIndex+1); this.host=this.host.substring(0,portColonIndex); } } @@ -138,6 +138,7 @@ getUrl: function(){ uri += encodeURI((this.username.length > 0)?(this.username):''); uri += encodeURI((this.password.length > 0)?(':'+this.password):''); uri += (this.host.length > 0)?(this.host):''; + uri += (this.port.length > 0)?(':'+this.port):''; uri += encodeURI((this.path.length > 0)?(this.path):''); uri += encodeURI((this.query.length > 0)?('?'+this.query):''); uri += encodeURI((this.reference.length > 0)?('#'+this.reference):''); diff --git a/frontends/php/popup.php b/frontends/php/popup.php index b533aad8..6e6205c5 100644 --- a/frontends/php/popup.php +++ b/frontends/php/popup.php @@ -50,7 +50,7 @@ break; case 'triggers': $page["title"] = "S_TRIGGERS_BIG"; - $min_user_type = USER_TYPE_ZABBIX_ADMIN; + $min_user_type = USER_TYPE_ZABBIX_USER; break; case 'logitems': $page["title"] = "S_ITEMS_BIG"; @@ -74,19 +74,23 @@ break; case 'screens': $page["title"] = "S_SCREENS_BIG"; - $min_user_type = USER_TYPE_ZABBIX_ADMIN; + $min_user_type = USER_TYPE_ZABBIX_USER; + break; + case 'slides': + $page["title"] = "S_SLIDESHOWS_BIG"; + $min_user_type = USER_TYPE_ZABBIX_USER; break; case 'graphs': $page["title"] = "S_GRAPHS_BIG"; - $min_user_type = USER_TYPE_ZABBIX_ADMIN; + $min_user_type = USER_TYPE_ZABBIX_USER; break; case 'simple_graph': $page["title"] = "S_SIMPLE_GRAPH_BIG"; - $min_user_type = USER_TYPE_ZABBIX_ADMIN; + $min_user_type = USER_TYPE_ZABBIX_USER; break; case 'sysmaps': $page["title"] = "S_MAPS_BIG"; - $min_user_type = USER_TYPE_ZABBIX_ADMIN; + $min_user_type = USER_TYPE_ZABBIX_USER; break; case 'plain_text': $page["title"] = "S_PLAIN_TEXT_BIG"; @@ -151,6 +155,8 @@ include_once "include/page_header.php"; 'real_hosts'=> array(T_ZBX_INT, O_OPT, null, IN('0,1'), null), 'itemtype'=> array(T_ZBX_INT, O_OPT, null, null, null), + 'reference'=> array(T_ZBX_STR, O_OPT, null, null, null), + "select"=> array(T_ZBX_STR, O_OPT, P_SYS|P_ACT, null, null) ); @@ -190,6 +196,7 @@ include_once "include/page_header.php"; '} catch(e){'. 'throw("Error: Target not found")'. '}'."\n"; + return $script; } ?> @@ -247,7 +254,7 @@ include_once "include/page_header.php"; else { if(str_in_array($srctbl,array('hosts','host_group','triggers','logitems','items', - 'applications','screens','graphs','simple_graph', + 'applications','screens','slides','graphs','simple_graph', 'sysmaps','plain_text','screens2','overview','host_group_scr'))) { if(ZBX_DISTRIBUTED) @@ -272,12 +279,12 @@ include_once "include/page_header.php"; $cmbGroups = new CComboBox('groupid',$groupid,'submit()'); $cmbGroups->AddItem(0,S_ALL_SMALL); - $db_groups = DBselect('select distinct g.groupid,g.name from groups g, hosts_groups hg, hosts h '. + $db_groups = DBselect('SELECT DISTINCT g.groupid,g.name from groups g, hosts_groups hg, hosts h '. ' where '.DBin_node('g.groupid', $nodeid). - ' and g.groupid=hg.groupid and hg.hostid in ('.$accessible_hosts.') '. - ' and hg.hostid = h.hostid '. - ($monitored_hosts ? ' and h.status='.HOST_STATUS_MONITORED : ''). - ($real_hosts ? ' and h.status<>'.HOST_STATUS_TEMPLATE : ''). + ' AND g.groupid=hg.groupid AND hg.hostid in ('.$accessible_hosts.') '. + ' AND hg.hostid = h.hostid '. + ($monitored_hosts ? ' AND h.status='.HOST_STATUS_MONITORED : ''). + ($real_hosts ? ' AND h.status<>'.HOST_STATUS_TEMPLATE : ''). ' order by name'); while($group = DBfetch($db_groups)) { @@ -302,7 +309,7 @@ include_once "include/page_header.php"; $hostid = get_request("hostid",get_profile("web.popup.hostid",0)); $cmbHosts = new CComboBox("hostid",$hostid,"submit()"); - $sql = 'SELECT distinct h.hostid,h.host FROM hosts h'; + $sql = 'SELECT DISTINCT h.hostid,h.host FROM hosts h'; if(isset($groupid)) { $sql .= ',hosts_groups hg WHERE '. @@ -315,9 +322,9 @@ include_once "include/page_header.php"; } $sql .= DBin_node('h.hostid', $nodeid). - " and h.hostid in (".$accessible_hosts.")". - ($monitored_hosts ? " and h.status=".HOST_STATUS_MONITORED : ""). - ($real_hosts ? ' and h.status<>'.HOST_STATUS_TEMPLATE : ''). + " AND h.hostid in (".$accessible_hosts.")". + ($monitored_hosts ? " AND h.status=".HOST_STATUS_MONITORED : ""). + ($real_hosts ? ' AND h.status<>'.HOST_STATUS_TEMPLATE : ''). ' order by host,h.hostid'; $db_hosts = DBselect($sql); @@ -337,6 +344,7 @@ include_once "include/page_header.php"; $btnEmpty = new CButton("empty",S_EMPTY, get_window_opener($dstfrm, $dstfld1, 0). get_window_opener($dstfrm, $dstfld2, ''). + ((isset($_REQUEST['reference']) && ($_REQUEST['reference'] =='dashboard'))?"window.opener.add2favorites();":''). " close_window(); return false;"); $frmTitle->AddItem(array(SPACE,$btnEmpty)); @@ -351,17 +359,17 @@ include_once "include/page_header.php"; $table = new CTableInfo(S_NO_HOSTS_DEFINED); $table->SetHeader(array(S_HOST,S_DNS,S_IP,S_PORT,S_STATUS,S_AVAILABILITY)); - $sql = "select distinct h.* from hosts h"; + $sql = "SELECT DISTINCT h.* from hosts h"; if(isset($groupid)) $sql .= ",hosts_groups hg where hg.groupid=".$groupid. - " and h.hostid=hg.hostid and "; + " AND h.hostid=hg.hostid AND "; else $sql .= " where "; $sql .= DBin_node('h.hostid', $nodeid). - " and h.hostid in (".$accessible_hosts.") ". - ($monitored_hosts ? " and h.status=".HOST_STATUS_MONITORED : ""). - ($real_hosts ? " and h.status<>".HOST_STATUS_TEMPLATE : ""). + " AND h.hostid in (".$accessible_hosts.") ". + ($monitored_hosts ? " AND h.status=".HOST_STATUS_MONITORED : ""). + ($real_hosts ? " AND h.status<>".HOST_STATUS_TEMPLATE : ""). " order by h.host,h.hostid"; @@ -369,10 +377,17 @@ include_once "include/page_header.php"; while($host = DBfetch($db_hosts)) { $name = new CLink($host["host"],"#","action"); - $name->SetAction( - get_window_opener($dstfrm, $dstfld1, $host[$srcfld1]). - (isset($srcfld2) ? get_window_opener($dstfrm, $dstfld2, $host[$srcfld2]) : ''). - " close_window(); return false;"); + if(isset($_REQUEST['reference']) && ($_REQUEST['reference'] =='dashboard')){ + $action = get_window_opener($dstfrm, $dstfld1, $srctbl). + get_window_opener($dstfrm, $dstfld2, $host[$srcfld2]). + "window.opener.add2favorites();"; + } + else{ + $action = get_window_opener($dstfrm, $dstfld1, $host[$srcfld1]). + (isset($srcfld2) ? get_window_opener($dstfrm, $dstfld2, $host[$srcfld2]) : ''); + } + + $name->SetAction($action." close_window(); return false;"); if($host["status"] == HOST_STATUS_MONITORED) $status=new CSpan(S_MONITORED,"off"); @@ -468,16 +483,16 @@ include_once "include/page_header.php"; $table = new CTableInfo(S_NO_TEMPLATES_DEFINED); $table->SetHeader(array(S_NAME)); - $sql = "select distinct h.* from hosts h"; + $sql = "SELECT DISTINCT h.* from hosts h"; if(isset($groupid)) $sql .= ",hosts_groups hg where hg.groupid=".$groupid. - " and h.hostid=hg.hostid and "; + " AND h.hostid=hg.hostid AND "; else $sql .= " where "; $sql .= DBin_node('h.hostid', $nodeid). - " and h.hostid in (".$accessible_hosts.") ". - " and h.status=".HOST_STATUS_TEMPLATE. + " AND h.hostid in (".$accessible_hosts.") ". + " AND h.status=".HOST_STATUS_TEMPLATE. " order by h.host,h.hostid"; $db_hosts = DBselect($sql); @@ -520,17 +535,24 @@ include_once "include/page_header.php"; $table = new CTableInfo(S_NO_GROUPS_DEFINED); $table->SetHeader(array(S_NAME)); - $db_groups = DBselect("select distinct groupid,name from groups ". + $db_groups = DBselect("SELECT DISTINCT groupid,name from groups ". ' where '.DBin_node('groupid', $nodeid). - " and groupid in (".$accessible_groups.") ". + " AND groupid in (".$accessible_groups.") ". " order by name"); while($row = DBfetch($db_groups)) { $name = new CLink($row["name"],"#","action"); - $name->SetAction( - get_window_opener($dstfrm, $dstfld1, $row[$srcfld1]). - (isset($srcfld2) ? get_window_opener($dstfrm, $dstfld2, $row[$srcfld2]) : ''). - " return close_window();"); + if(isset($_REQUEST['reference']) && ($_REQUEST['reference'] =='dashboard')){ + $action = get_window_opener($dstfrm, $dstfld1, $srctbl). + get_window_opener($dstfrm, $dstfld2, $row[$srcfld2]). + "window.opener.add2favorites();"; + } + else{ + $action = get_window_opener($dstfrm, $dstfld1, $row[$srcfld1]). + (isset($srcfld2) ? get_window_opener($dstfrm, $dstfld2, $row[$srcfld2]) : ''); + } + + $name->SetAction($action." close_window(); return false;"); $table->AddRow($name); } @@ -541,24 +563,31 @@ include_once "include/page_header.php"; $table = new CTableInfo(S_NO_TEMPLATES_DEFINED); $table->SetHeader(array(S_NAME)); - $sql = 'select distinct h.* from hosts h'; + $sql = 'SELECT DISTINCT h.* from hosts h'; if(isset($groupid)) $sql .= ',hosts_groups hg where hg.groupid='.$groupid. - ' and h.hostid=hg.hostid and '; + ' AND h.hostid=hg.hostid AND '; else $sql .= ' where '; - $sql .= DBin_node('h.hostid',$nodeid).' and status='.HOST_STATUS_TEMPLATE. - ' and h.hostid in ('.$accessible_hosts.') '. + $sql .= DBin_node('h.hostid',$nodeid).' AND status='.HOST_STATUS_TEMPLATE. + ' AND h.hostid in ('.$accessible_hosts.') '. ' order by h.host,h.hostid'; $db_hosts = DBselect($sql); while($row = DBfetch($db_hosts)) { $name = new CLink($row['host'],'#','action'); - $name->SetAction( - get_window_opener($dstfrm, $dstfld1, $row[$srcfld1]). - (isset($srcfld2) ? get_window_opener($dstfrm, $dstfld2, $row[$srcfld2]) : ''). - ' return close_window();'); + if(isset($_REQUEST['reference']) && ($_REQUEST['reference'] =='dashboard')){ + $action = get_window_opener($dstfrm, $dstfld1, $srctbl). + get_window_opener($dstfrm, $dstfld2, $row[$srcfld2]). + "window.opener.add2favorites();"; + } + else{ + $action = get_window_opener($dstfrm, $dstfld1, $row[$srcfld1]). + (isset($srcfld2) ? get_window_opener($dstfrm, $dstfld2, $row[$srcfld2]) : ''); + } + + $name->SetAction($action." close_window(); return false;"); $table->AddRow($name); } @@ -577,10 +606,18 @@ include_once "include/page_header.php"; '#', 'action' ); - $name->SetAction( - get_window_opener($dstfrm, $dstfld1, $row[$srcfld1]). - (isset($srcfld2) ? get_window_opener($dstfrm, $dstfld2, $row[$srcfld2]) : ''). - " close_window(); return false;"); + + if(isset($_REQUEST['reference']) && ($_REQUEST['reference'] =='dashboard')){ + $action = get_window_opener($dstfrm, $dstfld1, $srctbl). + get_window_opener($dstfrm, $dstfld2, $row[$srcfld2]). + "window.opener.add2favorites();"; + } + else{ + $action = get_window_opener($dstfrm, $dstfld1, $row[$srcfld1]). + (isset($srcfld2) ? get_window_opener($dstfrm, $dstfld2, $row[$srcfld2]) : ''); + } + + $name->SetAction($action." close_window(); return false;"); $table->AddRow($name); } @@ -599,10 +636,17 @@ include_once "include/page_header.php"; '#', 'action' ); - $name->SetAction( - get_window_opener($dstfrm, $dstfld1, $row[$srcfld1]). - (isset($srcfld2) ? get_window_opener($dstfrm, $dstfld2, $row[$srcfld2]) : ''). - " close_window(); return false;"); + if(isset($_REQUEST['reference']) && ($_REQUEST['reference'] =='dashboard')){ + $action = get_window_opener($dstfrm, $dstfld1, $srctbl). + get_window_opener($dstfrm, $dstfld2, $row[$srcfld2]). + "window.opener.add2favorites();"; + } + else{ + $action = get_window_opener($dstfrm, $dstfld1, $row[$srcfld1]). + (isset($srcfld2) ? get_window_opener($dstfrm, $dstfld2, $row[$srcfld2]) : ''); + } + + $name->SetAction($action." close_window(); return false;"); $table->AddRow($name); } @@ -618,9 +662,17 @@ include_once "include/page_header.php"; while($row = DBfetch($result)) { $name = new CLink($row["key_"],"#","action"); - $name->SetAction( - get_window_opener($dstfrm, $dstfld1, html_entity_decode($row[$srcfld1])). - " close_window(); return false;"); + if(isset($_REQUEST['reference']) && ($_REQUEST['reference'] =='dashboard')){ + $action = get_window_opener($dstfrm, $dstfld1, $srctbl). + get_window_opener($dstfrm, $dstfld2, $row[$srcfld2]). + "window.opener.add2favorites();"; + } + else{ + $action = get_window_opener($dstfrm, $dstfld1, html_entity_decode($row[$srcfld1])). + (isset($srcfld2) ? get_window_opener($dstfrm, $dstfld2, $row[$srcfld2]) : ''); + } + + $name->SetAction($action." close_window(); return false;"); $table->AddRow(array( $name, @@ -638,30 +690,39 @@ include_once "include/page_header.php"; S_STATUS)); - $sql = "select h.host,t.triggerid,t.description,t.expression,t.priority,t.status,count(d.triggerid_up) as dep_count ". - " from hosts h,items i,functions f, triggers t left join trigger_depends d on d.triggerid_down=t.triggerid ". - " where f.itemid=i.itemid and h.hostid=i.hostid and t.triggerid=f.triggerid". - ' and '.DBin_node('t.triggerid', $nodeid). - " and h.hostid not in (".$denyed_hosts.")". - ($monitored_hosts ? " and h.status=".HOST_STATUS_MONITORED : ""). - ($real_hosts ? " and h.status<>".HOST_STATUS_TEMPLATE : ""); + $sql = 'SELECT h.host,t.triggerid,t.description,t.expression,t.priority,t.status,count(d.triggerid_up) as dep_count '. + ' FROM hosts h,items i,functions f, triggers t left join trigger_depends d on d.triggerid_down=t.triggerid '. + ' WHERE f.itemid=i.itemid '. + ' AND h.hostid=i.hostid '. + ' AND t.triggerid=f.triggerid'. + ' AND '.DBin_node('t.triggerid', $nodeid). + ' AND h.hostid in ('.$accessible_hosts.')'. + ($monitored_hosts ? " AND h.status=".HOST_STATUS_MONITORED : ""). + ($real_hosts ? " AND h.status<>".HOST_STATUS_TEMPLATE : ""); if(isset($hostid)) - $sql .= " and h.hostid=$hostid"; + $sql .= ' AND h.hostid='.$hostid; - $sql .= " group by h.host, t.triggerid, t.description, t.expression, t.priority, t.status". - " order by h.host,t.description"; + $sql .= ' GROUP BY h.host, t.triggerid, t.description, t.expression, t.priority, t.status'. + ' ORDER BY h.host,t.description'; $result=DBselect($sql); - while($row=DBfetch($result)) - { + while($row=DBfetch($result)){ $exp_desc = expand_trigger_description_by_data($row); $description = new CLink($exp_desc,"#","action"); - $description->SetAction( - get_window_opener($dstfrm, $dstfld1, $row[$srcfld1]). - get_window_opener($dstfrm, $dstfld2, $exp_desc). - " close_window(); return false;"); - + + if(isset($_REQUEST['reference']) && ($_REQUEST['reference'] =='dashboard')){ + $action = get_window_opener($dstfrm, $dstfld1, $srctbl). + get_window_opener($dstfrm, $dstfld2, $exp_desc). + "window.opener.add2favorites();"; + } + else{ + $action = get_window_opener($dstfrm, $dstfld1, $row[$srcfld1]). + get_window_opener($dstfrm, $dstfld2, $exp_desc); + } + + $description->SetAction($action." close_window(); return false;"); + if($row['dep_count'] > 0) { $description = array( @@ -715,13 +776,13 @@ include_once "include/page_header.php"; S_DESCRIPTION,S_KEY,nbsp(S_UPDATE_INTERVAL), S_STATUS)); - $db_items = DBselect("select distinct h.host,i.* from items i,hosts h". - " where i.value_type=".ITEM_VALUE_TYPE_LOG." and h.hostid=i.hostid". - ' and '.DBin_node('i.itemid', $nodeid). - (isset($hostid) ? " and ".$hostid."=i.hostid " : ""). - " and i.hostid in (".$accessible_hosts.")". - ($monitored_hosts ? " and h.status=".HOST_STATUS_MONITORED : ""). - ($real_hosts ? " and h.status<>".HOST_STATUS_TEMPLATE : ""). + $db_items = DBselect("SELECT DISTINCT h.host,i.* from items i,hosts h". + " where i.value_type=".ITEM_VALUE_TYPE_LOG." AND h.hostid=i.hostid". + ' AND '.DBin_node('i.itemid', $nodeid). + (isset($hostid) ? " AND ".$hostid."=i.hostid " : ""). + " AND i.hostid in (".$accessible_hosts.")". + ($monitored_hosts ? " AND h.status=".HOST_STATUS_MONITORED : ""). + ($real_hosts ? " AND h.status<>".HOST_STATUS_TEMPLATE : ""). " order by h.host,i.description, i.key_, i.itemid"); while($db_item = DBfetch($db_items)) @@ -759,14 +820,15 @@ include_once "include/page_header.php"; S_STATUS )); - $sql = "select distinct h.host,i.* from hosts h,items i ". - ' where h.hostid=i.hostid and '.DBin_node('i.itemid', $nodeid). - " and h.hostid not in (".$denyed_hosts.")". - ($monitored_hosts ? " and h.status=".HOST_STATUS_MONITORED : ''). - ($real_hosts ? " and h.status<>".HOST_STATUS_TEMPLATE : ''); + $sql = 'SELECT DISTINCT h.host,i.* from hosts h,items i '. + ' WHERE h.hostid=i.hostid '. + ' AND '.DBin_node('i.itemid', $nodeid). + ' AND h.hostid IN ('.$accessible_hosts.')'. + ($monitored_hosts ? " AND h.status=".HOST_STATUS_MONITORED : ''). + ($real_hosts ? " AND h.status<>".HOST_STATUS_TEMPLATE : ''); if(isset($hostid)) - $sql .= " and h.hostid=$hostid"; + $sql .= ' AND h.hostid='.$hostid; $sql .= " order by h.host, i.description, i.key_, i.itemid"; @@ -779,11 +841,18 @@ include_once "include/page_header.php"; $row["description"] = $row['host'].':'.$row["description"]; - $description->SetAction( - get_window_opener($dstfrm, $dstfld1, $row[$srcfld1]). - (isset($srcfld2) ? get_window_opener($dstfrm, $dstfld2, $row[$srcfld2]) : ''). - " close_window(); return false;"); - + if(isset($_REQUEST['reference']) && ($_REQUEST['reference'] =='dashboard')){ + $action = get_window_opener($dstfrm, $dstfld1, $srctbl). + get_window_opener($dstfrm, $dstfld2, $row[$srcfld2]). + "window.opener.add2favorites();"; + } + else{ + $action = get_window_opener($dstfrm, $dstfld1, $row[$srcfld1]). + (isset($srcfld2) ? get_window_opener($dstfrm, $dstfld2, $row[$srcfld2]) : ''); + } + + $description->SetAction($action." close_window(); return false;"); + $table->AddRow(array( (isset($hostid) ? null : $row['host']), $description, @@ -801,14 +870,16 @@ include_once "include/page_header.php"; (isset($hostid) ? null : S_HOST), S_NAME)); - $sql = "select distinct h.host,a.* from hosts h,applications a ". - ' where h.hostid=a.hostid and '.DBin_node('a.applicationid', $nodeid). - " and h.hostid not in (".$denyed_hosts.")". - ($monitored_hosts ? " and h.status=".HOST_STATUS_MONITORED : ""). - ($real_hosts ? " and h.status<>".HOST_STATUS_TEMPLATE : ""); + $sql = 'SELECT DISTINCT h.host,a.* '. + ' FROM hosts h,applications a '. + ' WHERE h.hostid=a.hostid '. + ' AND '.DBin_node('a.applicationid', $nodeid). + ' AND h.hostid IN ('.$accessible_hosts.')'. + ($monitored_hosts ? " AND h.status=".HOST_STATUS_MONITORED : ""). + ($real_hosts ? " AND h.status<>".HOST_STATUS_TEMPLATE : ""); if(isset($hostid)) - $sql .= " and h.hostid=$hostid"; + $sql .= ' AND h.hostid='.$hostid; $sql .= " order by h.host,a.name"; @@ -818,11 +889,18 @@ include_once "include/page_header.php"; $name = new CLink($row["name"],"#","action"); - $name->SetAction( - get_window_opener($dstfrm, $dstfld1, $row[$srcfld1]). - (isset($srcfld2) ? get_window_opener($dstfrm, $dstfld2, $row[$srcfld2]) : ''). - " close_window(); return false;"); - + if(isset($_REQUEST['reference']) && ($_REQUEST['reference'] =='dashboard')){ + $action = get_window_opener($dstfrm, $dstfld1, $srctbl). + get_window_opener($dstfrm, $dstfld2, $row[$srcfld2]). + "window.opener.add2favorites();"; + } + else{ + $action = get_window_opener($dstfrm, $dstfld1, $row[$srcfld1]). + (isset($srcfld2) ? get_window_opener($dstfrm, $dstfld2, $row[$srcfld2]) : ''); + } + + $name->SetAction($action." close_window(); return false;"); + $table->AddRow(array(isset($hostid) ? null : $row['host'], $name)); } $table->Show(); @@ -832,17 +910,24 @@ include_once "include/page_header.php"; $table = new CTableInfo(S_NO_NODES_DEFINED); $table->SetHeader(S_NAME); - $result = DBselect('select distinct * from nodes where nodeid in ('.$accessible_nodes.')'); + $result = DBselect('SELECT DISTINCT * from nodes where nodeid in ('.$accessible_nodes.')'); while($row = DBfetch($result)) { $name = new CLink($row["name"],"#","action"); - $name->SetAction( - get_window_opener($dstfrm, $dstfld1, $row[$srcfld1]). - (isset($srcfld2) ? get_window_opener($dstfrm, $dstfld2, $row[$srcfld2]) : ''). - " close_window(); return false;"); - + if(isset($_REQUEST['reference']) && ($_REQUEST['reference'] =='dashboard')){ + $action = get_window_opener($dstfrm, $dstfld1, $srctbl). + get_window_opener($dstfrm, $dstfld2, $row[$srcfld2]). + "window.opener.add2favorites();"; + } + else{ + $action = get_window_opener($dstfrm, $dstfld1, $row[$srcfld1]). + (isset($srcfld2) ? get_window_opener($dstfrm, $dstfld2, $row[$srcfld2]) : ''); + } + + $name->SetAction($action." close_window(); return false;"); + $table->AddRow($name); } $table->Show(); @@ -858,7 +943,7 @@ include_once "include/page_header.php"; ' LEFT JOIN items i ON gi.itemid=i.itemid '. ' LEFT JOIN hosts h ON h.hostid=i.hostid '. ' LEFT JOIN nodes n ON n.nodeid='.DBid2nodeid('g.graphid'). - ' WHERE h.hostid NOT IN ('.$denyed_hosts.')'. + ' WHERE h.hostid IN ('.$accessible_hosts.')'. ' AND '.DBin_node('g.graphid', $nodeid); if(isset($hostid)) @@ -872,10 +957,17 @@ include_once "include/page_header.php"; $name = $row['node_name'].$row['host'].':'.$row['name']; $description = new CLink($row['name'],'#','action'); - $description->SetAction( - get_window_opener($dstfrm, $dstfld1, $row['graphid']). - get_window_opener($dstfrm, $dstfld2, $name). - ' close_window(); return false;'); + if(isset($_REQUEST['reference']) && ($_REQUEST['reference'] =='dashboard')){ + $action = get_window_opener($dstfrm, $dstfld1, $srctbl). + get_window_opener($dstfrm, $dstfld2, $row[$srcfld2]). + "window.opener.add2favorites();"; + } + else{ + $action = get_window_opener($dstfrm, $dstfld1, $row[$srcfld1]). + get_window_opener($dstfrm, $dstfld2, $name); + } + + $description->SetAction($action." close_window(); return false;"); switch($row['graphtype']){ case GRAPH_TYPE_STACKED: @@ -920,8 +1012,8 @@ include_once "include/page_header.php"; ' AND i.status='.ITEM_STATUS_ACTIVE. ' AND '.DBin_node('i.itemid', $nodeid). ' AND h.hostid not in ('.$denyed_hosts.')'. - ($monitored_hosts ? " and h.status=".HOST_STATUS_MONITORED : ''). - ($real_hosts ? " and h.status<>".HOST_STATUS_TEMPLATE : ''); + ($monitored_hosts ? " AND h.status=".HOST_STATUS_MONITORED : ''). + ($real_hosts ? " AND h.status<>".HOST_STATUS_TEMPLATE : ''); if(isset($hostid)) $sql .= ' AND h.hostid='.$hostid; @@ -938,11 +1030,18 @@ include_once "include/page_header.php"; $row["description"] = $row['node_name'].$row['host'].':'.$row["description"]; - $description->SetAction( - get_window_opener($dstfrm, $dstfld1, $row['itemid']). - get_window_opener($dstfrm, $dstfld2, $row[$srcfld2]). - ' close_window(); return false;'); - + if(isset($_REQUEST['reference']) && ($_REQUEST['reference'] =='dashboard')){ + $action = get_window_opener($dstfrm, $dstfld1, $srctbl). + get_window_opener($dstfrm, $dstfld2, $row[$srcfld2]). + "window.opener.add2favorites();"; + } + else{ + $action = get_window_opener($dstfrm, $dstfld1, $row[$srcfld1]). + get_window_opener($dstfrm, $dstfld2, $row[$srcfld2]); + } + + $description->SetAction($action." close_window(); return false;"); + $table->AddRow(array( (isset($hostid) ? null : $row['host']), $description, @@ -970,10 +1069,18 @@ include_once "include/page_header.php"; $name = $row['node_name'].$row['name']; $description = new CLink($row['name'],'#','action'); - $description->SetAction( - get_window_opener($dstfrm, $dstfld1, $row['sysmapid']). - get_window_opener($dstfrm, $dstfld2, $name). - ' close_window(); return false;'); + + if(isset($_REQUEST['reference']) && ($_REQUEST['reference'] =='dashboard')){ + $action = get_window_opener($dstfrm, $dstfld1, $srctbl). + get_window_opener($dstfrm, $dstfld2, $row[$srcfld2]). + "window.opener.add2favorites();"; + } + else{ + $action = get_window_opener($dstfrm, $dstfld1, $row[$srcfld1]). + get_window_opener($dstfrm, $dstfld2, $name); + } + + $description->SetAction($action." close_window(); return false;"); $table->AddRow($description); @@ -1000,8 +1107,8 @@ include_once "include/page_header.php"; ' AND i.status='.ITEM_STATUS_ACTIVE. ' AND '.DBin_node('i.itemid', $nodeid). ' AND h.hostid not in ('.$denyed_hosts.')'. - ($monitored_hosts ? " and h.status=".HOST_STATUS_MONITORED : ''). - ($real_hosts ? " and h.status<>".HOST_STATUS_TEMPLATE : ''); + ($monitored_hosts ? " AND h.status=".HOST_STATUS_MONITORED : ''). + ($real_hosts ? " AND h.status<>".HOST_STATUS_TEMPLATE : ''); if(isset($hostid)) $sql .= ' AND h.hostid='.$hostid; @@ -1018,11 +1125,18 @@ include_once "include/page_header.php"; $row["description"] = $row['node_name'].$row['host'].':'.$row["description"]; - $description->SetAction( - get_window_opener($dstfrm, $dstfld1, $row['itemid']). - get_window_opener($dstfrm, $dstfld2, $row[$srcfld2]). - ' close_window(); return false;'); - + if(isset($_REQUEST['reference']) && ($_REQUEST['reference'] =='dashboard')){ + $action = get_window_opener($dstfrm, $dstfld1, $srctbl). + get_window_opener($dstfrm, $dstfld2, $row[$srcfld2]). + "window.opener.add2favorites();"; + } + else{ + $action = get_window_opener($dstfrm, $dstfld1, $row[$srcfld1]). + get_window_opener($dstfrm, $dstfld2, $row[$srcfld2]); + } + + $description->SetAction($action." close_window(); return false;"); + $table->AddRow(array( (isset($hostid) ? null : $row['host']), $description, @@ -1033,6 +1147,37 @@ include_once "include/page_header.php"; } $table->Show(); } + elseif('slides' == $srctbl) + { + require_once "include/screens.inc.php"; + + $table = new CTableInfo(S_NO_NODES_DEFINED); + $table->SetHeader(S_NAME); + + $result = DBselect('select slideshowid,name from slideshows where '.DBin_node('slideshowid',$nodeid).' order by name'); + while($row=DBfetch($result)){ + if(!slideshow_accessiable($row["slideshowid"], PERM_READ_ONLY)) + continue; + + $name = new CLink($row["name"],"#","action"); + + if(isset($_REQUEST['reference']) && ($_REQUEST['reference'] =='dashboard')){ + $action = get_window_opener($dstfrm, $dstfld1, $srctbl). + get_window_opener($dstfrm, $dstfld2, $row[$srcfld2]). + "window.opener.add2favorites();"; + } + else{ + $action = get_window_opener($dstfrm, $dstfld1, $row[$srcfld1]). + (isset($srcfld2) ? get_window_opener($dstfrm, $dstfld2, $row[$srcfld2]) : ''); + } + + $name->SetAction($action." close_window(); return false;"); + + $table->AddRow($name); + } + + $table->Show(); + } elseif($srctbl == 'screens') { require_once "include/screens.inc.php"; @@ -1047,11 +1192,19 @@ include_once "include/page_header.php"; continue; $name = new CLink($row["name"],"#","action"); - $name->SetAction( - get_window_opener($dstfrm, $dstfld1, $row[$srcfld1]). - (isset($srcfld2) ? get_window_opener($dstfrm, $dstfld2, $row[$srcfld2]) : ''). - ' close_window(); return false;'); - + + if(isset($_REQUEST['reference']) && ($_REQUEST['reference'] =='dashboard')){ + $action = get_window_opener($dstfrm, $dstfld1, $srctbl). + get_window_opener($dstfrm, $dstfld2, $row[$srcfld2]). + "window.opener.add2favorites();"; + } + else{ + $action = get_window_opener($dstfrm, $dstfld1, $row[$srcfld1]). + (isset($srcfld2) ? get_window_opener($dstfrm, $dstfld2, $row[$srcfld2]) : ''); + } + + $name->SetAction($action." close_window(); return false;"); + $table->AddRow($name); } @@ -1081,11 +1234,18 @@ include_once "include/page_header.php"; $name = new CLink($row['name'],'#','action'); $row['name'] = $row['node_name'].$row['name']; - $name->SetAction( - get_window_opener($dstfrm, $dstfld1, $row[$srcfld1]). - (isset($srcfld2) ? get_window_opener($dstfrm, $dstfld2, $row[$srcfld2]) : ''). - ' close_window(); return false;'); - + if(isset($_REQUEST['reference']) && ($_REQUEST['reference'] =='dashboard')){ + $action = get_window_opener($dstfrm, $dstfld1, $srctbl). + get_window_opener($dstfrm, $dstfld2, $row[$srcfld2]). + "window.opener.add2favorites();"; + } + else{ + $action = get_window_opener($dstfrm, $dstfld1, $row[$srcfld1]). + (isset($srcfld2) ? get_window_opener($dstfrm, $dstfld2, $row[$srcfld2]) : ''); + } + + $name->SetAction($action." close_window(); return false;"); + $table->AddRow($name); } @@ -1111,11 +1271,18 @@ include_once "include/page_header.php"; $name = new CLink($row['name'],'#','action'); $row['name'] = $row['node_name'].$row['name']; - $name->SetAction( - get_window_opener($dstfrm, $dstfld1, $row[$srcfld1]). - (isset($srcfld2) ? get_window_opener($dstfrm, $dstfld2, $row[$srcfld2]) : ''). - ' close_window(); return false;'); - + if(isset($_REQUEST['reference']) && ($_REQUEST['reference'] =='dashboard')){ + $action = get_window_opener($dstfrm, $dstfld1, $srctbl). + get_window_opener($dstfrm, $dstfld2, $row[$srcfld2]). + "window.opener.add2favorites();"; + } + else{ + $action = get_window_opener($dstfrm, $dstfld1, $row[$srcfld1]). + (isset($srcfld2) ? get_window_opener($dstfrm, $dstfld2, $row[$srcfld2]) : ''); + } + + $name->SetAction($action." close_window(); return false;"); + $table->AddRow($name); } @@ -1142,10 +1309,19 @@ include_once "include/page_header.php"; if(!$all){ $name = new CLink(bold(S_MINUS_ALL_GROUPS_MINUS),'#','action'); - $name->SetAction( - get_window_opener($dstfrm, $dstfld1, create_id_by_nodeid(0,$nodeid)). - get_window_opener($dstfrm, $dstfld2, $row['node_name'].S_MINUS_ALL_GROUPS_MINUS). - ' return close_window();'); + + if(isset($_REQUEST['reference']) && ($_REQUEST['reference'] =='dashboard')){ + $action = get_window_opener($dstfrm, $dstfld1, $srctbl). + get_window_opener($dstfrm, $dstfld2, create_id_by_nodeid(0,$nodeid)). + "window.opener.add2favorites();"; + } + else{ + $action = get_window_opener($dstfrm, $dstfld1, create_id_by_nodeid(0,$nodeid)). + get_window_opener($dstfrm, $dstfld2, $row['node_name'].S_MINUS_ALL_GROUPS_MINUS); + + } + + $name->SetAction($action." close_window(); return false;"); $table->AddRow($name); $all = true; @@ -1157,6 +1333,7 @@ include_once "include/page_header.php"; $name->SetAction( get_window_opener($dstfrm, $dstfld1, $row[$srcfld1]). get_window_opener($dstfrm, $dstfld2, $row[$srcfld2]). + ((isset($_REQUEST['reference']) && ($_REQUEST['reference'] =='dashboard'))?"window.opener.add2favorites();":''). ' return close_window();'); $table->AddRow($name); diff --git a/frontends/php/profile.php b/frontends/php/profile.php index 8ba8e9b7..8f3a8c75 100644 --- a/frontends/php/profile.php +++ b/frontends/php/profile.php @@ -25,6 +25,7 @@ $page["title"] = "S_USER_PROFILE"; $page["file"] = "profile.php"; + $page['hist_arg'] = array(); include_once "include/page_header.php"; diff --git a/frontends/php/queue.php b/frontends/php/queue.php index 5320a9b4..1ca91ef6 100644 --- a/frontends/php/queue.php +++ b/frontends/php/queue.php @@ -70,18 +70,21 @@ include_once "include/page_header.php"; //ITEM_TYPE_HTTPTEST, ITEM_TYPE_EXTERNAL); - $result = DBselect("select i.itemid,i.nextcheck,i.description,i.key_,i.type,h.host,h.hostid ". - " from items i,hosts h ". - " where i.status=".ITEM_STATUS_ACTIVE." and i.type in (".implode(',',$item_types).") ". - " and ((h.status=".HOST_STATUS_MONITORED." and h.available != ".HOST_AVAILABLE_FALSE.") ". - " or (h.status=".HOST_STATUS_MONITORED." and h.available=".HOST_AVAILABLE_FALSE." and h.disable_until<=$now)) ". - " and i.hostid=h.hostid and i.nextcheck<$now and i.key_ not in ('status','icmpping','icmppingsec','zabbix[log]') ". - " and i.value_type not in (".ITEM_VALUE_TYPE_LOG.") ". - " and h.hostid in (".get_accessible_hosts_by_user($USER_DETAILS,PERM_READ_ONLY,null,null,get_current_nodeid()).")". -// " and h.hostid in (".get_accessible_hosts_by_user($USER_DETAILS,PERM_READ_ONLY,null,null,$ZBX_LOCALNODEID).")". -// " and ".DBin_node('h.hostid', $ZBX_LOCALNODEID). - " and ".DBin_node('h.hostid', get_current_nodeid()). - " order by i.nextcheck,h.host,i.description,i.key_"); + $result = DBselect('SELECT i.itemid,i.nextcheck,i.description,i.key_,i.type,h.host,h.hostid '. + ' FROM items i,hosts h '. + ' WHERE i.status='.ITEM_STATUS_ACTIVE. + ' AND i.type in ('.implode(',',$item_types).') '. + ' AND ((h.status='.HOST_STATUS_MONITORED.' AND h.available != '.HOST_AVAILABLE_FALSE.') '. + ' or (h.status='.HOST_STATUS_MONITORED.' AND h.available='.HOST_AVAILABLE_FALSE.' AND h.disable_until<='.$now.')) '. + ' AND i.hostid=h.hostid '. + ' AND i.nextcheck<'.$now. + " AND i.key_ not in ('status','icmpping','icmppingsec','zabbix[log]') ". + ' AND i.value_type not in ('.ITEM_VALUE_TYPE_LOG.') '. + ' AND h.hostid in ('.get_accessible_hosts_by_user($USER_DETAILS,PERM_READ_ONLY,null,null,get_current_nodeid()).')'. +// ' AND h.hostid in ('.get_accessible_hosts_by_user($USER_DETAILS,PERM_READ_ONLY,null,null,$ZBX_LOCALNODEID).')'. +// ' AND '.DBin_node('h.hostid', $ZBX_LOCALNODEID). + ' AND '.DBin_node('h.hostid', get_current_nodeid()). + ' order by i.nextcheck,h.host,i.description,i.key_'); $table = new CTableInfo(S_THE_QUEUE_IS_EMPTY); @@ -111,11 +114,16 @@ include_once "include/page_header.php"; $table->setHeader(array(S_ITEMS,S_5_SECONDS,S_10_SECONDS,S_30_SECONDS,S_1_MINUTE,S_5_MINUTES,S_MORE_THAN_5_MINUTES)); foreach($item_types as $type) { - $elements=array(item_type2str($type),$sec_5[$type],$sec_10[$type], - new CCol($sec_30[$type],"warning"), - new CCol($sec_60[$type],"average"), - new CCol($sec_300[$type],"high"), - new CCol($sec_rest[$type],"disaster")); + $elements=array( + item_type2str($type), + new CCol($sec_5[$type],($sec_5[$type])?"unknown_trigger":"normal"), + new CCol($sec_10[$type],($sec_10[$type])?"information":"normal"), + new CCol($sec_30[$type],($sec_30[$type])?"warning":"normal"), + new CCol($sec_60[$type],($sec_60[$type])?"average":"normal"), + new CCol($sec_300[$type],($sec_300[$type])?"high":"normal"), + new CCol($sec_rest[$type],($sec_rest[$type])?"disaster":"normal") + ); + $table->addRow($elements); } } diff --git a/frontends/php/report1.php b/frontends/php/report1.php index 92821249..58209e9b 100644 --- a/frontends/php/report1.php +++ b/frontends/php/report1.php @@ -1,7 +1,7 @@ <?php /* ** ZABBIX -** Copyright (C) 2000-2005 SIA Zabbix +** Copyright (C) 2000-2008 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 @@ -20,6 +20,8 @@ ?> <?php require_once "include/config.inc.php"; + require_once "include/blocks.inc.php"; + $page["title"] = "S_STATUS_OF_ZABBIX"; $page["file"] = "report1.php"; $page['hist_arg'] = array(); @@ -35,35 +37,9 @@ include_once "include/page_header.php"; ?> <?php show_table_header(S_STATUS_OF_ZABBIX_BIG); - - $table = new CTableInfo(); - - $table->SetHeader(array(S_PARAMETER,S_VALUE)); - - $status=get_status(); - - $table->AddRow(array(S_ZABBIX_SERVER_IS_RUNNING,new CSpan($status["zabbix_server"], ($status["zabbix_server"] == S_YES ? "off" : "on")))); -// $table->AddRow(array(S_VALUES_STORED,$status["history_count"])); -// $table->AddRow(array(S_TRENDS_STORED,$status["trends_count"])); - $table->AddRow(array(S_NUMBER_OF_HOSTS,array($status["hosts_count"]."(", - new CSpan($status["hosts_count_monitored"],"off"),"/", - new CSpan($status["hosts_count_not_monitored"],"on"),"/", - new CSpan($status["hosts_count_template"],"unknown"),"/", - $status["hosts_count_deleted"].")"))); - $table->AddRow(array(S_NUMBER_OF_ITEMS,array($status["items_count"]."(", - new CSpan($status["items_count_monitored"],"off"),"/", - new CSpan($status["items_count_disabled"],"on"),"/", - new CSpan($status["items_count_not_supported"],"unknown"), - ")[".$status["items_count_trapper"]."]"))); - $table->AddRow(array(S_NUMBER_OF_TRIGGERS,array($status["triggers_count"]. - "(".$status["triggers_count_enabled"]."/".$status["triggers_count_disabled"].")"."[", - new CSpan($status["triggers_count_on"],"on"),"/", - new CSpan($status["triggers_count_unknown"],"unknown"),"/", - new CSpan($status["triggers_count_off"],"off"),"]" - ))); - $table->AddRow(array(S_NUMBER_OF_EVENTS,$status["events_count"])); - $table->AddRow(array(S_NUMBER_OF_ALERTS,$status["alerts_count"])); - $table->Show(); + + $status = make_status_of_zbx(); + $status->Show(); ?> <?php diff --git a/frontends/php/styles/css_bb.css b/frontends/php/styles/css_bb.css index 20d8dd67..886a2186 100644 --- a/frontends/php/styles/css_bb.css +++ b/frontends/php/styles/css_bb.css @@ -17,6 +17,10 @@ body{ } +.enabled { color: #0088FF; } +.unknown { color: #999999; } +.off { color: #0088FF; } +.normal { background-color: #AADDDD; } /*//////////////// LINKS ////////////////////*/ @@ -27,10 +31,10 @@ a.highlight:hover { text-decoration:none; color: #0AF; } -A.enabled:link { color:#00AA00; text-decoration: none; } -A.enabled:visited { color:#00AA00; text-decoration: none; } -A.enabled:hover { color:#00AA00; text-decoration: underline; } -A.enabled:active { color:#00AA00; text-decoration: underline;} +A.enabled:link { color:#0088FF; text-decoration: none; } +A.enabled:visited { color:#0088FF; text-decoration: none; } +A.enabled:hover { color:#0088FF; text-decoration: underline; } +A.enabled:active { color:#0088FF; text-decoration: underline;} A.disabled:link { color:#AA0000; text-decoration: none; } A.disabled:visited { color:#AA0000; text-decoration: none; } @@ -47,10 +51,10 @@ A.unknown:visited { color:#777777; text-decoration: none; } A.unknown:hover { color:#AAAAAA; text-decoration: underline; } A.unknown:active { color:#777777; text-decoration: underline;} -A.off:link { color:#00AA00; text-decoration: none; } -A.off:visited { color:#00AA00; text-decoration: none; } -A.off:hover { color:#00AA00; text-decoration: underline; } -A.off:active { color:#00AA00; text-decoration: underline;} +A.off:link { color:#0088FF; text-decoration: none; } +A.off:visited { color:#0088FF; text-decoration: none; } +A.off:hover { color:#0088FF; text-decoration: underline; } +A.off:active { color:#0088FF; text-decoration: underline;} A.on:link { color:#AA0000; text-decoration: none; } A.on:visited { color:#AA0000; text-decoration: none; } @@ -160,6 +164,9 @@ table.tableinfo{ background-color: #5A5A5A; } +table.tableinfo tr td.normal { background-color: #AADDDD; border: 1px #AADDDD solid; } +table.tableinfo tr:hover td.normal { background-color: #AACCCC; border: 1px #AAD9DD solid; } + table.tableinfo tr.footer td { background: #5C7099 url('../images/gradients/table_head2_bb.gif') repeat-x top left; } @@ -209,13 +216,6 @@ table.history td.caption{ color:#0AF; } -table.tableinfo tr td.normal { background-color: #AADDDD; border: 1px #AADDAA solid; } -table.tableinfo tr:hover td.normal { background-color: #AACCCC; border: 1px #AAD9AA solid; } - -table.tableinfo tr td.average { background-color: #DDAAAA; border: 1px #DDAAAA solid; } -table.tableinfo tr:hover td.average { background-color: #DD9999; border: 1px #D8A5AA solid; } - - /*//////////////// DIVS ////////////////////*/ div.zabbix_logo{ @@ -225,6 +225,18 @@ div.zabbix_logo{ background-repeat: no-repeat; } +div.menuplus{ + background-image: url('../images/general/bttn/plus_bb.png'); +} + +div.arrowup{ + background-image: url('../images/general/bttn/arrowup_bb.png'); +} + +div.arrowdown{ + background-image: url('../images/general/bttn/arrowdown_bb.png'); +} + div#scrolltableft{ color: #0CF; } @@ -233,9 +245,13 @@ div#scrolltabright{ color: #0CF; } +span.green{ + color: #0088FF; +} + /*//////////////// PARAGRAPHS ////////////////////*/ -p.msgerror { color: #CC0000; } +p.msgerror { color: #FF2222; } p.msgok { color: #0088FF; } diff --git a/frontends/php/styles/default.css b/frontends/php/styles/default.css index bfad6714..31932332 100644 --- a/frontends/php/styles/default.css +++ b/frontends/php/styles/default.css @@ -1,170 +1,171 @@ -/* 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.
-**
-*/
-
-body{
- background-color:#e5e5e5;
- margin: 0px;
- padding: 0px;
- color:black;
- font-family:verdana, arial, helvetica, sans-serif;
- font-size:10px;
- text-decoration: none;
- line-height:16px;
-}
-
-/**************** MEDIA *****************/
-@media print {
- div.printless{
- visibility: hidden;
- display: none;
- }
- div.printonly{
- display: block;
- visibility:visible;
- }
-}
-
-@media screen {
- div.printless{
- visibility:visible;
- display:block;
- }
- div.printonly{
- visibility: hidden;
- display:none;
- }
-}
-
-/**************** OTHERS ****************/
-.top { vertical-align: top; }
-.footer { color:#CCCCCC; }
-
-.enabled { color: #00AA00; }
-.disabled { color: #AA0000; }
-.unknown { color: #AAAAAA; }
-.on { color: #AA0000; }
-.off { color: #00AA00; }
-
-.disaster { background-color: #FF0000; }
-.high { background-color: #FF8888; }
-.average { background-color: #DDAAAA; }
-.warning { background-color: #EFEFCC; }
-.information { background-color: #CCE2CC; }
-.unknown_trigger{ background-color: #BCBCBC; }
-.normal { background-color: #AADDAA; }
-
-.img { border-color:black; border-width:1px; }
-img.top { vertical-align:text-top }
-img.bottom { vertical-align:text-bottom }
-
-.center{
- width: 100%;
- text-align: center;
-}
-
-.vert{
- width:1px;
- /*writing-mode: tb-rl;*/
-}
-
-.rarr{
- font-size: 16px;
-}
-
-.bold {
- font-weight: bold;
-}
-
-.nowrap {
- white-space: nowrap;
- word-spacing: 0px;
-}
-
-.delimiter{
- font-weight:bold;
- color:#000;
-}
-
-/**************** HINT BOX *****************/
-
-#hint_box {
- top: 0;
- z-index: 100;
- position: absolute;
- background-color: #FFFFE0;
- padding: 2px;
- font-family: Verdana, Arial, Helvetica, sans-serif;
- font-size: 8pt;
- line-height:15px;
- border: 1px solid black;
- border-left: none;
- border-top: none;
- visibility: hidden;
-}
-
-/************** END OF HINT BOX ************/
-
-/************** COLOR PICKER ***************/
-#color_picker {
- top: 0;
- z-index: 100;
- position: absolute;
- background-color: white;
- padding: 2px;
- font-family: Verdana, Arial, Helvetica, sans-serif;
- font-size: 10px;
- line-height:15px;
- border: 1px solid black;
-}
-
-#color_picker table tr td {
- margin: 0px;
- padding: 2px;
-}
-
-#color_picker a {
- text-decoration: none;
- font-family: Verdana, Arial, Helvetica, sans-serif;
- font-size: 10px;
- padding: 0px;
- margin: 0px;
-}
-
-/************ END OF COLOR PICKER ***********/
-
-/************** DISCOVERY STATUS ************/
-.dhosts_active {
- padding: 5px;
- text-align: center;
- color: #0FA00F;
-}
-.dhosts_disabled {
- padding: 5px;
- text-align: center;
- color: #A00F0F;
-}
-.dservice_active {
- background: #0FA00F;
-}
-.dservice_disabled {
- background: #A00F0F;
-}
-/********** END OF DISCOVERY STATUS *********/
+/* 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. +** +*/ + +body{ + background-color:#e5e5e5; + margin: 0px; + padding: 0px; + color:black; + font-family:verdana, arial, helvetica, sans-serif; + font-size:10px; + text-decoration: none; + line-height:16px; +} + +/**************** MEDIA *****************/ +@media print { + div.printless{ + visibility: hidden; + display: none; + } + div.printonly{ + display: block; + visibility:visible; + } +} + +@media screen { + div.printless{ + visibility:visible; + display:block; + } + div.printonly{ + visibility: hidden; + display:none; + } +} + +/**************** OTHERS ****************/ +.top { vertical-align: top; } +.footer { color:#CCCCCC; } + +.enabled { color: #00AA00; } +.disabled { color: #AA0000; } +.unknown { color: #AAAAAA; } +.on { color: #AA0000; } +.off { color: #00AA00; } + +.disaster { background-color: #FF0000; } +.high { background-color: #FF8888; } +.average { background-color: #DDAAAA; } +.warning { background-color: #EFEFCC; } +.information { background-color: #CCE2CC; } +.unknown_trigger{ background-color: #BCBCBC; } +.normal { background-color: #AADDAA; } + +.img { border-color:black; border-width:1px; } +img.top { vertical-align:text-top } +img.bottom { vertical-align:text-bottom } +img.borderless { border-width: 0px; vertical-align: bottom; } + +.center{ + width: 100%; + text-align: center; +} + +.vert{ + width:1px; + /*writing-mode: tb-rl;*/ +} + +.rarr{ + font-size: 16px; +} + +.bold { + font-weight: bold; +} + +.nowrap { + white-space: nowrap; + word-spacing: 0px; +} + +.delimiter{ + font-weight:bold; + color:#000; +} + +/**************** HINT BOX *****************/ + +#hint_box { + top: 0; + z-index: 100; + position: absolute; + background-color: #FFFFE0; + padding: 2px; + font-family: Verdana, Arial, Helvetica, sans-serif; + font-size: 8pt; + line-height:15px; + border: 1px solid black; + border-left: none; + border-top: none; + visibility: hidden; +} + +/************** END OF HINT BOX ************/ + +/************** COLOR PICKER ***************/ +#color_picker { + top: 0; + z-index: 100; + position: absolute; + background-color: white; + padding: 2px; + font-family: Verdana, Arial, Helvetica, sans-serif; + font-size: 10px; + line-height:15px; + border: 1px solid black; +} + +#color_picker table tr td { + margin: 0px; + padding: 2px; +} + +#color_picker a { + text-decoration: none; + font-family: Verdana, Arial, Helvetica, sans-serif; + font-size: 10px; + padding: 0px; + margin: 0px; +} + +/************ END OF COLOR PICKER ***********/ + +/************** DISCOVERY STATUS ************/ +.dhosts_active { + padding: 5px; + text-align: center; + color: #0FA00F; +} +.dhosts_disabled { + padding: 5px; + text-align: center; + color: #A00F0F; +} +.dservice_active { + background: #0FA00F; +} +.dservice_disabled { + background: #A00F0F; +} +/********** END OF DISCOVERY STATUS *********/ diff --git a/frontends/php/styles/div.css b/frontends/php/styles/div.css index 1824b75c..19f412a8 100644 --- a/frontends/php/styles/div.css +++ b/frontends/php/styles/div.css @@ -36,6 +36,39 @@ div.zabbix_logo{ background: #FFFFFF url('../images/general/zabbix.png') no-repeat; } +div.menuplus{ + height: 18px; + width: 18px; + background-image: url('../images/general/bttn/plus.png'); + background-repeat:no-repeat; +} + +div.menuplus:hover{ + cursor:pointer; +} + +div.arrowup{ + height: 18px; + width: 18px; + background-image: url('../images/general/bttn/arrowup.png'); + background-repeat:no-repeat; +} + +div.arrowup:hover{ + cursor:pointer; +} + +div.arrowdown{ + height: 18px; + width: 18px; + background-image: url('../images/general/bttn/arrowdown.png'); + background-repeat:no-repeat; +} + +div.arrowdown:hover{ + cursor:pointer; +} + span.footer_sign{ padding-right: 5px; padding-left: 5px; @@ -53,16 +86,20 @@ span.ok{ color: #00AA00; font-weight: bold; } + span.fail{ color: #AA0000; font-weight: bold; } + span.green{ color: #00AA00; } + span.red{ color: #AA0000; } + span.orange{ color: #EE6000; -} +}
\ No newline at end of file diff --git a/frontends/php/styles/sbox.css b/frontends/php/styles/sbox.css index 0fc636c3..fed2f504 100644 --- a/frontends/php/styles/sbox.css +++ b/frontends/php/styles/sbox.css @@ -6,7 +6,6 @@ div#selection_box{ filter:alpha(opacity=40); -moz-opacity:.40; - -khtml-opacity: 0.4; opacity:.40; background-color:#0000FF; border:1px black solid; diff --git a/frontends/php/styles/table.css b/frontends/php/styles/table.css index 2d95161c..05e546dd 100644 --- a/frontends/php/styles/table.css +++ b/frontends/php/styles/table.css @@ -519,26 +519,44 @@ table.tableinfo tr.even_row:hover td { background-color: #EEEEFE; border: 1px # table.tableinfo tr td.center { vertical-align: middle; text-align: center; } -table.tableinfo tr td.disaster { background-color: #FF0000; border: 1px #FF0000 solid; } +table.tableinfo tr td.disaster_empty { border: 1px #FF0000 solid; } +table.tableinfo tr:hover td.disaster_empty { border: 1px #FF0000 solid; } + +table.tableinfo tr td.disaster { background-color: #FF0000; border: 1px #FF0000 solid; } table.tableinfo tr:hover td.disaster { background-color: #FA0000; border: 1px #FA0000 solid; } -table.tableinfo tr td.high { background-color: #FF8888; border: 1px #FF8888 solid; } +table.tableinfo tr td.high_empty { border: 1px #FF8888 solid; } +table.tableinfo tr:hover td.high_empty { border: 1px #FF8888 solid; } + +table.tableinfo tr td.high { background-color: #FF8888; border: 1px #FF8888 solid; } table.tableinfo tr:hover td.high { background-color: #FA8388; border: 1px #FA8388 solid; } +table.tableinfo tr td.average_empty { border: 1px #DDAAAA solid; } +table.tableinfo tr:hover td.average_empty { border: 1px #DDAAAA solid; } + table.tableinfo tr td.average { background-color: #DDAAAA; border: 1px #DDAAAA solid; } table.tableinfo tr:hover td.average { background-color: #D8A5AA; border: 1px #D8A5AA solid; } +table.tableinfo tr td.warning_empty { border: 1px #EFEFCC solid; } +table.tableinfo tr:hover td.warning_empty { border: 1px #EAEACC solid; } + table.tableinfo tr td.warning { background-color: #EFEFCC; border: 1px #EFEFCC solid; } table.tableinfo tr:hover td.warning { background-color: #EAEACC; border: 1px #EAEACC solid; } -table.tableinfo tr td.information { background-color: #CCE2CC; border: 1px #CCE2CC solid; } -table.tableinfo tr:hover td.information { background-color: #C7DDCC; border: 1px #C7DDCC solid; } +table.tableinfo tr td.information_empty { border: 1px #BBE2BB solid; } +table.tableinfo tr:hover td.information_empty { border: 1px #B7DDBB solid; } + +table.tableinfo tr td.information { background-color: #BBE2BB; border: 1px #CCE2CC solid; } +table.tableinfo tr:hover td.information { background-color: #B7DDBB; border: 1px #C7DDCC solid; } + +table.tableinfo tr td.unknown_trigger_empty { border: 1px #ACACAC solid; } +table.tableinfo tr:hover td.unknown_trigger_empty { border: 1px #ACA7AC solid; } table.tableinfo tr td.unknown_trigger { background-color: #BCBCBC; border: 1px #BCBCBC solid; } table.tableinfo tr:hover td.unknown_trigger { background-color: #BCB7BC; border: 1px #BCB7BC solid; } -table.tableinfo tr td.normal { background-color: #AADDAA; border: 1px #AADDAA solid; } -table.tableinfo tr:hover td.normal { background-color: #AAD9AA; border: 1px #AAD9AA solid; } +table.tableinfo tr td.normal { background-color: #AAFFAA; border: 1px #AAFFAA solid; } +table.tableinfo tr:hover td.normal { background-color: #AAF9AA; border: 1px #AAF9AA solid; } table.tableinfo tr td.active { background-color: #AADDAA; border: 1px #AADDAA solid; } table.tableinfo tr:hover td.active { background-color: #AAD9AA; border: 1px #AAD9AA solid; } diff --git a/frontends/php/tr_status.php b/frontends/php/tr_status.php index f5b29c8f..aec17e14 100644 --- a/frontends/php/tr_status.php +++ b/frontends/php/tr_status.php @@ -382,6 +382,7 @@ include_once "include/page_header.php"; ' AND h.hostid in ('.$available_hosts.') '. ' AND h.status='.HOST_STATUS_MONITORED.' '.$cond. order_by('h.host,h.hostid,t.description,t.priority,t.lastchange'); + $result = DBselect($sql); while($row=DBfetch($result)){ diff --git a/frontends/php/users.php b/frontends/php/users.php index db4712f1..2c00544e 100644 --- a/frontends/php/users.php +++ b/frontends/php/users.php @@ -481,12 +481,14 @@ include_once "include/page_header.php"; order_by('u.alias,u.name,u.surname,u.type','u.userid')); while($db_user=DBfetch($db_users)) { +//Log Out 10min ot Autologout time + $online_time = (($db_user['autologout'] == 0) || (ZBX_USER_ONLINE_TIME<$db_user['autologout']))?ZBX_USER_ONLINE_TIME:$db_user['autologout']; $db_sessions = DBselect('SELECT count(*) as count, max(s.lastaccess) as lastaccess'. ' FROM sessions s, users u'. ' WHERE s.userid='.$db_user['userid']. ' AND s.userid=u.userid '. - ' AND ((s.lastaccess+u.autologout)>='.time().' OR u.autologout=0)'); -//Log Out 10min + ' AND (s.lastaccess+'.$online_time.')>='.time()); + $db_ses_cnt=DBfetch($db_sessions); if($db_ses_cnt["count"]>0) |