Абстракция добавления событий щелчка к элементам, выбранным классом, с помощью jQuery - PullRequest
1 голос
/ 21 мая 2010

Я медленно набираю скорость с jQuery и начинаю хотеть абстрагировать свой код. У меня проблемы с попыткой определить события клика при загрузке страницы.

В приведенном ниже коде я пытаюсь просмотреть каждый элемент div с помощью класса 'block' и добавить события к некоторым его дочерним элементам, выбрав их по классу:

<script language="javascript" type="text/javascript">
$(document).ready(function (){

$('HTML').addClass('JS'); // if JS enabled, hide answers

 $(".block").each(function() { 
  problem = $(this).children('.problem');
  button = $(this).children('.showButton');

  problem.data('currentState', 'off');

  button.click(function() {
   if ((problem.data('currentState')) == 'off'){
    button.children('.btn').html('Hide');
    problem.data('currentState', 'on');
    problem.fadeIn('slow');
   } else if ((problem.data('currentState')) == 'on'){
    button.children('.btn').html('Solve');
    problem.data('currentState', 'off');
    problem.fadeOut('fast');
   }
   return false;

  });
 });
});
</script>

<style media="all" type="text/css">
.JS div.problem{display:none;}
</style>


<div class="block">
    <div class="showButton">
        <a href="#" title="Show solution" class="btn">Solve</a>
    </div>

    <div class="problem">
      <p>Answer 1</p>
    </div>
</div>

<div class="block">
    <div class="showButton">
        <a href="#" title="Show solution" class="btn">Solve</a>
    </div>

    <div class="problem">
      <p>Answer 2</p>
    </div>
</div>

К сожалению, используя это, на самом деле работает только последняя кнопка из divs. Событие не «локализовано» (если это правильное слово для него?), Т.е. событие применяется только к последнему $ (". Block") в каждом методе.

Так что я должен кропотливо добавлять идентификаторы для каждого элемента и определять мои события клика один за другим. Конечно, есть лучший способ! Может кто-нибудь сказать мне, что я делаю не так? И как мне избавиться от необходимости этих идентификаторов (я хочу, чтобы это работало на динамически генерируемых страницах, где я мог бы не знать, сколько «блоков» существует ...)

<script language="javascript" type="text/javascript">
$(document).ready(function (){

$('HTML').addClass('JS'); // if JS enabled, hide answers

 // Preferred version DOESN'T' WORK  
 // So have to add ids to each element and laboriously set-up each one in turn...

 $('#problem1').data('currentState', 'off');

 $('#showButton1').click(function() {
  if (($('#problem1').data('currentState')) == 'off'){
   $('#showButton1 > a').html('Hide');
   $('#problem1').data('currentState', 'on');
     $('#problem1').fadeIn('slow');
  } else if (($('#problem1').data('currentState')) == 'on'){
   $('#showButton1 > a').html('Solve');
   $('#problem1').data('currentState', 'off');
     $('#problem1').fadeOut('fast');
  }
  return false;

 });


 $('#problem2').data('currentState', 'off');

 $('#showButton2').click(function() {
  if (($('#problem2').data('currentState')) == 'off'){
   $('#showButton2 > a').html('Hide');
   $('#problem2').data('currentState', 'on');
     $('#problem2').fadeIn('slow');
  } else if (($('#problem2').data('currentState')) == 'on'){
   $('#showButton2 > a').html('Solve');
   $('#problem2').data('currentState', 'off');
     $('#problem2').fadeOut('fast');
  }
  return false;

 });

});
</script>

<style media="all" type="text/css">
.JS div.problem{display:none;}
</style>



<div class="block">
    <div class="showButton" id="showButton1">
        <a href="#" title="Show solution" class="btn">Solve</a>
    </div>

    <div class="problem" id="problem1">
      <p>Answer 1</p>
    </div>
</div>

<div class="block">
    <div class="showButton" id="showButton2">
        <a href="#" title="Show solution" class="btn">Solve</a>
    </div>

    <div class="problem" id="problem2">
      <p>Answer 2</p>
    </div>
</div>

Ответы [ 2 ]

0 голосов
/ 23 мая 2010

Извините, недостаточно репутации, чтобы голосовать за что-либо из вышеперечисленного как полезное, которым они, безусловно, были!

Ответ на самом деле был довольно прост - как правильно отметили @patrick и @Pointy, все, что мне нужно было сделать, это добавить ключевое слово var, чтобы объявить две мои переменные. DOH!

На самом деле я не мог заставить работать с предложениями кода, но мой теперь работает нормально, когда он был исправлен с вашей помощью. Спасибо!

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Untitled Document</title>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.1/jquery.min.js"></script>
<script language="javascript" type="text/javascript">
    $(document).ready(function (){

    $('HTML').addClass('JS'); // if JS enabled, hide answers

     $(".block").each(function() { 
      var problem = $(this).children('.problem');
      var button = $(this).children('.showButton');

      problem.data('currentState', 'off');

      button.click(function() {
       if ((problem.data('currentState')) == 'off'){
        button.children('.btn').html('Hide');
        problem.data('currentState', 'on');
        problem.fadeIn('slow');
       } else if ((problem.data('currentState')) == 'on'){
        button.children('.btn').html('Solve');
        problem.data('currentState', 'off');
        problem.fadeOut('fast');
       }
       return false;

      });
     });
    });
    </script>

<style media="all" type="text/css">
.JS div.problem{display:none;}
</style>

</head>

<body>

<div class="block">
    <div class="showButton">
        <a href="#" title="Show solution" class="btn">Solve</a>
    </div>

    <div class="problem">
      <p>Answer 1</p>
    </div>
</div>

<div class="block">
    <div class="showButton">
        <a href="#" title="Show solution" class="btn">Solve</a>
    </div>

    <div class="problem">
      <p>Answer 2</p>
    </div>
</div>

<div class="block">
    <div class="showButton">
        <a href="#" title="Show solution" class="btn">Solve</a>
    </div>

    <div class="problem">
      <p>Answer 3</p>
    </div>
</div>

</body>
</html>
0 голосов
/ 21 мая 2010

отредактировано , потому что я нашел HTML:)

Во-первых: вам нужно объявить «кнопку» и «проблему» с ключевым словом var.

Затем обработчик нажатия будет вызываться в контексте целевого элемента, поэтому вы не должны ссылаться на «кнопку» внутри него, а вместо этого на «$ (this)».

Далее вам нужно будет найти способ связать каждую кнопку с соответствующим «проблемным» элементом. Обработчик может найти сопутствующую "проблему", используя процедуры обхода jQuery DOM:

button.click(function() {
  var $button = $(this), $problem = $button.closest('div.block').find('.problem');
  if (($problem.data('currentState')) == 'off'){
    $button.children('.btn').html('Hide');
    $problem.data('currentState', 'on');
    $problem.fadeIn('slow');
  } else if (($problem.data('currentState')) == 'on'){
    $button.children('.btn').html('Solve');
    $problem.data('currentState', 'off');
    $problem.fadeOut('fast');
  }
  return false;
});

Теперь другой альтернативой будет использование механизма live, который позволит вам создать только одну функцию-обработчик. Это было бы очень похоже на это, но вместо того, чтобы привязывать обработчик к каждой «кнопке» <div>, вы просто устанавливаете его и ссылаетесь на селектор:

$('.button').live('click', function() {
  // as above
});
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...