Есть ли более простой способ сделать это расширяемое меню?

0

Я хочу создать расширяемое меню с тремя или несколькими элементами. Когда один из этих элементов нажат, он расширяется, чтобы отобразить <ul> который display: hidden под ним.
Кроме того, я хочу, чтобы он работал таким образом, что если один из элементов в этом меню уже расширен, если я нажму на любой другой элемент, он убирает содержимое первого элемента перед тем, как развернуть второй элемент (тот нажал).

Код у меня есть это. Мне пришлось определить другую функцию toggle для каждого из трех элементов, которые у меня есть, плюс дополнительная функция switchAll чтобы скрыть любой расширенный элемент, прежде чем приступать к расширению нового.

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

Кроме того, я хочу добиться этого с помощью Javascript, а не jQuery.

Соответствующий код следует:

HTML:

<ul>
    <li><a href="#" onclick="toggle();">one</a>
        <ul id="menu">
            <li>sacd</li>
            <li>safsdf</li>
        </ul>
    </li>
    <li><a href="#" onclick="toggle1();">two</a>
        <ul id="menu2">
            <li>jlkfd</li>
            <li>ljsdf</li>
        </ul>
    </li>
        <li><a href="#" onclick="toggle2();">three</a>
        <ul id="menu3">
            <li>sfsdvbg gb</li>
            <li>asdavffds</li>
        </ul>
    </li>
</ul>

CSS:

#menu {
    display: none;
}

#menu2 {
    display : none;
}

#menu3 {
    display : none;
}

JS:

var hidden = true;
var hidden2 = true;
var hidden3 = true;

function switchAll(other1, other2) {
    other1.style.display = "none";
    other2.style.display = "none";
    hidden = true;
    hidden2 = true;
    hidden3 = true;
};

function toggle() {
    var menu = document.getElementById("menu");
    var menu2 = document.getElementById("menu2");
    var menu3 = document.getElementById("menu3");
    if(hidden) {
        switchAll(menu2, menu3);
        menu.style.display = "block";
        hidden = false;
    } else {
        menu.style.display = "none";
        hidden = true;
    };
};

function toggle1() {
    var menu = document.getElementById("menu");
    var menu2 = document.getElementById("menu2");
    var menu3 = document.getElementById("menu3");
    if(hidden2) {
        switchAll(menu, menu3);
        menu2.style.display = "block";
        hidden2 = false;
     } else {
        menu2.style.display = "none";
        hidden2 = true;
    };
};

function toggle2() {
    var menu = document.getElementById("menu");
    var menu2 = document.getElementById("menu2");
    var menu3 = document.getElementById("menu3");
    if(hidden3) {
        switchAll(menu, menu2);
        menu3.style.display = "block";
        hidden3 = false;
    } else {
        menu3.style.display = "none";
        hidden3 = true;
    };
};
  • 0
    не могли бы вы опубликовать соответствующий код
  • 0
    Отступы здесь отображаются некорректно, но в JSFiddle они в порядке. Я не могу отформатировать это правильно здесь.
Показать ещё 1 комментарий
Теги:

4 ответа

1
Лучший ответ

Мой JSFiddle находится здесь: http://jsfiddle.net/naokiota/38W8X/12/

Это пример упрощения вашей функции:

HTML

    <ul>
        <li><a href="#" onclick="toggle(1);" >one</a>
            <ul class="submenu">
                <li>sacd</li>
                <li>safsdf</li>
            </ul>
        </li>
        <li><a href="#" onclick="toggle(2);" >two</a>
            <ul class="submenu">
                <li>jlkfd</li>
                <li>ljsdf</li>
            </ul>
        </li>
        <li><a href="#" onclick="toggle(3);" >three</a>
            <ul class="submenu">
                <li>sfsdvbg gb</li>
                <li>asdavffds</li>
            </ul>
        </li>
    </ul>

JavaScript

function toggle(n) {
    var menus = document.getElementsByClassName("submenu");
    for(var i=0;i<menus.length;i++){
        if((i == (n-1)) && (menus[i].style.display != "block")){
            menus[i].style.display = "block";
        }else{
            menus[i].style.display = "none";
        }
    } 
};

CSS

.submenu {
    display: none;
}

Надеюсь это поможет.

  • 0
    Этот работает отлично. Но он не свернет развернутый в данный момент элемент, нажав на него снова.
  • 1
    @JNat Спасибо. Я отредактировал мой ответ выше и JSFiddle jsfiddle.net/naokiota/38W8X/12
3

Если мой первый ответ на сложность здесь, это только css-альтернатива без анимации & js.

HTML

