2009-07-16 3 views
2

Я постараюсь сохранить это короткое. Я пытаюсь создать коробки текста, которые скрывают или показывают, когда пользователь нажимает кнопку расширения. Я использую метод toggle().jQuery.each() проблема

Разметка, как это:

<span id="toggle0">+</span> 
<div id="toggle0Container"> 
    blablabla... 
<div> 

<span id="toggle1">+</span> 
<div id="toggle1Container"> 
    blablabla... 
<div> 

<span id="toggle2">+</span> 
<div id="toggle2Container"> 
    blablabla... 
<div> 

// etc 

# toggle0 предполагается переключить # toggle0Container, то # toggle1 переключает # toggle1Container и так далее. Все это генерируется PHP, поэтому может быть любое количество этих контейнеров.

Вот код JQuery:

$(document).ready(function() { 
    // array of numbers, it's pretty redundant, there will never be more than 30 containers 
    var arr = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9 , 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36]; 
    // hide all containers first 
    jQuery.each(arr, function() { 
     $('#toggle' + this + 'Container').hide(); 
    }); 
    // now the toggle buttons 
    jQuery.each(arr, function() { 
     $('#toggle' + this).click(function() { 
      // this line is not working 
      $('#toggle' + this + 'Container').slideToggle('slow'); 
      // and this just changes the toggle button from + to - 
      if ($(this).html() == '+') { 
       $(this).html('-'); 
      } else { 
       $(this).html('+'); 
      } 
     }); 
    }); 
}); 

Он работает для переключения части (я добавил комментарий выше линии, которая не работает), за исключением. Где проблема?

ответ

2

я бы следовать подходу mgroves, но если вы действительно хотите сделать массив вещь, или просто хотите, чтобы выяснить, как использовать каждый() правильно, вот как вы должны использовать:

$(document).ready(function() { 
    // array of numbers, it's pretty redundant, there will never be more than 30 containers 
    var arr = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9 , 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36]; 
    // hide all containers first 
    jQuery.each(arr, function(index, item) { 
     $('#toggle' + item + 'Container').hide(); 
    }); 
    // now the toggle buttons 
    jQuery.each(arr, function(index, item) { 
     $('#toggle' + item).click(function() { 
      // this line is not working 
      $('#toggle' + item + 'Container').slideToggle('slow'); 
      // and this just changes the toggle button from + to - 
      if ($(this).html() == '+') { 
       $(this).html('-'); 
      } else { 
       $(this).html('+'); 
      } 
     }); 
    }); 
}); 
+0

Спасибо всем за ответы, они были очень полезны, но я пойду с массивом, спасибо DrJokepu за исправление каждого метода(). –

+0

Единственная точка этого ответа - показать вам, где ваш синтаксис выключен. Вы действительно, действительно не должны его использовать - особенно когда он ломает слишком много контейнеров, а нерушимое исправление намного проще. (Реальная причина, однако, в том, что избыточный массив вредит моим eeeyyyyyeeeesssssss.) – Matchu

5

Это потому, что «это» теперь находится в другом пространстве и относится к фактическому элементу #toggleN DOM, а не к одному из чисел в массиве.

Я хотел бы предложить вам канаву массива чисел, и использовать другой селектор, что-то вроде:


$("div[id^=toggle][id$=container]").hide(); 

