Форум: Форум PHPФорум ApacheФорум Регулярные ВыраженияФорум MySQLHTML+CSS+JavaScriptФорум FlashРазное
Новые темы: 0000000
MySQL на примерах. Авторы: Кузнецов М.В., Симдянов И.В. Самоучитель PHP 5 / 6 (3 издание). Авторы: Кузнецов М.В., Симдянов И.В. MySQL 5. В подлиннике. Авторы: Кузнецов М.В., Симдянов И.В. Программирование. Ступени успешной карьеры. Авторы: Кузнецов М.В., Симдянов И.В. Социальная инженерия и социальные хакеры. Авторы: Кузнецов М.В., Симдянов И.В.
ВСЕ НАШИ КНИГИ
Консультационный центр SoftTime

HTML+CSS+JavaScript

Выбрать другой форум

 

Здравствуйте, Посетитель!

вид форума:
Линейный форум Структурный форум

тема: Скрыть / открыть подкатегории
 
 автор: selma   (03.09.2012 в 09:07)   письмо автору
 
 

Доброго времени суток.

Возникла необходимость выводить разделы и подразделы в таком виде:


Раздел1 (+)
Раздел2 (+)
Раздел3 (+)


По нажатию на название раздела 1(2,3...n) , открывается данный раздел и показываются все подразделы этого раздела, а именно:


Раздел1 (-)
--Подраздел 1
--Подраздел 2
--Подраздел 3
Раздел2 (+)
Раздел3 (+)

При нажатии на имя раскрытого раздела, содержимое должно свернуться
Данные о разделах хранятся в MySQL в таком виде


CREATE TABLE IF NOT EXISTS `table` (
  `id` int(9) NOT NULL AUTO_INCREMENT,
  `name` varchar(250) NOT NULL,
  `parent` int(9) NOT NULL,
  PRIMARY KEY (`id`)
)  ;
--
-- Дамп данных таблицы `table`
--
INSERT INTO `table` (`id`, `name`, `parent`) VALUES
(1, 'Раздел1', 0),
(2, 'Раздел2', 0),
(3, 'Раздел3', 0),
(4, 'ПодРаздел1', 1),
(5, 'ПодРаздел2', 1),
(6, 'ПодРаздел3', 1),
(7, 'ПодРаздел1', 2),
(8, 'ПодРаздел2', 2),
(9, 'ПодРаздел1', 3),


Вывод делаю таким образом:


<script language="JavaScript">
function expandit(id)
  {
  obj = document.getElementById(id);
  if (obj.style.display=="none") obj.style.display="";
  else obj.style.display="none";
  }
</script>
<?php
$res 
mysql_query("SELECT t1.name AS level1, t2.name AS level2, t2.parent AS par
                    FROM table t1
                    LEFT JOIN table t2 
                    ON (t1.id = t2.parent)
                    WHERE t1.parent = '0'"
);
$title NULL;
while (
$line mysql_fetch_assoc($res))   
  { 
  if(
$title != $line['level1']) 
    { 
    echo 
"<b style=\"cursor:pointer;\" onClick=\"expandit('ans".$line['par']."')\">".$line['level1']."</b><br/>";  
    
$title $line['level1']; 
    }
  echo 
"<span id = \"ans".$line['par']."\" style=\"display:none\">".$line['level2']."</span><br/>";
  }
?>


Проблема в том, что при развертывании подразделов, показывает лишь первый подраздел, остальные не видны, в чем моя ошибка?

  Ответить  
 
 автор: confirm   (03.09.2012 в 09:53)   письмо автору
 
   для: selma   (03.09.2012 в 09:07)
 

Вы покажите результирующий код вашего меню, а не запрос к MySQL.

  Ответить  
 
 автор: selma   (03.09.2012 в 10:59)   письмо автору
 
   для: confirm   (03.09.2012 в 09:53)
 

Не поняла, какой код? исходный код страницы или что?

Выводит так:


Раздел1
--Подраздел1
Раздел2
Раздел3


по нажатию на любой раздел, выводит только первый подраздел нажатого раздела
а нужно чтобы выводило все подразделы нажатого раздела

исходный код страницы:
<b style="cursor:pointer;" onClick="expandit('ans1')">Раздел1</b><br/>
<span id = "ans1" style="display:none">Подраздел1</span><br/>
<span id = "ans1" style="display:none">Подраздел2</span><br/>
<span id = "ans1" style="display:none">Подраздел3</span><br/>

  Ответить  
 
 автор: confirm   (03.09.2012 в 12:06)   письмо автору
 
   для: selma   (03.09.2012 в 10:59)
 