<ul class="box">
    <li id="a"><a href="#a">one</a>
        <ul>
            <li>sacd</li>
            <li>safsdf</li>
        </ul>
    </li>
    <li id="b"><a href="#b">two</a>
        <ul>
            <li>jlkfd</li>
            <li>ljsdf</li>
        </ul>
    </li>
    <li id="c"><a href="#c">three</a>
        <ul>
            <li>sfsdvbg gb</li>
            <li>asdavffds</li>
        </ul>
    </li>
</ul>

CSS

.box>li>ul{
 display: none;
}
.box>li:target>ul{
 display:block;
}

DEMO

http://jsfiddle.net/vvLu2/

нет javascript...

  • 0
    Хорошо, я не знал, что это можно сделать, используя только CSS. Однако, если я нажму на расширенный элемент, он не свернется.
  • 0
    вот почему я впервые опубликовал свое сложное решение ... этот скрипт позволяет улучшить ограничения некоторых простых действий. Нет способа свернуть выбранный элемент, щелкнув по нему.
1

Сохраните текущий расширенный элемент в переменной.

var current = null;
function toggle(element) {
    if(current === null) {
        // Show 'element'
        current = element;
    }
    else if(element === current) {
        // Hide 'current'
        current = null;
    }
    else {
        // Show 'element' and hide 'current'
        current = element;
    }
}
0

Да, есть более простой/(более удобный и анимированный) способ написать что-то подобное.

  1. он анимирован
  2. может обрабатывать бесконечные коммутаторы
  3. не использует дисплей нет
  4. не использует циклы
  5. только один обработчик событий управляет всеми элементами
  6. вы можете применять любой тип стиля
  7. вы можете добавить несколько аккордеонов, просто добавив класс accordion

Я написал этот код некоторое время назад и оптимизировал его и сжал.

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

это Аккордеон.

function h(e){
 var p='parentNode',a=e.target,b=a[p],f=48,u='px',y=b.firstChild==a?b[p]:y;
 !y.c||(y.c==b||(y.c.style.height=f+u,y.c.x=f)),
 y.c=y.c==b?null:b,
 a!=b.firstChild||(b.x=b.x>f?f:(f+b.childNodes[1].offsetHeight),
 b.style.height=b.x+u)
}
document.getElementById('container').addEventListener('click',h,false);

DEMO

http://jsfiddle.net/YjCbM/1/

Вот еще одна версия

function handler(e){
 e=e||window.event;
 var target=e.target||e.srcElement;
 var action=target.dataset['action']||'no action';
 !(action=='toggle')||(target.childNodes[1].classList.toggle('show'));
 !target.dataset['url']||alert(target.dataset['url']);
}
var firstUL=document.getElementsByTagName('ul')[0];
firstUL.addEventListener('click',handler,false);

http://jsfiddle.net/Jj6FY/1/

Считываемые версии (немного разные)

это в основном плагин аккордеона

(function(D){
function acsf(e){
 var a=e.target.parentNode,h;
 if(a.parentNode==this&&a.firstChild==e.target){
  if(this.c==a){
   this.c.style.height='';
   delete this.c
  }else{
   if(this.c){
    this.c.style.height=''
   }
   this.c=a;
   this.c.style.height=(a.firstChild.offsetHeight+
   this.c.childNodes[1].offsetHeight)+'px'
  }
 }
}
 function acsinit(){
  var acs=D.getElementsByClassName('accordion'),acsl=acs.length;
  while(acsl--){
   acs[acsl].addEventListener('click',acsf,false);
  }
  window.removeEventListener('load',acsinit,false);
 }
 window.addEventListener('load',acsinit,false);
})(document)

css для анимации.

#container>div{
 width:512px;height:48px;overflow:hidden;
 -webkit-transition:all 300ms ease;
 background-color:rgba(0,0,0,0.5);
}
#container>div>div:nth-child(1){
 line-height:48px;text-align:center;
 background-color:rgba(0,0,0,0.5);
}

Структура html

<div id="container" class="accordion">
 <div>
  <div>Title</div>
  <div>description</div>
 </div>
 <div>
  <div>Title</div>
  <div>description</div>
 </div>
</div>

И если вы хотите, чтобы их можно было закрыть, вам нужно использовать циклы, чтобы проверить, переключены ли они или нет.

что-то вроде того:

function openAll(){
 var elements=container.childNodes,l=elements.length;
 while(l--){
  if(elements[l].classList.contains('hidden')){
   elements[l].classList.remove('hidden');
  }
 }
}

Ещё вопросы

Сообщество Overcoder
Наверх
Меню