$("span[id^=toggle]").click(function() { 
    $(this).find("span[id^=toggle][id$=container]").slideToggle("slow"); 
    // .. do your other html stuff 
} 

Просто канава этих eachs и заменить переключаемые селекторы с теми.

+1

Малой опечатка в вашем 'find' вызова, то есть^а чем^= –

+0

спасибо - исправлено –

1

Я хотел бы предложить положить класс на кнопке переключения (диапазон), как «Toggler» и ваш тумблер контейнер типа «контейнер» или что-то для того, чтобы упростить JavaScript:

$(function() { 
    // hide all containers first 
    $(".container").hide(); 
    // now the toggle buttons 
    $(".toggler").click(function() { 
      var container = $("#" + $(this).attr("id") + "Container"); 
      container.slideToggle("slow"); 

      $(this).html(container.is(":visible") ? "-" : "+"); 
    }); 
}); 

Дайте, что выстрел.

1

Как заявили в mgroves, ваш объем становится все поднятым, используя каждый(). См. this для получения дополнительной информации.

2

EDIT

Мне нравится mgroves решение лучше для вашего конкретного случая использования, но я оставлю свой ответ на который объясняет, как вы можете принять индекс и элемент в качестве параметра по методу .each

ОРИГИНАЛЬНЫЙ ОТВЕТ

Как уже говорилось, контекст это не то, что вы думаете, в т он указывает, на что вы ссылаетесь. Вот замечательная статья Remy Sharp под названием «jQuery's this: demystified», которую я рекомендую вам прочитать.

Функция .each может принимать два параметра, которые очень помогут вам, и вам не понадобится этот массив чисел.

$('span[id^=toggle']').each(function(idx, elem) { 

    // idx is the current index of the jQuery object 
    $('#toggle' + idx).click(function() { 

     // elem is the current element 
     $(elem).next('#toggle' + idx + 'Container').slideToggle('slow'); 

     if ($(elem).html() == '+') { 
      $(elem).html('-'); 
     } else { 
      $(elem).html('+'); 
     } 

    }); 

}); 
1

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

$(function() { 
    // hide all containers first 
    $(".container").hide(); 
    // now the toggle buttons 
    $(".toggler").click(function() { 
    $(this).next().slideToggle("slow"); 

    if (container.is(":visible")) { 
     $(this).html("-"); 
    } 
    else { 
     $(this).html("+"); 
    } 
    }); 
}); 

Если вы не можете легко получить классы на пролетах, вероятно, можно построить подобный селектор используя что-то вроде $ ('# SpanContainer > span '), чтобы выбрать их по имени тега, опустившись из их содержащего элемента.

0

Я недавно написал довольно существенный сценарий для такого поведения. Я сделал несколько другой маршрут, в котором я решил обернуть все элементы данного элемента hide/show в содержащем div. Это позволяет вам иметь несколько «триггеров» для одного раздела, если вам это нужно, и вы можете добавить произвольное количество элементов hide/show, не беспокоясь о их нумерации. Я бы структурировать это что-то вроде этого:

<div class="expSecWrapper"> 
    <div class="expSecTrigger">Insert Trigger Here</div> 
    <div class="expSecBody"> 
     Content to hide/show 
    </div> 
</div> 

И тогда код JQuery будет что-то вроде этого:

$(document).ready(function(){ 
    var targets = $(".expSecWrapper") 
    targets.find(".expSecTrigger").click(function(){ 
     targets.find(".expSecBody").hide() 
     $(this).parents(".expSecWrapper").eq(0).children(".expSecBody").toggle(); 
    }) 
}) 

Вы можете добавить в остальных соответствующих JS для вашего приложения.

У этого есть несколько ограничений, таких как необходимость того, чтобы тело hide/show было прямым потомком обертки. Он может применяться к выпадающим спискам, переключателям, что угодно. Он также может быть установлен в гнездо, поэтому вы можете иметь несколько уровней, если скрывать/показывать.

Наконец-то то, что на самом деле вам даже не нужно использовать итератор .each для назначения этого поведения. Что-то вроде .click() назначит поведение целой группе объектов jQuery. Пока вы используете селектор, который будет захватывать все ваши цели.

Извините, пришлось отредактировать пару раз.

0

Вы должны указать своим элементам класс, который можно найти, а затем использовать next.

Сделайте разметку что-то вроде этого:

<span class="toggleButton">+</span> 
<div class="toggleContainer"> 
    blablabla... 
<div> 

Теперь код, чтобы справиться с этим становится столь же простым, как это:

$('.toggleButton').click(function() { 
    $(this).next('.toggleContainer').slideToggle('slow'); 
}); 
Смежные вопросы