У меня есть два неупорядоченных списка внутри div с известным классом. Мне нужно изменить элементы списка в первом списке, чтобы они охватывали класс «время». Далее я хотел бы изменить элементы второго списка на интервалы с классом «частота». Наконец, я хотел бы удалить теги <ul>, оставив только промежутки в div. Как:
<div id = "training-labels">
<ul>
<li>30 mins</li>
</ul>
<ul>
<li>Annually</li>
<li>First 2 weeks</li>
</ul>
</div>
К этому
<span class = "time">30 mins</span>
<span class = "frequency">Annually</span>
<span class = "frequency">First 2 weeks</span>
Мне удалось изменить содержимое каждого списка на диапазоны:
$('#training-labels ul:nth-of-type(1) li').wrapInner('<span class = "time" />').contents();
$('#training-labels ul:nth-of-type(2) li').wrapInner('<span class = "frequency" />').contents();
Но не удалось удалить теги ul и li, оставив только промежутки.
Это лучший подход или есть лучший способ добиться этого с помощью JQuery?
Я установил здесь Fiddle
$('#training-labels ul:nth-of-type(1) li').wrapInner('<span class = "time" />').contents();
$('#training-labels ul:nth-of-type(2) li').wrapInner('<span class = "frequency" />').contents();
.time {
color: green;
}
.frequency {
color: red;
}
<script src = "https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id = "training-labels">
<ul>
<li>30 mins</li>
</ul>
<ul>
<li>Annually</li>
<li>First 2 weeks</li>
</ul>
</div>
$('#training-labels ul:nth-of-type(1) li').wrap('<span class = "time"/>').contents().unwrap();
$('#training-labels ul:nth-of-type(2) li').wrap('<span class = "frequency"/>').contents().unwrap();
$('#training-labels ul:nth-of-type(1) span').unwrap();
$('#training-labels ul:nth-of-type(1) span').unwrap();
.time {
color: green;
}
.frequency {
color: red;
}
<script src = "https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id = "training-labels">
<ul>
<li>30 mins</li>
</ul>
<ul>
<li>Annually</li>
<li>First 2 weeks</li>
</ul>
</div>
Метод JQuery wrap():
Функция .wrap() может принимать любую строку или объект, которые можно передать фабричной функции $() для указания структуры DOM.
Метод JQuery unwrap():
Удалите родителей набора совпадающих элементов из DOM, оставив совпавшие элементы на их месте.
Примечание. Поскольку к родительскому элементу div (с идентификатором training-labels) не прикреплен класс, оба интервала находятся в одной строке.
Спасибо за объяснение, это сработало! Хотя я заменил последние две строки на $('#training-labels ul span').unwrap(); чтобы развернуть все промежутки одновременно.
Если мы можем быть уверены, что у всех ul1 есть времена, а у всех ul2 есть частоты
const $div = $('#training-labels');
const $uls = $('ul', $div); // save
$div.empty(); // clear
$uls.each(function(i, ul) {
$("li", ul).each(function(j, li) {
$(`<span class = "${i===0 ? "time" : "frequency" }">${li.textContent}</span><br/>`)
.appendTo($div)
});
});
.time {
color: green;
}
.frequency {
color: red;
}
<script src = "https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id = "training-labels">
<ul>
<li>30 mins</li>
</ul>
<ul>
<li>Annually</li>
<li>First 2 weeks</li>
</ul>
</div>
В противном случае
const $div = $('#training-labels')
$('ul:nth-of-type(1) li', $div).wrapInner('<span class = "time" />').contents();
$('ul:nth-of-type(2) li', $div).wrapInner('<span class = "frequency" />').contents();
$div.html(function() {
return $div.find("span")
.map(function() { return this.outerHTML })
.get()
.join("<br/>"); // or space or something else
});
.time {
color: green;
}
.frequency {
color: red;
}
<script src = "https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id = "training-labels">
<ul>
<li>30 mins</li>
</ul>
<ul>
<li>Annually</li>
<li>First 2 weeks</li>
</ul>
</div>
Мой подход
let $div = $('#training-labels');
let $time = $('ul:nth-of-type(1) li', $div).clone().wrapInner('<span class = "time" />').contents();
let $freq = $('ul:nth-of-type(2) li', $div).clone().wrapInner('<span class = "frequency" />').contents();
$div.replaceWith($().add($time).add($freq));
Это не отличается от решения unwrap, за исключением того, что оно не так сильно привязано к структуре тега. Часть clone не является строго обязательной, но это означает, что на самом деле существует только одно обновление DOM, которое происходит после создания полной замены.
Хотя вы уже приняли ответ, я хотел бы найти время, чтобы показать не-JavaScript (или jQuery) подход, основанный только на CSS, который может работать для вас, в зависимости от желаемого конечного результата:
/* a simple reset to remove default font-sizes, box-sizing, margins and padding: */
*, ::before, ::after {
box-sizing: border-box;
font-family: system-ui;
font-size: 16px;
margin: 0;
padding: 0;
}
/* removing default list-markers from the <li> elements: */
ul {
list-style-type: none;
}
/* wrapping the outer <div> elements which wrap your <ul>
elements in a <main> element in order to style and
align the content; this is unnecessary for the demo
functionality: */
main {
/* taking advantage of grid display to position items on
the vertical (block) axis: */
display: grid;
/* separating tracks with a 'gutter': */
gap: 1em;
/* defining the inline-size - the size of the element
along the inline-axis (horizontal in most latin-
derived languages, such as French, English...): */
inline-size: clamp(15rem, 70vw, 1100px);
/* a 1em margin before the start of the element on its
block axis (perpendicular to the inline axis,
vertical in most Latin-derived languages): */
margin-block-start: 1em;
/* using margins to centre the element: */
margin-inline: auto;
}
/* default styles for the .content elements (the class-name
given to the <div> elements which wrap the <ul> elements:*/
.content {
border: 2px solid var(--color, currentColor);
padding: 0.5em;
}
/* styling the <li> elements as inline-block; which allows them
to flow inline but take a specified size (inline or block),
and margins: */
#inlineBlock li {
display: inline-block;
}
/* using flex layout on the <ul> elements, which positions the
<li> children along the inline-axis (by default) while allowing
them to be sized according to their content or declaration: */
#flex ul {
display: flex;
}
/* this was posted purely for the sake of completeness, and I don't
recommend it since the track sizing looks more tabular than
is possibly required: */
#grid {
display: grid;
/* this defines two columns with each column sized to fit the
content within: */
grid-template-columns: repeat(2, fit-content);
}
#grid ul {
/* we use this to effectively pretend the <ul> elements don't
exist, to allow the <li> elements to be placed into the
grid rather than the <ul> elements: */
display: contents;
}
/* because each row/column track of a grid has an equal number of
divisions/"cells", and because we're pretending (display: contents)
that the <ul> elements don't exist, this is to ensure that
the <li> contents of the second <ul> don't fill the first row track;
this can be adjusted if you'd prefer that to happen, but I didn't
expect that it's required: */
#grid li:only-child {
grid-column: span 2;
}
/* going back to the land before time, we use a simple floats to
allow the <li> elements to run inline: */
#float li {
float: left;
}
/* to ensure the first <li> always starts on a new line: */
#float li:first-child {
clear: left;
}
/* selecting all <li> elements that are not the :first-child,
contained within a <div> that does not have an id of "grid": */
.content:is(:not(#grid)) li:not(:first-child)::before {
/* placing a comma before those elelements: */
content: ", ";
}
/* selecting the :last-child <li> descendant of .content elements
(which do not have the id of "grid"), and styling their ::after
pseudo-element: */
.content:is(:not(#grid)) li:last-child::after {
/* adding a full-stop/period: */
content: '.';
}
/* styling the ::after pseudo-element of an <li> which is the :only-child
of its parent, and within a .content element without the id of "grid": */
.content:is(:not(#grid)) li:only-child::after {
/* adding a colon after the text of the element: */
content: ': ';
}
<main>
<div id = "inlineBlock" class = "content" style = "--color: hsl(120deg 80% 70% / 1)">
<ul>
<li>30 mins</li>
</ul>
<ul>
<li>Annually</li>
<li>First 2 weeks</li>
</ul>
</div>
<div id = "flex" class = "content" style = "--color: hsl(160deg 80% 70% / 1)">
<ul>
<li>30 mins</li>
</ul>
<ul>
<li>Annually</li>
<li>First 2 weeks</li>
</ul>
</div>
<div id = "grid" class = "content" style = "--color: hsl(200deg 80% 70% / 1)">
<ul>
<li>30 mins</li>
</ul>
<ul>
<li>Annually</li>
<li>First 2 weeks</li>
</ul>
</div>
<div id = "float" class = "content" style = "--color: hsl(240deg 80% 70% / 1)">
<ul>
<li>30 mins</li>
</ul>
<ul>
<li>Annually</li>
<li>First 2 weeks</li>
</ul>
</div>
</main>
Демонстрация JS Fiddle.
Использованная литература:
CSS:
Сделал новую версию без накрутки и энного