5 * Copyright 1999-2001 (c) VA Linux Systems
6 * http://fusionforge.org
8 * This file is part of FusionForge.
10 * FusionForge is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
15 * FusionForge is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with FusionForge; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
27 * Extends the basic Error class to add HTML functions
28 * for displaying all site dependent HTML, while allowing
29 * extendibility/overriding by themes via the Theme class.
31 * Make sure browser.php is included _before_ you create an instance
36 require_once $gfcommon.'include/constants.php';
37 require_once $gfcommon.'include/Navigation.class.php';
39 class Layout extends Error {
42 * Which doctype to use. Can be configured in the
43 * constructor. If set to 'strict', headerHTMLDeclaration will
44 * create a doctype definition that uses the strict doctype,
45 * otherwise it will use the transitional doctype.
46 * @var string $doctype
48 var $doctype = 'transitional';
51 * Which cssfiles to use. Can be configured in the
54 * @var array $cssurls is a list of urls that should point to
55 * the used stylesheets.
60 * The default main page content
61 * @var string $rootindex
63 var $rootindex = 'index_std.php';
66 * The base directory of the theme in the servers file system
67 * @var string $themedir
72 * The base url of the theme
73 * @var string $themeurl
78 * The base directory of the css files in the servers file system
84 * The base url of the css files
85 * @var string $cssbaseurl
90 * The base directory of the image files in the servers file system
96 * The base url of the image files
97 * @var string $imgbaseurl
102 * The base directory of the js files in the servers file system
108 * The base url of the js files
109 * @var string $jsbaseurl
114 * kept for backwards compatibility
117 * The base directory of the theme
118 * @var string $themeroot
119 * @todo: remove in 5.0
120 * @deprecated deprecated since 4.9
125 * The base directory of the theme
126 * @var string $themeroot
127 * @todo: remove in 5.0
128 * @deprecated deprecated since 4.9
133 * The navigation object that provides the basic links. Should
140 * The color bars in pm reporting
142 var $COLOR_LTBACK1 = '#C0C0C0';
146 * Layout() - Constructor
149 // parent constructor
152 $this->navigation = new Navigation();
154 // determine rootindex
155 if ( file_exists(forge_get_config('custom_path') . '/index_std.php') ) {
156 $this->rootindex = forge_get_config('custom_path') . '/index_std.php';
158 $this->rootindex = $GLOBALS['gfwww'].'index_std.php';
161 // determine theme{dir,url}
162 $this->themedir = forge_get_config('themes_root') . '/' . forge_get_config('default_theme') . '/';
163 if (!file_exists ($this->themedir)) {
164 html_error_top(_("Can't find theme directory!"));
167 $this->themeurl = util_make_url('themes/' . forge_get_config('default_theme') . '/');
169 // determine {css,img,js}{url,dir}
170 if (file_exists ($this->themedir . 'css/')) {
171 $this->cssdir = $this->themedir . 'css/';
172 $this->cssbaseurl = $this->themeurl . 'css/';
174 $this->cssdir = $this->themedir;
175 $this->cssbaseurl = $this->themeurl;
178 if (file_exists ($this->themedir . 'images/')) {
179 $this->imgdir = $this->themedir . 'images/';
180 $this->imgbaseurl = $this->themeurl . 'images/';
182 $this->imgdir = $this->themedir;
183 $this->imgbaseurl = $this->themeurl;
186 if (file_exists ($this->themedir . 'js/')) {
187 $this->jsdir = $this->themedir . 'js/';
188 $this->jsbaseurl = $this->themeurl . 'js/';
190 $this->jsdir = $this->themedir;
191 $this->jsbaseurl = $this->themeurl;
194 // determine CSS stylesheets
195 $this->cssurls[] = util_make_url ('/themes/css/fusionforge.css');
197 /* check if a personalized css stylesheet exist, if yes include only
198 this stylesheet. New stylesheets should use the <themename>.css file.
200 $theme_cssfile = forge_get_config('default_theme') . '.css';
201 if (file_exists($this->cssdir . $theme_cssfile)) {
202 $this->cssurls[] = $this->cssbaseurl . $theme_cssfile;
204 /* if this is not the case, then include the compatibility stylesheet
205 that contains all removed styles from the code and check if a
206 custom stylesheet exists.
207 Used for compatibility with existing stylesheets
209 $this->cssurls[] = util_make_url('/themes/css/gforge-compat.css');
210 if (file_exists($this->cssdir . 'theme.css')) {
211 $this->cssurls[] = $this->cssbaseurl . 'theme.css';
215 // for backward compatibility
216 $this->themeroot = $this->themedir;
217 $this->imgroot = $this->imgbaseurl;
220 function addJavascript($js) {
221 if (isset($this->js_min[$js])) {
222 $js = $this->js_min[$js];
224 if (!isset($this->js[$js])) {
225 $this->js[$js] = true;
226 $filename = $GLOBALS['fusionforge_basedir'].'/www'.$js;
227 if (file_exists($filename)) {
228 $js .= '?'.date ("U", filemtime($filename));
230 echo '<script type="text/javascript" src="'.$js.'"></script>'."\n";
234 function addStylesheet($css, $media) {
235 if (isset($this->css_min[$css])) {
236 $css = $this->css_min[$css];
238 if (!isset($this->css[$css])) {
239 $this->css[$css] = true;
240 $filename = $GLOBALS['fusionforge_basedir'].'/www'.$css;
241 if (file_exists($filename)) {
242 $css .= '?'.date ("U", filemtime($filename));
245 $media = ' media="'.$media.'"';
247 echo ' <link rel="stylesheet" type="text/css" href="'.$css.'"'.$media.' />'."\n";
252 * header() - generates the complete header of page by calling
253 * headerStart() and bodyHeader().
255 function header($params) {
256 $this->headerStart($params); ?>
259 $this->bodyHeader($params);
264 * headerStart() - generates the header code for all themes up to the
266 * Override any of the methods headerHTMLDeclaration(), headerTitle(),
267 * headerFavIcon(), headerRSS(), headerSearch(), headerCSS(), or
268 * headerJS() to adapt your theme.
270 * @param array Header parameters array
272 function headerStart($params) {
273 $this->headerHTMLDeclaration();
276 <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
278 $this->headerTitle($params);
279 $this->headerFavIcon();
281 $this->headerSearch();
290 * headerLink() - creates the link headers of the page (FavIcon, RSS and Search)
291 * @deprecated deprecated since 4.9, use the individual header-functions
292 * @todo remove in 5.0
294 function headerLink() {
295 $this->headerFavIcon();
297 $this->headerSearch();
301 * headerHTMLDeclaration() - generates the HTML declaration, i.e. the
302 * XML declaration, the doctype definition, and the opening <html>.
305 function headerHTMLDeclaration() {
306 print '<?xml version="1.0" encoding="utf-8"?>';
307 if ($this->doctype=='strict') {
308 echo '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">';
310 echo '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">';
312 echo '<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="'
313 . _('en') . '" lang="' . _('en') . '">';
317 * headerTitle() - creates the <title> header
319 * @param array Header parameters array
321 function headerTitle($params) {
322 echo $this->navigation->getTitle($params);
327 * headerFavIcon() - creates the favicon <link> headers
330 function headerFavIcon() {
331 echo $this->navigation->getFavIcon();
335 * headerRSS() - creates the RSS <link> headers
338 function headerRSS() {
339 echo $this->navigation->getRSS();
343 * headerSearch() - creates the search <link> header
346 function headerSearch() {
347 echo '<link rel="search" title="'
348 . forge_get_config ('forge_name').'" href="'
349 . util_make_url ('/export/search_plugin.php')
350 . '" type="application/opensearchdescription+xml"/>';
354 * Create the CSS headers for all cssfiles in $cssfiles and
355 * calls the plugin cssfile hook.
357 function headerCSS() {
358 // include the common css
359 foreach ($this->cssurls as $cssurl) {
360 echo '<link rel="stylesheet" type="text/css" href="' . $cssurl . '" />';
363 plugin_hook ('cssfile',$this);
367 * headerJS() - creates the JS headers and calls the plugin javascript hook
368 * @todo generalize this
370 function headerJS() {
372 <script type="text/javascript" src="/scripts/prototype/prototype.js"></script>
373 <script type="text/javascript" src="/scripts/scriptaculous/scriptaculous.js"></script>
374 <script type="text/javascript" src="/scripts/codendi/Tooltip.js"></script>
375 <script type="text/javascript" src="/scripts/codendi/LayoutManager.js"></script>
376 <script type="text/javascript" src="/scripts/codendi/ReorderColumns.js"></script>
377 <script type="text/javascript" src="/scripts/codendi/codendi-1236793993.js"></script>
378 <script type="text/javascript" src="/scripts/codendi/validate.js"></script>
379 <script type="text/javascript" src="'. util_make_uri('/js/common.js') .'"></script>
380 <script type="text/javascript">';
381 plugin_hook ("javascript",false);
384 plugin_hook ("javascript_file",false);
387 function bodyHeader($params){
390 <table border="0" width="100%" cellspacing="0" cellpadding="0" id="headertable">
392 <td><a href="<?php echo util_make_url ('/'); ?>"><?php echo html_image('logo.png',198,52,array('border'=>'0')); ?></a></td>
393 <td><?php $this->searchBox(); ?></td>
394 <td align="right"><?php
395 $items = $this->navigation->getUserLinks();
396 for ($j = 0; $j < count($items['titles']); $j++) {
397 echo util_make_link($items['urls'][$j], $items['titles'][$j], array('class'=>'lnkutility'), true);
400 $params['template'] = ' {menu}';
401 plugin_hook ('headermenu', $params);
406 <td> </td>
411 <table border="0" width="100%" cellspacing="0" cellpadding="0">
417 <?php echo $this->outerTabs($params); ?>
424 <td align="left" class="toptab" width="9"><img src="<?php echo $this->imgbaseurl; ?>tabs/topleft.png" height="9" width="9" alt="" /></td>
425 <td class="toptab" width="30"><img src="<?php echo $this->imgbaseurl; ?>clear.png" width="30" height="1" alt="" /></td>
426 <td class="toptab"><img src="<?php echo $this->imgbaseurl; ?>clear.png" width="1" height="1" alt="" /></td>
427 <td class="toptab" width="30"><img src="<?php echo $this->imgbaseurl; ?>clear.png" width="30" height="1" alt="" /></td>
428 <td align="right" class="toptab" width="9"><img src="<?php echo $this->imgbaseurl; ?>tabs/topright.png" height="9" width="9" alt="" /></td>
433 <!-- Outer body row -->
435 <td class="toptab"><img src="<?php echo $this->imgbaseurl; ?>clear.png" width="10" height="1" alt="" /></td>
436 <td valign="top" width="99%" class="toptab" colspan="3">
438 <!-- Inner Tabs / Shell -->
440 <table border="0" width="100%" cellspacing="0" cellpadding="0">
444 if (isset($params['group']) && $params['group']) {
452 echo $this->projectTabs($params['toptab'],$params['group']);
462 <td align="left" class="projecttab" width="9"><img src="<?php echo $this->imgbaseurl; ?>tabs/topleft-inner.png" height="9" width="9" alt="" /></td>
463 <td class="projecttab" ><img src="<?php echo $this->imgbaseurl; ?>clear.png" width="1" height="1" alt="" /></td>
464 <td align="right" class="projecttab" width="9"><img src="<?php echo $this->imgbaseurl; ?>tabs/topright-inner.png" height="9" width="9" alt="" /></td>
468 <td class="projecttab" ><img src="<?php echo $this->imgbaseurl; ?>clear.png" width="10" height="1" alt="" /></td>
469 <td valign="top" width="99%" class="projecttab">
475 function footer($params) {
479 <!-- end main body row -->
483 <td width="10" class="footer3" ><img src="<?php echo $this->imgbaseurl; ?>clear.png" width="2" height="1" alt="" /></td>
486 <td align="left" class="footer1" width="9"><img src="<?php echo $this->imgbaseurl; ?>tabs/bottomleft-inner.png" height="11" width="11" alt="" /></td>
487 <td class="footer3"><img src="<?php echo $this->imgbaseurl; ?>clear.png" width="1" height="1" alt="" /></td>
488 <td align="right" class="footer1" width="9"><img src="<?php echo $this->imgbaseurl; ?>tabs/bottomright-inner.png" height="11" width="11" alt="" /></td>
492 <!-- end inner body row -->
495 <td width="10" class="footer2"><img src="<?php echo $this->imgbaseurl; ?>clear.png" width="2" height="1" alt="" /></td>
498 <td align="left" class="footer2" width="9"><img src="<?php echo $this->imgbaseurl; ?>tabs/bottomleft.png" height="9" width="9" alt="" /></td>
499 <td class="footer2" colspan="3"><img src="<?php echo $this->imgbaseurl; ?>clear.png" width="1" height="1" alt="" /></td>
500 <td align="right" class="footer2" width="9"><img src="<?php echo $this->imgbaseurl; ?>tabs/bottomright.png" height="9" width="9" alt="" /></td>
504 $this->footerEnd($params);
507 function footerEnd($params) { ?>
509 <!-- PLEASE LEAVE "Powered By FusionForge" on your site -->
511 <?php echo $this->navigation->getPoweredBy(); ?>
514 <?php echo $this->navigation->getShowSource(); ?>
523 function getRootIndex() {
524 return $this->rootindex;
528 * boxTop() - Top HTML box
530 * @param string Box title
531 * @param bool Whether to echo or return the results
532 * @param string The box background color
534 function boxTop($title) {
536 <!-- Box Top Start -->
538 <table cellspacing="0" cellpadding="0" width="100%" border="0" style="background:url('.$this->imgbaseurl.'vert-grad.png)">
539 <tr class="align-center">
540 <td valign="top" align="right" width="10" style="background:url('.$this->imgbaseurl.'box-topleft.png)"><img src="'.$this->imgbaseurl.'clear.png" width="10" height="20" alt="" /></td>
541 <td width="100%" style="background:url('.$this->imgbaseurl.'box-grad.png)"><span class="titlebar">'.$title.'</span></td>
542 <td valign="top" width="10" style="background:url('.$this->imgbaseurl.'box-topright.png)"><img src="'.$this->imgbaseurl.'clear.png" width="10" height="20" alt="" /></td>
546 <table cellspacing="2" cellpadding="2" width="100%" border="0">
550 <!-- Box Top End -->';
554 * boxMiddle() - Middle HTML box
556 * @param string Box title
557 * @param string The box background color
559 function boxMiddle($title) {
561 <!-- Box Middle Start -->
564 <tr class="align-center">
565 <td colspan="2" style="background:url('.$this->imgbaseurl.'box-grad.png)"><span class="titlebar">'.$title.'</span></td>
569 <!-- Box Middle End -->';
573 * boxBottom() - Bottom HTML box
575 * @param bool Whether to echo or return the results
577 function boxBottom() {
579 <!-- Box Bottom Start -->
586 <!-- Box Bottom End -->';
590 * boxGetAltRowStyle() - Get an alternating row style for tables
592 * @param int Row number
594 function boxGetAltRowStyle($i) {
596 return ' class="altRowStyleEven"';
598 return ' class="altRowStyleOdd"';
603 * listTableTop() - Takes an array of titles and builds the first row of a new table.
605 * @param array The array of titles
606 * @param array The array of title links
608 function listTableTop ($title_arr,$links_arr=false,$selected=false) {
610 <table cellspacing="0" cellpadding="0" width="100%" border="0">
611 <tr class="align-center">
612 <!-- <td valign="top" align="right" width="10" style="background:url('.$this->imgbaseurl.'box-grad.png)"><img src="'.$this->imgbaseurl.'box-topleft.png" width="10" height="75" alt="" /></td> -->
613 <td style="background:url('.$this->imgbaseurl.'box-grad.png)">
614 <table width="100%" border="0" cellspacing="1" cellpadding="2" >
615 <tr class="tableheading">';
616 $count=count($title_arr);
618 for ($i=0; $i<$count; $i++) {
619 $return .= '<td>'.util_make_link ($links_arr[$i],$title_arr[$i],array('class'=>'sortbutton')).'</td>';
622 for ($i=0; $i<$count; $i++) {
624 <td>'.$title_arr[$i].'</td>';
627 return $return.'</tr>';
630 function listTableBottom() {
631 return '</table></td>
632 <!-- <td valign="top" align="right" width="10" style="background:url('.$this->imgbaseurl.'box-grad.png)"><img src="'.$this->imgbaseurl.'box-topright.png" width="10" height="75" alt="" /></td> -->
636 function outerTabs($params) {
637 $menu = $this->navigation->getSiteMenu();
639 echo $this->tabGenerator($menu['urls'], $menu['titles'], false, $menu['selected'], '');
644 * Prints out the quicknav menu, contained here in case we
645 * want to allow it to be overridden.
647 function quickNav() {
648 if (!session_loggedin()) {
651 // get all projects that the user belongs to
652 $groups = session_get_user()->getGroups () ;
654 if (count ($groups) < 1) {
657 sortProjectList ($groups) ;
660 <form id="quicknavform" name="quicknavform" action=""><div>
661 <select name="quicknav" id="quicknav" onChange="location.href=document.quicknavform.quicknav.value">
662 <option value="">'._('Quick Jump To...').'</option>';
664 foreach ($groups as $g) {
665 $group_id = $g->getID() ;
666 $menu =& $this->navigation->getProjectMenu($group_id);
669 <option value="' . $menu['starturl'] . '">'
670 . $menu['name'] .'</option>';
672 for ($j = 0; $j < count($menu['urls']); $j++) {
674 <option value="' . $menu['urls'][$j] .'"> '
675 . $menu['titles'][$j] . '</option>';
676 if (@$menu['adminurls'][$j]) {
678 <option value="' . $menu['adminurls'][$j]
679 . '"> '
680 . _('Admin') . '</option>';
692 * projectTabs() - Prints out the project tabs, contained here in case
693 * we want to allow it to be overriden
695 * @param string Is the tab currently selected
696 * @param string Is the group we should look up get title info
698 function projectTabs($toptab, $group_id) {
699 // get group info using the common result set
700 $menu =& $this->navigation->getProjectMenu($group_id, $toptab);
702 echo $this->tabGenerator($menu['urls'], $menu['titles'], true, $menu['selected'], 'white');
705 function tabGenerator($TABS_DIRS,$TABS_TITLES,$nested=false,$selected=false,$sel_tab_bgcolor='white',$total_width='100%') {
707 $count=count($TABS_DIRS);
708 $width=intval((100/$count));
713 <table class="tabGenerator" ';
715 if ($total_width != '100%') {
716 $return .= 'style="width:' . $total_width . ';"';
726 for ($i=0; $i<$count; $i++) {
729 // this is the first tab, choose an image with end-name
732 $issel=($selected==$i);
733 $bgimg=(($issel)?'theme-'.$inner.'-selected-bg.png':'theme-'.$inner.'-notselected-bg.png');
734 // $rowspan=(($issel)?'rowspan="2" ' : '');
737 <td '.$rowspan.'valign="top" width="10" style="background:url('.$this->imgbaseurl . 'theme-'.$inner.'-end-'.(($issel) ? '' : 'not').'selected.png)">'.
738 '<img src="'.$this->imgbaseurl . 'clear.png" height="25" width="10" alt="" /></td>'.
739 '<td '.$rowspan.'style="background:url('.$this->imgbaseurl . $bgimg.')" width="'.$width.'%" align="center">'.util_make_link ($TABS_DIRS[$i],$TABS_TITLES[$i],array('class'=>(($issel)?'tabsellink':'tablink')),true).'</td>';
740 } elseif ($i==$count-1) {
742 // this is the last tab, choose an image with name-end
744 $wassel=($selected==$i-1);
745 $issel=($selected==$i);
746 $bgimg=(($issel)?'theme-'.$inner.'-selected-bg.png':'theme-'.$inner.'-notselected-bg.png');
747 // $rowspan=(($issel)?'rowspan="2" ' : '');
749 // Build image between current and prior tab
752 <td '.$rowspan.'colspan="2" valign="top" width="20" style="background:url('.$this->imgbaseurl . 'theme-'.$inner.'-'.(($wassel) ? '' : 'not').'selected-'.(($issel) ? '' : 'not').'selected.png)">'.
753 '<img src="'.$this->imgbaseurl . 'clear.png" height="2" width="20" alt="" /></td>'.
754 '<td '.$rowspan.'style="background:url('.$this->imgbaseurl . $bgimg.')" width="'.$width.'%" align="center">'.util_make_link ($TABS_DIRS[$i],$TABS_TITLES[$i],array('class'=>(($issel)?'tabsellink':'tablink')),true).'</td>';
756 // Last graphic on right-side
759 <td '.$rowspan.'valign="top" width="10" style="background:url('.$this->imgbaseurl . 'theme-'.$inner.'-'.(($issel) ? '' : 'not').'selected-end.png)">'.
760 '<img src="'.$this->imgbaseurl . 'clear.png" height="2" width="10" alt="" /></td>';
766 $wassel=($selected==$i-1);
767 $issel=($selected==$i);
768 $bgimg=(($issel)?'theme-'.$inner.'-selected-bg.png':'theme-'.$inner.'-notselected-bg.png');
769 // $rowspan=(($issel)?'rowspan="2" ' : '');
771 // Build image between current and prior tab
774 <td '.$rowspan.'colspan="2" valign="top" width="20" style="background:url('.$this->imgbaseurl . 'theme-'.$inner.'-'.(($wassel) ? '' : 'not').'selected-'.(($issel) ? '' : 'not').'selected.png)">'.
775 '<img src="'.$this->imgbaseurl . 'clear.png" height="2" width="20" alt="" /></td>'.
776 '<td '.$rowspan.'style="background:url('.$this->imgbaseurl . $bgimg.')" width="'.$width.'%" align="center">'.util_make_link ($TABS_DIRS[$i],$TABS_TITLES[$i],array('class'=>(($issel)?'tabsellink':'tablink')),true).'</td>';
783 // Building a bottom row in this table, which will be darker
785 if ($selected == 0) {
787 $end_cols=((count($TABS_DIRS)*3)-3);
788 } elseif ($selected == (count($TABS_DIRS)-1)) {
789 $beg_cols=((count($TABS_DIRS)*3)-3);
792 $beg_cols=($selected*3);
793 $end_cols=(((count($TABS_DIRS)*3)-3)-$beg_cols);
797 $return .= '<td colspan="'.$beg_cols.'" height="1" class="notSelTab"><img src="'.$this->imgbaseurl.'clear.png" height="1" width="10" alt="" /></td>';
799 $return .= '<td colspan="3" height="1" class="selTab"><img src="'.$this->imgbaseurl.'clear.png" height="1" width="10" alt="" /></td>';
801 $return .= '<td colspan="'.$end_cols.'" height="1" class="notSelTab"><img src="'.$this->imgbaseurl.'clear.png" height="1" width="10" alt="" /></td>';
813 function searchBox() {
814 echo $this->navigation->getSearchBox();
818 * beginSubMenu() - Opening a submenu.
820 * @return string Html to start a submenu.
822 function beginSubMenu () {
829 * endSubMenu() - Closing a submenu.
831 * @return string Html to end a submenu.
833 function endSubMenu () {
834 $return = '</strong></p>';
839 * printSubMenu() - Takes two array of titles and links and builds the contents of a menu.
841 * @param array The array of titles.
842 * @param array The array of title links.
843 * @return string Html to build a submenu.
845 function printSubMenu ($title_arr,$links_arr) {
846 $count=count($title_arr);
850 for ($i=0; $i<$count; $i++) {
851 $return .= util_make_link ($links_arr[$i],$title_arr[$i]).' | ';
853 $return .= util_make_link ($links_arr[$i],$title_arr[$i]);
858 * subMenu() - Takes two array of titles and links and build a menu.
860 * @param array The array of titles.
861 * @param array The array of title links.
862 * @return string Html to build a submenu.
864 function subMenu ($title_arr,$links_arr) {
865 $return = $this->beginSubMenu () ;
866 $return .= $this->printSubMenu ($title_arr,$links_arr) ;
867 $return .= $this->endSubMenu () ;
872 * multiTableRow() - create a mutlilevel row in a table
874 * @param string the row attributes
875 * @param array the array of cell data, each element is an array,
876 * the first item being the text,
877 * the subsequent items are attributes (dont include
878 * the bgcolor for the title here, that will be
879 * handled by $istitle
880 * @param boolean is this row part of the title ?
883 function multiTableRow($row_attr, $cell_data, $istitle) {
887 $return .=' class="align-center multiTableRowTitle"';
890 for ( $c = 0; $c < count($cell_data); $c++ ) {
892 for ( $a=1; $a < count($cell_data[$c]); $a++) {
893 $return .= $cell_data[$c][$a].' ';
897 $return .='<span class="multiTableRowTitle">';
899 $return .= $cell_data[$c][0];
913 * feedback() - returns the htmlized feedback string when an action is performed.
915 * @param string feedback string
916 * @return string htmlized feedback
918 function feedback($feedback) {
923 <div class="feedback">'.strip_tags($feedback, '<br>').'</div>';
927 * warning_msg() - returns the htmlized warning string when an action is performed.
929 * @param string msg string
930 * @return string htmlized warning
932 function warning_msg($msg) {
937 <div class="warning_msg">'.strip_tags($msg, '<br>').'</div>';
942 * error_msg() - returns the htmlized error string when an action is performed.
944 * @param string msg string
945 * @return string htmlized error
947 function error_msg($msg) {
952 <div class="error">'.strip_tags($msg, '<br>').'</div>';
958 * getThemeIdFromName()
960 * @param string the dirname of the theme
961 * @return integer the theme id
963 function getThemeIdFromName($dirname) {
964 $res = db_query_params ('SELECT theme_id FROM themes WHERE dirname=$1',
966 return db_result($res,0,'theme_id');
969 function confirmBox($msg, $params, $buttons, $image='*none*') {
970 if ($image == '*none*') {
971 $image = html_image('stop.png','48','48',array());
974 foreach ($params as $b => $v) {
975 $prms[] = '<input type="hidden" name="'.$b.'" value="'.$v.'" />'."\n";
977 $prm = join(' ', $prms);
979 foreach ($buttons as $b => $v) {
980 $btns[] = '<input type="submit" name="'.$b.'" value="'.$v.'" />'."\n";
982 $btn = join(' '."\n ", $btns);
985 <div id="infobox" style="margin-top: 15%; margin-left: 15%; margin-right: 15%; text-align: center;">
986 <table align="center">
989 <td>'.$msg.'<br/></td>
992 <td colspan="2" align="center">
994 <form action="' . getStringFromServer('PHP_SELF') . '" method="get" >
1005 function html_input($name, $id = '', $label = '', $type = 'text', $value = '', $extra_params = '') {
1009 $return = '<div class="field-holder">
1012 $return .= '<label for="' . $id . '">' . $label . '</label>
1015 $return .= '<input id="' . $id . '" type="' . $type . '"';
1016 //if input is a submit then name is not present
1018 $return .= ' name="' . $name . '"';
1021 $return .= ' value="' . $value . '"';
1023 if (is_array($extra_params)) {
1024 foreach ($extra_params as $key => $extra_params_value) {
1025 $return .= $key . '="' . $extra_params_value . '" ';
1033 function html_checkbox($name, $value, $id = '', $label = '', $checked = '', $extra_params = '') {
1037 $return = '<div class="field-holder">
1039 $return .= '<input name="' . $name . '" id="' . $id . '" type="checkbox" value="' . $value . '" ';
1041 $return .= 'checked="checked" ';
1043 if (is_array($extra_params)) {
1044 foreach ($extra_params as $key => $extra_params_value) {
1045 $return .= $key . '="' . $extra_params_value . '" ';
1050 $return .= '<label for="' . $id . '">' . $label . '</label>
1053 $return .= '</div>';
1057 function html_text_input_img_submit($name, $img_src, $id = '', $label = '', $value = '', $img_title = '', $img_alt = '', $extra_params = '', $img_extra_params = '') {
1065 $img_alt = $img_title;
1067 $return = '<div class="field-holder">
1070 $return .= '<label for="' . $id . '">' . $label . '</label>
1073 $return .= '<input id="' . $id . '" type="text" name="' . $name . '"';
1075 $return .= ' value="' . $value . '"';
1077 if (is_array($extra_params)) {
1078 foreach ($extra_params as $key => $extra_params_value) {
1079 $return .= $key . '="' . $extra_params_value . '" ';
1083 <input type="image" id="' . $id . '_submit" src="' . $this->imgbaseurl . $img_src . '" alt="' . $img_alt . '" title="' . $img_title . '"';
1084 if (is_array($img_extra_params)) {
1085 foreach ($img_extra_params as $key => $img_extra_params_value) {
1086 $return .= $key . '="' . $img_extra_params_value . '" ';
1094 function html_select($vals, $name, $label = '', $id = '', $checked_val = '', $text_is_value = false, $extra_params = '') {
1098 $return = '<div class="field-holder">
1101 $return .= '<label for="' . $id . '">' . $label . '</label>
1104 $return .= '<select name="' . $name . '" id="' . $id . '" ';
1105 if (is_array($extra_params)) {
1106 foreach ($extra_params as $key => $extra_params_value) {
1107 $return .= $key . '="' . $extra_params_value . '" ';
1111 $rows = count($vals);
1112 for ($i = 0; $i < $rows; $i++) {
1113 if ( $text_is_value ) {
1115 <option value="' . $vals[$i] . '"';
1116 if ($vals[$i] == $checked_val) {
1117 $return .= ' selected="selected"';
1121 <option value="' . $i . '"';
1122 if ($i == $checked_val) {
1123 $return .= ' selected="selected"';
1126 $return .= '>' . htmlspecialchars($vals[$i]) . '</option>';
1134 function html_textarea($name, $id = '', $label = '', $value = '', $extra_params = '') {
1138 $return = '<div class="field-holder">
1141 $return .= '<label for="' . $id . '">' . $label . '</label>
1144 $return .= '<textarea id="' . $id . '" name="' . $name . '" ';
1145 if (is_array($extra_params)) {
1146 foreach ($extra_params as $key => $extra_params_value) {
1147 $return .= $key . '="' . $extra_params_value . '" ';
1154 $return .= '</textarea>
1159 function html_table_top($cols, $summary = '', $class = '', $extra_params = '') {
1160 $return = '<table summary="' . $summary . '" ';
1162 $return .= 'class="' . $class . '" ';
1164 if (is_array($extra_params)) {
1165 foreach ($extra_params as $key => $extra_params_value) {
1166 $return .= $key . '="' . $extra_params_value . '" ';
1170 $return .= '<thead><tr>';
1171 $nbCols = count($cols);
1172 for ($i = 0; $i < $nbCols; $i++) {
1173 $return .= '<th scope="col">' . $cols[$i] . '</th>';
1175 $return .= '</tr></thead>';
1179 function getMonitorPic($title = '', $alt = '') {
1180 return $this->getPicto('ic/mail16w.png', $title, $alt, '15', '15');
1183 function getReleaseNotesPic($title = '', $alt = '') {
1184 return $this->getPicto('ic/manual16c.png', $title, $alt, '15', '15');
1187 /* no picto for download */
1188 function getDownloadPic($title = '', $alt = '') {
1189 return $this->getPicto('ic/save.png', $title, $alt, '15', '15');
1192 function getHomePic($title = '', $alt = '') {
1193 return $this->getPicto('ic/home16b.png', $title, $alt);
1196 function getFollowPic($title = '', $alt = '') {
1197 return $this->getPicto('ic/tracker20g.png', $title, $alt);
1200 function getForumPic($title = '', $alt = '') {
1201 return $this->getPicto('ic/forum20g.png', $title, $alt);;
1204 function getDocmanPic($title = '', $alt = '') {
1205 return $this->getPicto('ic/docman16b.png', $title, $alt);
1208 function getMailPic($title = '', $alt = '') {
1209 return $this->getPicto('ic/mail16b.png', $title, $alt);
1212 function getPmPic($title = '', $alt = '') {
1213 return $this->getPicto('ic/taskman20g.png', $title, $alt);
1216 function getSurveyPic($title = '', $alt = '') {
1217 return $this->getPicto('ic/survey16b.png', $title, $alt);
1220 function getScmPic($title = '', $alt = '') {
1221 return $this->getPicto('ic/cvs16b.png', $title, $alt);
1224 function getFtpPic($title = '', $alt = '') {
1225 return $this->getPicto('ic/ftp16b.png', $title, $alt);
1228 function getPicto($url, $title, $alt, $width = '20', $height = '20') {
1232 return html_image($url, $width, $height, array('title'=>$title, 'alt'=>$alt));
1236 * toSlug() - protect a string to be used as a link or an anchor
1238 * @param string $string the string used as a link or an anchor
1239 * @param string $space the caracter used as a replacement for a space
1240 * @return a protected string with only alphanumeric caracters
1242 function toSlug($string, $space = "-") {
1243 if (function_exists('iconv')) {
1244 $string = @iconv('UTF-8', 'ASCII//TRANSLIT', $string);
1246 $string = preg_replace("/[^a-zA-Z0-9- ]/", "-", $string);
1247 $string = strtolower($string);
1248 $string = str_replace(" ", $space, $string);
1251 function widget(&$widget, $layout_id, $readonly, $column_id, $is_minimized, $display_preferences, $owner_id, $owner_type) {
1252 $element_id = 'widget_'. $widget->id .'-'. $widget->getInstanceId();
1253 echo '<div class="widget" id="'. $element_id .'">';
1254 echo '<div class="widget_titlebar '. ($readonly?'':'widget_titlebar_handle') .'">';
1255 echo '<div class="widget_titlebar_title">'. $widget->getTitle() .'</div>';
1257 echo '<div class="widget_titlebar_close"><a href="/widgets/updatelayout.php?owner='. $owner_type.$owner_id .'&action=widget&name['. $widget->id .'][remove]='. $widget->getInstanceId() .'&column_id='. $column_id .'&layout_id='. $layout_id .'">'. $this->getPicto('ic/close.png', 'Close','Close') .'</a></div>';
1258 if ($is_minimized) {
1259 echo '<div class="widget_titlebar_maximize"><a href="/widgets/updatelayout.php?owner='. $owner_type.$owner_id .'&action=maximize&name['. $widget->id .']='. $widget->getInstanceId() .'&column_id='. $column_id .'&layout_id='. $layout_id .'">'. $this->getPicto($this->_getTogglePlusForWidgets(), 'Maximize', 'Maximize') .'</a></div>';
1261 echo '<div class="widget_titlebar_minimize"><a href="/widgets/updatelayout.php?owner='. $owner_type.$owner_id .'&action=minimize&name['. $widget->id .']='. $widget->getInstanceId() .'&column_id='. $column_id .'&layout_id='. $layout_id .'">'. $this->getPicto($this->_getToggleMinusForWidgets(), 'Minimize', 'Minimize') .'</a></div>';
1263 if (strlen($widget->hasPreferences())) {
1264 echo '<div class="widget_titlebar_prefs"><a href="/widgets/updatelayout.php?owner='. $owner_type.$owner_id .'&action=preferences&name['. $widget->id .']='. $widget->getInstanceId() .'&layout_id='. $layout_id .'">'. _('Preferences') .'</a></div>';
1267 if ($widget->hasRss()) {
1268 echo '<div class="widget_titlebar_rss"><a href="'.$widget->getRssUrl($owner_id, $owner_type).'">rss</a></div>';
1272 if ($is_minimized) {
1273 $style = 'display:none;';
1275 echo '<div class="widget_content" style="'. $style .'">';
1276 if (!$readonly && $display_preferences) {
1277 echo '<div class="widget_preferences">'. $widget->getPreferencesForm($layout_id, $owner_id, $owner_type) .'</div>';
1279 if ($widget->isAjax()) {
1280 echo '<div id="'. $element_id .'-ajax">';
1281 echo '<noscript><iframe width="99%" frameborder="0" src="'. $widget->getIframeUrl($owner_id, $owner_type) .'"></iframe></noscript>';
1284 echo $widget->getContent();
1287 if ($widget->isAjax()) {
1288 echo '<script type="text/javascript">'."
1289 document.observe('dom:loaded', function () {
1290 $('$element_id-ajax').update('<div style=\"text-align:center\">". $this->getPicto('ic/spinner.gif','spinner','spinner') ."</div>');
1291 new Ajax.Updater('$element_id-ajax',
1292 '". $widget->getAjaxUrl($owner_id, $owner_type) ."'
1299 function _getTogglePlusForWidgets() {
1300 return 'ic/toggle_plus.png';
1302 function _getToggleMinusForWidgets() {
1303 return 'ic/toggle_minus.png';
1310 // c-file-style: "bsd"