最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Ignore visibility of outer elements and select the first visible child element in a jQuery selector - Stack Overflo

programmeradmin3浏览0评论

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?

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?

Share Improve this question edited Feb 15, 2017 at 2:39 Josh Crozier 241k56 gold badges400 silver badges313 bronze badges asked Jan 22, 2016 at 16:14 HeinziHeinzi 172k61 gold badges381 silver badges546 bronze badges 2
  • 4 You can't, if the element is hidden, it's hidden, and elements inside a hidden parent element, are hidden. – adeneo Commented Jan 22, 2016 at 16:16
  • Try something similar to this: jsfiddle/jabark/p80ttvtb/4 – Jamie Barker Commented Jan 22, 2016 at 16:29
Add a ment  | 

8 Answers 8

Reset to default 1

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./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>

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>

JS Fiddle

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.

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./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>

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:

Updated Example

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./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 puted 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.

Updated Example

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./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>

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./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>

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./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>

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;
    }
});

与本文相关的文章

发布评论

评论列表(0)

  1. 暂无评论