Как уменьшить размер этого jQuery-скрипта и сделать его более гибким? - PullRequest
2 голосов
/ 06 июля 2011

Я только что создал скрипт, который показывает / скрывает (переключает) блок HTML. Есть четыре кнопки, каждая из которых может переключать свой блок HTML. Когда какой-либо блок HTML открыт, но пользователь нажал на другую кнопку, кроме кнопки, связанной с этим блоком HTML ... он скрывает этот блок HTML и показывает новый.

Вот что у меня есть на данный момент:

$('.btn_add_event').click( function() {

    $('.block_link, .block_photos, .block_videos').hide();
    $('.block_event').toggle();

});

$('.btn_add_link').click( function() {

    $('.block_event, .block_photos, .block_videos').hide();
    $('.block_link').toggle();

});

$('.btn_add_photos').click( function() {

    $('.block_event, .block_link, .block_videos').hide();
    $('.block_photos').toggle();

});

$('.btn_add_videos').click( function() {

    $('.block_event, .block_link, .block_photos').hide();
    $('.block_videos').toggle();

});

Есть идеи, как уменьшить размер кода? Кроме того, этот скрипт не очень гибкий. Представьте, что вы добавили две новые кнопки и блоки.

Ответы [ 9 ]

0 голосов
/ 06 июля 2011

Если вы поместите постфиксы класса в массив, вы можете легко сделать этот код более динамичным.Этот код предполагал, что не имеет значения, в каком порядке вызывается переключение или скрытие.Если это имеет значение, вы можете просто запомнить правильное имя класса внутри (внутреннего) цикла и переключать этот класс после цикла.

Преимущество этого подхода состоит в том, что вы можете расширять массив с помощью класса exta безнеобходимо изменить оставшуюся часть кода.

var classes = new Array('videos', 'event', 'link', 'photos');

for (var i = 0; i < classes.length; ++i)
{ 
    $('.btn_add_' + classes[i]).click( 
    function() 
    {
        for (var j = 0; j < classes.length; ++j)
        {
            if (this.hasClass('btn_add_' + classes[j]))
            {
                $('.block_' + classes[j]).toggle();
            }
            else
            {
                $('.block_' + classes[j]).hide();
            }
        }

    });
}

Вы можете сделать этот код более элегантным, не назначая этим элементам классы, такие как btn_add_event, но предоставив им два класса: btn_add и event,или даже прибегнуть к предоставлению им идентификаторов.Мое решение основано на вашем описании вашего текущего HTML.

0 голосов
/ 06 июля 2011

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

<html>
<head>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js" ></script>

<script type="text/javascript">

  // Enables show/hide functionality on click. 
  // The elements within 'container' matching the selector 'blocks' are hidden
  // When elements within 'container' matching the selector 'clicker' are clicked
  //  their attribute with the name 'clickerAttr' is appended to the selector 
  //  'subject' to identify a target, usually one of the 'blocks'. All blocks 
  //  except the target are hidden. The target is shown.
  // 
  // Change clickerAttr from 'linkTarget' to 'id' if you want XHTML compliance
  // 
  // container: grouping of related elements for which to enable this functionality
  // clicker: selector to element type that when clicked triggers the show/hide functionality
  // clickerAttr: name of the DOM attribute that will be used to adapt the 'subject' selector
  // blocks: selector to the html blocks that will be shown or hidden when the clicker is clicked
  // subject: root of the selector to be used to identify the one html block to be shown
  // 
  function initToggle(container,clicker,clickerAttr,blocks,subject) {

    $(container).each(
        function(idx,instance) { 
            var containerElement = $(instance);
            var containedBlocks = containerElement.find(blocks);    

            containerElement.find(clicker).each(function(idxC, instanceClicker) {

                var tgtE = containerElement.find(subject+instanceClicker.getAttribute(clickerAttr));
                var clickerBlocks = containedBlocks.not(tgtE);

                $(instanceClicker).click(function(event) { 
                    clickerBlocks.hide();
                    tgtE.toggle();
                });
            });

            // initially cleared
            containedBlocks.hide(); 
        }
    );
  }

  $(function() {

    initToggle('.toggle','a.link','linkTarget','div.block','div.');

  });
</script>

</head>
<body>

Example HTML block toggle:

