How to detect HTML hidden Attribute with pure javascript - javascript

I'm working in the analytics field and most of the time I'm using CSS selector to solve my issue. Right now I'm working on a website were I need to detect if a <p> element is hidden or not. so here is the two possible situation :
<p namehere hidden>This paragraph should be hidden.</p>
<p namehere This paragraph should be hidden.</p>
What's the most simple way to return a boolean regarding the hidden status of the <p> element ?
Thanks !

Probably the quickest and simplest way to achieve this is the following
var elements = document.querySelectorAll('p:not([hidden])');
Fabio

You could catch all the p elements with getElementsByTagName function, iterate over them and check if specified element has hidden attribute different than null.
Note: If hidden attribute is null - element has no hidden attribute.
var elems = document.getElementsByTagName('p');
Array.from(elems).forEach(function(v,i) {
if (v.getAttribute('hidden') == null) {
console.log(v);
}
});
<p namehere hidden>This paragraph should be hidden.</p>
<p namehere>This paragraph should be hidden.</p>

You're looking for getAttribute. In this case, getAttribute would return null if there's no attribute or '' if there was one.
You can iterate over tags like so:
var paragraphs = document.getElementsByTagName("p");
for(var i = 0; i < paragraphs.length; i++){
if(paragraphs[i].getAttribute("hidden") !== null){
// The paragraph is hidden and can be accessed with paragraphs[i]
console.log(paragraphs[i].innerHTML + ' is hidden');
} else {
// The paragraph not is hidden and can be accessed with paragraphs[i]
console.log(paragraphs[i].innerHTML + ' is not hidden');
}
}
<p>Paragraph 1</p>
<p hidden>Paragraph 2</p>
<p>Paragraph 3</p>

Quite an old question, but... Methods described here don't seem to be
"(...) the most simple way to return a boolean regarding the hidden
status of the element (...)"
While getting all <p> element is necessary, using getAttribute() method is NOT. Instead, simply test the hidden attribute from the element object:
Just returning a boolean related to the hidden attribute: (Array.from() syntax)
Array.from(
document.getElementsByTagName("p"),
element => console.log(element.hidden)
);
<p namehere hidden>This paragraph should be hidden.</p>
<p namehere>This paragraph should be hidden.</p>
If you want to do an action depending on the boolean return, you should prefer this syntax:
//Using forEach() method instead of map() for better loop handling
Array
.from(document.getElementsByTagName('p'))
.forEach( element => {
if(element.hidden){
console.log("This element is hidden.");
}else{
console.log("This element is not hidden");
}
}
);
<p namehere hidden>This paragraph should be hidden.</p>
<p namehere>This paragraph should be hidden.</p>
Eventually, no getAttribute() method, no comparison operator, only boolean property check. Sounds more straightforward IMHO.
Ref : HTMLElement.hidden property (MDN)

If you are working with Jquery you can directly use hasClass function.
Jquery hasClass
If you are looking for pure javascript you can use this function
function hasClass(element, className) {
return new RegExp(' ' + className + ' ').test(' ' + element.className + ' ');}

Related

How to use 1 id for everything instead of 3 (for the following code)

