how to detect if div is hidden by javascript - javascript

I have a DIV, that is sometimes hidden, and in this case I don't want that google adds appear/are loaded at all inside this DIV.
What is the best practice to make such a check with javascript?

You should look at the computed style of the node you want, via window.getComputedStyle, rather than the style attribute of the node, as css elsewhere may be effecting it too.
Checking whether a node is covered by another node is much more difficult, one way is to use document.elementFromPoint to find out which node is top-most at a specific point, then do this where your node should be until you're satisfied it's visible. For example, check the centre of the node is your node.
function isHidden(node, checkIfCovered) {
var absPosition = function absPosition(node) {
var x = 0, y = 0,
h = node.offsetHeight || 0, w = node.offsetWidth || 0;
do {
node.offsetLeft && (x = x + node.offsetLeft);
node.offsetTop && (y = y + node.offsetTop);
} while (node = node.offsetParent);
return {x: x, y: y, h: h, w: w};
},
o, style;
if (checkIfCovered && document.elementFromPoint) { // only if supported
o = absPosition(node); // get position & size
o.centre = {x: o.x + o.w / 2, y: o.y + o.h / 2}; // centre of node
if (document.elementFromPoint(o.centre.x, o.centre.y) !== node) {
return true; // another node is in the centre => covered
}
}
do { // loop up over parent nodes
if (node.nodeType === 9) break; // skip #document
style = window.getComputedStyle(node);
if ( style.display === 'none'
|| style.visibility === 'hidden'
|| style.opacity === '0'
) {
return true;
}
} while (node = node.parentNode);
// passed all tests, not hidden
return false;
}
Example usage
isHidden(document.getElementById('myDivId')); // true->hidden
isHidden(document.getElementById('myDivId'), true); // true->hidden or covered
Further things to consider
Is the node located where it is possible to scroll into view? See Fabrizio Calderan's comment.
Now edited in. Are the parent nodes hidden? You may want to loop up the DOM tree to find this out. It's okay if they are covered though, obviously. See Loïc Faure-Lacroix's comment.

if your div has an ID, try this:
if((document.getElementById('your_div_id').style.display=='none') || (document.getElementById('your_div_id').style.visibility=='hidden')){
//its hidden
}else{
//its not
}

you can check it by
var div = document.getElementById('div_id');
if( div.style.visibility=="hidden"
|| div.style.display=="none")
{ alert("div is hidden"); }

var isVisible = element.offsetWidth > 0 || element.offsetHeight > 0;
isVisible will give you is the div hidden or visible.

<script>
function isHidden(divId){
styleValue = document.getElementById(divId).style.display;
if(styleValue == 'none'){
return true;
}
else{
return false;
}
}
</script>
returnValue = isHidden(); //return true if hidden

There are a couple of ways to know if an object is hidden or not. There are couple of ways to find out but the truth is that it's much more complicated than most solution out there.
I can't unfortunately mash it up at the moment but I can tell how to do it.
An hidden object may still have display to something different than none or visibility to default. If parent objects are hidden, then child elements are also hidden but the display attributes remain unchanged.
In other word, you'll have to bubble every parent element until you find an hidden element or the root.
That said, css attributes like display and visibility isn't the only way to hide an element. You can also check for overflow: hidden and if the object is outside of the bounding box.
Pseudo code
def visible(initial, element)
if element.invisible or element.hidden
// Element was simply hidden so false
return false
if element != initial and elemen.has_overflow_hidden && initial.outside(element)
// Here we check if our element is inside the bounding box of a overflow hidden
// Parent.
return false
if element.opacity == 0
return false
if element == element.parent
// reached the root
return true
visible(initial, element.parent)
if (visible(element, element))
do something
else
do something else
As far as I can say, it's unfortunately not handling every cases. But it should be more than enough. It doesn't handle z-index, It might not work well with position absolute, relative and fixed.

In jquery:
$('#div').is(':visible');
$('#div').is(':hidden');

