how to find out the element which does not contain any class? - javascript

How to find out the element which does not contain any class?
<p>You will receive the ebook in your email</p>
<p class="active">You will NOT receive the ebook in your email</p>
I want to find the paragraph element which does not contain any class.
Sample code is much appreciated.
Keep Coding...

You can use the :not() pseudo class:
let matches = document.querySelectorAll('p:not([class])');
for (let p of matches) {
console.log(p.textContent);
}
<p>You will receive the ebook in your email</p>
<p class="active">You will NOT receive the ebook in your email</p>
If you want to also match elements that have the class attribute, but which is still empty, then add that in the selector: p:not([class]), p[class=""]. Of course, you can then also think of a class attribute that has just space(s), ...etc.

You could filter your paragraphs by the length of their classList
var allParagraphs = Array.from(document.querySelectorAll("p")).filter(({classList}) => classList.length === 0)
console.log(allParagraphs)
//for older browsers
var allP = [];
document.querySelectorAll("p").forEach(function(el) {
if(el.classList.length === 0) allP.push(el);
})
console.log(allP);
<p>no class</p>
<p>nope</p>
<p class="df">öldskjf</p>
<p class="ölsdf">slkdf </p>

Related

Excluding inner tags from string using Regex

I have the following text:
If there would be more <div>matches<div>in</div> string</div>, you will merge them to one
How do I make a JS regex that will produce the following text?
If there would be more <div>matches in string</div>, you will merge them to one
As you can see, the additional <div> tag has been removed.
I would use a DOMParser to parseFromString into the more fluent HTMLDocument interface to solve this problem. You are not going to solve it well with regex.
const htmlDocument = new DOMParser().parseFromString("this <div>has <div>nested</div> divs</div>");
htmlDocument.body.childNodes; // NodeList(2): [ #text, div ]
From there, the algorithm depends on exactly what you want to do. Solving the problem exactly as you described to us isn't too tricky: recursively walk the DOM tree; remember whether you've seen a tag yet; if so, exclude the node and merge its children into the parent's children.
In code:
const simpleExampleHtml = `<div>Hello, this is <p>a paragraph</p> and <div>some <div><div><div>very deeply</div></div> nested</div> divs</div> that should be eliminated</div>`
// Parse into an HTML document
const doc = new DOMParser().parseFromString(exampleHtml, "text/html").body;
// Process a node, removing any tags that have already been seen
const processNode = (node, seenTags = []) => {
// If this is a text node, return it
if (node.nodeName === "#text") {
return node.cloneNode()
}
// If this node has been seen, return its children
if (seenTags.includes(node.tagName)) {
// flatMap flattens, in case the same node is repeatedly nested
// note that this is a newer JS feature and lacks IE11 support: https://caniuse.com/?search=flatMap
return Array.from(node.childNodes).flatMap(child => processNode(child, seenTags))
}
// If this node has not been seen, process its children and return it
const newChildren = Array.from(node.childNodes).flatMap(child => processNode(child, [...seenTags, node.tagName]))
// Clone the node so we don't mutate the original
const newNode = node.cloneNode()
// We can't directly assign to node.childNodes - append every child instead
newChildren.forEach(child => newNode.appendChild(child))
return newNode
}
// resultBody is an HTML <body> Node with the desired result as its childNodes
const resultBody = processNode(doc);
const resultText = resultBody.innerHTML
// <div>Hello, this is <p>a paragraph</p> and some very deeply nested divs that should be eliminated</div>
But make sure you know EXACTLY what you want to do!
There's lots of potential complications you could face with data that's more complex than your example. Here are some examples where the simple approach may not give you the desired result.
<!-- nodes where nested identical children are meaningful -->
<ul>
<li>Nested list below</li>
<li>
<ul>
<li>Nested list item</li>
</ul>
</li>
</ul>
<!-- nested nodes with classes or IDs -->
<span>A span with <span class="some-class">nested spans <span id="DeeplyNested" class="another-class>with classes and IDs</span></span></span>
<!-- places where divs are essential to the layout -->
<div class="form-container">
<form>
<div class="form-row">
<label for="username">Username</label>
<input type="text" name="username" />
</div>
<div class="form-row"
<label for="password">Password</label>
<input type="text" name="password" />
</div>
</form>
</div>
Simple approach without using Regex by using p element of html and get its first div content as innerText(exclude any html tags) and affect it to p, finally get content but this time with innerHTML:
let text = 'If there would be more <div>mathces <div>in</div> string</div>, you will merge them to one';
const p = document.createElement('p');
p.innerHTML = text;
p.querySelector('div').innerText = p.querySelector('div').innerText;
console.log(p.innerHTML);