<div class="toggle">
    <a href="javascript:;" linkTarget="A" class="link"> a </a> <br />
    <a href="javascript:;" linkTarget="B" class="link"> b </a> <br />
    <a href="javascript:;" linkTarget="C" class="link"> c </a> <br />
    <div class="A block">   A       </div>
    <div class="B block">   B       </div>
    <div class="C block">   C       </div>
</div> <!-- toggle -->

This next one is not enabled, to show scoping.

<div class="toggle2">
    <a href="javascript:;" linkTarget="A" class="link"> a </a> <br />
    <div class="A block">A</div>
</div> <!-- toggle2 -->

This next one is enabled, to show use in multiple positions on a page, such as in a portlet library.    

<div class="toggle">
    <a href="javascript:;" linkTarget="A" class="link"> a </a> <br />
    <div class="A block">A</div>
</div> <!-- toggle (2) -->

</body>
</html>
0 голосов
/ 06 июля 2011

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

var classNames = [ 'btn_add_event', 'block_link', 'block_photos', 'block_videos' ];

var all = '.' + classNames.join(', .'); // generate a jquery format string for selection

$(all).click( function() {

    var j = classNames.length;

    while(j--){
     if( this.className === classNames[j] ){

        var others = classNames.splice(j, 1); // should leave all classes but the one on this button

        $('.' + others.join(', .')).hide();
        $('.' + classNames[j]).toggle();

     }
    }
}

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

0 голосов
/ 06 июля 2011

Это зависит от того, как структурирован ваш HTML.

Предположим, у вас что-то вроде этого

<div class="area">
  <div class="one"></div>
  <div class="two"></div>
  <div class="three"></div>
</div>
...
<div class="sender">
  <a class="one"></a>
  <a class="two"></a>
  <a class="three"></a>
</div>

У вас есть класс, общий для отправителя и получателя.

Ваш js будет выглядеть так:

$('.sender > a').click(function() {
  var target = $(this).attr('class');
  $('.area > .' + target).show().siblings().hide();
});

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

0 голосов
/ 06 июля 2011

Как сказал Сэм, я бы использовал класс, который разделяют все блоки, поэтому вам никогда не придется изменять этот код. Во-вторых, вы можете попробовать перейти к ближайшему блоку, избегая его названия. Этот подход лучше, чем жесткое кодирование каждого конкретного блока, но если дерево html dom изменится, вам нужно будет провести рефакторинг. Наконец, но лучше всего, вы можете передать имя класса нужного блока в качестве переменной функции. Ниже вы можете скопировать вставку, близкую к тому, с которой вы начали.

$('.myAddButtonClass').click( function() {

    $('.mySharedBlockClass').filter(':visible').hide();
//find a good way to 'traverse' to your desired block, or name it specifically for now.
//$(this).closest(".mySharedBlockClass").show()  complete guess
    $('.specificBlockClass').show();
});
0 голосов
/ 06 июля 2011

К сожалению, я не смог проверить это, но, если я правильно помню, должно работать следующее:

function toogleFunc(clickObject, toogleTarget, hideTarget)
{
  $(clickObject).click(function()
  {
    $(hideTarget).hide();
    $(toogleTarget).toggle();
  });
}

И вызов:

toogleFunc(
  ".btn_add_videos",
  ".block_videos", 
  ".block_event, .block_link, .block_photos"
);

и до сих пор

0 голосов
/ 06 июля 2011

попробуйте

   $('input[type=button]').click( function() {
        $('div[class^=block]').hide(); // I resumed html block is div
        $(this).toggle();
});
0 голосов
/ 06 июля 2011

Вы можете обратиться по ссылке ниже,

http://chandreshmaheshwari.wordpress.com/2011/05/24/show-hide-div-content-using-jquery/

, вызвать function showSlidingDiv() событие onclick и динамически передать свой класс кнопки.

Это может быть полезно.

Спасибо.

0 голосов
/ 06 июля 2011

Я продолжал читать это «Когда любой блок HTML открыт, но пользователь нажал на другую кнопку, кроме кнопки, связанной с этим блоком HTML», думая, что мои глаза подводили меня, когда это просто плохой английский.

Если вы хотите сделать его более динамичным, вы можете добавить общее ключевое слово класса. затем когда событие щелчка поднимается. Вы можете сделать это, хотя все классы, которые имеют ключевое слово и пусть он скрывает их все (кроме текущего, по которому щелкнули), а затем показывает текущее с помощью ключевого слова this.

...