There are a couple of ways I could do this (That I'm aware of).
Test css display
if ($('#foo').css('display') == 'none')
Test the visibility
if ($('#foo').is(':visible'))
In the visibility I can check if the element is there.
Elements are considered visible if they consume space in the document.
Visible elements have a width or height that is greater than zero.
Elements with visibility: hidden or opacity: 0 are considered visible,
since they still consume space in the layout.
Source
But, note that in both I can't test the visibility (by the user) because:
Hiding an element can be done by setting the display property to
"none" or the visibility property to "hidden". However, notice that
these two methods produce different results:
visibility: hidden hides an element, but it will still take up the same
space as before. The element will be hidden, but still affect the
layout.
display: none hides an element, and it will not take up any space. The
element will be hidden, and the page will be displayed as if the
element is not there:
Source
So in neither of the examples I test if the element is visible in all senses for the user.
So my question is:
What're the differences between the two if's codes from above?
What's the best way to test if an element is visible to the user:
Should I have to use something like:
if ($('#foo').is(':visible') &&
$('#foo').css('opacity') > 0 &&
$('#foo').css('visibility') != 'hidden')
I think your best bet is to implement a custom function like below and test/improve as new things come up,
$.fn.isReallyVisible = function () { //rename function name as you like..
return (this.css('display') != 'none' &&
this.css('visibility') != 'hidden' &&
this.css('opacity') > 0);
}
The above should be cross browser proof as we are using jQuery .css function (specifically for opacity).
DEMO
The difference between the two is that being hidden using "visible" attribute leaves the element on the page, just not actually displayed. So, it's spacing will be taken into account when the page renders the rest of the display.
It seems that doing it the other way actually stops the element from being put onto the page, which can change how other elements on the page are laid out.
usually testing the visible part is enough from my experience, but if you are wanting to be more complete, then yeah you would have to check using "&&" conditions on multiple attributes.
It really all depends on how clean the code you are using is, and how well tested the rest of the UI aspect of the system is.
The other thing to consider is what is the purpose of the test. Are you testing code that you wrote, or how the browser is using Javascript to render the page? You want to be testing the code that you are creating, and rely on the fact that the browser works (because if the browser stops working, then the whole thing is unreliable anyway). So if your code tells the element to set some attribute, then checking for that attribute is all the testing you need to do. Anything on top of that can only really be proven by testing outside of the code itself (as in manualy looking at the page and other things like that).
If you want to see if an element exists in the DOM you could just do this:
$.fn.exists = function () {
return this.length > 0;
}
Usage:
$('#myid').exists();
Related
Is it possible to do a callback for the below?
$('.element').css("visibility","visible");
I came across this but seems like there are issues using this in chrome.
$('.element').css("visibility","visible").promise().done(function(){
alert( 'done! start stuff...' );
});
Basically I'm looking for a way to confirm that the $('.element') is visible before proceeding to the next line.
Setting an element to be visible is synchronous so there is no reason or purpose to using a promise with that. There is nothing to wait for that to take effect.
$('.element').css("visibility","visible");
console.log($('.element').css("visibility")); // will show "visible" immediately
If, on the other hand, you want to wait for a repaint so the item is actually drawn on the screen, that is a different story. You will have to either force a repaint (which is a tricky non-standard thing to do in browsers these days as they try to avoid synchronous repaints) or you will have to use a slight delay with setTimeout() which allows a repaint to happen.
For making an element visible, try display:block or display:inline-block (and a bunch of other display properties other than display:hidden).
Here is a difference between display and visibility properties.
Also, making an element visible doesn't guarantee that it is visible to user since it could be child of hidden parent element. You can use visible selector of jquery to confirm the same.
$('.element').css("display","block");
if ( $('.element').is( ":visible" )
{
}
I need to determine the height of a DOM element using javascript - specifically, in my case, a div containing some text. Due to the way that HTML works, I can only reliably do this if the element is visible. The general purpose solution is to show the element, get it's height, and then hide it - simple enough in the single element case.
However, in the general case, the element in question may be a child of other elements that are hidden, thus preventing the above solution from working - calling jQuery's show() function on the element in question doesn't actually cause it to be shown due to the hidden parent, so you still can't get the height.
How can I make an element visible long enough to get its height, taking into account any parent elements that need to be made visible to make it work?
Use case: I'm trying to write some code that I can apply to any table element, that creates some other elements whose height should match the height of the table header. I want to keep the code generic enough that it will work regardless of where in the DOM the table is located, or if it is currently visible. An alternate solution would be to have some javascript that simply adjusts the size of the created elements when the size of the table header changes (such as when it is shown), but conceptually that seems less efficient. Still, if it is easier, I will accept that as an answer.
Edit: To give an example, while keeping in mind I am going for a general solution that is not tied to this specific HTML layout, consider the following HTML:
<div style="display:none; line-height:22px; font-size:18px;">
...Some random text or other content...
<div id="desired_size">
I want to find the height of this div when visible
</div>
...Possibly some more content/other stuff...
</div>
The goal is to get the height of that inner div, but I can't do that because it isn't displayed - it is hidden due to the parent div being hidden. If all I know about the HTML is the desired_size div, how would I go about making it visible enough to get the height? Granted, this example is trivial, but I'm trying to generalize it.
Edit 2: One suggestion was to clone the element and move it to somewhere that is visible. This works, but with a caveat: any inherited CSS properties that would affect the size are lost.
Edit 3: I'm trying to write a block of code that I can re-use in a variety of web pages, not just coding to a specific layout. As such, I can't make any assumptions about or changes to the parent HTML. The example above shows one case where this can cause difficulties.
Edit 4: As has been pointed out, it would be trivial to change the HTML such that the visual appearance is the same, but the issue doesn't exist. However, I am trying to find a solution that works with the HTML as written, regardless of how the HTML is written.
demo - http://jsbin.com/tosusanowu/edit?html,js,output
Assuming you know that desired_size div has always a parent that is hidden.
$(function(){
var desired_size = getDesiredSize('#desired_size');
});
function getDesiredSize(el) {
var $el = $(el), $parent = $el.parent(), desired_size = 0;
$parent.attr('style', 'opacity:0;position:absolute');
desired_size = $el.height();
$parent.attr('style', 'display:none');
return desired_size;
}
<div style="display:none;">
...Some random text or other content...
<div id="desired_size">
I want to find the height of this div when visible
</div>
...Possibly some more content/other stuff...
</div>
The following javascript/jQuery function should work in the general case where the HTML structure is unknown, as requested:
function getHeight(objectID){
var object=$('#'+objectID);
var nextObject=object;
var changedObjects=[];
var counter=0; //to prevent infinite looping
while(!object.is(':visible') && counter<100){
counter+=1;
var curObject=nextObject; //store a reference for use in loop
nextObject=curObject.parent();
var curStyle=curObject.css('display') //see if current object is hidden
if(curStyle!='none')
continue; //don't mess with non-hidden objects
//see if the display style is inline, or from a CSS file
var inlineStyles=curObject.attr("style");
if(typeof(inlineStyles)!=='undefined'){
inlineStyles.split(";").forEach(function(element){
var style = element.split(":");
if ($.trim(style[0]) === 'display') {
//Record the fact that the display properly is an inline style
curObject.data('floatinghead_inline_style',true);
return false; //break out of the forEach loop
}
});
}
curObject.show(); //if object is hidden, show it for now
visitedObjects.push(curObject); //save a reference so we can put it back later
}
var height=object.height(); //this should work properly, since object should now be visible
visitedObjects.forEach(function(item){
if(item.data('floatinghead_inline_style')===true)
item.hide();
else
item.css('display','');
})
}
The above code makes no assumptions about the HTML structure, particularly the depth of the object in question from the hidden parent element. Also, unlike the "clone item to a different, visible, location in the DOM" option, it should properly take into account any inherited attributes that affect the height.
I want to implement a simple menu just by using Vanilla JS. So I have a working onclick function, where I just twist visibility property on click of the menu item. CSS is by default set on visibility:hidden
function getContentP() {
var div = document.getElementById("menu1Content");
if (div.style.visibility === "hidden") {
div.style.visibility = "visible";
} else {
div.style.visibility = "hidden";
}
};
<a href="#menu1" onclick="getContentP()">
<h2>title</h2>
</a>
<!-- CONTENT BOX, show on clicks-->
<div id="menu1Content" style="background: #fefefe">
Some content to make it visible
</div>
This works as expected, but really slowly, and with poor results.
Any good suggestion to improve the code? And maybe add some nice transitions like fadeIn effect without using jQuery?
Thanks a lot.
Im not sure what slowly means in this case or what poor results you are seeing, but in general the thing that jumps out at me is the usage of onclick. When passing code like that to a dom element the runtime will essentially eval the snippet which is bad for a number of reasons, and certainly not great for performance (also likely can never be optimized by the vm).
element.addEventListener('click', function() { 'your stuff here' }, false);
may give you better performance but id be shocked if you can even tell the difference unless this is called thousands or maybe millions of times.
You could also cache the dom element since you seem be doing a lookup by id, then you dont have to do a potentially expensive dom search every time the thing is clicked.
I'm not css guru but you can probably get something cool with this without too much effort.
[from comments] I usually need two clicks on the link to get it to show in the first place, which is really strange
No, that is anything but strange.
element.style.property only allows you to access CSS values that where set either directly via a style attribute on the element, or by assigning a value to element.style.property via script.
Both is not the case here, and your class="hidden" that you had in your code initially (before editing it out) was likely to set the element’s visibility hidden from the stylesheet, right?
Therefor, when you check the current visibility of the element here for the first time,
if (div.style.visibility === "hidden") {
that condition is not true, so you set the visibility to hidden in your else-branch – and therefor the element stays hidden.
Now, on your second click, the value hidden was set via script, so now you can read it back. Now that if condition results in true, and your script sets the element to visible.
Easy way to work around this – turn the logic around:
Check div.style.visibility === "visible", and set the element to hidden if that’s true, and visible if it is false.
The element is hidden (via the stylesheet) when your page first loads. Because of what I explained before, div.style.visibility can’t read the value on the first click, so the condition will be false, and the element will be made visible.
The HTML (note the added id):
<a href="#" id="menu1Toggle" style="visibility: hidden;">
<h2>title</h2>
</a>
The handler (note the added ev and preventDefault()):
function getContentP(ev)
{
var div = document.getElementById("menu1Content");
div.style.visibility = div.style.visibility === "hidden" ? "visible" : "hidden";
ev.preventDefault();
};
Attach the event with:
document.getElementById("menu1Toggle").onclick = getContentP;
You could use opacity if you want to fadeIn/Out. Just add a CSS transition. An easy toggle method would be:
elem.style.opacity = +!parseInt(elem.style.opacity);
Not sure if this would perform better/worse, but here is a Fiddle
I have bunch of images in a wrapper div. I need to hide all of them except the one user clicks on.
What is the most performance concise way of doing that?
Should I apply class on all of them to hide them all and than filter out the one that was clicked and show only that one or should I loop over them all hiding them as loop progresses with exception of the one that was clicked or something else?
Tnx
In modern desktop browsers you won't see any difference. Browsers are tuned so that they are blazing fast in rendering any changes is DOM three. Guts tell me that it might be sligtly faster to loop through all images and set visibility depending on item clicked using style attribute and not using class. In that way you have to process only N elements and no external CSS files are involved. If you hide all and show the element with was clicked, you process N + 1 elements.
In your situation I would use solution that is fastest, more managable and clean from the developers standpoint as there won't be much difference in the final result if you use one method or another.
PS: If you're using jquery, you can use the following:
Lets say, your div has id='test-div', and there are several images in it. All these images can be accessed as:
$('#test-div img')
Now, lets assume you know the id of image which got clicked. Lets assume id='my-image'.
You can execute the following to hide all other images (except 'my-image'):
$('#test-div img').not('#my-image').addClass('hide')
One of the most performant ways would be to let CSS do the visibility. It sounds to me like you're only displaying one at a time, in which case you can do it with two DOM operations by using classes;
// scope above
var lastClicked = null;
// then in click listener, 1st param `e`
if (lastClicked) lastClicked.className = ''; // remove visible class
lastClicked = e.target; // get clicked node
lastClicked.className = 'visible'; // add visible class
I'm assuming event.target but depending how the listener is attached, you might want to use this or some other logic. Further, if you expect element.classList support, you can use add and remove from that.
Example CSS of how to show only nodes with class token visible.
selector:not(.visible) {
display: none;
}
I'd like to hide (remove) all <div> that contain a certain string. Like a filter. Think of it having the functionality of a browser add-on.
Basically anything that is
Within a tag within the div, or
Immediately inside the div (but not a tag)
Any ideas of how to best do this efficiently? Ideally I'd like a way to have the browser respond well to this by not only hiding the div, but removing it in such a way that the page has no large blank spaces.
I'm really not super fluent in javascript, so thought I'd see if I could get some pointers here. (And is better to use straight JS or JQuery?)
thanks!
First, make a plan:
Find all the nodes that have the phrase. This SO Q will help.
For each node you find, go up the dom tree until you find the first enclosing div to remove. See JQuery dom transversal helpers
Then remove the appropriate divs. You may want to animate their removal, use jquery for that too.
Re: Use jquery? Up to you. If you want your code to work on multiple browsers then jquery will help. Your problem can be solved with or without jquery.
Good luck.
Try my JQuery plugin searchEngine
Syntax
$(selector).searchengine(textFilter,action,caseSensitive)
For your case , invoke it as following :
var myTxt="dfvdf...."
$('div').searchengine(myTxt,'remove',false);
If you want to remove also all <p> that contains myTxt :
$('div,p').searchengine(myTxt,'remove',false);
if you want to hide it instead of removing it :
$('div').searchengine(myTxt,'hide',false);
if you want to show it after that :
$('div').searchengine(myTxt,'show',false);
and so forth
Demo : http://jsfiddle.net/abdennour/k3x53/1/
Hacked together from this answer: Get all visible DIVs on a page with javascript?
This is fairly simple with jQuery, but you requested non-jquery so I will give it a quick go:
function removeDivs(withString) {
var divs = document.getElementsByTagName("DIV");
for(var i = 0; i < divs.length; i++) {
div = divs[i];
if (div.style.display != "none" && div.innerHTML.indexOf(withString) > -1) {
div.style.display = "none";
}
}
}
I would note that you said "phrase inside them", but did not specify the level to which you wanted to find out that the phrase is inside. In the case of nested divs, this will hide all the divs as far up as it can go that have the phrase in their innerHTML. In other words, since innerHTML contains all the contained divs, any div containing a div that has the phrase in it will also be hidden, and so forth on up the tree.
Another note, this is not efficient at all in that it probably will end up redundantly hiding divs that don't need to be hidden.
If I were to do it, I would use jQuery and try to get something a little more efficient...it would be re-inventing the wheel not to IMHO (unless there are technical restrictions or browser restrictions that prevent jQuery from running).