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

HTML+CSS+JavaScript

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

 

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

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

тема: toggle. Показать/скрыть блок
 
 автор: Neverhood   (25.04.2012 в 13:05)   письмо автору
 
 

Здравствуйте, сообщество softtime!
в JavaScript разбираюсь очень поверхностно, поэтому прошу вашей помощи ткнуть меня носом.
Имеется код:

<html>
    <head>
    <script type="text/javascript">
             function getRealDisplay(elem) {
                if (elem.currentStyle) {
                    return elem.currentStyle.display
                } else if (window.getComputedStyle) {
                    var computedStyle = window.getComputedStyle(elem, null )

                    return computedStyle.getPropertyValue('display')
                }
            }

            function hide(el) {
                if (!el.getAttribute('displayOld')) {
                    el.setAttribute("displayOld", el.style.display)
                }

                el.style.display = "none"
            }

            displayCache = {}

            function isHidden(el) {
                var width = el.offsetWidth, height = el.offsetHeight,
                    tr = el.nodeName.toLowerCase() === "tr"

                return width === 0 && height === 0 && !tr ?
                    true : width > 0 && height > 0 && !tr ? false :    getRealDisplay(el)
            }

            function toggle(el) {
                isHidden(el) ? show(el) : hide(el)
            }


            function show(el) {

                if (getRealDisplay(el) != 'none') return

                var old = el.getAttribute("displayOld");
                el.style.display = old || "";

                if ( getRealDisplay(el) === "none" ) {
                    var nodeName = el.nodeName, body = document.body, display

                    if ( displayCache[nodeName] ) {
                        display = displayCache[nodeName]
                    } else {
                        var testElem = document.createElement(nodeName)
                        body.appendChild(testElem)
                        display = getRealDisplay(testElem)

                        if (display === "none" ) {
                            display = "block"
                        }

                        body.removeChild(testElem)
                        displayCache[nodeName] = display
                    }

                    el.setAttribute('displayOld', display)
                    el.style.display = display
                }
            }
        </script>
        
<style>
        .hidden1 { display: none }
        </style>

    </head>
    <body>
        <table border="1">
            <tr>
                <td onclick="javascript:toggle('hidden1')">Заголовок</td>
            </tr>
            <tr>
                <td class="hidden1">Подзаголовок</td>
            </tr>
            <tr>
                <td class="hidden1">Запись один</td>
            </tr>
            <tr>
                <td class="hidden1">Запись два</td>
            </tr>
            <tr>
                <td onclick="javascript:toggle('hidden2')">Заголовок №2</td>
            </tr>
            <tr>
                <td class="hidden2">Подзаголовок №2</td>
            </tr>
            <tr>
                <td class="hidden2">Запись один №2</td>
            </tr>
            <tr>
                <td class="hidden2">Запись два №2</td>
            </tr>
        </table>
    </body>
</html>