Javascript remove text from a class

I need to remove the text 'at' from this title.
<p>Marge Makes Pancakes Email at</p>
The text in this title is dynamically created so I can't change the whole thing.
I tried using this but it doesn't work.
<script>var elements=document.getElementsByClassName("spotlight__title");elements[0].innerHTML=elements[0].innerHTML.replace(/at/g,"");</script>
You need to iterate over collection returned from getElementsByClassName.
var elements = document.getElementsByClassName("spotlight__title");
Array.from(elements).forEach( element =>
element.innerHTML = element.innerHTML.replace(/at/g,"")
)
You can use querySelectorAll to find all elements by using a CSS Selector and then iterate over them to replace text according to your regex.
function replaceText(target, re, newText) {
document.querySelectorAll(target).forEach(function(element) {
element.textContent = element.textContent.replace(re, newText).trim();
});
}
replaceText('.spotlight__title', /at$/g, '');
<p>
Marge Makes Pancakes Email 1 at
</p>
<p>
Marge Makes Pancakes Email 2 at
</p>
<p>
Marge Makes Pancakes Email 3 at
</p>

How to display just one element with same id

This is my first question at stack overflow
i just wanted to know a simple solution for the following case
<div *ngFor="let d of w.event">
<div class="date" id="d.date" >
<p>
<span style="font-size:1.75em">{{d.date | date:'dd'}}</span>
<br>
<strong> {{d.date | date:'EEE'}}</strong>
</p>
</div>
the looped div can have the same id
I just want to display the first div with a particular date and ignore the rest
can this be achieved with CSS or JavaScript
You can't use the same id on two elements. It's one of the few restrictions on ids.
You can use a class:
<div class="show">Yes</div> <div class="show">No</div>
...and then show either the first or second by using index 0 or index 1 after getting a list of matching elements:
var list = document.querySelectorAll(".show");
list[0].style.display = "none"; // Hides the first one
// or
list[1].style.display = "none"; // Hides the second one
Some other thoughts:
1. Rather than using style.display as I did above, you might add a class that hides the element.
2. You might use separate ids (or classes) for the elements so you don't need to index, e.g.:
<div id="show-yes">Yes</div> <div id="show-no">No</div>
then
document.getElementById("show-yes").style.display = "none";
// or
document.getElementById("show-no").style.display = "none";
On all browsers in my experience, you can do the first thing above (with querySelectorAll) with your invalid HTML with a selector like "[id=show], but don't. Fix the HTML instead.
In your question update, you show:
<div *ngFor="let d of w.event">
<div class="date" id="d.date" >
...
You've said you're aware of the fact you can't have multiple elements with the same id, so why code that? You can easily give them unique ids:
<div *ngFor="let d of w.event; let i = index">
<div class="date" id="d.date{{i}}" >
...
First of all, in HTML ID is a unique selector so one ID can be associate with only one element. if you want to achieve your desired functionality you have to assign different id for both DIV. and use javascript to hide and show DIV
<div id="showYes">Yes</div> <div id="showNo">No</div>
If you want to show one at a time you can go with *ngIf , as it will show only one at a time
<div id="show" *ngIf='your_status'>Yes</div>
<div id="show" *ngIf='!your_status'>No</div>
After your question update , you can create custom filter that will only return unique date , so only first unique date will be shown
// CREATE A PIPE FILTER :
import { Pipe, PipeTransform } from '#angular/core';
#Pipe({name: 'checkUniqueDate'})
export class UniqueDatePipe implements PipeTransform {
transform(dataArray) {
let dates = [];
return dataArray.filter(data => {
return if(dates.indexOf(data.date) === -1) {
dates.push(data.date);
return true;
} else {
return false;
}
});
}
}
// TEMPLATE SIDE :
<div *ngFor="let d of (w.event | checkUniqueDate )">
Add the date in class also, then you can try below code
.YOUR_DATE{
display:none
}
.YOUR_DATE:first-child{
displany:inline
}

