Page 1 of 1

Tree view overflows in IE7 and 8

Posted: Fri Sep 04, 2009 2:09 am
by TomAndresen
I've "inherited" a PHP solution, based on ProjectPier, developed by freelance developer with whom we have lost contact. I'm now taking over maintenance and support on the solution, and, still being somewhat green when it comes to PHP, have run into a snag.

The solution includes a file tree view, implemented using what appears to be an older version of Open Cube menu / Infinite Menu. The problem is that the menu overflows past the bounds of it's container:
Image

This occurs in IE7 and 8, but not in IE6 and Firefox.

The script itself is pretty obfuscated, and I am not sure if the problem is with the script or the PHP that uses it:

This is the overall code for the sidebar:

Code: Select all

<?php if (isset($folders) && is_array($folders) && count($folders)) { ?>
<div class="sidebarBlock">
  <h2><?php echo lang('folders') ?></h2>
  <div class="blockContent" id="sidebarFolderList">
    <div style="float:none; margin-bottom:10px;"><a href="<?php echo ProjectFiles::getIndexUrl($order, $page) ?>"><?php echo lang('show all files') ?></a></div>
    <div style="float:none; margin-bottom:10px;"><a href="<?php echo get_url('files', 'add_folder') ?>" id="sidebar_add_folder"><?php echo lang('add folder') ?></a></div>
    <div id="sidebarFolderTree">
      <?php $tree_html->PrintTree();?>
      <script language="JavaScript" src="<?php echo ROOT_URL.'/public/assets/javascript/treemenu/tmenu_code.js'; ?>"></script>
    </div>
    <?php if(0){?>
    <ul>
      <?php if ($current_folder instanceof ProjectFolder) { ?>
      <li><a href="<?php echo ProjectFiles::getIndexUrl($order, $page) ?>"><?php echo lang('all files') ?></a></li>
      <?php } else { ?>
      <li><a href="<?php echo ProjectFiles::getIndexUrl($order, $page) ?>" class="selected"><?php echo lang('all files') ?></a></li>
      <?php } // if ?>
      <?php foreach ($folders as $folder) { ?>
      <?php if (($current_folder instanceof ProjectFolder) && ($current_folder->getId() == $folder->getId())) { ?>
      <li><a href="<?php echo $folder->getBrowseUrl($order) ?>" class="selected"><?php echo clean($folder->getName()) ?></a>
        <?php if ($folder->canEdit(logged_user())) { ?>
        <a href="<?php echo $folder->getEditUrl() ?>" class="blank" title="<?php echo lang('edit folder') ?>"><img src="<?php echo icon_url('edit.gif') ?>" alt="" /></a>
        <?php } // if ?>
        <?php if ($folder->canDelete(logged_user())) { ?>
        <a href="<?php echo $folder->getDeleteUrl() ?>" class="blank" title="<?php echo lang('delete folder') ?>"><img src="<?php echo icon_url('cancel_gray.gif') ?>" alt="" /></a>
        <?php } // if ?>
      </li>
      <?php } else { ?>
      <li><a href="<?php echo $folder->getBrowseUrl($order) ?>"><?php echo clean($folder->getName()) ?></a>
        <?php if ($folder->canEdit(logged_user())) { ?>
        <a href="<?php echo $folder->getEditUrl() ?>" class="blank" title="<?php echo lang('edit folder') ?>"><img src="<?php echo icon_url('edit.gif') ?>" alt="" /></a>
        <?php } // if ?>
        <?php if ($folder->canDelete(logged_user())) { ?>
        <a href="<?php echo $folder->getDeleteUrl() ?>" class="blank" title="<?php echo lang('delete folder') ?>"><img src="<?php echo icon_url('cancel_gray.gif') ?>" alt="" /></a>
        <?php } // if ?>
      </li>
      <?php } // if ?>
      <?php } // foreach ?>
    </ul>
    <?php }?>
  </div>
</div>
<?php } // if ?>
<?php if (isset($important_files) && is_array($important_files) && count($important_files)) { ?>
<div class="sidebarBlock">
  <h2><?php echo lang('important files') ?></h2>
  <div class="blockContent">
    <ul>
      <?php foreach ($important_files as $important_file) { ?>
      <li> <a href="<?php echo $important_file->getDetailsUrl() ?>"><?php echo clean($important_file->getFilename()) ?></a><br />
        <span class="desc"><?php echo lang('revisions on file', $important_file->countRevisions()) ?></span> </li>
      <?php } // foreach ?>
    </ul>
  </div>
</div>
<?php } // if ?>
 
And this is the treeview class it uses:

Code: Select all

 
<?php
/**
 * XHTML Tree view builder
 * @version 1.0.0.0
 * @author removed
 */
class HtmlTree {
    
    /**
     * Tree
     * @var array
     */
    private $dir;
    /**
     * XHTML code
     * @var string
     */
    private $html;
    /**
     * HREF Target
     * @var string
     */
    private $target;
    /**
     * Element ID
     * @var string
     */
    private $id;
    /**
     * Id of selector field.
     * @var string
     */
    private $field_name;
    /**
     * Maximum allowed depth for subfolders selector
     * @var mixed
     */
    private $max_depth;
    /**
     * Disables/enables root level files
     * @var boolean
     */
    private $no_root_files;
    