Пытаюсь сделать следующее:
имеется условный блок, в который включено Заголовок, Подзаголовок, Запись один, Запись два. Необходимо реализовать возможность скрытия/раскрытия блока при нажатии на Заголовок. При этом показан может быть только один блок, остальные в этот момент должны быть скрытыми.
Код js взят здесь. Никак не соображу как заставить его работать в связке с моей таблицей.
Или может если есть более простое решение подскажите.
Делаю именно для таблицы.
PS. В приведенном выше коде ничего не работает у меня. Блин, даже onclick не хочет ни на что реагировать... :((( js дается мне явно труднее чем php

  Ответить  
 
 автор: Neverhood   (25.04.2012 в 14:20)   письмо автору
 
   для: Neverhood   (25.04.2012 в 13:05)
 

Я так понимаю, что для разных условных блоков должен быть свой style hidden, то есть нужно дополнительно используя javascript или php пробежаться по N-му количеству записей и присвоить им свои display:none (может в js это делается проще, не знаю). Это реализовать можно. Как с остальным-то быть? :) Кто-нибудь?
PS: количество условных блоков не ограничено каким-то одним количеством и формируется php-скриптом (к общему сведению).

  Ответить  
 
 автор: ЯСА   (25.04.2012 в 20:36)   письмо автору
 
   для: Neverhood   (25.04.2012 в 14:20)
 

1. Скрипт ваш здесь вообще не по делу. Он предназначен для обработки XML-документов (о чём свидетельствует используемое в скрипте свойство nodeName).

2. Таблица от прочих тегов отличается тем, что имеет связную структуру - положение и размеры каждой строки и ячейки зависят от положения и размеров ВСЕХ других строк и ячеек. Т.е. если измените свойства одной ячейки (например, добавите ей высоту) - это повлечёт изменение размеров всех ячеек строки. А изменение ширины одной ячейки может изменить ширину всех ячеек столбца.

3. Соответственно, даже в вашем "одностолбцовом" варианте выключение видимости ячейки с самым широким содержимым приведёт к общему уменьшению ширины всей таблицы (до значения следующей по ширине ячейки).

4. Ну а если же ваша таблица имеет несколько столбцов, то там вообще будет "кошмар в степени ужас". Запустите пример и посмотрите - что стало с положением ячеек и с бордерами:
<table border="1" cellpadding="10" cellspacing="0">
<tr><td>1Left</td><td>1Right</td></tr>
<tr><td style="display: none">2Left</td><td>2Right</td></tr>
<tr><td>3Left</td><td>3Right</td></tr>
</table>

-----

Я всё это не к тому, что "с таблицей сделать ничего нельзя", а к тому, что изменение свойства displaу - это не самый лучший вариант.
Совет: напишите обычный HTML-код для двух случаев: а) изначальное состояние таблицы и б) состояние таблицы после клика. Запустите оба кода поочередно в браузере и сделайте два скрина окна (нажатие кнопки PrintScreen и "вставка" в программе Paint с последующим сохранением файла в каком-либо из web-форматов). Прикрепите эти файлы к следующему сообщению, в котором опишите - на что именно вы как бы кликнули в первом скрине, чтобы получился второй скрин.

Уверен, что задача ваша решается самым простейшим образом.
И как только будет понятно - что именно вам надо - так сразу же многие из здесь присутствующих вам дадут код для решения этой задачи. В крайнем случае, если более желающих не найдётся, - я помогу.

  Ответить  
 
 автор: Neverhood   (26.04.2012 в 00:01)   письмо автору
34.6 Кб
 
   для: ЯСА   (25.04.2012 в 20:36)
 

Спасибо, что откликнулись и огромное спасибо за содержательный и понятный ответ!
Прикрепляю скриншоты того, чего хочется добиться. То есть нажатием на бухгалтерию должен появится скрытый блок бухгалтерии с кабинетами и фамилиями сотрудников. Соответственно, если нажать отдел кадров, то блок бухгалтерии должен свернуться, а отдел кадров раскрыться (где только это не реализовано, почти на каждом сайте).
С блочными элементами типа div это действительно должно решаться наипростейшим способом (чувствую это :)), но увяз в таблицах и цепляюсь за них не замечая, возможно, элементарного решения...
И код.
before:

<html>
<head>
<style>
.title {
    background-color: grey; color: #fff; text-align: center; width: 200px;
}
.subtitle {
    font-size: 12px; background-color: #CACACA;
}
.surname {
    text-align: center;
}
</style>
</head>
<body>
<table border="1">
    <tr>
        <td class="title">Бухгалтерия</td>
    </tr>
    <tr>
        <td class="subtitle">Кабинет №1</td>
    </tr>
    <tr>
        <td class="surname">Иванова А. П.</td>
    </tr>
    <tr>
        <td class="surname">Козлова В. Я.</td>
    </tr>
    <tr>
        <td class="subtitle">Кабинет №2</td>
    </tr>
    <tr>
        <td class="surname">Петрушин Г. А.</td>
    </tr>
    <tr>
        <td class="title">Отдел кадров</td>
    </tr>
</table>
</body>
</html>


after:

