I have this HTML code:
<li class="_33c randomtext3" data-gt="{"alert_id":1576605904117859,"notif_type":"pub_comment","from_uids"}">
<li class="_33c randomtext5" data-gt="{"alert_id":1576605904117859,"notif_type":"year_comment","from_uids"}">
<li class="_33c randomtext4" data-gt="{"alert_id":1576605904117859,"notif_type":"group_comment","from_uids"}">
<li class="_33c randomtext7" data-gt="{"alert_id":1576605904117859,"notif_type":"pub_comment","from_uids"}">
<li class="_33c randomtext5" data-gt="{"alert_id":1576605904117859,"notif_type":"pub_comment","from_uids"}">
The order of the lines is varied, (using [2] doesn't work)
I want to delete the <li> with a certain text (data-gt="...group_comment..."), "group_comment" is the certain text (the line 3, sometimes it is on another line).
I tried with document.querySelectorAll('[data-gt]'); with a NodeList(5), but how to find in that NodeList the certain text?
Thank you.
Use the attribute value selector and wildcard selector.
document.querySelectorAll('li[data-gt*=group_comment]')
See https://www.geeksforgeeks.org/wildcard-selectors-and-in-css-for-classes/
const matches = document.querySelectorAll('[data-gt*="group_comment"]')
matches.forEach( x => x.classList.add("hidden") )
.hidden {
display: none;
}
<ul>
<li class="_33c randomtext3" data-gt="{"alert_id":1576605904117859,"notif_type":"pub_comment","from_uids"}"> pub_comment </li>
<li class="_33c randomtext5" data-gt="{"alert_id":1576605904117859,"notif_type":"year_comment","from_uids"}"> year_comment </li>
<li class="_33c randomtext4" data-gt="{"alert_id":1576605904117859,"notif_type":"group_comment","from_uids"}"> group_comment </li>
<li class="_33c randomtext7" data-gt="{"alert_id":1576605904117859,"notif_type":"pub_comment","from_uids"}">pub_comment</li>
<li class="_33c randomtext5" data-gt="{"alert_id":1576605904117859,"notif_type":"pub_comment","from_uids"}">pub_comment</li>
</ul>
You should use attribute selector combined with the contains modifier *
const commments = document.querySelectorAll('[data-gt*="group_comment"]')
You can see the different modifiers here: Attribute Selectors
Related
Let's say my code looks like that
const menu = document.querySelector(".menu");
//now i need to select <a> tags with 'design' and 'development', but using menu element i've already selected.
//const firstLineChilds = menu.querySelector(???);
<ul class="menu">
<li>Design</li>
<li>Development</li>
<li>
<ul class="sub-menu">
<li>DevOps</li>
<li>Managment</li>
</ul>
</li>
</ul>
Is it even possible to to this the 'clean way'? Or i just need to use menu.parentNode.querySelector(".menu > li > a")
You can chain querySelector and other such methods and it will search children of previous returned node: document.querySelector(".menu").querySelectorAll("a") or menu.querySelectorAll("a")
Converting the hrefs to an Array (in the snippet the spread syntax is used for that) enables you to filter them:
const relevantHrefs = [...document.querySelectorAll(".menu li a")]
.filter(href => ["Design", "Development"].find(h => href.textContent === h));
console.log(relevantHrefs);
// based on comment, this is maybe what OP needs
const menu = [...document.querySelectorAll(".menu > li:nth-child(-n+2) a")];
console.log(menu);
<ul class="menu">
<li>Design</li>
<li>Development</li>
<li>
<ul class="sub-menu">
<li>DevOps</li>
<li>Managment</li>
</ul>
</li>
</ul>
Yes, you can use :scope in conjunction with child combinators, in menu.querySelectorAll():
const menu = document.querySelector(".menu")
const firstLineChilds = menu.querySelectorAll(":scope > li > a");
console.log(firstLineChilds);
<ul class="menu">
<li>Design</li>
<li>Development</li>
<li>
<ul class="sub-menu">
<li>DevOps</li>
<li>Managment</li>
</ul>
</li>
</ul>
If you use descendant combinators, you'll still get the nested a elements, which is not what you want. See What does the ">" (greater-than sign) CSS selector mean?
Let's say that I have a nested <ul> that looks like this:
<ul>
<ul class="pizzatype">
<h1>Margherita</h1>
<li class="ingredient">Tomato sauce</li>
<li class="ingredient">Mozzarella</li>
<li class="ingredient">Origano</li>
</ul>
<ul class="pizzatype">
<h1>Spicy salamino</h1>
<li class="ingredient">Tomato sauce</li>
<li class="ingredient">Mozzarella</li>
<li class="ingredient">Salamino</li>
</ul>
<ul class="pizzatype">
<h1>Onion n' Tuna</h1>
<li class="ingredient">Tomato sauce</li>
<li class="ingredient">Mozzarella</li>
<li class="ingredient">Tuna</li>
<li class="ingredient">Onion</li>
</ul>
</ul>
And a script that console.log the childrens of class "pizzatype":
var pizzatype = document.querySelectorAll('.pizzatype');
console.log(pizzatype[1].children[3]);
The console.log at children[3] returns: <li class="ingredient">Salamino</li>
But I'm looking for a parameter that returns just Salamino
Anyone can help?
Also, is there any reference site that I can consult to find out which parameters can be asked, starting from the children function? Like children.text, children.value etc
Use textContent to get the text of an element
console.log(pizzatype[1].children[3].textContent);
What you're currently doing is pointing to the li element it's self. You need to target the text of this element.
You can do this by using .innerText. You can also use .innerHTML, which will return the text in raw format and won't automatically encode/decode text.
console.log(pizzatype[1].children[3].innerHTML);
I have an element like this
<ul>
<li data-ud="321" data-id="42">
<li data-ud="322" data-id="42">
<li data-ud="323" data-id="42">
<li data-ud="324" data-id="42">
<li data-ud="321" data-id="43">
<li data-ud="322" data-id="43">
<li data-ud="323" data-id="43">
<li data-ud="324" data-id="43">
<li data-ud="321" data-id="44">
<li data-ud="322" data-id="44">
<li data-ud="323" data-id="44">
<li data-ud="324" data-id="44">
<li data-ud="321" data-id="45">
<li data-ud="322" data-id="45">
<li data-ud="323" data-id="45">
<li data-ud="324" data-id="45">
</ul>
Now I want to select a element with data-id=45 and data-ud=322. I have tried but it didn't work.
Thanks in advance
To use 'and' in a selector, simply don't use any other separator, eg a li and class myclass would be:
li.myclass
to find by attribute, use [attribute=x], so to combine the two:
li[data-id=45][data-ud=322]
or, with jquery:
$("li[data-id=45][data-ud=322]")
This can be difficult to read and prone to errors eg a space between the two [][] will give a totally different result, so you can instead use filter to the same effect:
$("li").filter("[data-id=45]").filter("[data-ud=322]")
Fiddle example: https://jsfiddle.net/o9fdhphf/
Try the following:
$('li[data-id=45][data-ud=322 ]');
$("[data-ud=322][data-id=45]").text()
OR
$("[data-ud=321] + [data-id=45]").text()
JSFiddle
I have a portfolio site set up and I have my portfolio set up to shuffle through by selecting certain filters. What I want to do is set some header text, based upon which filter they choose.
The issues is when I select a link, let's say advertising, Advertising will show up as my header text. However if I select something else, say branding, it doesn't change, it stays at advertising.
here is my html
<div id="portfolio-filter-container">
<h2 class="workFilterSelect">FILTER OPTIONS: <span class="currentFilter">ALL</span></h2>
</div>
<ul id="portfolio-filter">
<!--<li class="workFilterSelect">FILTER OPTIONS:</li>-->
<li class="workFilterButtons">All</li>
<li class="workFilterButtons">Advertising</li>
<li class="workFilterButtons">Branding</li>
<li class="workFilterButtons">Catalog</li>
<li class="workFilterButtons">Corporate ID</li>
<li class="workFilterButtons">Consumer Relations</li>
<li class="workFilterButtons">Incentive/Loyalty</li>
<li class="workFilterButtons">Packaging</li>
<li class="workFilterButtons">Product Launch</li>
<li class="workFilterButtons">Promotion</li>
<li class="workFilterButtons">Public Relations</li>
<li class="workFilterButtons">Sales Support</li>
<li class="workFilterButtons">Social Media</li>
<li class="workFilterButtons">Tradeshows</li>
<li class="workFilterButtons">Web/Mobile</li>
</ul>
<div id="bottomWrapper">
and here is my script
$(document).ready(function(){
$(".workFilterButtons a").click(function(){
$(".currentFilter").replaceWith($(this).append());
});
});
by default the page is set to "ALL" when loaded, but as you can see I am trying to gett he dynamic text to work within the .currentFilter span
Any help would be greatly appreciated.
If you only want text you use text() method to both get and set. Also you don't want to replace the element or it won't be found again because it will no longer exist
Try
$(".workFilterButtons a").click(function(){
$(".currentFilter").text($(this).text());
});
You don't need to replace the element with the clicked <a> element (unless you really want to), all you need to do is update the text:
$(document).ready(function () {
$(".workFilterButtons a").click(function () {
// selecting the element with the class
// of 'currentFilter', and setting its
// text (using the text() method) to
// the textContent of the clicked <a>
// element:
$(".currentFilter").text(this.textContent);
});
});
$(document).ready(function() {
$(".workFilterButtons a").click(function() {
$(".currentFilter").text(this.textContent);
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="portfolio-filter-container">
<h2 class="workFilterSelect">FILTER OPTIONS: <span class="currentFilter">ALL</span></h2>
</div>
<ul id="portfolio-filter">
<!--<li class="workFilterSelect">FILTER OPTIONS:</li>-->
<li class="workFilterButtons">All
</li>
<li class="workFilterButtons">Advertising
</li>
<li class="workFilterButtons">Branding
</li>
<li class="workFilterButtons">Catalog
</li>
<li class="workFilterButtons">Corporate ID
</li>
<li class="workFilterButtons">Consumer Relations
</li>
<li class="workFilterButtons">Incentive/Loyalty
</li>
<li class="workFilterButtons">Packaging
</li>
<li class="workFilterButtons">Product Launch
</li>
<li class="workFilterButtons">Promotion
</li>
<li class="workFilterButtons">Public Relations
</li>
<li class="workFilterButtons">Sales Support
</li>
<li class="workFilterButtons">Social Media
</li>
<li class="workFilterButtons">Tradeshows
</li>
<li class="workFilterButtons">Web/Mobile
</li>
</ul>
<div id="bottomWrapper"></div>
JS Fiddle demo.
Incidentally, the reason your original code didn't work, and couldn't work, is because of this line:
$(".currentFilter").replaceWith($(this).append());
This replaced the selected element(s) with the clicked <a> element, which meant that, in future, the there was no .currentFilter element to replace or update.
On the other hand, if you want to put the clicked <a> element into the .currentFilter span-element, then you could try the following approach:
$(document).ready(function () {
$(".workFilterButtons a").click(function () {
// finding those <li> elements whose text, when trimmed
// (removing leading and trailing white-space) is equal
// to an empty string (''):
var emptyLi = $('.workFilterButtons').filter(function () {
return $(this).text().trim() === '';
}),
// caching the '.currentFilter' element(s):
currentFilter = $('.currentFilter'),
// checking for those elements in the
// currentFilter jQuery object that have
// a descendant <a> element, and finding
// length of that collection, and then
// checking that it's greater than 0:
hasA = currentFilter.has('a').length > 0;
// appending the contents of the currentFilter
// element into the found emptyLi element:
emptyLi.append(currentFilter.contents());
// if there are no <a> elements in the
// currentFilter element(s):
if (!hasA) {
// we replace the contents (textNode 'all')
// with the clicked <a> element:
currentFilter.contents().replaceWith(this);
} else {
// otherwise we append the clicked link to
// the currentFilter; this works because
// once we get to this stage the <a> element
// if it exists has already been moved back
// to the empty <li>, therefore we can't
// use '.contents().replace()' because
// there are no contents remaining by this point
// (and yes, this was incredibly counter-intuitive
// to me for quite a long time, which is why this
// update took a while):
currentFilter.append(this);
}
});
});
$(document).ready(function() {
$(".workFilterButtons a").click(function() {
var emptyLi = $('.workFilterButtons').filter(function() {
return $(this).text().trim() === '';
}),
currentFilter = $('.currentFilter'),
hasA = currentFilter.has('a').length > 0;
emptyLi.append(currentFilter.contents());
if (!hasA) {
currentFilter.contents().replaceWith(this);
} else {
currentFilter.append(this);
}
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="portfolio-filter-container">
<h2 class="workFilterSelect">FILTER OPTIONS: <span class="currentFilter">ALL</span></h2>
</div>
<ul id="portfolio-filter">
<!--<li class="workFilterSelect">FILTER OPTIONS:</li>-->
<li class="workFilterButtons">All
</li>
<li class="workFilterButtons">Advertising
</li>
<li class="workFilterButtons">Branding
</li>
<li class="workFilterButtons">Catalog
</li>
<li class="workFilterButtons">Corporate ID
</li>
<li class="workFilterButtons">Consumer Relations
</li>
<li class="workFilterButtons">Incentive/Loyalty
</li>
<li class="workFilterButtons">Packaging
</li>
<li class="workFilterButtons">Product Launch
</li>
<li class="workFilterButtons">Promotion
</li>
<li class="workFilterButtons">Public Relations
</li>
<li class="workFilterButtons">Sales Support
</li>
<li class="workFilterButtons">Social Media
</li>
<li class="workFilterButtons">Tradeshows
</li>
<li class="workFilterButtons">Web/Mobile
</li>
</ul>
<div id="bottomWrapper"></div>
JS Fiddle demo.
References:
JavaScript:
Node.textContent.
String.prototype.trim().
jQuery:
append().
click().
contents().
filter().
has().
replaceWith().
text().
I changed your class="currentFilter" to id="currentFilter" so now you won't need a .each() to do what you want to do, the selector selects only 1 element and not an array of 1 element.
Also changed replaceWith() with text(), and likewise append() replaced with text().
Here's a fiddle if you want to see it in action
https://jsfiddle.net/s6bpwycn/
I have the following HTML:
<ul id="sortable1 venuetags" class="connectedSortable">
<li id="venuetagli">fried</li>
<li id="venuetagli">garlic</li>
<li id="venuetagli">rosemary</li>
<li id="venuetagli">new potatoes</li>
</ul>
And am trying to get the values of each using JQuery:
$('#venuetagli').each(function(j,li) {
console.log(j,li)
})
However, from the console I am only getting the first value returned.
The ids are supposed to must be unique that is why you are getting single element use class selector instead. Also the id of UL would not have space.
Html
<ul id="sortable1 venuetags" class="connectedSortable">
<li class="venuetagli">fried</li>
<li class="venuetagli">garlic</li>
<li class="venuetagli">rosemary</li>
<li class="venuetagli">new potatoes</li>
</ul>
Javascript
$('.venuetagli').each(function(j,li) {
console.log(j,li)
});
You can simple get the li with ul using parent-child selector
$('#sortable1 li').each(function(j,li) {
console.log(j,li)
});
Just for the test and never recommended way, you can get elements having same id using attribute selector.
$('[id=venuetagli]').each(function(j,li) {
console.log(j,li);
});
Id must be assign to a single element in complete page else it will return only one of those element or unexpected result:
Here is demo with class
<ul id="sortable1 venuetags" class="connectedSortable">
<li class="venuetagli">fried</li>
<li class="venuetagli">garlic</li>
<li class="venuetagli">rosemary</li>
<li class="venuetagli">new potatoes</li>
</ul>
and jQuery:
$('.venuetagli').each(function(j,li) {
console.log(j,li)
})