I have the following html (it's a card) where a class is added to change the look of it:
<div class="card-small-half" id="card-1">
<a href="components/">
<div class="action-bar">
<p>Add Page</p>
<i class="material-icons">add</i>
</div>
</a>
</div>
and a switch made with a label that checks and unchecks an input type checkbox:
<div class="switch-wrapper" id="switch-wrapper-1">
<input type="checkbox" id="input-1" class="display-none">
<label class="switch" for="input-1"></label>
<p id="switch-caption-1">Visible</p>
</div>
With the following Javascript I add a class called "card-disabled" to the card:
window.onload = function () {
function check() {
if (document.getElementById("input-1").checked) {
document.getElementById("switch-caption-1").textContent = "Disabled";
$('#card-1').addClass('card-disabled');
} else {
document.getElementById("switch-caption-1").textContent = "Visible";
$('#card-1').removeClass('card-disabled');
}
}
document.getElementById('input-1').onchange = check;
check();
}
I know in css you can call id's or classes like so:
#switch-wrapper-1 input { /* styles */ }
or
#switch-wrapper-1 p { /* styles */ }
How can I do this with javascript, so I don't have to use an id for every element and instead use a global id for every wrapper.
EDIT:
The wrapper and input id's are unique! I want to call the paragraph inside the unique wrapper element something like this:
document.getElementById("switch-wrapper-1 p").textContent = "Disabled";
The 'p' here means paragraph
Is this possible and if so: how?
Query Selector is your friend here. You can use CSS selectors to retrieve DOM elements. In your case this call would return the first paragraph child in the #switch-wrapper-1 element.
var node = document.querySelector('#switch-wrapper-1 p');
If you also use jQuery, then as suggested in comments, you can simply use the $ function.
var $node = $('#switch-wrapper-1 p');
To select an individual element inside of an element with a specific ID using Javascript you can do:
document.getElementById('hello').getElementsByTagName('input')[0];
So in your example it would be:
document.getElementById('switch-wrapper-1').getElementsByTagName('input')[0].onchange = check;
The [0] is used because getElementsByTagName returns an array of all the child elements inside the parent element with the specified tag. Note that you will have to keep the unique ID on the input field if you want the for attribute on the label to function correctly.

How to get class name of element has specific text using javascript/jquery?

I need a JavaScript or jQuery way of extracting the Class name of DIV element by the text it contains.
Let's illustrate. If I had let's say following code:
<div class="_className">UniqueText</div>
I need to to know how to programmatically do something like this:
getClassNameWhereText("UniqueText");
In this case output should be:
_className
Is there a way to do this?
JQuery :contains selector select element has specific text but it isn't exact. For example
$("div:contains(UniqueText)")
Select both of bottom divs
<div class="_className">UniqueText</div>
<div class="_className2">UniqueText2</div>
You can use .filter() to filter selected element by text.
var className = $("*").filter(function(){
return $(this).text() == "UniqueText";
}).attr("class");
var className = $("*").filter(function(){
return $(this).text() == "UniqueText";
}).attr("class");
console.log(className);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="_className">UniqueText</div>
<div class="_className2">UniqueText2</div>
By getting all the div with each function you can search through all the divs and place a condition in which you the value of the div is equal to the particular text that you want to find. Then get the class name by using .attr('class').
$( "div" ).each(function(){
if($(this).text() == "UniqueText"){
var output = $(this).attr('class');
$(".output").html(output);
}
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="_classname">UniqueText</div>
<div class="output"></div>
It might be a bit long for a code but it gets the work done nicely. :)
You can use :contains(word)
var className = $( "div:contains('John')" ).attr("class");
console.log(className)
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="foo">John Resig</div>
<div class="bar">George Martin</div>
<div class="foo">Malcom John Sinclair</div>
<div class="baz">J. Ohn</div>
You can keep an id for your div, as per your information your text will be unique.
<div id="UniqueText" class="_className">UniqueText</div>
and the js code will be
function getClassNameWhereText(text){
var className = $('#'+text).attr('class');
console.log(className);
}
UPDATE : if you want to using contains
then you can do this,
function getClassNameWhereText(text){
var val = document.getElementById(text).value;
if(text.indexOf(val)>=0){
var className = $('#'+text).attr('class');
console.log(className);
}
}
This should be faster than using jQuery (but a bit more to type):
var xpath = "//div[text()='UniqueText']";
var result = document.evaluate(xpath,
document, null, XPathResult.FIRST_ORDERED_NODE_TYPE);
var node = result.singleNodeValue;
if (node) {
console.log(node.className);
} else {
console.error("Not found!");
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="_className">UniqueText</div>
The reason is, browser's CSS selectors don't support :contains selector, and jQuery needs to emulate it by checking every node matching the rest of the selector. Ditto for using .filter. But XPath is done natively by the browser.
You also cannot specify exact match using the jQuery :contains, like here. If substring matching was indeed needed, you can change the XPath:
var xpath = "//div[contains(text(),'UniqueText')]";
XPath is very powerful, but a bit finicky and largely unknown, so I find it is very under-utilised, even when its use would be a perfect fit.

How to replace text in multiple divs according conditional?

I need to replace the text of many divs, where according to the text of each div, put a text or another.
Example: If the text is 0, replace it with "no quota" and if it is different from 0, put "Yes it has".
Html code:
<div><p id="text">1</p></div>
<div><p id="text">0</p></div>
<div><p id="text">1</p></div>
JS code:
$('#text').text(function(){
if($(this).text() == '0')
{
$(this).text('No quota');
}
else
{
$(this).text('"Yes it has');
}
});
But only changes the first element and the others left with the same text.
As I can change the text for each item? Greetings from Chile.
you have multiple instances of the same id. each id needs to be unique - which is why its only affecting the first item. Change the id to a class and you will be able to change each p to the new text. Also spotted a typo in the last else text (correctedin the code below).
<div><p class="text">1</p></div>
<div><p class="text">0</p></div>
<div><p class="text">1</p></div>
$('.text').each(function(){
if($(this).text() == '0')
{
$(this).text('No quota');
}
else
{
$(this).text('Yes it has');
}
});
ID is to be used as unique identification number hence only first item changed. Change ID to CLASS should solve the issue.
There are two problems.
First, as others have noted, you should be using a class instead of ID if you want to match multiple elements.
Second, when you give a function argument to .text(), it receives the old text as an argument, and should return the new text rather than calling .html() within it. So it should be:
$('.text').text(function(i, oldtext) {
return oldtext == '0' ? 'No quota' : 'Yes it has';
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div><p class="text">1</p></div>
<div><p class="text">0</p></div>
<div><p class="text">1</p></div>

Iterate over every element and get only the content that is directly in the node

let's assume I have this code
<p>FirstLevelP
<span>SecondLevelSpan</span>
</p>
<p>FirstLevelP
<span>SecondLevelSpan
<p>ThirdLevelP</p>
</span>
</p>
Is it possible to iterate through every element that I have right now, but only get the content, that's in the direct node of it, modify the text and then have it in the original content?
Example, If I go through every $('p').each and would extract the text I would also get the text inside the span.
Basically this:
FirstelElement: FirstLevelPSecondLevelSpan
SecondElement: SecondLevelSpanSecondLevelSpanThirdLevelP
But I want to have it like this
FirstelElement: FirstLevelP
SecondElement: SecondLevelSpan
ThirdElement: FirstLevelP
FourthElement: SecondLevelSpan
FifthElement: ThirdLevelP
Is this possible?
In my research I already found this answer here
$("#foo")
.clone() //clone the element
.children() //select all the children
.remove() //remove all the children
.end() //again go back to selected element
.text();
But this would only solve half of my problems. I would still need to modify the text in the original content! Thanks in advance guys.
EDIT FOR CLARIFICATION
So basically, want I want to achieve is something like this:
For every element, I want to check if there is a dot at the end. If not I want to add one. I already managed to do this for headlines, like this:
foreach (pq($content)->filter(':header') as $headline) {
if (substr(pq($headline)->text(), 0, -1) != '.') {
$content = preg_replace('#(' . pq($headline) . ')#', pq($headline) . '.', pq($content));
}
}
The problem, as I stated, is, that when I have nested elements it would add the dot after the whole element, and not after each sub element if neccessary.
To work with my "assumed" code, it should look like this
<p>FirstLevelP.
<span>SecondLevelSpan.</span>
</p>
<p>FirstLevelP.
<span>SecondLevelSpan.
<p>ThirdLevelP.</p>
</span>
</p>
But unfortunatley, it currently looks like this
<p>FirstLevelP
<span>SecondLevelSpan</span>.
</p>
<p>FirstLevelP
<span>SecondLevelSpan
<p>ThirdLevelP</p>
</span>.
</p>
Note the dots.
finding and changing text without child elements works this ways:
// search every element
$("body *").each(function(index, el) {
// find first text node
var node = $(el).contents().filter(function() {
return this.nodeType === 3;
})[0];
// change text
node.textContent = "new text";
});
Edit, Updated
Try
$("body *").each(function (i, el) {
if ($(el).is("p, span")) {
$(el).text(function (idx, text) {
var t = text.split("\n")[0];
// if `text` string's last character is not `.`
// concat `.` to `text` string ,
// return `text` original string's with `.` added
return t.slice(-1) !== "." ? t + "." : t
})
}
})
$("body *").each(function (i, el) {
if ($(el).is("p, span")) {
$(el).text(function (idx, text) {
var t = text.split("\n")[0];
return t.slice(-1) !== "." ? t + "." : t
})
}
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<p>FirstLevelP
<span>SecondLevelSpan</span>
</p>
<p>FirstLevelP
<span>SecondLevelSpan
<p>ThirdLevelP</p>
</span>
</p>

How to use jquery to select all elements that have two specific attributes

I have some markup where a lot of id's have an id attribute, as well as innerText. I want to select each of these elements, performing a function on the id.
How do I do that?
Something like this?
$('[id]:not(:empty)').each(function(i, el) {
// do stuff
});
Give them a common class:
HTML
<div id="first" class="all"></div>
<div id="second" class="all"></div>
<div id="third" class="all"></div>
jQuery
$('div.all').each(function(index){
processid(this.id);
});
If you are talking about selecting elements whose id (or some permutation of it) is included in its text then
$('[id]').filter(function(){
return $(this).text().indexOf( this.id ) >= 0; // the this.id should be altered to match the permutation you seek ..
}).css('color','red'); // turn those to red
After you comment to #lonesomeday (at the question comments) here is what to do ..
$('[id]').each(function(){
processid(this.id);
});
First select by a regular ID selector and then loop over that selection by filtering .text() non-empty.
$("[id]").each(function() {
if ($(this).text() != "") {
// do stuff
}
});

Categories

Resources