<html>
<head>
<style>
.title {
    background-color: grey; color: #fff; text-align: center; width: 200px;
}
.subtitle {
    font-size: 12px; background-color: #CACACA;
}
.surname {
    text-align: center;
}
</style>
</head>
<body>
<table border="1">
    <tr>
        <td class="title">Бухгалтерия</td>
    </tr>
    <tr>
        <td class="title">Отдел кадров</td>
    </tr>
    <tr>
        <td class="subtitle">Кабинет №3</td>
    </tr>
    <tr>
        <td class="surname">Петренко В. А.</td>
    </tr>
    <tr>
        <td class="subtitle">Кабинет №4</td>
    </tr>
    <tr>
        <td class="surname">Теркина А. В.</td>
    </tr>
    <tr>
        <td class="surname">Павлова З. М.</td>
    </tr>
</table>
</body>
</html>

  Ответить  
 
 автор: ЯСА   (26.04.2012 в 08:37)   письмо автору
2.6 Кб
 
   для: Neverhood   (26.04.2012 в 00:01)
 

Ага... понятно, желающих нет.
-----

Несколько общих соображений:

1. При повторном клике на, например, уже ранее "открытую" "Бухгалтерию" надо её "закрыть".
Что приведет таблицу к изначальному виду, где будут только лишь наименования отделов.
Это как бы логично вытекает из практики пользования всевозможными гаджетами.

2. Не знаю, будут ли на вашей странице ещё какие-то таблицы, поэтому для однозначной
идентификации именно этой таблицы присвоил ей id="TBL"

3. Полагаю нужным принудительно установить размер и стиль шрифта в ячейках таблицы.
Попадётся плоховидящий, с дефолтным font-size: 36px - ширины в 200px ячейке не хватит.

4. Очевидно, что персон в таблице будет в сумме больше, чем кабинетов и названий отделов.
Для уменьшения веса кода класс "surname" ликвидирован, а его правила установлены для всех ячеек таблицы.
В двух других оставшихся классах эти правила "для всех ячеек" - отменены.

5. Чтобы не было "прыжков" контента, следующего за таблицей, запуск начального скрипта таблицы сделан
не после onload'а всего контента страницы, а сразу после закрывающего тега </table>.
Из этих же соображений таблице установлен нулевой начальный отступ снизу и прописан тег <BR> после таблицы.
(В прикрепленном коде после таблицы прописана горизонтальная линия <HR>,
коя при исполнении п. 5 должна быть неподвижной при любых состояниях таблицы).
-----

Теперь про скрипт: он состоит из двух функций: 1) предварительного оформления и 2) обработки клика.
Плюс сразу после закрывающего тега </table> - одна строка, запускающая первую функцию.

ПЕРВАЯ ФУНКЦИЯ (предварительная):
а) делает невидимыми все "кабинеты" и "персоны";
б) назначает "отделам" обработку клика второй функцией;
в) запускает вторую функцию для всех "отделов" по очереди с целью определения высоты для каждого открытого "отдела";
г) определяет среди этих высот максимальную и разницу между нею и каждой запоминает, чтобы назначать таблице снизу отступ;
д) исчисляет нужный отступ для таблицы только из "отделов", и прописывает его.

ВТОРАЯ ФУНКЦИЯ (обработка клика):
а) открывает "кабинеты+персоны" для "отдела" + делает отступ снизу и запоминает "отдел" до следующего клика;
б) если следующий клик будет по тому же "отделу", то она оставит в таблице только "отделы" (+ нужный отступ снизу);
в) если же следующий клик будет по иному "отделу", то закроет предыдущий и откроет нужный (+ нужный отступ снизу);
г) кроме всего, в функции реализован "первый проход", когда нужные отступы ещё только определяются.
-----

PS. Проверял в FF, Opera, Chrome.
MSIE сейчас под рукой нет.
А в нём обязательно что-либо "вылезет": в этом отношении MSIE - лучший валидатор.
Так что посмотрите в MSIE сами и отпишитесь о впечатлениях.

