#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/BaLoOwj4. Ах, мой плохой — я просто более внимательно прочитал документы
appendTo
, и в нем говорится: «Однако, если существует более одного целевого элемента, клонированные копии вставленного элемента будут созданы для каждой цели, кроме последней, и этот новый набор (исходный элемент плюс клоны) возвращается». Попробуйте.detach()
вместо этого посмотреть вверх.5. Я посмотрел
.detach()
, но не уверен, как включить это в ваш код. Не могли бы вы обновить свой фрагмент с помощью рабочего решения?