if element is displayed > hide all elements underneath it (plain JS) - javascript

My goal is to detect if my element is displayed firstly; I guess narrowed down to display: block;.
If it is; I'd like to iterate through all the elements underneath it within the document to add classes to them. The elements are dynamic; so I just need to add a common selector so that I can hide them (or display: none;) them - when my first element's display: block; is met.
Below is what I have; I'm mainly wondering how to detect if elements are underneath #banner > if so add a common selector (class) to them so that I can then hide (display:none;)
function CheckIfExistThenHideBelow () {
var inElgbl = document.getElementById('banner');
if (typeof(inElgbl) != 'undefined' && inElgbl != null)
{
// How to check if below element inElgbl in doc?
var divsToHide = document.getElementsByClassName("below");
for(var i = 0; i < divsToHide.length; i++){
divsToHide[i].style.display = "none";
}
}

This is simpler than you think. Just loop over the target element's siblings that come after it and hide each by applying a class.
function removeSiblingsAfter(someElement){
// Check some element to see if it is currently being displayed as a block
if(getComputedStyle(someElement).display === "block"){
// Begin looping while there is a next sibling that is an element
while(someElement.nextElementSibling){
// Adjust the looping variable to be the next sibling
// so that the loop can eventually end
someElement = someElement.nextElementSibling;
someElement.classList.add("hidden"); // Hide each sibling
}
}
}
removeSiblingsAfter(document.getElementById("sampleTarget"));
.hidden { display:none; }
<div>Sibling Before<div>
<div id="sampleTarget">Target Element</div>
<div>Sibling After</div>
<div>
Sibling After
</div>
<div>Sibling After</div>

Related

How do I toggle DOM elements to show and hide

On my index.JS file, I created elements using documentCreateElement and appended them to the DOM to show data from an api. Then I created an event listener which works where if I click my H3 element, it will show my H4 and P element. But I want it to where if I click my H3 element again, I want the H4 and P elements to hide. This is the code I have for my click event listener:
`H3.addEventListener(‘click’, clickFunction)
Function clickFunction() {
Div.append(h4)
Div.append(p)
}`
Can someone please help me?
I tried to look up toggling functions online or incorporate CSS hidden class to the h4 and p elements but nothing was hiding
Try modifying your clickFunction() to check if the elements are already displayed or not.
let isDisplayed = false;
function clickFunction() {
if (isDisplayed) {
// If the elements are already displayed, hide them
h4.style.display = "none";
p.style.display = "none";
isDisplayed = false;
} else {
// If the elements are not displayed, show them
div.appendChild(h4);
div.appendChild(p);
isDisplayed = true;
}
}
h3.addEventListener("click", clickFunction);
In above example, its a boolean variable isDisplayed to keep track of whether the elements are currently displayed or not. When the h3 element is clicked, the clickFunction() is called, and it checks the value of isDisplayed. If its true, it means the elements are already displayed, so we hide them by setting their display style to "none" and setting isDisplayed to false. If it's false, it means the elements are not displayed, so we show them by appending them to the div and setting isDisplayed to true.
Note that you'll need to deeclare the isDisplayed variable outside of the clickFunction() so that its value is preserved between function calls. And make sure to select the h4, p, and div elements using document.querySelector() or a smilar method before using them in the function.
You can try this in your clickFunction
Function clickFunction() {
if(!Div.hasChildNodes()) {
Div.append(h4)
Div.append(p)
} else {
Div.removeChild(Div.childNodes(0))
Div.removeChild(Div.childNodes(1))
}
}
Check this for more info.
Follow the below steps-
Find the existing p and h4 elements.
If found then remove those using the removeChild method, else append those using the append method.
Here is a working demo of toggling the elements-
let h3 = document.querySelector('h3');
h3.addEventListener('click', clickFunction)
let div = document.querySelector('div');
function clickFunction() {
// Find already exists p and h4 elements
let p_exists = document.querySelector('p');
let h4_exists = document.querySelector('h4');
// If found then remove one by one
if (p_exists && h4_exists) {
div.removeChild(h4_exists);
div.removeChild(p_exists);
}
// Else, create and append
else {
let h4 = document.createElement('h4')
h4.innerText = "I am a h4 element";
let p = document.createElement('p')
p.innerText = "I am a p element";
div.append(h4, p);
}
}
<h3>Click</h3>
<div></div>
Using a CSS style rule and checking for the existence of the CSS style rule class name on each HTML element's class list is a common method for toggling the display state of an element.
I used a hide class name in the code snippet but you can change to a 'show' class name with some minor modifications to the code and CSS rules.
var H3 = document.getElementById("h3-elem");
H3.addEventListener("click", clickFunction);
var Div = document.getElementById("div-elem");
function clickFunction() {
var h4 = document.getElementById("h4-elem");
var p = document.getElementById("p-elem");
if (!h4) {
h4 = appendH4();
}
if (!p) {
p = appendP();
}
// Option 1:
// Use the built-in 'toggle()' method on the class list
// for each element.
// https://developer.mozilla.org/en-US/docs/Web/API/DOMTokenList/toggle
// h4.classList.toggle("hide");
// p.classList.toggle("hide");
// Option 2:
// Check if the class list for the 'h4' and 'p' elements
// contain 'hide' class name. If the class list does not
// contain the class name then add the 'hide' class name
// to the class list.
if (h4.classList.contains("hide")) {
h4.classList.remove("hide");
} else {
h4.classList.add("hide");
}
if (p.classList.contains("hide")) {
p.classList.remove("hide");
} else {
p.classList.add("hide");
}
}
// Set to hide initially. After creation of the element,
// the 'clickFunction' will determine the display state
// of the element by checking for the existense of the
// 'hide' class name.
function appendH4() {
var h4 = document.createElement("h4");
h4.id = "h4-elem";
h4.className = "hide";
h4.textContent = "Header 4";
Div.append(h4);
return h4;
}
function appendP() {
var p = document.createElement("p");
p.id = "p-elem";
p.className = "hide";
p.textContent = "A paragraph";
Div.append(p);
return p;
}
.hide {
display: none;
}
<h3 id="h3-elem">Header 3</h3>
<div id="div-elem"></div>

How to select an element with specific css value in javascript

I want to select an element if it has a css as display block then do this function. If the element has the css as display block then remove ('hide') class from the header class.. This is what I want to do.. Any help?
Well, there are two solutions depending on what you want:
Solution 1
Looping through all elements and removing hide class from the current element if it has display block value in its style.
var elements = document.getElementsByTagName("*");
for(let i = 0; i < elements.length; i++) {
if(elements[i].style.display == "block") {
elements[i].classList.remove("hide");
}
}
Solution 2
Getting the reference of the element via HTML id.
var element = document.getElementById("YourElementID");
if(element.style.display == "block") {
element.classList.remove("hide");
}
You can define an id like this in your HTML file:
<div id="YourElementID">Div</div>
I am assuming that you want to determine if the element has the "hide" class by checking its display style. you don't need to do that, you can easily check its class list by using the following code:
element.classList.contains("hide");
There are several ways of collecting all the elements with display: block and i am not sure, which one performs best - or whether it performs good at all.
If you want all the Element instances of the page, which have a computed style of display: block you can do something like:
var $els = Array.from(document.body.querySelectorAll('*')).filter(function($el) {
return getComputedStyle($el).display === 'block';
});
Or ES6:
const $els = Array.from(document.body.querySelectorAll('*')).filter($el => getComputedStyle($el).display === 'block');
If you want the Element instances which have display: block literally set in the style-attribute, you have to do something like this:
var $els = Array.from(document.body.querySelectorAll('*')).filter(function($el) {
return $el.style.display === 'block';
});
I think it would perform better, if the selector in querySelectorAll() would be a little more specific.
Another option would be to use the TreeWalker API, but then you have to do a mutation, because you have to iterate over all the elements and push them to an array:
var $els = [];
walker = document.createTreeWalker(document.body, NodeFilter.SHOW_ELEMENT);
while (walker.nextNode()) {
if (getComputedStyle(walker.currentNode).display === 'block') {
$els.push(walker.currentNode);
}
}
Once you have all your elements, you can do something with them.
A little bit more information would be helpful, especially what exactly you want to achieve, once you have the elements, because then i could also provide more help. Maybe provide a code example?

Adding new element to nested classes

I need to use JS to create a new element within specific nested classes in HTML. So in this example, I need to create a new span with the class of "paw-print" only where the "collies" class is nested within "dogs".
Here's what I have so far: https://jsfiddle.net/p50e228w/6/
The problem is that my current JS works on the first instance, but not on the other. I currently have document.getElementsByClassName set to "collies" but I need to target that class only when it's inside the parent "dogs" class.
What am I missing here?
var span = document.createElement("span");
span.className = "paw-print";
var wrap = document.getElementsByClassName("collies");
for(var i = 0; i < wrap.length; i++) {
wrap[i].appendChild(span);
}
I can use jQuery, but I've been using vanilla JS just because I'm such a noob and want to understand what my code is doing.
There are 2 issues with your code.
Positioning : The images are being given a absolute position, and they rest in the same position based on the page layout. So set relative positioning for the parent container.
CSS
.relative {
position: relative;
}
You need to append that to parent element which is collie here.
You can use querySelectorAll to find the nested relation ship that you are looking for.
var collies = document.querySelectorAll('.dogs .collies');
for (var i = 0; i < collies.length; i++) {
var span = document.createElement("span");
span.className = "paw-print";
collies[i].appendChild(span);
}
Fiddle
If you want to append to parent ( element with class 'dog')
$('.dogs .collies').each(function() // finds elements in the dom with parent element 'dog' and it's child element 'collies'
{
$(this) // 'this' would represent 'collies' element
.closest('.dogs') // .closest('.dogs') would get it's nearest occurence in the heirarchy ( basically it's parent )
.append($('<span/>', { class: 'paw-print'})); // create a dynamic span element and append to 'this'
});
If you want to append to child( element with class 'collies')
$('.dogs .collies').each(function()
{
$(this).append($('<span/>', { class: 'paw-print'}));
});
In addition to this, you also need to set position: relative as pointed out by Rob.
Example : https://jsfiddle.net/DinoMyte/1zxn8193/1/

Show/Hide Elements with multiple attributes by attribute selection (Javascript)

I try to find an easy solution (I am a totally coding beginner, just use javascript in widgets of a "out of the box" page) for the following problem:
There are multiple attributes visitor can select by click Remove/Show
attribute a (Remove/Show)
attribute b (Remove/Show)
attribute c (Remove/Show)
a.s.o.
based on visitors "selection", I would like to show or hide the list of elements:
element 1 (attribute a and b) - Remove if "a" OR "b" has been selected
element 2 (attribute a) - remove if "a" has been selected
element 3 (attribute a and c) - remove, if "a" OR "c" has been selected
a.s.o.
I am able already to hide elements based on a "selection", but in my solution every element show and hide only based on the unique ID (and so also only on the single selection).
The Javascript I found for that is:
<script type="text/javascript">
//<![CDATA[
function swap(openlink,closelink, linkid, dataid)
{
if( document.getElementById(dataid).style.display == 'none')
{
document.getElementById(dataid).style.display='inline';
document.getElementById(linkid).firstChild.nodeValue=closelink;
} else
{
document.getElementById(dataid).style.display='none';
document.getElementById(linkid).firstChild.nodeValue=openlink;
}
}
//]]>
</script>
And than I could use this HTML Code to Remove/Show the elements:
attribute a Remove
attribute b Remove
attribute c Remove
And my element will be Remove/Show by this:
<div id="showmeA" style="display:inline">Element 1</div>
<div id="showmeB" style="display:inline">Element 2</div>
<div id="showmeB" style="display:inline">Element 3</div>
Is there an easy way to add 2 ids to one "element", so that for example Element 1 could be hidden by id=showmeA AND id=showmeB?
You said the issue yourself: IDs are unique.
This is exactly why you should use something else than id, and class attribute is perfectly fine as it does not have to be unique.
Then, this means that the function will not look for your elements using getElementById() but getElementsByClassName().
Note that this function get elements, this involves that you have to loop through these elements and hide / show the ones targeted.
function swap(openlink, closelink, linkid, dataclass) {
var elements = document.getElementsByClassName(dataclass);
for (var i = 0; i < elements.length; i++) {
var element = elements[i];
if(element.style.display == 'none') {
element.style.display='inline';
document.getElementById(linkid).firstChild.nodeValue=closelink;
} else {
element.style.display='none';
document.getElementById(linkid).firstChild.nodeValue=openlink;
}
}
}
Do not forget to replace id by class attributes to your HTML, you can put in as much as you want, they simply must be separated by a space:
<div class="showmeA showmeB">Element 1</div>
<div class="showmeB">Element 2</div>
<div class="showmeC">Element 3</div>
Here is an example that you can use to better understand the function and attributes used in your solution, this solves your issue: https://jsfiddle.net/sy2mxscf/
It is also important to inform you that inline Javascript is bad, you should reconsider your code when your Javascript skill will increase.
In order to solve the issue pointed out in the comments, you have to use some kind of counter and increment it when you hide the element, decrement it when you show element of one of his class, and displaying the associate element when this counter is 0.
This is also why you need two differentiated links: the "Remove" to increment, and the "Show" to decrement.
There are several way to implement this solution:
Use an associative array in Javascript
Use a custom attribute on the element
Add and remove specific classes
I chose the last one but this may be not the best one, this is just one of the possibilities.
https://jsfiddle.net/sy2mxscf/2/
The idea is to add or remove a custom "hidemeX" class. If you click on two different "Remove" links targeting the same element, two classes will be added. If you then click on any "Show" link, the associate class will be removed. But there is still a "hidemeX" class remaining until you click on the second link, so the element is not displayed thanks to CSS.
As Delgan says, its better to use class here, and you can use those <a>'s id as their class, so when you use your function swap, you can easily trace back to decide if the elements is selected, so the div should be removed.
Below is how you can separate javascript logic and html structure.
var swap = function(e) {
var close = 'Remove', open = 'Show';
var next = this.text === close ? open : close;
// Set the clicked <a>'s text.
this.text = next;
// Get divs that will affect by this <a>
var affectTarget = this.id;
// Affected div elements
var targets = document.getElementsByClassName(affectTarget);
var i, len = targets.length;
var visible;
var watch, wLen, j;
// For each <div> that will be affect by the clicked <a>, we have to chec :
for (i = 0; i < len; ++i) {
// Get the classes that used as a list to show which <a> will have a effect on it.
watch = targets[i].classList;
wLen = watch.length;
// visibilty is default to inline, if no <a> that it watches is selected, then it'll show
visible = "inline";
for (j = 0; j < wLen; ++j) {
// If any of the <a> it watches is selected, set the visibilty to none.
if (document.getElementById(watch[j]).text === open) {
visible = "none";
break;
}
}
targets[i].style.display = visible;
}
};
// For each switcher, we register a click event for it.
var switchers = document.querySelectorAll("a.showSwitcher");
var i, len = switchers.length;
for (i = 0; i < len; ++i) {
switchers[i].addEventListener('click', swap);
}
attribute a Remove
attribute b Remove
attribute c Remove
<hr/>
<div class="swaplinkA swaplinkB" style="display:inline">Element 1</div>
<div class="swaplinkA"style="display:inline">Element 2</div>
<div class="swaplinkA swaplinkC"style="display:inline">Element 3</div>

Removing a div with no id or class with Javascript

My wordpress blog is having issues with syntax highlighter evolved plugin, and there's this weird div element popping out:
<div style="z-index: -1; position:absolute; top:0px; left: 0px; width: 100%; height: 4031px;"></div>
This causes my page to extend, creating a big space at the end of the page. This also is found on every wordpress blog. Funny thing is, only chrome sees that (using Inspect Element). I've already tried in IE9 developer tools and FF firebug, the div is not there and my page is fine.
NOTE: I've already posted a separate question here. And my question here is different from that.
I want to fix this little problem so bad, and it just came to my mind to use JavaScript for this. What I want to do is: Remove the div with javascript.
It's easy removing a div with an ID or class, but this one doesn't have any. I also do not want to affect all the other divs. How can I accomplish this?
P.S. It has no parent IDs or class. It's right after the container class div. It's parent is <body>.
EDIT: Here's the html:
If it's always last or close to last you can use jQuery or normal CSS3 selectors
$('body > div:last-child').remove();
OR
$('body > div:nth-last-child(n)').remove();
More on CSS3 Selectors and .remove()
OR you could use CSS i.e.
body > div:last-child (or div:nth-last-child(n)) {
display: none;
}
You could do something like this:
var els = document.getElementsByTagName('div');
for (var i = 0; l = els.length; i < l; i++) {
if (els[i].innerHTML == 'style....') {
els[i].parentNode.removeChild(els[i]);
}
}
If you are using jQuery, You can reference the div using a parent or sibling div that might have an ID or class defined.
For examample :
<div id="parentDIVID">
<div>your problem div</div>
</div>
Then you can use jQuery to reference your problem div like this : $("#parentDIVID > div")
If you can provide more html code surrounding your problem div, we can construct a jQuery selector that will work in your case.
Update : Based on the markup provided
function removeDiv() {
var parent = document.getElementById("stimuli_overlay").parentNode;
var children = document.getElementById("stimuli_overlay").parentNode.childNodes;
for (var i = 0; i < children.length; i++) {
if (children[i].style.zIndex == -1)
parent.removeChild(children[i]);
}
}
Update: Based on the fact that you can't rely on the div used below.
If the div really is the always the last div in the document, this is actually easier:
var divs, div;
divs = document.getElementsByTagName("div");
if (divs.length > 0) {
div = divs.item(divs.length - 1);
div.parentNode.removeChild(div);
}
Live example
length - 1 will remove the last div in the document. If you needed to skip a lightbox div or something, adjust to use - 2 or - 3, etc.
Old Answer using the earlier information:
Given that structure, something along these lines:
// Get the div that follows it, which conveniently has an ID
var div = document.getElementById('stimuli_overlay');
// If that worked...
if (div) {
// ...move to the previous div, with a bit of paranoia about blank non-element
// nodes in-between
div = div.previousSibling;
while (div && (div.nodeType !== 1 || div.tagName !== "DIV")) {
div = div.previousSibling;
}
// Check that this really is the right div
if (div && div.tagName === "DIV"
// The following checks look for some of the style properties that your
// screenshot shows are set on the div
&& div.style.position == "absolute"
&& div.style.zIndex == "-1"
&& div.style.top == "0px"
&& div.style.left == "0px"
&& div.style.width == "100%"
&& /* ...possibly more checks here... */) {
// Remove it
div.parentNode.removeChild(div);
}
}

Categories

Resources