jQuery — отдельные стили для представления сетки / списка

#jquery

#jquery

Вопрос:

Для каждого экземпляра .content есть кнопки сетки и списка, настроенные для переключения функций для styleList() загрузки и styleGrid() при загрузке, а также при нажатии.

Проблема с моим кодом заключается в том, что переключение сетки / списка применяется ко всем .items , а не только к тем, которые связаны с кнопками.

Как мне изменить код так, чтобы функции styleList() and styleGrid() применялись только к каждому экземпляру .content и не повторялись по каждому .item ?

ПРИМЕЧАНИЕ: мне также нужно решение для работы, appendTo и prependTo в дополнение к изменению CSS мне нужно будет перемещать элементы внутри каждого .item в зависимости от представления.

 function styleList() {
  $(".item").each(function() {
    var $this = $(this);
    $this.find("img").css("border", "");
    $this.find("img").prependTo($(this).find(".test"));
  });
}

function styleGrid() {
  $(".item").each(function() {
    var $this = $(this);
    $this.find("img").css("border", "4px solid green");
    $this.find("img").appendTo($(this).find(".test"));
  });
}
$(".content").each(function() {
  var $this = $(this);
  if ($this.find(".list").attr("data-view") == "list") {
    styleList();
  }
  if ($this.find(".list").attr("data-view") == "grid") {
    styleGrid();
  }
});
$(".toggle--list").on("click", function() {
  var $this = $(this).closest(".content");
  $this.find(".toggle").removeClass("active");
  $this.find(".toggle--list").addClass("active");
  styleList();
});

$(".toggle--grid").on("click", function() {
  var $this = $(this).closest(".content");
  $this.find(".toggle").removeClass("active");
  $this.find(".toggle--grid").addClass("active");
  styleGrid();
}); 
 .test {
  border: 3px solid yellow;
  padding: 1.3rem
}

.view {
  display: flex;
}

.view>div {
  padding: 1.3rem;
}

.active {
  background: blue;
}

.list {
  display: flex;
  flex-direction: column;
}

.item {
  display: flex;
  padding: 10px;
  margin-top: 20px;
  border: 1px solid #ddd;
} 
 <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="content">
  <div class="view">
    <div class="toggle toggle--grid">
      <div class="icon icon--grid">grid</div>
    </div>
    <div class="toggle toggle--list active">
      <div class="icon icon--list">list</div>
    </div>
  </div>
  <div class="list" data-view="list">
    <div class="item">
      <img class="image" src="http://placehold.it/200x150" />
      <div class="test"></div>
    </div>
  </div>
</div>
<div class="content">
  <div class="view">
    <div class="toggle toggle--grid active">
      <div class="icon icon--grid">grid</div>
    </div>
    <div class="toggle toggle--list">
      <div class="icon icon--list">list</div>
    </div>
  </div>
  <div class="list" data-view="grid">
    <div class="item">
      <img class="image" src="http://placehold.it/200x150" />
      <div class="test"></div>
    </div>
    <div class="item">
      <img class="image" src="http://placehold.it/200x150" />
      <div class="test"></div>
    </div>
    <div class="item">
      <img class="image" src="http://placehold.it/200x150" />
      <div class="test"></div>
    </div>
  </div>
</div> 

Ответ №1:

Если вы хотите, чтобы ваши styleList styleGrid функции и изменяли только ближайший элемент, вы можете передать $this его в качестве параметра, например:

 $(".toggle--list").on("click", function() {
  var $this = $(this).closest(".content");
  $this.find(".toggle").removeClass("active");
  $this.find(".toggle--list").addClass("active");

  styleList($this); // passing $this (".content" element) to style function
});

function styleList(content) {
  // don't need to use .each() as .css() will apply to all elements matching the selector
  content.find(".item img").css("border", "");
}
 

Я уверен, что у вас могут быть причины для создания функций для оформления разделов вашего HTML, но, как правило, намного проще оставить стиль для CSS и вместо этого использовать JavaScript для переключения классов / атрибутов. Вот упрощенная версия, которая достигает того же (я думаю):

 $(".toggle").on("click", function() {
  var $this    = $(this);
  var $content = $this.parents(".content");
  var style    = $this.attr("data-toggle-style"); // "list" or "grid"

  // Handle .active class
  $content.find(".toggle.active").removeClass("active");
  $this.addClass("active");

  // Set [data-style] attr to inherit CSS styles
  $content.find(".list").attr("data-style", style);
}) 
 .view {
  display: flex;
}

.view>div {
  padding: 1.3rem;
}

.active {
  background: blue;
}

.list {
  display: flex;
  flex-direction: column;
}

.item {
  display: flex;
  padding: 10px;
  margin-top: 20px;
  border: 1px solid #ddd;
}

/* Add styles here instead of JS */
.list[data-style="grid"] img {
    border: 4px solid green;
}
.list[data-style="list"] img {
    /* something else */
} 
 <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

<div class="content">
  <div class="view">
    <div class="toggle" data-toggle-style="grid">
      <div class="icon icon--grid">grid</div>
    </div>

    <div class="toggle active" data-toggle-style="list">
      <div class="icon icon--list">list</div>
    </div>
  </div>

  <div class="list">
    <div class="item">
      <img class="image" src="https://via.placeholder.com/200x150" />
    </div>
  </div>
</div>

<div class="content">
  <div class="view">
    <div class="toggle active" data-toggle-style="grid">
      <div class="icon icon--grid">grid</div>
    </div>

    <div class="toggle" data-toggle-style="list">
      <div class="icon icon--list">list</div>
    </div>
  </div>

  <div class="list">
    <div class="item">
      <img class="image" src="https://via.placeholder.com/200x150" />
    </div>
  </div>
</div> 

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

Комментарии:

1. Спасибо за ответ. Что делать, если вместо того, чтобы просто изменять css , я хотел использовать appendTo where, если, например, styleList() я перемещаю div в одну позицию внутри, в то .item время как в styleGrid() том же div должен быть перемещен в другое место внутри .item ?

2. Это звучит достаточно просто — .appendTo() отсоединяет / перемещает элементы, чтобы ваши styleList / styleGrid функции можно было легко адаптировать для этого.

3. Я пытался добавить .appendTo() что-то в ваш код, но у меня возникли проблемы с его настройкой внутри функции. Кажется, каждый раз, когда я вызываю styleGrid() it, он дублирует элементы: codepen.io/moofawsaw/pen/BaLoOwj

4. Ах, мой плохой — я просто более внимательно прочитал документы appendTo , и в нем говорится: «Однако, если существует более одного целевого элемента, клонированные копии вставленного элемента будут созданы для каждой цели, кроме последней, и этот новый набор (исходный элемент плюс клоны) возвращается». Попробуйте .detach() вместо этого посмотреть вверх.

5. Я посмотрел .detach() , но не уверен, как включить это в ваш код. Не могли бы вы обновить свой фрагмент с помощью рабочего решения?