UPDATE: в MSIE 8 тоже всё нормально.

  Ответить  
 
 автор: Neverhood   (26.04.2012 в 19:35)   письмо автору
 
   для: ЯСА   (26.04.2012 в 08:37)
 

Мог ли я подумать о таком ответе? Никогда! Вы же мне все расписали, да еще и весь код как на блюдечке. Мне аж неловко. Просил-то я о другом - ткнуть меня носом, а тут... Буду разбирать и изучать. Еще раз огромное спасибо за проделанную работу!

  Ответить  
 
 автор: Rivs29   (12.10.2014 в 02:41)   письмо автору
 
   для: ЯСА   (26.04.2012 в 08:37)
 

Полезный код. Мне такой же очень нужен.

  Ответить  
 
 автор: Rivs29   (12.10.2014 в 02:41)   письмо автору
 
   для: ЯСА   (26.04.2012 в 08:37)
 

Спасибо.

  Ответить  
 
 автор: confirm   (12.10.2014 в 04:26)   письмо автору
 
   для: ЯСА   (26.04.2012 в 08:37)
 

Можно проще:

<style>
#tbl {
    width: 400px;
    border-collapse: separate;
}

#tbl td {
    width: 100%;
    border: 1px solid #999;    
}      

.head td {
    background: #ddd;
    cursor: pointer;
}
</style>

<script>
function toggle(e) {
     if(e.tagName=='TD' && e.parentNode.className=='head') {
        var row = document.getElementById('tbl').rows; e = e.parentNode;
        for(i=0, k=row.length; i<k; i++) {
            if(row[i].className == 'head') {
                var mode = row[i] != e ? 1 : 0;
                continue;    
            }
            if(!row[i].style.display && mode) row[i].style.display = 'none';
            else if(!mode) row[i].style.display == 'none' ? row[i].style.display = '' : row[i].style.display = 'none';
        }
    }
}
</script>    

<table id="tbl" onclick="toggle(event.target || event.srcElement)"> 
    <tr class="head"> 
        <td>Заголовок</td> 
    </tr> 
    <tr style="display:none"> 
        <td>Подзаголовок</td> 
    </tr> 
    <tr style="display:none"> 
        <td>Запись один</td> 
    </tr> 
    <tr style="display:none"> 
        <td>Запись два</td> 
    </tr> 
    <tr class="head"> 
        <td>Заголовок №2</td> 
    </tr> 
    <tr style="display:none"> 
        <td>Подзаголовок №2</td> 
    </tr> 
    <tr style="display:none"> 
        <td>Запись один №2</td> 
    </tr> 
    <tr style="display:none"> 
        <td>Запись два №2</td> 
    </tr> 
</table>

  Ответить  
 
 автор: Rivs29   (12.10.2014 в 16:52)   письмо автору
402.1 Кб
 
   для: confirm   (12.10.2014 в 04:26)
 

Спасибо, оно работает. Только мне надо немного в другой структуре таблиц. В общем я разобрался, хоть и по другому, но не хватает такого элемента, чтобы, например ссылка, которая раскрывает то, что нужно, ещё скрывала всё остальное, что имеет изначальный style="dispay:none".

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

  Ответить  
 
 автор: confirm   (12.10.2014 в 19:24)   письмо автору
 
   для: Rivs29   (12.10.2014 в 16:52)
 

Ну так в этом случае надо еще же и индекс ячейки знать, этот индекс связывать с индексом строки текущей, а по нему уже и принимать решение. Изначально индекс ячейки активной можно "вынести за пределы":

<style>
#tbl { 
    width: 400px; 
    border-collapse: separate; 


#tbl td { 
    border: 1px solid #999;     
}       