You're looking at the DOM elements (in this case) DIV, CSS property. There are two ways to hide an element.
One is display: none, the other is visibility: hidden.
In jQuery you would then do something like:
if !($('#div-id').css('display') == 'none'){
JAVASCRIPT_TO_LOAD_ADS_GOES_HERE
}
In the case of visibility hidden, do the same, but compare .css('visibility') to hidden.

Related

How to make click event only trigger on text (not other whitespace within the same element) [duplicate]

I have a Div which is as big as half of my page using CSS:
<div id="bigdiv">
CLICK ON THIS TEXT
</div>
I am trying to write a javascript or jquery code which detects click on the text and not the rest of the element. Is there a way to do that?
Since we cannot listen for events directly on the textNodes themselves, we have to take a more creative path to solving the problem. One thing we can do is look at the coordinates of the click event, and see if it overlaps with a textNode.
First, we'll need a small helper method to help us track whether a set of coordinates exists within a set of constraints. This will make it easier for us to arbitrarily determine if a set of x/y values are within the a set of dimensions:
function isInside ( x, y, rect ) {
return x >= rect.left && y >= rect.top
&& x <= rect.right && y <= rect.bottom;
}
This is fairly basic. The x and y values will be numbers, and the rect reference will be an object with at least four properties holding the absolute pixel values representing four corners of a rectangle.
Next, we need a function for cycling through all childNodes that are textNodes, and determining whether a click event took place above one of them:
function textNodeFromPoint( element, x, y ) {
var node, nodes = element.childNodes, range = document.createRange();
for ( var i = 0; node = nodes[i], i < nodes.length; i++ ) {
if ( node.nodeType !== 3 ) continue;
range.selectNodeContents(node);
if ( isInside( x, y, range.getBoundingClientRect() ) ) {
return node;
}
}
return false;
}
With all of this in place, we can now quickly determine if a textNode was directly below the clicked region, and get the value of that node:
element.addEventListener( "click", function ( event ) {
if ( event.srcElement === this ) {
var clickedNode = textNodeFromPoint( this, event.clientX, event.clientY );
if ( clickedNode ) {
alert( "You clicked: " + clickedNode.nodeValue );
}
}
});
Note that the initial condition if ( event.srcElement ) === this allows us to ignore click events originating from nested elements, such as an image or a span tag. Clicks that happen over textNodes will show the parent element as the srcElement, and as such those are the only ones we're concerned with.
You can see the results here: http://jsfiddle.net/jonathansampson/ug3w2xLc/
Quick win would be to have
<div id="bigdiv">
<span id="text">TEXT HERE</span>
</div>
Script:
$('#text').on('click', function() {
.....
});
Let's alter the content dinamically - I will make the clicking on lala available:
<div id="gig">
<div id="smthing">one</div>lala
<div id="else"></div>
</div>
Script:
var htmlText = $('#gig').text(); //the big divs text
var children = $('#gig').children(); //get dom elements so they can be ignored later
$.each(children, function (index, child) {
var txt = $(child).text().trim();
if (txt != '') { //if a child has text in him
htmlText = htmlText.replace(txt, 'xxx'); //replace it in the big text with xxx
}
});
htmlText = htmlText.split("xxx"); //split for xxx make it arrat
var counter = 0; //the part when the text is added
$.each(htmlText, function (i, el) {
htmlText[i] = el.trim();
if (htmlText[i] != "") { //if there is something here than it's my text
htmlText[i] = '<span id="text">' + htmlText[i] + '</span>'; //replace it with a HTML element personalized
counter++; //mark that you have replaced the text
} else { // if there is nothing at this point it means that I have a DOM element here
htmlText[i] = $(children[i - counter])[0].outerHTML; //add the DOM element
}
});
if (children.length >= htmlText.length) { //you might have the case when not all the HTML children were added back
for (var i = htmlText.length - 1; i < children.length; i++) {
htmlText[i + 1] = $(children[i])[0].outerHTML; //add them
}
}
htmlText = htmlText.join(""); //form a HTML markup from the altered stuff
$('#gig').html(htmlText); // replace the content of the big div
$('#text').on('click', function (data) { //add click support
alert('ok');
});
See a working example here: http://jsfiddle.net/atrifan/5qc27f9c/
P.S: sorry for the namings and stuff I am a little bit tired.
Are you able to do this, is this what you are looking for?
What the code does:
It's making only the text inside the div although the div could have other divs as well, makes only the text that has no HTML container like a div a span a p an a or something like that and alters it adding it in a span and making it available for clicking.
EDIT - Solution without adding wrapping element
Doing this without a wrapping element is quite a hassle. I managed to get it to work, however this will only work for one liners that are centered vertically AND horizontally.
To see the HTML and CSS that goes along with this, see the
jsFiddle: http://jsfiddle.net/v8jbsu3m/3/
jQuery('#bigDiv').click(function(e) {
// Get the x and y offest from the window
margin_top = jQuery(this).offset().top;
margin_left = jQuery(this).offset().left;
// Get the dimensions of the element.
height = jQuery(this).height();
width = jQuery(this).width();
// Retrieve the font_size and remove the px addition
font_size = parseInt(jQuery(this).css('font-size').replace('px', ''));
// Retrieve the position of the click
click_x = e.pageX;
click_y = e.pageY;
// These variables will be used to validate the end result
var in_text_y = false;
var in_text_x = false;
// Determine the click relative to the clicked element
relative_x = click_x - margin_left;
relative_y = click_y - margin_top;
// Determine whether the y-coordinate of the click was in the text
if (relative_y >= (parseFloat(height) / 2) - (parseFloat(font_size) / 2) &&
relative_y <= (parseFloat(height) / 2) + (parseFloat(font_size) / 2))
in_text_y = true;
// This piece of code copies the string and places it in a invisible div
// If this div has the same font styling and no paddings etc... it can
// be used to get the width of the text
text = jQuery(this).text();
text_width = jQuery('#widthTester').html(text).width();
// Determine whether the x-coordinate of the click was in the text
if (relative_x >= (parseFloat(width) / 2) - (parseFloat(text_width) / 2) &&
relative_x < (parseFloat(width) / 2) + (parseFloat(text_width) / 2))
in_text_x = true;
// If the x and y coordinates were both in the text then take action
if (in_text_x && in_text_y)
alert('You clicked the text!');
});
Also, this code can be optimized, since the same calculcation is done multiple times, but I thought that leaving the calculcations there better illustrated what was going on.
Solution by adding a wrapping element
If you put a span around the text, then you can add an onClick event handler to the span.
<div id="bigdiv">
<span>CLICK ON THIS TEXT</span>
</div>
jQuery code
jQuery('#bigdiv span').click(function() {
jquery(this).remove();
});
If you want to go straight through HTML, you can use
<div id="bigdiv" onclick="myFunction();">
and then simply apply the function afterwards in JS:
function myFunction(){
//...
}
EDIT: sorry, if you want the text to be affected, put in <p> around the text or <span> ie.
<div id="bigdiv">
<p onclick="myFuncion();"> TEXT </p>
</div>

