I am writing a chrome extension where I working on a webpage which lists some things. So, basically, I am reading that table and doing some calculation in the javascript and showing them. Now, there is a filter option on the webpage. After filtering, it doesn't show some things on the list according to the filter selected. And it does so, by making the display as none. It makes the display as none by doing something like below:
[data-assignee]:not([data-aggr-assignees*="|xyz|"]) {
display: none;
}
So, when I am trying to find the elements whose display is not none to see the filtered items, it is giving all items since looks like it is not changing the CSS property of the items. I checked the style.display values of all the elements and it is coming '' for all. Can someone help me in how can I get the elements whose display is block in this kind of case?
You can query selector the whole document with * and go through each element with a for loop to check if its inline display property is set to none. Of course, this will only handle cases when the element is hidden with inline CSS.
<div style="display: block;">
DIV
</div>
<span style="display: none;"></span>
<script>
var allElems = document.querySelectorAll("*");
var visibleElems = [];
var hiddenElems = [];
for(let i = 0; i < allElems.length; i++){
if(allElems[i].style.display != "none"){
visibleElems.push(allElems[i]);
} else {
hiddenElems.push(allElems[i]);
}
}
console.log("Visible elements: "+visibleElems);
console.log("Hidden elements: "+hiddenElems);
</script>
If you want to check the display property of the elements from the CSS stylesheet, you will need to use window.getComputedStyle.
.hidden{
display: none;
}
<div style="display: block;">
DIV
</div>
<textarea class="hidden"></textarea>
<span style="display: none;"></span>
<style>
</style>
<div class="hidden">
</div>
<select class="hidden"></select>
<script>
var allElems = document.querySelectorAll("*");
var visibleElems = [];
var hiddenElems = [];
for(let i = 0; i < allElems.length; i++){
if(allElems[i].style.display == "none"||window.getComputedStyle(allElems[i], null).getPropertyValue("display")=="none"){
hiddenElems.push(allElems[i]);
} else {
visibleElems.push(allElems[i]);
}
}
console.log("Visible elements: "+visibleElems);
console.log("Hidden elements: "+hiddenElems);
</script>
Related
On my web page I want to 'hide' or 'unhide' several elements (C and F in this example) that are already inside a DIV element,
such as:
<div> Select A or B <span name='hide' > or C</span></div>
<div> Also select D or E <span name='hide' > or F</span></div>
(etc)
I use javascript to hide all 'hide' elements when the page is opened, except when the page is opened on localhost, than all is shown.
I do not necessarily know how many 'hide' elements there are (dynamically generated).
var hids=document.getElementsByName('hide');
if(hids!=null) {
for(var j=0; j< hids.length; j++) {
if(localhost==true) { // only if on localhost
hids[j].style.visibility='visible';
}
else hids[j].style.visibility='hidden';
}
}
But, the 'name' attribute is not valid for SPAN. When I use DIV instead of SPAN it messes up the format. How should I solve this properly?
Use class instead of name:
<span class="my-class"> or C</span>
and getElementsByClassName instead of getElementsByName:
document.getElementsByClassName("my-class");
If span doesn't have a name attribute, try with class name
var hids=document.getElementsByClassName('hide');
And change your html to
<div> Select A or B <span class='hide' > or C</span></div>
<div> Also select D or E <span class='hide' > or F</span></div>
You can use querySelectorAll to find by className hide
var localhost = false;
var hids = document.querySelectorAll('.hide');
if (hids != null) {
for (var j = 0; j < hids.length; j++) {
if (localhost) { // only if on localhost
hids[j].style.visibility = 'visible';
} else hids[j].style.visibility = 'hidden';
}
}
<div> Select A or B <span class='hide'> or C</span></div>
<div> Also select D or E <span class='hide'> or F</span></div>
(etc)
Resource
document.querySelectorAll()
Use data-XXX attribute instead of name, e.g.: <span data-name='hide'>
For sure, in this case, you will need to fetch them like this:
document.getElementsByTagName("data-name") and do another filtering based on the value of the data-name tag.
Im not sure the name property should be used here. I believe names are intended to be unique. So instead maybe through class name;
let localhost = true;
let hideList = document.getElementsByClassName("hide");
if (hideList != null) {
for (var j=0; j < hideList.length; j++ ) {
if (localhost === true) {
hideList[j].style.visibility = 'visible'
} else {
hideList[j].style.visibility = 'hidden'
}
}
}
As for the <div> messing up your formatting; thats likely due to a style property: display. <span>'s behave like display: inline; while <div>'s behave like display: block;. You can override this default behavior in your own CSS. Go ahead and turn those <spans>'s into <div>'s and apply some CSS:
<div> Select A or B <div class="hide"> or C</div></div>
<div> Also select D or E <div class="hide"> or F</div></div>
<style>
.hide {
display: inline;
}
</style>
The result should be visually identical to when using spans.
I'm trying to only show certain divs. The way I have decided to do this is to first hide all elements that start with "page" and then only show the correct divs. Here's my (simplified) code:
<form>
<input type="text" onfocus="showfields(1);">
<input type="text" onfocus="showfields(2);">
</form>
<div class="page1 row">Some content</div>
<div class="page1 row">Some content</div>
<div class="page2 row">Some content</div>
<div class="page2 row">Some content</div>
<script>
function showfields(page){
//hide all items that have a class starting with page*
var patt1 = /^page/;
var items = document.getElementsByClassName(patt1);
console.log(items);
for(var i = 0; i < items.length; i++){
items[i].style.display = "none";
}
//now show all items that have class 'page'+page
var item = document.getElementsByClassName('page' + page);
item.style.display = '';
}
</script>
When I console.log(items); I get a blank array. I'm pretty sure the regexp is right (get all items starting with 'page').
The code I'm using is old school JS, but I'm not adverse to using jQuery. Also if there is a solution that doesn't use regexp, that's fine too as I'm new to using regexp's.
getElementsByClassName only matches on classes, not bits of classes. You can't pass a regular expression to it (well, you can, but it will be type converted to a string, which is unhelpful).
The best approach is to use multiple classes…
<div class="page page1">
i.e. This div is a page, it is also a page1.
Then you can simply document.getElementsByClassName('page').
Failing that, you can look to querySelector and a substring matching attribute selector:
document.querySelectorAll("[class^=page]")
… but that will only work if pageSomething is the first listed class name in the class attribute.
document.querySelectorAll("[class*=page]")
… but that will match class attributes which mention "page" and not just those with classes which start with "page" (i.e. it will match class="not-page".
That said, you could use the last approach and then loop over .classList to confirm if the element should match.
var potentials = document.querySelectorAll("[class*=page]");
console.log(potentials.length);
elementLoop:
for (var i = 0; i < potentials.length; i++) {
var potential = potentials[i];
console.log(potential);
classLoop:
for (var j = 0; j < potential.classList.length; j++) {
if (potential.classList[j].match(/^page/)) {
console.log("yes");
potential.style.background = "green";
continue elementLoop;
}
}
console.log("no");
potential.style.background = "red";
}
<div class="page">Yes</div>
<div class="notpage">No</div>
<div class="some page">Yes</div>
<div class="pageXXX">Yes</div>
<div class="page1">Yes</div>
<div class="some">Unmatched entirely</div>
Previous answers contain parts of the correct one, but none really gives it.
To do this, you need to combine two selectors in a single query, using the comma , separator.
The first part would be [class^="page"], which will find all the elements whose class attribute begins with page, this selector is thus not viable for elements with multiple classes, but this can be fixed by [class*=" page"] which will find all the elements whose class attribute have somewhere the string " page" (note the space at the beginning).
By combining both selectors, we have our classStartsWith selector:
document.querySelectorAll('[class^="page"],[class*=" page"]')
.forEach(el => el.style.backgroundColor = "green");
<div class="page">Yes</div>
<div class="notpage">No</div>
<div class="some page">Yes</div>
<div class="pageXXX">Yes</div>
<div class="page1">Yes</div>
<div class="some">Unmatched entirely</div>
You can use jQuery solution..
var $divs = $('div[class^="page"]');
This will get all the divs which start with classname page
$(document).ready(function () {
$("[class^=page]").show();
$("[class^=page]").hide();
});
Use this to show hide div's with specific css class it will show/hide all div's with css class mention.
Please Note: I am looking for a Javascript only solution, jQuery will not help as I can't use it with the given application I am working within.
I have the following HTML in my DOM:
<div class="mktoFormRow">
<div class="mktoFieldDescriptor mktoFormCol" style="margin-bottom: 10px;">
<div class="mktoOffset" style="width: 10px;"></div>
<div class="mktoFieldWrap">
<label for="Agency__c" class="mktoLabel mktoHasWidth" style="width: 100px;">
<div class="mktoAsterix">*</div>Agency:</label>
<div class="mktoGutter mktoHasWidth" style="width: 10px;"></div>
<div class="mktoLogicalField mktoCheckboxList mktoHasWidth" style="width: 150px;">
<input name="Agency__c" id="Agency__c" type="checkbox" value="yes" class="mktoField">
<label for="Agency__c"></label>
</div>
<div class="mktoClear"></div>
</div>
<div class="mktoClear"></div>
</div>
<div class="mktoClear"></div>
I want to use Javascript to target the first label (in this example, the one with for="Agency__c") whenever the div with a class of mktoCheckboxList is present.
This is as far as I've been able to figure out in Javascript, but I'm at a loss. My thought process is to target the previous element before mktoCheckboxList by either by element type of label or its class of mktoLabel.
var checkboxes = document.getElementsByClassName('mktoCheckboxList');
var count = checkboxes.length;
for (i = 0; i < count; i++) {
console.log(checkboxes[i].previousElementSibling);
}
This solution needs to be agnostic of an actual name value, as I want this to work whenever a checkbox is presented without knowing what it's properties are, hence the use of the class / elements.
Here's my jsfiddle: http://jsfiddle.net/darcyvoutt/1y9s00k7/
document.querySelector is now supported by all major browsers (see can i use).
document.querySelector(".mktoCheckboxList label")
will select the first label it finds inside .mktoFieldDescriptor.
You can also do it on an element:
parent.querySelector("label");
If you need to check if a div contains a specific element before retrieving another you can do:
querySelectorAll(".mktoFieldDescriptor").filter(function(container){
// Remove the containers that do not contain .mktoCheckboxList.
return !!container.querySelector(".mktoCheckboxList");
}).map(function(container){
// Get the first label.
return container.querySelector("label")
}).forEach(function(label){
// Do your label stuff.
});
One possible solution would be:
var checkboxes = document.getElementsByClassName('mktoCheckboxList');
var count = checkboxes.length;
for (i = 0; i < count; i++) {
console.log(checkboxes[i].parentNode.querySelector('label'));
}
Please note that this solution will work only if you have a single .mktoCheckboxList element in the same div with the label.
Fiddle
Here's one possible approach:
Bind every input with it's label. Then lookup the input you need to work with, and get the label elem by that:
// Scan the page for labels:
var labels = document.getElementsByTagName('LABEL');
// Find the corresponding input:
for (var i = 0; i < labels.length; i++) {
if (labels[i].htmlFor != '') {
// Assign a reference to the label from the actual form element:
var elem = document.getElementById(labels[i].htmlFor);
if (elem)
elem.label = labels[i];
}
}
After that's done, you can easily do:
// Lookup all inputs:
var inputs = document.getElementsByTagName("input");
for (var i = 0, max = inputs.length; i < max; i++){
// Act only on checkboxes:
if (inputs[i].type === 'checkbox')
console.log(inputs[i]); // Look! It's the label!
}
Using this method you use nothing but the tag name input and type checkbox in order to locate your labels.
You could use document.evaluate and address the label you want via XPath. Untested:
//div[contains(#class, 'mktoCheckboxList')]/preceding::label[1]
In css I have set all the <hr> elements in my html to "display:none;" which works.
I have an onclick event listener set up to change the "display" to "block".
I use:
document.getElementsByTagName("hr").innerHTML.style.display = "block";
I get an error "Cannot read property 'style' of undefined".
Do it the following way:
var hrItems = document.getElementsByTagName("hr");
for(var i = 0; i < hrItems.length; i++) {
hrItems[i].style.display = 'block';
}
This is incorrect in two ways
getElementsByTagName gives you a list on elements and there is no method to operate on all elements, so you'll have to loop through all of them and add the required style individually.
innerHTML returns a string containing the mark up in an element but <hr> doesn't have any thing in it and the style property is on the <hr> itself.
var hrs = document.getElementsByTagName("hr");
for(var i = 0; i < hrs.length; i++) {
hrs[i].style.display = 'block';
}
Simple (and very effective) solution:
tag your body with a class-element
<body class="no_hr"> <article><hr/> TEXT Foo</article> <hr/> </body>
in css don't hide hr directly, but do
.no_hr hr {
display:none;
}
now define a second style in your css
.block_hr hr{
display:block;
}
in your buttons onClick, change the one and only body class from no_hr to block_hr
onclick() {
if ( document.body.className == "no_hr" ) {
document.body.className = "block_hr";
} else {
document.body.className = "no_hr";
}
}
This is a very charming solution, because you don't have to iterate over elements yourself, but let your browsers optimized procedures do their job.
For people who want a solution that doesn't require JavaScript.
Create an invisible checkbox at the top of the document and make sure that people can click on it.
<input type="checkbox" id="ruler"/>
<label for="ruler">Click to show or hide the rules</label>
Then tell the stylesheet that the <hr>s should be hidden by default, but should be visible if the checkbox is checked.
#ruler, hr {display:none}
#ruler:checked ~ hr {display:block}
Done. See fiddle.
getElementsByTagName() returns a node list, and therefore you must iterate through all the results. Additionally, there is no innerHTML property of an <hr> tag, and the style must be set directly on the tag.
I like writing these types of iterations using Array.forEach() and call:
[].forEach.call(document.getElementsByTagName("hr"), function(item) {
item.style.display = "block";
});
Or, make it even easier on yourself and use jQuery:
$("hr").show();
<div __jx__id="___$_15" style="position: absolute; overflow: hidden;">
I would like to modify the above div by adding display:block to the style using javascript
<div __jx__id="___$_15" style="display:block;position: absolute; overflow: hidden;">
I tried using
function getAllElementsWithAttribute(attribute)
{
var matchingElements = [];
var allElements = document.getElementsByTagName('*');
for (var i = 0; i < allElements.length; i++)
{
if (allElements[i].getAttribute(attribute))
{
// Element exists with attribute. Add to array.
matchingElements.push(allElements[i]);
}
}
return matchingElements;
}
getAllElementsWithAttribute('__jx__id="___$_15);
adapted from
Get elements by attribute when querySelectorAll is not available without using libraries?
the selector itself is not working let alone add the additonal display:block to the div
The name of your attribute is __jx__id and the value is ___$_15.
so try: getAllElementsWithAttribute("__jx__id");
If you also want to filter by the value of the attribute then you'll need to pass it in seperately: getAllElementsWithAttributeAndValue("__jx__id", "___$_15");
A lot easier with jQuery:
$("div[__jx__id]").css({display:block});
or even
$("div[__jx__id]").show();