Можно конечно и на span сделать, но лучше на списках. Примерно так:
<style>
ul {
    list-style: none;
    cursor: pointer;
}

ul ul {display: none;}

.sub {display: inline-block;}
</style>

<script>
function showTree(e) {
   if(e.tagName=='LI' && e.lastChild.tagName=='UL') {
       var u = e.parentNode.getElementsByTagName('ul');
       for(var i=0; i<u.length; i++) u[i].className = u[i].className.replace('sub','');
       e.lastChild.className = 'sub';
   }
}       
</script>

<ul onclick="showTree(event.target || event.srcElement)">
  <li>Root 1
    <ul>
      <li><a href="#">Sub 1-1</a></li>
      <li><a href="#">Sub 1-2</a></li>
      <li><a href="#">Sub 1-3</a></li>
    </ul>
  </li>
  <li>Root 2
    <ul>
      <li><a href="#">Sub 2-1</a></li>
      <li><a href="#">Sub 2-2</a></li>
      <li><a href="#">Sub 2-3</a></li>
    </ul>
  </li>
  <li>Root 3
    <ul>
      <li><a href="#">Sub 3-1</a></li>
      <li><a href="#">Sub 3-2</a></li>
      <li><a href="#">Sub 3-3</a></li>
    </ul>
  </li>
</ul>

PS. Если меню (вложения его) будут без излишеств, то вместо управления классом вложений его, меняйте видимость их:
for(var i=0; i<u.length; i++) u[i].style.display = 'none';
       e.lastChild.style.display = 'inline-block';

а в стилях для ul ul пропишите нужное.

  Ответить  
 
 автор: ЯСА   (03.09.2012 в 15:05)   письмо автору
 
   для: selma   (03.09.2012 в 10:59)
 

Метод getElementById () возвращает первый в коде элемент с указанным ID.
Второго-третьего-десятого элемента с тем же значением ID этим методом вы не увидите и не "достанете".

Отсюда, кстати, вытекает правило, что ID на странице должны быть уникальными.
Какой смысл тегу иметь идентификатор, по которому нельзя к этому тегу обратиться?
-----

Задачу вашу можно решить, используя другой метод - getElementsByName () и, соответственно,
другой атрибут - NAME вместо ID у тегов <SPAN>.

Значения атрибутов NAME на странице вполне могут повторяться:
обратите внимание на буквочку s в названии метода getElementsByName () -
эта буквочка говорит о множественном числе элементов с каким-то значением NAME
(а у метода getElementById (), как видите, таковой буквочки нет).
<script>
function expandit (x)
{
for (var s = document.getElementsByName (x), j = 0, lj = s.length; j < lj; j++)
   with (s [j].style) display = (display == 'none') ? '' : 'none';

</script>

<b style="cursor: pointer" onClick="expandit ('ans1')">Раздел1</b><br/>
<span name="ans1" style="display: none">Подраздел1</span><br/>
<span name="ans1" style="display: none">Подраздел2</span><br/>
<span name="ans1" style="display: none">Подраздел3</span><br/>

PS. Это, правда, будет не очень валидно (атрибуты NAME тегам <SPAN> по спецификации HTML4 как бы не положены),
но зато будет везде работать.

  Ответить  
 
 автор: selma   (04.09.2012 в 09:22)   письмо автору
 
   для: ЯСА   (03.09.2012 в 15:05)
 

ЯСА огромное спасибо

работает, только юзабилити нарушается неравномерным расстоянием между закрытыми категориями.
Я так поняла, что расстояние между родителями завсисит от кол-ва подкатегорий содержащихся в родителе
Это как нибудь можно обойти?

Например чтобы все родители были один за одним:

Раздел1
Раздел2
Раздел3


А при нажатии, получалось:

Раздел1
-Подраздел1
-Подраздел2
Раздел2
Раздел3

  Ответить  
 
 автор: ЯСА   (04.09.2012 в 11:34)   письмо автору
 
   для: selma   (04.09.2012 в 09:22)
 

Расстояние между разделами зависит напрямую от количества тегов <br>, которыми у вас разделены <span>'ы с подразделами.
Ведь их (тегов <br>) функция скрытия/открытия никак не затрагивает.

Решение простое - убрать теги <br> вовсе, а тегам <span> в блоке стилей присвоить значение {display: block}.

Ну, или - как полностью безумный вариант - можно теги <br> переместить внутрь тегов <span>, вот так:
<span name="ans1" style="display: none">Подраздел1<br/></span>
<span name="ans1" style="display: none">Подраздел2<br/></span>
<span name="ans1" style="display: none">Подраздел3<br/></span>

Самое смешное, что этот бред собачий (последний вариант - с помещением тега <br> внутрь inline-тега <span>) пройдёт без замечаний в любом валидаторе :-)

  Ответить  
 
 автор: selma   (05.09.2012 в 07:36)   письмо автору
 
   для: ЯСА   (04.09.2012 в 11:34)
 