    /**
     * Class constructor
     *
     * @param array $tree_array Array of tree elements
     * @param string $target HREF Target
     */
    function __construct($tree_array, $target = '_self', $id = 'tmenu0', $field_name = null) {
        $this->dir = $tree_array;
        $this->target = $target;
        $this->id = $id;
        $this->field_name = $field_name;
        $this->max_depth = FALSE;
    } /* end function */
    
    private function buildHtmlTree() {
        if ($this->dir) {
            $this->html = $this->html . '<!-- Begin Directory Tree ' . $this->id . ' -->' . "\n";
            $this->html = $this->html . '<ul id="' . $this->id . '" style="display:none;">' . "\n";
            $this->CookTreeDir ( $this->dir );
            $this->html = $this->html . '</ul>' . "\n";
            $this->html = $this->html . '<!-- Close Directory Tree ' . $this->id . ' -->' . "\n";
        }
    }
    
    private function buildHtmlSelectList($select = null) {
        $this->cur_depth = 0;
        if ($this->dir) {
            $this->html = $this->html . '<!-- Begin Folders selection ' . $this->id . ' -->' . "\n";
            $this->html = $this->html . '<select name="' . $this->field_name . '" id="' . $this->id . '">' . "\n";
            if (! $this->no_root_files) {
                $this->html = $this->html . "<option value=\"NULL\">" . lang ( 'none' ) . "</option>\n";
            }
            $this->CookSelectDir ( $this->dir, $select );
            $this->html = $this->html . '</select>' . "\n";
            $this->html = $this->html . '<!-- Close Folders selection ' . $this->id . ' -->' . "\n";
        }
    }
    
    /**
     * Returns generated XHTML for given tree
     * @param array $dir
     * @param string $tab
     */
    private function CookSelectDir($dir, $select = null, $spacer = null) {
        $spacer = (is_null ( $spacer )) ? "&nbsp;" : "&nbsp;&nbsp;&nbsp;" . $spacer;
        if ($dir) {
            foreach ( $dir as $value ) {
                $selected = '';
                if (! is_null ( $select )) {
                    $selected = ($select == $value [1]) ? 'selected="selected"' : '';
                }
                $count_level = substr_count ( $spacer, "&nbsp;" );
                $count_level = ($count_level == 1) ? 0 : ($count_level - 1) / 3;
                if ($count_level <= $this->max_depth) {
                    $this->html = $this->html . '<option ' . $selected . ' value="' . $value [1] . '" depth="' . $count_level . '">' . $spacer . $value [0] . "</option>\n";
                    if ($value [2]) {
                        $this->CookSelectDir ( $value [2], $select, $spacer );
                    }
                }
            }
        }
    } /* end function */
    
    /**
     * Returns generated XHTML for given tree
     * @param array $dir
     * @param string $tab
     */
    private function CookTreeDir($dir, $tab = null) {
        $tab = (is_null ( $tab )) ? "\t" : "\t" . $tab;
        if ($dir) {
            foreach ( $dir as $value ) {
                if ($value [2]) {
                    $this->html = $this->html . $tab . '<li expanded="1"><a href="' . $value [3] . '" target="' . $this->target . '">' . $value [0] . '</a>' . "\n";
                    $this->html = $this->html . $tab . "<ul>\n";
                    $this->CookTreeDir ( $value [2], $tab );
                    $this->html = $this->html . $tab . "</ul></li>\n";
                } else {
                    $this->html = $this->html . $tab . '<li><a href="' . $value [3] . '" target="' . $this->target . '">' . $value [0] . '</a></li>' . "\n";
                }
            }
        }
    } /* end function */
    
 
    /**
     * Outputs HTML select element with current folders tree
     *
     * @param string $id
     * @param string $field_name
     * @param integer $select
     * @param integer $max_depth
     * @param boolean $disable_root_files
     */
    public function PrintSelector($id = null, $field_name = null, $select = null, $max_depth = 99, $disable_root_files = false) {
        $this->max_depth = $max_depth;
        $this->no_root_files = $disable_root_files;
        if (is_string ( $id )) {
            $this->id = $id;
        }
        if (is_string ( $field_name )) {
            $this->field_name = $field_name;
        }
        $this->buildHtmlSelectList ( $select );
        echo $this->html;
    } /* end function */
    
    /**
     * Outputs  tree
     */
    public function PrintTree() {
        $this->buildHtmlTree ();
        echo $this->html;
    }
 
}
 
?>
 
Any ideas and insights on how to fix the problem would be much appreciated.

Re: Tree view overflows in IE7 and 8

Posted: Fri Sep 04, 2009 12:04 pm
by kaszu
That's a CSS issue, not PHP.
I assume this menu is from time when there were no IE7 and IE8. Problem could be that IE6 doesn't support 'min-height' property (which is most likely used in that menu for standard compliant browsers), but instead 'height' is used to simulate it. This is fixed (now min-height is supported and height works as expected) in IE7 and IE8, which could be causing menu to break.
Look at the source if there are conditional comments for IE, something like following

Code: Select all

<!--[if IE]>
<link rel="stylesheet" type="text/css" href="PATH_TO_CSS_FILE" /><![endif]-->
open that css and search for rule, which is for menu. Replace 'height' with 'min-height' and use separate selector to target IE6

Code: Select all

* html MY_SELECTOR { height: ...; }
This is just a guess, since I haven't seen you CSS/HTML. Please post your css & html, then we will be able to help more.