Плохая практика — генерация кода javascript для getElementById из PHP во время цикла

#javascript #php #html #mysql

#javascript #php #HTML #mysql

Вопрос:

Я создаю html-таблицу из запроса mysql через PHP. Я заполняю каждую строку таблицы одной записью из результирующего набора запроса.

Я использую функцию javascript getElementById , чтобы показать диалоговое окно или закрыть его.

Поскольку у меня много строк, я добавил код javascript к данным цикла while / таблицы. Это создает тонну javacode, и я очень уверен, что это хороший пример плохой практики.

Как я могу это сделать, не генерируя (программно) уникальную функцию javascript для каждой строки? Можно ли использовать массив?

Это мой код

 <?php while($r = mysqli_fetch_assoc($result)){  $current_row_number  ; ?>
    <tr>
      <td>
    <!--Popup Window-->   
    <dialog id="window<?php echo $current_row_number; ?>">  
    <h3>Description</h3>  
    <p><?php echo $r['description']; ?></p>  
    <button id="exit<?php echo $current_row_number; ?>">Close</button>  
    </dialog>  
    <button id="show<?php echo $current_row_number; ?>">View</button> 
    <!--Popup Window-->   
     <script type="text/javascript">

    var dialog<?php echo $current_row_number; ?> = document.getElementById('window<?php echo $current_row_number; ?>');  
    document.getElementById('show<?php echo $current_row_number; ?>').onclick = function() {  dialog<?php echo $current_row_number; ?>.show();   };  
    document.getElementById('exit<?php echo $current_row_number; ?>').onclick = function() {  dialog<?php echo $current_row_number; ?>.close();  };  

     </script>
     </td>
    </tr>
<?php?>
  

генерирует этот пример вывода:

  <script type="text/javascript">

var dialog8 = document.getElementById('window8');  
document.getElementById('show8').onclick = function() {  dialog8.show();   };  
document.getElementById('exit8').onclick = function() {  dialog8.close();  };  
 </script>
 <script type="text/javascript">

var dialog9 = document.getElementById('window9');  
document.getElementById('show9').onclick = function() {  dialog9.show();   };  
document.getElementById('exit9').onclick = function() {  dialog9.close();  };  

 </script>
 <script type="text/javascript">

var dialog10 = document.getElementById('window10');  
document.getElementById('show10').onclick = function() {  dialog10.show();   };  
document.getElementById('exit10').onclick = function() {  dialog10.close();  };  

 </script>
  

и так далее…

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

Выполнение повторяющихся задач в коде — плохая практика, и код java script выглядит очень хреново

Заранее благодарю вас

Ответ №1:

Да, действительно, во всем этом нет необходимости.

Внутри обработчика событий this ссылается на элемент, к которому был присоединен обработчик событий, а target свойство объекта event сообщает вам, где началось событие. Вы можете использовать эту информацию, чтобы иметь единый обработчик в таблице, который обрабатывает нажатия на эти кнопки. Поместите класс на кнопки, который указывает, должны ли они «показывать» или «скрывать», затем сделайте что-то вроде этого (см. Комментарии):

 document.getElementById("the-table").addEventListener("click", function(e) {
    // Find the row
    var row = e.target;
    while (row.tagName != "TR") {
        if (row === this) {
            // The click wasn't on a row, ignore it
            return;
        }
        row = row.parentNode;
    }

    // Find the button
    var button = e.target;
    while (button.tagName != "BUTTON") {
        if (button === this) {
            // The click wasn't on a button, ignore it
            return;
        }
        button = button.parentNode;
    }

    // Find the dialog
    var dialog = row.querySelector("dialog");
    if (!dialog) {
        // Couldn't find it
        return;
    }

    // Now, use the `className` or `classList` on `button` to determine
    // whether to show or hide, and do that on `dialog`
}, false);
  

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

Вот упрощенный пример, использующий h3 вместо dialog :

 document.getElementById("the-table").addEventListener("click", function(e) {
  // Find the row
  var row = e.target;
  while (row.tagName != "TR") {
    if (row === this) {
      // The click wasn't on a row, ignore it
      return;
    }
    row = row.parentNode;
  }

  // Find the button
  var button = e.target;
  while (button.tagName != "BUTTON") {
    if (button === this) {
      // The click wasn't on a button, ignore it
      return;
    }
    button = button.parentNode;
  }

  // Find the "dialog"
  var dialog = row.querySelector("h3");
  if (!dialog) {
    // Couldn't find it
    return;
  }

  // Now, use the `className` or `classList` on `button` to determine
  // whether to show or hide, and do that on `dialog`
  if (button.className == "show") {
    dialog.className = "";
  } else {
    dialog.className = "hidden";
  }
}, false);  
 .hidden {
  display: none;
}  
 <table id="the-table">
  <tbody>
    <tr>
      <td>
        <h3 class="hidden">Dialog 1</h3>
        <div>
          <button class="show">Show 1</button>
          <button class="hide">Hide 1</button>
        </div>
      </td>
    </tr>
    <tr>
      <td>
        <h3 class="hidden">Dialog 2</h3>
        <div>
          <button class="show">Show 2</button>
          <button class="hide">Hide 2</button>
        </div>
      </td>
    </tr>
    <tr>
      <td>
        <h3 class="hidden">Dialog 3</h3>
        <div>
          <button class="show">Show 3</button>
          <button class="hide">Hide 3</button>
        </div>
      </td>
    </tr>
    <tr>
      <td>
        <h3 class="hidden">Dialog 4</h3>
        <div>
          <button class="show">Show 4</button>
          <button class="hide">Hide 4</button>
        </div>
      </td>
    </tr>
  </tbody>
</table>