Welcome to php club

PHP FAQ from PHPclub.ru: Tree/DemoPrintDynamic ...

Начало | Каталог | Изменения | НовыеКомментарии | Вам запрещён доступПользователи | Вам запрещён доступРегистрация | Вход:  Пароль:  

Деревья в базах данных => Примеры скриптов => Вывод деревьев => С дозагрузкой

Генерация динамического дерева


popoff


tree_print_dynamic.html

<?php

// tree_print_dynamic - скрипт вывода дерева с динамической дозагрузкой
// (c) 2005 Yuri Popoff, http://popoff.donetsk.ua/
// Специально для PHP Club Cookbook & FAQ
//
// Динамическая загрузка данных реализована с помощью
// Subsys_JsHttpRequest: JavaScript DHTML loader.
// (C) 2005 Dmitry Koterov, http://forum.dklab.ru/users/DmitryKoterov/

if(!empty($_GET['is-inline']))
{
  include(
'JsHttpRequest.php');

  
$JsHttpRequest =&new Subsys_JsHttpRequest_Php("windows-1251");
}

/////////////////////////////////////
/// Подготовка данных
/// Целиком и полностью зависит от того, каким способом хранения деревьев
/// Вы пользуетесь.
/// Здесь привиден лишь пример, в которм дерево задается прямо в скрипте
/// !!!!!!!!
/// Для работы основной части скрипта - вывода дерева не имеет никакого значения,
/// каким именно способом Вы подготовили данные. Для подготовки данных обычно
/// не требуется загружать все дерево, а нужно загрузить только некоторую
//  его часть - ту, которая, собственно, будет показываться.
/// !!!!!!!!
/////////////////////////////////////

// Пример дерева.
//1  root
//2  1
//3  1.1
//4  1.1.1
//5  1.1.2
//6  1.1.3
//7  1.1.3.1
//8  1.2
//9  1.3
//10 1.3.1
//11 1.3.2
//12 1.4
//13 1.4.1
//14 2
//15 3
//16 3.1

$a_tree=array(
  array(
'k_item' =>1,'s_name' =>'root','a_tree' => array(
    array(
'k_item' =>2,'s_name' =>'1','a_tree' => array(
      array(
'k_item' =>3,'s_name' =>'1.1','a_tree' => array(
        array(
'k_item' =>4,'s_name' =>'1.1.1','a_tree' => array()),
        array(
'k_item' =>5,'s_name' =>'1.1.2','a_tree' => array()),
        array(
'k_item' =>6,'s_name' =>'1.1.3','a_tree' => array(
          array(
'k_item' =>7,'s_name' =>'1.1.3.1','a_tree' => array())
          )),
        )),
      array(
'k_item' =>8,'s_name' =>'1.2','a_tree' => array()),
      array(
'k_item' =>9,'s_name' =>'1.3','a_tree' => array(
        array(
'k_item' =>10,'s_name' =>'1.3.1','a_tree' => array()),
        array(
'k_item' =>11,'s_name' =>'1.3.2','a_tree' => array())
        )),
      array(
'k_item' =>12,'s_name' =>'1.4','a_tree' => array(
        array(
'k_item' =>13,'s_name' =>'1.4.1','a_tree' => array())
        )),
      )),
    array(
'k_item' =>14,'s_name' =>'2','a_tree' => array()),
    array(
'k_item' =>15,'s_name' =>'3','a_tree' => array(
      array(
'k_item' =>16,'s_name' =>'3.1','a_tree' => array())
      ))
    ))
  );

// возвращает самый верхний уровень (под)дерева $a_tree,
//  подготавливает этот уровень к отображению
function tree_level(&$a_tree,$is_top)
{
  
$a_level=array();
  for(
$i=0;$i<count($a_tree);$i++)
  {
    if(empty(
$a_tree[$i]['a_tree']))
    {
      
$s_state='leaf';
      
$url_open='';
    }
    else
    {
      
$s_state='close';
      
$url_open='?k_item='.urlencode($a_tree[$i]['k_item']).'&is-inline=1';
    }
    
$a_level[]=array(
      
'a_tree' => array(),
      
'k_item' => $a_tree[$i]['k_item'],
      
's_name' => $a_tree[$i]['s_name'],
      
'state' => $s_state,
      
'url' => '?k_item='.urlencode($a_tree[$i]['k_item']),
      
'url-open' => $url_open,
      
'is-top' => $is_top
      
);
  }
  return
$a_level;
}

