jQuery Grouping by first letter - javascript

I have list of posts in Wordpress its looks like this:
<div class="products uk-grid uk-grid-width-medium-1-4">
<h3>AShape(14)</h3>
<h3>AShape(20)</h3>
<h3>CShape(38)</h3>
<h3>FShape(1)</h3>
<h3>FShape(4)</h3>
<h3>ZShape(2)</h3>
<h3>ZShape(24)</h3>
</div>
I need to find some way to pass all links through script and transform it in letter groups. So it should take first letter from all <h3> of links and make groups like this:
<div class="products uk-grid uk-grid-width-medium-1-4">
<div>
<span>A</span>
<h3>AShape(14)</h3>
<h3>AShape(20)</h3>
</div>
<div>
<span>C</span>
<h3>CShape(38)</h3>
</div>
<div>
<span>F</span>
<h3>FShape(1)</h3>
<h3>FShape(4)</h3>
</div>
<div>
<span>Z</span>
<h3>ZShape(2)</h3>
<h3>ZShape(24)</h3>
</div>
</div>
How i can do it using jQuery?
here i have simple codepen: http://codepen.io/ponciusz/pen/EPgQKP

You could iterate over each of the children elements and create corresponding containers for each letter. In the example below, a div container is appending with a custom data-letter attribute if a container does not already exist for that letter.
As I mentioned in the comments, I'd also suggest placing the a element inside of the h3 elements as well:
$('.products > h3').each(function () {
var letter = $('a', this).text().charAt(0);
if (!$(this).parent().find('[data-letter="'+ letter +'"]').length) {
$(this).parent().append('<div data-letter="'+ letter+'"><span>'+ letter +'</span></div>');
}
$(this).parent().find('[data-letter="'+ letter +'"]').append(this);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="products uk-grid uk-grid-width-medium-1-4">
<h3>AShape(14)</h3>
<h3>AShape(20)</h3>
<h3>CShape(38)</h3>
<h3>FShape(1)</h3>
<h3>FShape(4)</h3>
<h3>ZShape(2)</h3>
<h3>ZShape(24)</h3>
</div>

Related

Remove repeated after 1st occurrence

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" class="skill-items">
<div role="listitem" class="skill-item">
<div class="skill-category">Accents</div>
<div>Australian</div>
</div>
<div role="listitem" class="skill-item">
<div class="skill-category">Accents</div>
<div>English (RP)</div>
</div>
<div role="listitem" class="skill-item">
<div class="skill-category">Dance</div>
<div>Hip Hop</div>
</div>
<div role="listitem" class="skill-item">
<div class="skill-category">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?
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
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" class="skill-items">
<div role="listitem" class="skill-item">
<div class="skill-category">Accents</div>
<div>Australian</div>
</div>
<div role="listitem" class="skill-item">
<div class="skill-category">Accents</div>
<div>English (RP)</div>
</div>
<div role="listitem" class="skill-item">
<div class="skill-category">Dance</div>
<div>Hip Hop</div>
</div>
<div role="listitem" class="skill-item">
<div class="skill-category">Dance</div>
<div>Jaz</div>
</div>
</div>

Copy first character of string to another div jquery or javascript

Is it possible with jQuery or Javascript to copy the first character of a string that's user generated to another div?
As an example, the contact list on iPhone. The first letter of the contact name is used in the circle adjacent to the name.
With the correct snippet the output would be as follows, where 'First name, Last name' will be different.
<div class="initial">F</div>
<div class="name">First name, Last name</div>
<div class="initial">J</div>
<div class="name">John Smith</div>
I tried to get some ideas from these other posts:
How do I make the first letter of a string uppercase in JavaScript?
How can I get the first three letters of a string in JQuery?
Detect character in div and remove it Javascript or jQuery
However, I'm not sure where to start and how to output the result to the 'initial' div.
The simple way to do this is to provide a function to text() of the .initial elements which reads the first character from the sibling .name and returns it, like this:
$('.initial').text(function() {
return $(this).next('.name').text().slice(0, 1).toUpperCase();
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="initial"></div>
<div class="name">Foo Bar</div>
<div class="initial"></div>
<div class="name">John Smith</div>
a vanilla JS solution i came up with:
https://jsfiddle.net/y0c9be6g/
<div class="initial"></div>
<div class="name">Bob Smith</div>
<div class="initial"></div>
<div class="name">Jim Halpert </div>
<div class="initial"></div>
<div class="name">Billy Baldwin</div>
<script>
var names = document.querySelectorAll(".name");
var initials = document.querySelectorAll(".initial");
function addInitial(item){
item.previousSibling.previousSibling.innerHTML = item.textContent.charAt(0);
}
names.forEach(addInitial);
</script>

How do I replace instances of a word in multiple tags on page load?

Trying to replace a word that possibly will come in a foreach loop of a database items in razor view.
What I've tried so far
<section class="section bg-gray">
<div class="container">
<div class="row gap-y">
#foreach (var item in Model)
{
<div class="col-md-6 col-lg-4">
<div class="card d-block">
<p class="text-justify">#item.Text</p>
<p class="text-center mt-7">
<a class="btn btn-primary" href="#">Read more</a>
</p>
</div>
</div>
}
</div>
<script src="~/Scripts/jquery-3.3.1.min.js"></script>
<script type="text/javascript">
$(document).ready(function () {
var elements = getElementsByClassName("text-justify");
$(elements).each(function(element) {
element.innerHTML = element.innerHTML.replace(/wordToReplace/g, 'newWord');
});
});
</script>
</div>
</section>
Excuse my poor JavaScript, I'm new on front-end. I looked for similar questions but closer topics are usually about replacing instances of a word in one tag. Please help.
You don't need jQuery for this - you can use document.querySelectorAll and just replace the desired text of the elements that match the selector.
Note that I have dodgied up a text element and for the desired class and replacing justify with justified to demonstrate the usage.
let elements = document.querySelectorAll(".text-justify");
elements.forEach(function(element){
let textContent = element.innerText;
let newTextContent = textContent.replace(/justify/g, 'justified');
element.innerText = newTextContent;
})
<p class="text-justify">This is a text with the class of text-justify</p>
<p>This is a text without the class of text-justify</p>
<p class="text-justify">This is a text with the class of text-justify</p>
You don't need jQuery for this - use a simple forEach loop. I've also refactored some other parts of your code (eg you were missing document:
document.getElementsByClassName("text-justify").forEach(element => element.innerHTML = element.innerHTML.replace(/word/g, "newWord"));
But if you really want to use jQuery:
$(".text-justify").html((index, element) => element.replace(/word/g, "newWord"));

How to select leaf node using jQuery :contains selector?

I want to get leaf elements containing specific text, and I used :contains selector. However, this selector selects includes every parent nodes too. Here is my example.
<div id='parent1'>
<p id='target1'>Red balloon</p>
<div id='target2'>Blue balloon</div>
</div>
<div id='parent2'>
<span id='target3'>Brown balloon</span>
</div>
In this case, I just want to get elements containing text balloon. I expected to get 3 elements(target1, target2, target3) by $(":contains('balloon')"), but it returns every nodes including parent nodes of targets. (e.g. html, body, and every parent div)
How can I select only targets?
p.s Above HTML is only example. HTML can be vary, so the answer should be generic.
use indexOf("balloon") > -1 to find id the word balloon is found
var arr = $("div").children().map(function(){
if($(this).text().indexOf("balloon") > -1 )
return $(this).attr("id")
}).get();
console.log(arr)
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id='parent1'>
<p id='target1'>Red balloon</p>
<div id='target2'>Blue balloon</div>
</div>
<div id='parent2'>
<span id='target3'>Brown balloon</span>
</div>
The solution below, look for all elements containing the word and clone these elements, This way we can be sure only to get "correct" amount of elements
Just remove .length and you have access to the elements.
var s = $(":contains('balloon')").not("script").filter(function() {
return (
$(this).clone() //clone the element
.children() //select all the children
.remove() //remove all the children
.end() //again go back to selected element
.filter(":contains('balloon')").length > 0)
}).length;
console.log(s)
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id='parent1'>
<p id='target1'>Red balloon</p>
<div id='target2'>Blue balloon</div>
</div>
<div id='parent2'>
<span id='target3'>Brown balloon</span>
</div>

Hide only on certain elements

I'm using a script that checks for any tag that also has a SRC="self". My function should function like this:
Check if img src="self"
If true, hide the parent div
If false, do nothing
Currently the function actually hides every img regardless of src. If I replace the jQuery hide() action then the function works perfectly. It just seems like it isn't quite performing the hide function like I anticipated.
function changeSourceAll() {
var images = document.getElementsByTagName('img');
for (var i = 0; i < images.length; i++) {
if (images[i].src.indexOf('self') !== -1) {
$(".redditThumbnail").hide();
}
else (){}
}
}
changeSourceAll();
Sample HTML is below. I have multiple .listrow div elements identical to this and the function removes all the .redditThumbnail divs.
<div class="listrow news">
<div class="newscontainer">
<div class="redditThumbnail"></div>
<div class="articleheader news">
<div class="actionmenu">
<p class="mediumtext floatleft alignleft">
author
</p>
<div id="redditUsername"></div>
<div class="floatright">
<div class="redditPermalink material-icons"></div>
</div>
</div>
<p class="redditTitle mediatitle news"></p>
</div>
</div>
</div>
Thanks!
You could use an attribute-equals selector to find all of the <img> elements that point to "self" and then hide their parents :
// Hide the closest thumbnail for elements that match this constraint
$('img[src="self"]').closest('.redditThumbnail');
Example
$(function() {
$('button').click(function(){
$('img[src="self"]').closest('.redditThumbnail').hide();
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class='redditThumbnail'>
A (has self)
<img src='self' />
</div>
<div class='redditThumbnail'>
B (doesn't have self)
<img src='self-test' />
</div>
<div class='redditThumbnail'>
C (has self)
<img src='self' />
</div>
<hr />
<button>Hide Self-Referencing Images</button>
The issue with hiding every img is because you select and hide all .redditThumbnail elements for every matching item. To fix this you could use this:
$(images[i]).closest('.redditThumbnail').hide();
However a better approach entirely would be to use filter() and find only the .redditThumbnail elements which match the requirements. Try this:
$('.redditThumbnail').filter(function() {
return $(this).find('img[src="self"]').length != 0;
}).hide();
You are hiding all: $(".redditThumbnail").hide();. I guess you should do something like $(images[i]).hide();

Categories