Get only visible element using pure javascript

I have elements like below
<div class="one">send Message</div>
<div class="one">send Message</div>
<div class="one">send Message</div>
I have a web page where there is send Message buttons like above, in which only one button is visible at a time.Other two buttons are hidden via some javascript codes.So for example if 2nd button is visible , I should be able to get only that element.
So my code will be something like
document.querySelector(".one:visible");
In jquery the code is $(".one:visible"); , which works fine , But I need to know how to do this via pure javascript.
Here's something you can use, pure Javascript:
// Get all elements on the page (change this to another DOM element if you want)
var all = document.getElementsByTagName("*");
for (var i = 0, max = all.length; i < max; i++) {
if (isHidden(all[i]))
// hidden
else
// visible
}
function isHidden(el) {
var style = window.getComputedStyle(el);
return ((style.display === 'none') || (style.visibility === 'hidden'))
}
I have something shorter:
Array.from(document.querySelectorAll('.one')).filter(s =>
window.getComputedStyle(s).getPropertyValue('display') != 'none'
);
Returns all elements with attribute display block set.
Use getBoundingClientRect. It will return height and width of zero if the element is not in the DOM, or is not displayed.
Note that this cannot be used to determine if an element is not visible due to visibility: hidden or opacity: 0. AFAIK this behavior is identical to the jQuery :visible "selector". Apparently jQuery uses offsetHeight and offsetWidth of zero to check for non-visibility.
This solution will also not check if the item is not visible due to being off the screen (although you could check that easily enough), or if the element is hidden behind some other element.
See also Detect if an element is visible (without using jquery)
var $el = document.querySelectorAll('.one');
var visibleElements;
for (var i = 0; i < $el.length; i++) {
var currentElement = $el[i];
var $style = window.getComputedStyle(currentElement, null);
if (!currentElement) {
return false;
} else if (!$style) {
return false;
} else if ($style.display === 'none') {
return false;
} else {
visibleElements.push(currentElement);
}
}
First we get all the elements using document querySelectorAll. Then, we need to iterate over all the elements. To get the style, use getComputedStyle.
After that :visible check only for display and we do it the same way.
A more comprehensive approach:
function isVisible(el) {
while (el) {
if (el === document) {
return true;
}
var $style = window.getComputedStyle(el, null);
if (!el) {
return false;
} else if (!$style) {
return false;
} else if ($style.display === 'none') {
return false;
} else if ($style.visibility === 'hidden') {
return false;
} else if (+$style.opacity === 0) {
return false;
} else if (($style.display === 'block' || $style.display === 'inline-block') &&
$style.height === '0px' && $style.overflow === 'hidden') {
return false;
} else {
return $style.position === 'fixed' || isVisible(el.parentNode);
}
}
}
This would check for any possible way an element could be visible in the dom to my knowledge minus the z-index cases.
If you're using the hidden attribute :
document.querySelector(".one:not([hidden])");
So all jQuery's :visible selector does is check the display property.
If that's all you want, this is all you'd need.
(window.getComputedStyle(el).getPropertyValue('display') !== 'none')
However, this is lacking in many use cases. If you seek a more comprehensive solution, keep reading.
Both Element.getBoundingClientRect() and window.getComputedStyle() are useful for determining if the element is visible and in the viewport.
You can't use getBoundingRect() alone to determine the visibility, and while you could use getComputedStyle() solely, it's not the optimal solution in terms of performance.
Both of these functions used in conjunction with each other is the best option (around 22% faster than getComputedStyle() alone.
function inViewport(els) {
let matches = [],
elCt = els.length;
for (let i=0; i<elCt; ++i) {
let el = els[i],
b = el.getBoundingClientRect(), c;
if (b.width > 0 && b.height > 0 &&
b.left+b.width > 0 && b.right-b.width < window.outerWidth &&
b.top+b.height > 0 && b.bottom-b.width < window.outerHeight &&
(c = window.getComputedStyle(el)) &&
c.getPropertyValue('visibility') === 'visible' &&
c.getPropertyValue('opacity') !== 'none') {
matches.push(el);
}
}
return matches;
}
With a usage example of...
var els = document.querySelectorAll('.one'),
visibleEls = inViewport(els);
This ensures that the display is not set to "none", the visibility is "visible", the width and height are greater than 0, and the element is within the bounds of the viewport.

Detect click on the inner text of the element without wrapping the text in a second element

I have a Div which is as big as half of my page using CSS:
<div id="bigdiv">
CLICK ON THIS TEXT
</div>
I am trying to write a javascript or jquery code which detects click on the text and not the rest of the element. Is there a way to do that?
Since we cannot listen for events directly on the textNodes themselves, we have to take a more creative path to solving the problem. One thing we can do is look at the coordinates of the click event, and see if it overlaps with a textNode.
First, we'll need a small helper method to help us track whether a set of coordinates exists within a set of constraints. This will make it easier for us to arbitrarily determine if a set of x/y values are within the a set of dimensions:
function isInside ( x, y, rect ) {
return x >= rect.left && y >= rect.top
&& x <= rect.right && y <= rect.bottom;
}
This is fairly basic. The x and y values will be numbers, and the rect reference will be an object with at least four properties holding the absolute pixel values representing four corners of a rectangle.
Next, we need a function for cycling through all childNodes that are textNodes, and determining whether a click event took place above one of them:
function textNodeFromPoint( element, x, y ) {
var node, nodes = element.childNodes, range = document.createRange();
for ( var i = 0; node = nodes[i], i < nodes.length; i++ ) {
if ( node.nodeType !== 3 ) continue;
range.selectNodeContents(node);
if ( isInside( x, y, range.getBoundingClientRect() ) ) {
return node;
}
}
return false;
}
With all of this in place, we can now quickly determine if a textNode was directly below the clicked region, and get the value of that node:
element.addEventListener( "click", function ( event ) {
if ( event.srcElement === this ) {
var clickedNode = textNodeFromPoint( this, event.clientX, event.clientY );
if ( clickedNode ) {
alert( "You clicked: " + clickedNode.nodeValue );
}
}
});
Note that the initial condition if ( event.srcElement ) === this allows us to ignore click events originating from nested elements, such as an image or a span tag. Clicks that happen over textNodes will show the parent element as the srcElement, and as such those are the only ones we're concerned with.
You can see the results here: http://jsfiddle.net/jonathansampson/ug3w2xLc/
Quick win would be to have
<div id="bigdiv">
<span id="text">TEXT HERE</span>
</div>
Script:
$('#text').on('click', function() {
.....
});
Let's alter the content dinamically - I will make the clicking on lala available:
<div id="gig">
<div id="smthing">one</div>lala
<div id="else"></div>
</div>
Script:
var htmlText = $('#gig').text(); //the big divs text
var children = $('#gig').children(); //get dom elements so they can be ignored later
$.each(children, function (index, child) {
var txt = $(child).text().trim();
if (txt != '') { //if a child has text in him
htmlText = htmlText.replace(txt, 'xxx'); //replace it in the big text with xxx
}
});
htmlText = htmlText.split("xxx"); //split for xxx make it arrat
var counter = 0; //the part when the text is added
$.each(htmlText, function (i, el) {
htmlText[i] = el.trim();
if (htmlText[i] != "") { //if there is something here than it's my text
htmlText[i] = '<span id="text">' + htmlText[i] + '</span>'; //replace it with a HTML element personalized
counter++; //mark that you have replaced the text
} else { // if there is nothing at this point it means that I have a DOM element here
htmlText[i] = $(children[i - counter])[0].outerHTML; //add the DOM element
}
});
if (children.length >= htmlText.length) { //you might have the case when not all the HTML children were added back
for (var i = htmlText.length - 1; i < children.length; i++) {
htmlText[i + 1] = $(children[i])[0].outerHTML; //add them
}
}
htmlText = htmlText.join(""); //form a HTML markup from the altered stuff
$('#gig').html(htmlText); // replace the content of the big div
$('#text').on('click', function (data) { //add click support
alert('ok');
});
See a working example here: http://jsfiddle.net/atrifan/5qc27f9c/
P.S: sorry for the namings and stuff I am a little bit tired.
Are you able to do this, is this what you are looking for?
What the code does:
It's making only the text inside the div although the div could have other divs as well, makes only the text that has no HTML container like a div a span a p an a or something like that and alters it adding it in a span and making it available for clicking.
EDIT - Solution without adding wrapping element
Doing this without a wrapping element is quite a hassle. I managed to get it to work, however this will only work for one liners that are centered vertically AND horizontally.
To see the HTML and CSS that goes along with this, see the
jsFiddle: http://jsfiddle.net/v8jbsu3m/3/
jQuery('#bigDiv').click(function(e) {
// Get the x and y offest from the window
margin_top = jQuery(this).offset().top;
margin_left = jQuery(this).offset().left;
// Get the dimensions of the element.
height = jQuery(this).height();
width = jQuery(this).width();
// Retrieve the font_size and remove the px addition
font_size = parseInt(jQuery(this).css('font-size').replace('px', ''));
// Retrieve the position of the click
click_x = e.pageX;
click_y = e.pageY;
// These variables will be used to validate the end result
var in_text_y = false;
var in_text_x = false;
// Determine the click relative to the clicked element
relative_x = click_x - margin_left;
relative_y = click_y - margin_top;
// Determine whether the y-coordinate of the click was in the text
if (relative_y >= (parseFloat(height) / 2) - (parseFloat(font_size) / 2) &&
relative_y <= (parseFloat(height) / 2) + (parseFloat(font_size) / 2))
in_text_y = true;
// This piece of code copies the string and places it in a invisible div
// If this div has the same font styling and no paddings etc... it can
// be used to get the width of the text
text = jQuery(this).text();
text_width = jQuery('#widthTester').html(text).width();
// Determine whether the x-coordinate of the click was in the text
if (relative_x >= (parseFloat(width) / 2) - (parseFloat(text_width) / 2) &&
relative_x < (parseFloat(width) / 2) + (parseFloat(text_width) / 2))
in_text_x = true;
// If the x and y coordinates were both in the text then take action
if (in_text_x && in_text_y)
alert('You clicked the text!');
});
Also, this code can be optimized, since the same calculcation is done multiple times, but I thought that leaving the calculcations there better illustrated what was going on.
Solution by adding a wrapping element
If you put a span around the text, then you can add an onClick event handler to the span.
<div id="bigdiv">
<span>CLICK ON THIS TEXT</span>
</div>
jQuery code
jQuery('#bigdiv span').click(function() {
jquery(this).remove();
});
If you want to go straight through HTML, you can use
<div id="bigdiv" onclick="myFunction();">
and then simply apply the function afterwards in JS:
function myFunction(){
//...
}
EDIT: sorry, if you want the text to be affected, put in <p> around the text or <span> ie.
<div id="bigdiv">
<p onclick="myFuncion();"> TEXT </p>
</div>

finding if a particular div is invisible (visible = false) using javascript

using the below code i am finding if a div is invisible.
if(document.getelementbyid("header").style.visible){
alert("Yes");
}
else{
alert("No");
}
checking the visible property because in the code behind header.visible = false is defined depending upon the condition. But it always returning "No". Please tell the correct way.
There isn't a visible property, but visibility, and it can have the following values:
visible
hidden
collapse
See the MDN article.
You can use display and visibility to check if element is visible or not
var elem = document.getelementbyid("header");
if(elem .style.visibility == "hidden" || elem.style.display == 'none'){
alert("No"); // element is visible
}
else{
alert("Yes");
}
Remember that there is not style.visible in javascript. Depending on how do you hide a div, you need to check
if(document.getelementbyid("header").style.visibility != "hidden") {
//visible
} else {
//not visible
}
or
if(document.getelementbyid("header").style.display != "none") {
//visible
} else {
//not visible
}
At the same time, above code will only check if exact element has display none or visibility hidden. But at the same time, it will return visible when parent element is not visible. Because of that, you may do next:
var element = document.getelementbyid("header");
if(element.offsetWidth > 0 || element.offsetHeight > 0) {
//visible
} else {
//not visible
}
Browser always returns 0 width and height of an element if it is not visible
If you're using jQuery:
var isVisible = $("#header").is(":visible");
The CSS property is visibility. Bear in mind that the property may not contain the value you expect if it has been set using CSS, rather than by the style attribute.

jQuery selector to check if an element is animating to hidden

Is there a way to tell if an element is either hidden or is currently in the process of hiding (via an animation)? The only way I can think to do it is to store a flag in the element's data when you call show or hide, but I was wondering if there was another way?
Could you do a custom jQuery selector for it
(function($) {
var endOpacity,
oldStep = jQuery.fx.step.opacity;
$.fx.step.opacity = function( fx ) {
endOpacity = fx.end;
return oldStep(fx);
};
$.expr[':'].hiding = function(obj){
var $this = $(obj);
return ($this.is(':hidden') || ($this.is(':animated') && endOpacity === 0));
};
})(jQuery);
This worked for me (it may require some more testing though).
So just add :hiding it will match hidden elements, and elements that are currently being animated to 0. It will now only match elements that are disappearing, not appearing.
You get the hidden one with $(":hidden") and then the animating ones with $(":animated") and with the :animated check the .queue() if it has the hide method inside.
You can check if the element is animated like this:
if( !$('.your-element').is(':animated') ) {
// do animation...
} else {
return false;
}

Categories

Resources