Get innerHTML from same tags

I am having a trouble for fetching innerHTML of the following two strong tags
<div>
<strong>data 1</strong>
<span class="and">and</span>
<strong>data 2 </strong>
</div>
<div>
<strong>data 3</strong>
<span class="and">and</span>
<strong>data 4 </strong>
</div>
i want to get data1, data2 in console but i'm unable to achieve anything.
I have tried document.querySelector("strong") but it just provide me data1.
How can i fetch data2 data3 & data4 from other strong tag?
Any help is appreciated.
i know i can do
document.getElementsByTagName("strong")['increment_operator'].innerHTML;
and
document.querySelectorAll("strong");
querySelector finds the first result and stop searching whereas querySelectorAll finds all.
Try code below to log html of strong tag:
var elems = document.getElementsByTagName('strong');
for (i=0;i < elems.length;i++{
console.log(elems[i].innerHTML)
}
To get innerHTML of the last strong tag in html run code below:
var elems = document.getElementsByTagName('strong')[:1];
console.log(elems[elems.length-1].innerHTML);
If you have same tag and you want specific tag innerHTML then give unique ids and then try to fetch or if you want to fetch all strong tag innerhtml then use queryselectorall()
As example
<div>
<strong>data 1</strong>
<span class="and">and</span>
<strong>data 2 </strong>
</div>
<div>
<strong>data 3</strong>
<span class="and">and</span>
<strong>data 4 </strong>
</div>
var a = document.querySelectorAll("strong");
for (var i = 0; i < a.length; i++) {
alert(a[i].innerHTML);
}
Summing up the partials:
The document.querySelector(commaSeperatedStringOfSelectors) only finds the first node in the documentsatisfying the selectors it is given. So you need to be more specific with it, need to supply some queryable selectors to your html elements, like id class.
But if you want to select more widely follow:
document.querySelectorAll(commaSeperatedStringOfSelectors) to get an array of all the nodes satisfying the selectors. Then you can select the element you need by index. fiddle
Or you need to use #Andriy Ivaneyko's answer style, use getElementByTagName('tagname'), getElementsByClassName('class'), or getElementById('id').
Note: document.querySelectorAll(commaSeperatedStringOfSelectors) is more versatile, it gives you opportunity to be both more specific or more unspecific. You can use a string like that in it: 'strong, div.animals, a'.
Ok i did my job by doing following.
var divLength = document.getElementsByTagName("div").length;
var z = 0;
for(i=0; i<divLength; i++){
var dataFromFirstStrong = document.getElementsByTagName("strong")[z].innerHTML;
z++;
var dataFromSecondStrong = document.getElementsByTagName("strong")[z].innerHTML;
z++;
}

Last id of an Element Javascript

How can i read the last element id using javascript?
for example :
<div id='print'>
<p id=1>some data</p>
<p id=2>some data</p>
<p id=3>some data</p>
<p id=4>some data</p>
<p id=5>some data</p>
</div>
I need to detect the id of last
I need max number of the id actually.it's generated sequentially.
First off, id values cannot be numbers. They must start with a non-number.
You can get the last child with this plain javascript (no jQuery required):
var lastChild = document.getElementById("print").lastChild;
var lastChildID = lastChild.id;
or in one line, it would be this:
var lastChildID = document.getElementById("print").lastChild.id
FYI, in case you need access to any other children you can always get all the children and then fetch the one you want:
var children = document.getElementById("print").children;
if (children.length > 1) {
var first = children[0];
var last = children[children.length - 1];
var second = children[1];
}
Now that you've explained what you're really trying to do, I'd suggest this:
<div id='print'>
<p data-num="1">some data</p>
<p data-num="2">some data</p>
<p data-num="3">some data</p>
<p data-num="4">some data</p>
<p data-num="5">some data</p>
</div>
And, then this javascript:
var lastValue = document.getElementById("print").lastChild.getAttribute("data-num");
Using the data-xxx format is forward compatible with the HTML5 specification and usable in older browsers with getAttribute().
Try this:
getElementById('print').lastChild.id;
If you use jQuery you could do something like this $("div#print :last-child").attr('id')
In jQuery you can simply use their selectors to find this:
$("p").last().attr("id");
Try this way:-
$('p:last').attr('id')
OR
$('div#print p:last').attr('id')

Categories