//Ищет вершину $k_item и загружает всех ее непосредственных детей в $a_level
// Возвращает истину, если вершина $k_item найдена и ложь, если не найдена
// Если в $want_path передана истина, то $a_level будет содержать в себе не
// только уровень, но и весь путь к этому уровню
function tree_find(&$a_tree,$k_item,$want_path,$is_top=true)
{
  if(empty(
$k_item)||!is_numeric($k_item)) return false;
  
$k=-1;
  for(
$i=0;$i<count($a_tree);$i++)
  {
    if(
$a_tree[$i]['k_item']==$k_item)
    {
      
$a_level=tree_level($a_tree[$i]['a_tree'],false);
      
$k=$i;
      break;
    }
    
$a_level=tree_find($a_tree[$i]['a_tree'],$k_item,$want_path,false);
    if(
$a_level)
    {
      
$k=$i;
      break;
    }
  }
  if(
$k<0) return false;
  if(!
$want_path) return $a_level;
  return array(
    array(
      
'a_tree' => $a_level,
      
'k_item' => $a_tree[$k]['k_item'],
      
's_name' => $a_tree[$k]['s_name'],
      
'state' => 'open',
      
'url' => '?k_item='.urlencode($a_tree[$k]['k_item']),
      
'url-open' => '',
      
'is-top' => $is_top,
      
'is-bold' => $a_tree[$k]['k_item']==$k_item
    
));
}

if(!isset(
$_GET['k_item'])) $_GET['k_item']=$a_tree[0]['k_item'];

$a_level=tree_find($a_tree,$_GET['k_item'],empty($_GET['is-inline']));
if(
$a_level===false)
{
  if(empty(
$_GET['is-inline']))
    
header("Location: ?");
  else
    echo
'Item not found: '.htmlspecialchars($_GET['k_item']);
  exit;
}

/////////////////////////////////////
/// Функция, которая по готовому массиву дерева определяет позицию
/// каждого элемента в дереве (первый, последний, нужна ли линия и т.п.)
/// В исходном массиве должен быть установлен элемент массива "is-top",
///    в случае, если соответсвующий элемент дерева является элементом верхнего
///    уровня
/// В результате устанавливаются следующие элементы массива:
///    position - позиция элемента в дереве:
///      single - этот элемент является одновременно и первым и последним
///      first - это самый первый элемент уровня
///      inside - есть элементы до и после этого элемента
///      last - это самый последний элемент уровня
///    want-line - требуется ли линия слева от этого элемента
///    state - состояние элемента дерева.
///      эта функция не устанавливает состояние для элементов, а только
///      проверяет, что бы состояние было одним из допустимых состояний.
///      если установленное в исходном дереве состояние не является допустимым,
///      то оно меняется на состояние по умолчанию:
///      - leaf - у этого элемента дерева нет детей
///      - open - открытый элемент дерева
///      - close - закрытый элемент дерева
/////////////////////////////////////
function tree_position(&$a_tree)
{
  for(
$i=0;$i<count($a_tree);$i++)
  {
    if(!isset(
$a_tree[$i])) continue;
    if(
$i)
    {
      if(
$i<count($a_tree)-1)
      {
        
$a_tree[$i]['position']='inside';
        
$a_tree[$i]['want-line']=true;
      }
      else
        
$a_tree[$i]['position']='last';
    }
    else
    {
      if(
count($a_tree)==1)
      {
        if(!empty(
$a_tree[$i]['is-top']))
          
$a_tree[$i]['position']='single';
        else
          
$a_tree[$i]['position']='last';
      }
      else
      {
        if(!empty(
$a_tree[$i]['is-top']))
          
$a_tree[$i]['position']='first';
        else
          
$a_tree[$i]['position']='inside';
        
$a_tree[$i]['want-line']=true;
      }
    }
    if(empty(
$a_tree[$i]['state']))
      
$a_tree[$i]['state']='';
    switch(
$a_tree[$i]['state'])
    {
      case
'leaf':
      case
'open':
      case
'close':
        break;
      default:
        
$a_tree[$i]['state']='leaf';
    }
    if(!empty(
$a_tree[$i]['a_tree']))
      
tree_position($a_tree[$i]['a_tree']);
  }
}

tree_position($a_level);

/////////////////////////////////////
/// Другие вспомагательные функции
/////////////////////////////////////

function tree_template_load(&$a_level)
{
  include(
'tree_print_dynamic.php');
}

function
tree_template_load_html(&$a_level)
{
  include(
'tree_print_dynamic_html.php');
}

/////////////////////////////////////
/// Собственно вывод дерева
/////////////////////////////////////

if(!empty($_GET['is-inline']))
{
//Загружается часть дерева
  
tree_template_load($a_level);
}
else
{
//Загружается html-страница
  
tree_template_load_html($a_level);
}

?>


tree_print_dynamic_html.php

<!--
  tree_print_dynamic - скрипт вывода дерева с динамической дозагрузкой
  (c) 2005 Yuri Popoff, http://popoff.donetsk.ua/
  Специально для PHP Club Cookbook & FAQ

  ---------
  В этом файле определяется вид html-страницы, на которой расположено дерево.
