I'm trying to clean up the results presented on my HTML file with Jquery. I want to keep removing words that are repeated more than one time.
A quick example
Accents Australian
Accents English (RP)
Dance Hip Hop
Dance Jazz
It should be output as
Accents
- Australian
- English (RP)
Dance
- Hip Hop
- Jazz
My original HTML looks like this
<div role="list" >
<div role="listitem" >
<div >Accents</div>
<div>Australian</div>
</div>
<div role="listitem" >
<div >Accents</div>
<div>English (RP)</div>
</div>
<div role="listitem" >
<div >Dance</div>
<div>Hip Hop</div>
</div>
<div role="listitem" >
<div >Dance</div>
<div>Jaz</div>
</div>
</div>
I tried my best but I'm not landing in a good place
$('.skill-category').text(function(index, oldText) {
return oldText.replace($(this).parent().next().find('.skill-category').text(), '');
})
Any suggestion?
CodePudding user response:
Please check below working code:
const category = [...document.querySelectorAll('.skill-item > .skill-category')];
const texts = new Set(category.map(x => x.innerHTML));
category.forEach(category => {
if(texts.has(category.innerHTML)){
texts.delete(category.innerHTML);
}
else{
category.remove()
}
})
As per you question and shared HTML above is the working code for the same and if you add more similar things it will help. Please let me know if you find any issues
CodePudding user response:
Your question can be broken into two problems:
- You want to group the elements with the same value for
.skill-category
- You want to change
<div>
elements into a list.
Grouping the elements could by done like so:
- For every category, take a look at the previous element.
- Does it contain the same category? If not, then continue to the next category.
- If so, take everything after
.skill-category
(in your example HTML, that's a single<div>
. Cut-and-paste it at the end of the aforementioned previous element.
For the second problem:
Changing an element (<div>
to <li>
) is not possible. You can create a new <li>
and move what's inside the <div>
into it. Of course, you'll need a <ul>
that wraps the <li>s
as well.
- Take the
.skill-category
elements - Find all the content that follows the category (in your case, 1
<div>
elements) - Put the contents of the matched elements into a new
<li>
. - Put all the
<li>s
of a single category into a<ul>
. - Remove the matched elements (in your case, the
<div>(s)
) since we've moved all their content to a different node. They're now empty tags and useless. - Put the
<ul>
after the.skill-category
.
// Grouping the results.
$('.skill-category').each(function() {
// Get the previous .skill-item and find the category.
var prev = $(this).parent().prev('.skill-item').find('.skill-category');
// Check if the previous category === this category.
var same = !!(prev.length && prev.text() === $(this).text());
if (!same) {
return; // Do nothing.
}
// Take every element after the category and move it to the
// previous .skill-item.
prev.after($(this).nextAll());
// Then remove the now-empty category.
// All content has been moved to the previous element, after all.
$(this).parent().remove();
});
// Wrapping the contents of a category in a list.
$('.skill-category').each(function() {
var list = $('<ul></ul');
// Find everything after the category.
$(this).nextAll().each(function() {
// Create a <li> and move the child elements to it.
// Then add the <li> to the <ul>.
$('<li></li>').append($(this).contents()).appendTo(list);
}).remove(); // remove the now empty elements.
// Add the list to current .skill-category.
$(this).append(list);
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div role="list" >
<div role="listitem" >
<div >Accents</div>
<div>Australian</div>
</div>
<div role="listitem" >
<div >Accents</div>
<div>English (RP)</div>
</div>
<div role="listitem" >
<div >Dance</div>
<div>Hip Hop</div>
</div>
<div role="listitem" >
<div >Dance</div>
<div>Jaz</div>
</div>
</div>