Огромное спасибо, вы АЯС, как всегда в точку. Я вам очень благодарна

  Ответить  
 
 автор: selma   (11.09.2012 в 02:04)   письмо автору
 
   для: selma   (05.09.2012 в 07:36)
 

Чтобы не плодить темы, решила спросить здесь, ибо вопрос всё по тому же коду

<?php 
$res 
mysql_query("SELECT t1.name AS level1, t2.name AS level2,  t2.id AS id, 
                    FROM table t1 
                    LEFT JOIN table t2  
                    ON (t1.id = t2.parent) 
                    WHERE t1.parent = '0'"
); 
$title NULL
while (
$line mysql_fetch_assoc($res))    
  {  
  if(
$title != $line['level1'])  
    {  
    echo 
"<b style=\"cursor:pointer;\" onClick=\"expandit('ans".$line['id']."')\">".$line['level1']."</b><br/>";   
    
$title $line['level1'];  
    } 
  echo 
"<div id ='ans".$line['id']."' style='display:none'>".$line['level2']."</div>"
  } 
?>


есть некий массив, допустим $arr = array('12','25','42');

Как сделать, чтобы при выводе подразделов в собранном виде, и при совпадении ID разделов с элементом массива, все содержимое раздела в котором присутствует совпадающий элемент раскрылось?

  Ответить  
 
 автор: ЯСА   (11.09.2012 в 08:06)   письмо автору
 
   для: selma   (11.09.2012 в 02:04)
 

Можно, конечно, решить и на javascript - вывести этот массив в скриптовом виде и по onload страницы запустить цикл, перебирающий элементы этого массива и запускающий функцию expandit ('ans' + элемент_массива)

Но рациональнее это сделать в PHP.
Перед формированием строки
echo "<div id ='ans".$line['id']."' style='display:none'>".$line['level2']."</div>";
проверить на совпадение $line ['id'] с элементами массива и при таковом выводить без display: none
echo "<div id ='ans".$line['id']."'>".$line['level2']."</div>";

  Ответить  
 
 автор: selma   (11.09.2012 в 09:18)   письмо автору
 
   для: ЯСА   (11.09.2012 в 08:06)
 

не все так просто

сделала так (допустим что в массиве всегда 2 значения):

if ($arr[0] == $line['id'] OR $arr[1] == $line['id']) 
  { 
  $disp = 'display:block'; 
  }
else   { $disp = 'display:none';  }

echo "<div id ='ans".$line['id']."' style='".$disp."'>".$line['level2']."</div>";


НО, теперь при совпадении показывает только совпавший элемент, а мне нужно чтобы показало все элементы скрытого раздела, в котором присутствует совпавший элемент

Предположим что у нас с элементом массива совпал Подраздел1
выведет так:
Раздел1 
-Подраздел1 
Раздел2 
Раздел3

а надо:
Раздел1 
-Подраздел1 
-Подраздел1 
Раздел2 
Раздел3


если сделать как сказали вы, т.е при совпадении убирать display:none. То открывает все разделы, при этом не выделяя совпадающие

  Ответить  
 
 автор: ЯСА   (11.09.2012 в 09:37)   письмо автору
 
   для: selma   (11.09.2012 в 09:18)
 

Пытаюсь понять логику вашего кода, но пока не понимаю.

То, что вы теги <span> для ПОДразделов заменили на <div> - это понятно.
Но вот остальное...

1. Вроде бы договорились у ПОДразделов писать не id, а name.
Но вы в предлагаем PHP-коде упорно прописываете им id.
Это - "непонятка" номер раз.

2. Во-вторых, в предыдущих примерах все ПОДразделы одного раздела имели у вас одно и то же значение для атрибута name.
Если это положение сохранилось, то все ПОДразделы одного раздела должны иметь одно и то же значение $line['id'] и при совпадении с элементом массива они все должны получить стиль display: block и все должны быть видны при выводе.
Однако, как следует из вашего PHP-кода и разъяснений к нему, ситуация у вас изменилась - ПОДразделы одного раздела теперь имеют у вас разные значения.
Это - "непонятка" номер два.