.head td { 
    background: #ddd; 
    cursor: pointer; 

</style>

<script>
function toggle(e) { 
     if(e.tagName=='TD' && e.parentNode.className=='head') { 
        var row = document.getElementById('tbl').rows, tr = e.parentNode, cel = tr.cells, idx;
         
        for(i=0, k=row.length; i<k; i++) { 
            if(row[i].className == 'head') {
                for(j=0, n=cel.length; j<n; j++) {
                    if(tr==row[i] && cel[j] == e) {
                        idx = i+j+1;
                        break;
                    }
                }
                continue;    
            }     
             
            if(i != idx && !row[i].style.display) row[i].style.display = 'none';
            else if(i == idx) row[idx].style.display == 'none' ? row[idx].style.display = '' : row[idx].style.display = 'none';   
        } 
    } 
}
</script>

<table id="tbl" onclick="toggle(event.target || event.srcElement)">  
    <tr class="head">  
        <td>1</td><td>2</td><td>3</td>  
    </tr>
      
    <tr style="display:none">  
        <td colspan="3">1-1</td>  
    </tr>
    <tr style="display:none">  
        <td colspan="3">2-1</td>  
    </tr>
    <tr style="display:none">  
        <td colspan="3">3-1</td>  
    </tr>
      
    <tr class="head">  
        <td>4</td><td>5</td><td>6</td>  
    </tr>
      
    <tr style="display:none">  
        <td colspan="3">4-1</td>  
    </tr>
    <tr style="display:none">  
        <td colspan="3">5-1</td>  
    </tr>
    <tr style="display:none">  
        <td colspan="3">6-1</td>  
    </tr>
     
    <tr class="head">  
        <td>7</td><td>8</td><td>9</td>  
    </tr>
      
    <tr style="display:none">  
        <td colspan="3">7-1</td>  
    </tr>
    <tr style="display:none">  
        <td colspan="3">8-1</td>  
    </tr>
    <tr style="display:none">  
        <td colspan="3">9-1</td>  
    </tr>  
</table>


Вот только в вашем случае лучше все это сделать на чистом CSS+UL+LI, и только если нужны эффекты то JQ+UL+LI+DIV.

  Ответить  
 
 автор: Rivs29   (12.10.2014 в 21:14)   письмо автору
 
   для: confirm   (12.10.2014 в 19:24)
 

Большое спасибо! Чудный код и всё замечательно работает, сам бы я такой код не написал. Насчёт ul+li я и не предположил, но и tr+td вполне подходит, то, что нужно. )))
Благодарю!

  Ответить  
 
 автор: Rivs29   (13.10.2014 в 13:00)   письмо автору
 
   для: confirm   (12.10.2014 в 19:24)
 

А если я в td вставляю картинку, оно вроде уже не работает?

  Ответить  
 
 автор: Rivs29   (13.10.2014 в 13:11)   письмо автору
 
   для: confirm   (12.10.2014 в 19:24)
 

Хотя если прописать background то работает, и это хорошо.

  Ответить  
 
 автор: confirm   (13.10.2014 в 13:26)   письмо автору
 
   для: Rivs29   (13.10.2014 в 13:11)
 

Почему это не работает, все будет работать, обработка на любом элементе таблицы делегируется самой таблице, а функция проверяет по какому элементу произошел щелчок. Если перекрыть всю ячейку изображением, значит условие должно выполняться по тегу не TD, а IMG, а тег TR, который надо получить, будет не первым, а вторым по счету вверх.

  Ответить  
 
 автор: Rivs29   (13.10.2014 в 14:41)   письмо автору
 
   для: confirm   (13.10.2014 в 13:26)
 

А как изменить код, если внутри каждой открывающей TD обязательно есть img?

  Ответить  
 
 автор: confirm   (13.10.2014 в 20:48)   письмо автору
 
   для: Rivs29   (13.10.2014 в 14:41)
 

Изменяйте.

Условием начало цикла является:

if(e.tagName=='TD' && e.parentNode.className=='head')

Если ячейки заголовка, это будут картинки, значит условие должно быть:

if(e.tagName=='IMG' && e.parentNode.parentNode.className=='head')

Переменные:

e = e.parentNode; //теперь это ячейка

Все далее как и ранее.

var row = document.getElementById('tbl').rows, tr = e.parentNode, cel = tr.cells, idx;

....

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

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