Jquery думает, что мой <g>элемент виден, даже если для параметра display установлено значение none и / или для параметра visibility установлено значение hidden - PullRequest
1 голос
/ 10 июля 2020

Пожалуйста, взгляните на пример, который я создал ниже. Когда вы нажимаете кнопку, <g> переключается, а зеленая точка отображается или скрывается.

Как ни странно, is(':visible') ВСЕГДА возвращает true, даже если visibility установлен на hidden.

Почему это происходит?

console.log('Jquery running...')

$("button").click( () => {
  var prev = $("g").attr('visibility');
  if (prev === 'hidden') {
$('g').attr('visibility', 'visible');
  } else {
$('g').attr('visibility', 'hidden');
  }

  console.log('element is visible:', el.is(':visible'));
});

var el = $('g');
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<p>My Example</p>

<svg width="20" height="30">

<g>
<circle cx="10" cy="10" r="10" fill="green"></circle>
</g>
</svg>

<button> Toggle Dot </button>

ОБНОВЛЕНИЕ

Я также пробовал установить display на none раньше, и это тоже не сработало

Ответы [ 2 ]

2 голосов
/ 10 июля 2020

Есть два отдельных случая, требующих внимания:

visibility: hidden

Элементы с visibility: hidden согласно документации JQuery по-прежнему считаются видимыми для селектора :visible:

Элементы с visibility: hidden или opacity: 0 считаются видимыми, поскольку они по-прежнему занимают место в макете.

display: none

Элементы с display: none не занимают место в макете, поэтому теоретически не должны выбираться селектором :visible. Когда мы смотрим на JQuery код , используемый для определения, является ли элемент видимым или нет, он основывается на трех значениях:

jQuery.expr.pseudos.visible = function( elem ) { 
        return !!( elem.offsetWidth || elem.offsetHeight || elem.getClientRects().length );
};

По крайней мере, в Chrome, offsetWidth и offsetHeight не определены для элементов SVG.

Это оставляет нас с клиентскими прямоугольниками, и здесь проблема, кажется, l ie, поскольку все еще существует клиентский прямоугольник, связанный с g элемент, для которого display установлено значение none:

console.log('Jquery running...')

$('button').click(() => {
  var prev = $('g').css('display');
  if (prev === 'none') {
    $('g').css('display', 'block');
  } else {
    $('g').css('display', 'none');
  }
  
  console.log(el[0].getClientRects().length); // 1
})

var el = $('g');
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<p>My Example</p>

<svg width="20" height="30">

<g>
<circle cx="10" cy="10" r="10" fill="green"></circle>
</g>
</svg>

<button> Toggle Dot </button>

Похоже на ошибку в Chrome, потому что он корректно работает в Firefox. Однако, похоже, есть путаница относительно того, что getClientRects() должно возвращать в случае внутренних элементов SVG.

2 голосов
/ 10 июля 2020

Переключение видимости circle работает

Jquery исходный код:

jQuery.expr.pseudos.visible = function( elem ) {
    return !!( elem.offsetWidth || elem.offsetHeight || elem.getClientRects().length );
};

Здесь offsetWidth, offsetHeight, getClientRects() возвращает null для g элемент

console.log('Jquery running...')

$("button").click(() => {
  el.toggle();

  console.log('element is visible:', el.is(':visible'));
});

var el = $('g circle');
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<p>My Example</p>

<svg width="20" height="30">

<g>
<circle cx="10" cy="10" r="10" fill="green"></circle>
</g>
</svg>

<button> Toggle Dot </button>
...