Reputation: 172280
HTML:
<div class="outer">
<div id="inner1" class="inner" style="display: none"></div>
<div id="inner2" class="inner"></div>
<div id="inner3" class="inner"></div>
</div>
JavaScript (fiddle):
var $first_visible = $("div.inner:visible:first");
This returns the first visible inner div, which is inner2
.
However, as soon as the outer div is hidden (let's say I want to fade it in at some later time):
<div class="outer" style="display: none">
<div id="inner1" class="inner" style="display: none"></div>
<div id="inner2" class="inner"></div>
<div id="inner3" class="inner"></div>
</div>
all inner divs are considered hidden and the selector does not return inner2
any more.
How would I need to modify my jQuery selector to ignore the container's visibility?
Upvotes: 13
Views: 1728
Reputation: 33
If I understood you correctly, you can simulate the effects of the parent being hidden using CSS like this.
HTML
<div class="outer hide">
<div id="inner1" class="inner hide">Inner 1</div>
<div id="inner2" class="inner">Inner 2</div>
<div id="inner3" class="inner">Inner 3</div>
</div>
CSS
.hide {
background: rgba(0,0,0,0);
color: rgba(0,0,0,0);
border-color: rgba(0,0,0,0);
// For an SVG
fill: rgba(0,0,0,0);
stroke-opacity: 0;
}
The reason why you can't use the visibility/display/opacity property is because as @Umesh mentioned that the all descendant elements will also get their display/visibility/opacity as not visible as if the element doesn't exist in the document tree.
But using this method you set the alpha to 0 of the element and this doesn't effect the descendants unless they have inherit
set for those properties.
Hope this helps.
Upvotes: 1
Reputation: 31
Take a flag value and loop each div.inner
to get first visible element. Then check its css property.
Below is the tested code :
var isValid=true;
$("div.inner").each(function() {
if($(this).css("display") == "block" && isValid) {
$("div#result").text($(this).attr('id'));isValid=false;
}
});
Upvotes: 0
Reputation: 29
MDN says:
When you use none, all descendant elements also have their display turned off. The document is rendered as though the element doesn't exist in the document tree.
Hence, whatever the HTML elements are child to the parent element will not be rendered in the HTML page.
And moreover, whatever styles that has been applied on the parent element will not be rendered in HTML page.
In order to achieve what you want and if you consider that your HTML element should be in the document tree then try using CSS visibility property. For example:
<div class="outer" style="visibility: hidden">
<div id="inner1" class="inner" style="display: none"></div>
<div id="inner2" class="inner" style="visibility: visible"></div>
<div id="inner3" class="inner"></div>
</div>
Upvotes: 1
Reputation: 1679
See here i have checked style attribute for ignore first div. And check with hidden selector for get all other div.
$(document).ready(function(){
var currElements=$('.inner[style!="display: none"]:hidden'); // Here you are get two div with id inner2 and inner3
alert(currElements[0].id); // First div
alert(currElements[1].id); // First div
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="outer" style="display: none">
<div id="inner1" class="inner" style="display: none">Inner 1</div>
<div id="inner2" class="inner">Inner 2</div>
<div id="inner3" class="inner">Inner 3</div>
</div>
Upvotes: 0
Reputation: 42054
My proposal is to use a filter function but only to select the first visible element (but this is also hidden because the parent is hidden):
var $first_visible = $('div.inner').filter(function() { return !(this.style.visibility != '' || this.style.display != ''); }).first();
$(function () {
var $first_visible = $('div.inner').filter(function() {
return !(this.style.visibility != '' || this.style.display != '');
}).first();
$('body').append('<p>' + $first_visible.attr('id') + '</p>');
});
<script src="http://code.jquery.com/jquery-1.11.3.js"></script>
<div class="outer" style="display: none">
<div id="inner1" class="inner" style="display: none;"></div>
<div id="inner2" class="inner"></div>
<div id="inner3" class="inner"></div>
</div>
Upvotes: 0
Reputation: 240968
One option would be to show the parent element, check for the first visible element, and then hide the parent element again.
Alternatively, since the element has inline CSS, you could filter the elements based on whether the display
property is set to none
and then retrieve the first one in the filtered collection:
var $first_visible = $(".inner").filter(function () {
return this.style.display !== 'none';
}).first();
var $first_visible = $(".inner").filter(function () {
return this.style.display !== 'none';
}).first();
$("div#result").text('First visible: #' + $first_visible[0].id);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="outer" style="display: none;">
<div id="inner1" class="inner" style="display: none"></div>
<div id="inner2" class="inner"></div>
<div id="inner3" class="inner"></div>
</div>
<div id="result"></div>
However, the better approach would be to check the computed style of the element using the .getComputedStyle()
method. In doing so, you can determine whether the display
of the element is set to none
even if the element doesn't have inline CSS.
var $first_visible = $(".inner").filter(function () {
return window.getComputedStyle(this, null).getPropertyValue('display') !== 'none';
}).first();
var $first_visible = $(".inner").filter(function () {
return window.getComputedStyle(this, null).getPropertyValue('display') !== 'none';
}).first();
$("div#result").text('First visible: #' + $first_visible[0].id);
#inner1 { display: none; }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="outer" style="display: none;">
<div id="inner1" class="inner"></div>
<div id="inner2" class="inner"></div>
<div id="inner3" class="inner"></div>
</div>
<div id="result"></div>
Upvotes: 0
Reputation: 379
write two classes : first one to display and last one to hide. With that you can select all divs whoses "visible" even if parent is "hidden"
var $first_visible = $("div.inner.enable");
console.log($first_visible);
$("div#result").text($first_visible[0].id);
.disable{
display : none;
}
.enable{
display : block;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="outer disable">
<div id="inner1" class="inner disable">1</div>
<div id="inner2" class="inner enable">2</div>
<div id="inner3" class="inner enable">3</div>
</div>
<div id="result"></div>
Upvotes: 0
Reputation: 30557
As adeneo said, once its hidden, there isnt much you can do.
However, you can check before hand, show it regardless, then hide it again if it was hidden
var wasVisible = $(".outer").is(':visible');
$(".outer").show();
var $first_visible = $("div.inner:visible:first");
if (!wasVisible) {
$(".outer").hide();
}
console.log($first_visible.length);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div class="outer" style="display: none">
<div id="inner1" class="inner" style="display: none"></div>
<div id="inner2" class="inner"></div>
<div id="inner3" class="inner"></div>
</div>
Upvotes: 1