-->
<html>
  <head>
    <script language="JavaScript" src="JsHttpRequest.js"></script>
    <script>
      function tree_collapse(id)
      {
        var o_img = document.getElementById(id+'-img');
        var o_tr = document.getElementById(id+'-tr');
        if(!o_img||!o_tr) return;
        o_tr.style.display= 'none';
        o_img.src=o_img.src.replace(/-open-/g, "-close-");
      }

      function tree_expand(id,url)
      {
        var o_img = document.getElementById(id+'-img');
        var o_tr = document.getElementById(id+'-tr');
        var o_td = document.getElementById(id+'-td');
        if(!o_img||!o_tr||!o_td) return;
        if(o_tr.style.display == 'none')
        {
          o_tr.style.display= '';
          o_img.src=o_img.src.replace(/-close-/g, "-open-");
          o_td.innerHTML=
            '<b style="color:#888888;font-size:8pt;">Loading...</b>';

          var req = new Subsys_JsHttpRequest_Js();
          req.onreadystatechange = function() {
            if (req.readyState == 4) {
              o_td.innerHTML=req.responseText;
            }
          };
          req.caching = true;
          req.open('GET', url, true);
          req.send({});
        }
        else
        {
          o_tr.style.display= 'none';
          o_img.src=o_img.src.replace(/-open-/g, "-close-");
        }
      }
    </script>
  </head>
  <body>
    <?php tree_template_load($a_level); ?>
  </body>
</html>


tree_print_dynamic.php

<!--
  tree_print_dynamic - скрипт вывода дерева с динамической дозагрузкой
  (c) 2005 Yuri Popoff, http://popoff.donetsk.ua/
  Специально для PHP Club Cookbook & FAQ

  ---------
  В этом файле определятся вид одного уровня дерева
-->
<?php if(!count($a_level)) { ?>
  No items inside
<?php } else { ?>
  <table cellpadding="0" cellspacing="0" width="100%" border="0">
    <?php for($i=0;$i<count($a_level);$i++) { ?>
      <tr>
        <?php if(!empty($a_level[$i]['url-open'])) { ?>
          <td
            width="16"
            valign="top"
            onclick="tree_expand('tree-<?= $a_level[$i]['k_item'] ?>',
                                 '<?= $a_level[$i]['url-open'] ?>');"
            style="cursor:hand;"><a href="<?= $a_level[$i]['url'] ?>"
            onClick="return false;"
            ><img
              id="tree-<?= $a_level[$i]['k_item'] ?>-img"
              src="tree-close-<?= $a_level[$i]['position'] ?>.gif"
              border="0"
            /></a></td
          >
        <?php } else { ?>
          <td width="16" valign="top"><img
            id="tree-<?= $a_level[$i]['k_item'] ?>-img"
            src="tree-leaf-<?= $a_level[$i]['position'] ?>.gif"
            border="0" /></td>
        <?php } ?>
        <td style="font-size:8pt;">
          <?php if(!empty($a_level[$i]['is-bold'])) { ?>
            <b style="font-size:8pt;">
              <?= $a_level[$i]['s_name'] ?>
            </b>
          <?php } else { ?>
            <a href="<?= $a_level[$i]['url'] ?>" style="font-size:8pt;"><?= $a_level[$i]['s_name'] ?></a>
          <?php } ?>
        </td>
      </tr>
      <?php if(!empty($a_level[$i]['want-line'])) { ?>
        <tr id="tree-<?= $a_level[$i]['k_item'] ?>-tr" <?php if(empty($a_level[$i]['a_tree'])) { ?>style="display:none;"<?php } ?>>
          <td background="tree-line.gif">&nbsp;</td>
          <td id="tree-<?= $a_level[$i]['k_item'] ?>-td">
            <?php if(!empty($a_level[$i]['a_tree'])) { ?>
              <?php tree_template_load($a_level[$i]['a_tree']); ?>
            <?php } else { ?>
              &nbsp;
            <?php } ?>
          </td>
        </tr>
      <?php } else { ?>
        <tr id="tree-<?= $a_level[$i]['k_item'] ?>-tr" <?php if(empty($a_level[$i]['a_tree'])) { ?>style="display:none;"<?php } ?>>
          <td>&nbsp;</td>
          <td id="tree-<?= $a_level[$i]['k_item'] ?>-td">
            <?php if(!empty($a_level[$i]['a_tree'])) { ?>
              <?php tree_template_load($a_level[$i]['a_tree']); ?>
            <?php } else { ?>
              &nbsp;
            <?php } ?>
          </td>
        </tr>
      <?php } ?>
    <?php } ?>
  </table>
<?php } ?>


Попробовать этот пример:
http://popoff.donetsk.ua/try/tree_dynamic/tree_print_dynamic.html


Закачать все файлы примера в zip-архиве (14 340 байт):
http://download.popoff.donetsk.ua/tree_print_dynamic.zip


 
Много комментариев (8). [Показать комментарии/форму]