Согласитесь, очень трудно "въехать" в код, логика которого вами спонтанно меняется и вы об этих изменениях ни гу-гу не пишете :-((

  Ответить  
 
 автор: selma   (11.09.2012 в 10:05)   письмо автору
 
   для: ЯСА   (11.09.2012 в 09:37)
 

Простите что ввела в заблуждение:

1. Действительно везде вместо id стоит name, это я скопировала старый код указанный в начале этой темы

<?php  
$res 
mysql_query("SELECT t1.name AS level1, t2.name AS level2,  t2.id AS id,  t1.id_r AS par
                                        FROM table t1  
                                        LEFT JOIN table t2   
                                       ON (t1.id = t2.parent)  
                                      WHERE t1.parent = '0'"
);  
$title NULL;  
$arr = array('12','25','42');
while (
$line mysql_fetch_assoc($res))     
  {   
  if(
$title != $line['level1'])   
    {   
    echo 
"<b style=\"cursor:pointer;\" onClick=\"expandit('ans".$line['par']."')\">".$line['level1']."</b><br/>";    
    
$title $line['level1'];   
    }  
  if (
$arr[0] == $line['id'] OR $arr[1] == $line['id'])  
  {  
  
$disp 'display:block';  
  } 
else   { 
$disp 'display:none';  }

echo 
"<div name ='ans".$line['par']."' style='".$disp."'>".$line['level2']."</div>";  
  }  
?>


2. Попытаюсь разъяснить с идентификаторами

Есть разделы и подразделы, каждый из разделов и подразделов имеет свой id (это видно из первого сообщения темы)

$line['id'] уникальное ID Подраздела
$line[par'] уникальное ID Раздела

я сравниваю, не ID Разделов, а ID подразделов (потому что массив $arr несет в себе значения id подразделов)

наглядное отображение кода (при условии, что подраздел1 имеет ID:12, а подраздел6 имеет ID:25 ):

<div style="cursor:pointer;" onClick="expandit('ans1')"> Раздел1</div>
<div name = 'ans1' style='display:block'>подраздел1</div>
<div name = 'ans1' style='display:none'>подраздел2</div>
<div name = 'ans1' style='display:none'>подраздел3</div>
<div style="cursor:pointer;" onClick="expandit('ans2')">Раздел2</div>
<div name = 'ans2' style='display:none'>подраздел4</div>
<div name = 'ans2' style='display:none'>подраздел5</div>
<div name = 'ans2' style='display:block'>подраздел6</div>
<div style="cursor:pointer;" onClick="expandit('ans3')">Раздел3</div>


т.е по исходному коду все ровно, а на странице отображается:

Раздел1  
-Подраздел1  
Раздел2 
-Подраздел6  
Раздел3


а должно
Раздел1  
-Подраздел1  
-Подраздел2
-Подраздел3 
Раздел2 
-Подраздел4
-Подраздел5
-Подраздел6  
Раздел3

  Ответить  
 
 автор: selma   (11.09.2012 в 10:36)   письмо автору
 
   для: selma   (11.09.2012 в 10:05)
 

Впринципе мысль уловила. Нужно имея значения id-подразделов, вытаскивать id-разделов, и уже их сравнивать.

Что-то подобное получилось, но уж больно дико выглядит...

  Ответить  
 
 автор: selma   (12.09.2012 в 07:38)   письмо автору
 
   для: selma   (11.09.2012 в 10:36)
 

Уважаемый АЯС, апочему-то наш JS не работает в IE:((
можно какой-нибудь хак дописать?

  Ответить  
 
 автор: ЯСА   (12.09.2012 в 08:01)   письмо автору
 
   для: selma   (12.09.2012 в 07:38)
 

Хак простой - спанам (или дивам? - я уже запутался) подразделов надо прописать и NAME, и ID оновременно. И с одинаковым значением:
<script>
function expandit (x)
{
for (var s = document.getElementsByName (x), j = 0, lj = s.length; j < lj; j++)
   with (s [j].style) display = (display == 'none') ? '' : 'none';

</script>

<b style="cursor: pointer" onclick="expandit ('ans1')">Раздел1</b><br/>
<span name="ans1" id="ans1" style="display: none">Подраздел1</span><br/>
<span name="ans1" id="ans1" style="display: none">Подраздел2</span><br/>
<span name="ans1" id="ans1" style="display: none">Подраздел3</span><br/>

  Ответить  
 
 автор: selma   (12.09.2012 в 08:03)   письмо автору
 
   для: ЯСА   (12.09.2012 в 08:01)
 

сейчас у меня везде DIV, спасибо за подсказку.

  Ответить  
Rambler's Top100
вверх

Rambler's Top100 Яндекс.Метрика Яндекс цитирования