Как я проверяю, действительно ли элемент видим с JavaScript? [дубликат]

Начиная с версии 2.0.9, в highcharts-export-server вы можете включить moment.js, выполнив npm install в интерактивном режиме или установив переменную среды HIGHCHARTS_MOMENT в 1.

Похожие проблемы: https://github.com/highcharts/node-export-server/issues/119

117
задан Peter Mortensen 30 October 2016 в 16:53
поделиться

12 ответов

Для пункта 2.

Я вижу, что никто не предлагал использовать document.elementFromPoint (x, y) , для меня это самый быстрый способ проверить, является ли элемент вложенным или скрытым другим. Вы можете передать смещения целевого элемента в функцию.

Вот тестовая страница PPK на elementFromPoint .

94
ответ дан 24 November 2019 в 02:09
поделиться

Проверьте offsetHeight свойство элементов. Если это - больше чем 0, это видимо.Примечание: этот подход не покрывает ситуацию, когда стиль visibility:hidden установлен. Но тот стиль является чем-то странным так или иначе.

-1
ответ дан 24 November 2019 в 02:09
поделиться

Я не хотел бы перенаправить Вас к jQuery (как, часто делается), но эта дискуссия о том, когда элементы действительно видимы, очень проницательна.

И начиная с jQuery 1.3.2 это больше не проблема.

0
ответ дан 24 November 2019 в 02:09
поделиться

Вот пример сценария и тестовый пример. Покрывает позиционированные элементы, видимость: скрыта, отображение: нет. Не тестировал z-index, предположим, что он работает.

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
  <head>
    <title></title>
    <style type="text/css">
    div {
      width: 200px;
      border: 1px solid red;
    }
    p {
      border: 2px solid green;
    }
    .r {
      border: 1px solid #BB3333;
      background: #EE9999;
      position: relative;
      top: -50px;
      height: 2em;
    }
    .of {
      overflow: hidden;
      height: 2em;
      word-wrap: none; 
    }
    .of p {
      width: 100%;
    }

    .of pre {
      display: inline;
    }
    .iv {
      visibility: hidden;
    }
    .dn {
      display: none;
    }
    </style>
    <script src="http://www.prototypejs.org/assets/2008/9/29/prototype-1.6.0.3.js"></script>
    <script>
      function isVisible(elem){
        if (Element.getStyle(elem, 'visibility') == 'hidden' || Element.getStyle(elem, 'display') == 'none') {
          return false;
        }
        var topx, topy, botx, boty;
        var offset = Element.positionedOffset(elem);
        topx = offset.left;
        topy = offset.top;
        botx = Element.getWidth(elem) + topx;
        boty = Element.getHeight(elem) + topy;
        var v = false;
        for (var x = topx; x <= botx; x++) {
          for(var y = topy; y <= boty; y++) {
            if (document.elementFromPoint(x,y) == elem) {
              // item is visible
              v = true;
              break;
            }
          }
          if (v == true) {
            break;
          }
        }
        return v;
      }

      window.onload=function() {
        var es = Element.descendants('body');
        for (var i = 0; i < es.length; i++ ) {
          if (!isVisible(es[i])) {
            alert(es[i].tagName);
          }
        }
      }
    </script>
  </head>
  <body id='body'>
    <div class="s"><p>This is text</p><p>More text</p></div>
    <div class="r">This is relative</div>
    <div class="of"><p>This is too wide...</p><pre>hidden</pre>
    <div class="iv">This is invisible</div>
    <div class="dn">This is display none</div>
  </body>
</html>
-1
ответ дан 24 November 2019 в 02:09
поделиться

Catch mouse-drag and viewport events (onmouseup, onresize, onscroll).

When a drag ends do a comparison of the dragged item boundary with all "elements of interest" (ie, elements with class "dont_hide" or an array of ids). Do the same with window.onscroll and window.onresize. Mark any elements hidden with a special attribute or classname or simply perform whatever action you want then and there.

The hidden tests are pretty easy. For "totally hidden" you want to know if ALL corners are either inside the dragged-item boundary or outside the viewport. For partially hidden you're looking for a single corner matching the same test.

0
ответ дан 24 November 2019 в 02:09
поделиться

Библиотека элементов Prototype - одна из самых мощных библиотек запросов с точки зрения методов. Я рекомендую вам проверить API.

Несколько советов:

  1. Проверка видимости может быть проблемой, но вы можете использовать метод Element.getStyle () и Element.visible () методы, объединенные в пользовательскую функцию. С помощью getStyle () вы можете проверить фактический вычисленный стиль.

  2. Я не знаю точно, что вы имеете в виду под словом «снизу» :) Если вы имели в виду, что он имеет определенного предка, например, обертка div, вы можете использовать Element.up (cssRule) :

     var child = $ ("myparagraph");
    if (! child.up ("mywrapper")) {
     // Я потерял маму!
    }
    else {
     // Я нашел свою маму!
    }
    

    Если вы хотите проверить братьев и сестер дочернего элемента, вы тоже можете это сделать:

     var child = $ ("myparagraph");
    if (! child.previous ("mywrapper")) {
     // Я потерял своего брата!
    } 
    else {
     // Я нашел своего брата!
    }
    
  3. Опять же, Element lib может помочь вам, если я правильно понимаю, что вы имеете в виду :) Вы можете проверить фактические размеры области просмотра и смещение вашего элемента , чтобы вы могли вычислить если ваш элемент находится вне экрана.

Удачи!

Я вставил тестовый пример для prototypejs на http://gist.github.com/117125 . Похоже, в вашем случае мы вообще не можем доверять getStyle () . Для максимальной надежности функции isMyElementReallyVisible вы должны объединить следующее:

  • Проверка вычисляемого стиля (у dojo есть хорошая реализация , которую вы можете позаимствовать)
  • Проверка смещения окна просмотра (прототип собственного метода)
  • Проверка z-index для "снизу" проблема (в Internet Explorer может быть ошибка)
2
ответ дан 24 November 2019 в 02:09
поделиться

Это то, что у меня есть. Он охватывает как 1, так и 3. Однако я все еще борюсь с 2, поскольку я не так хорошо знаком с Prototype (я больше люблю jQuery).

function isVisible( elem ) {
    var $elem = $(elem);

    // First check if elem is hidden through css as this is not very costly:
    if ($elem.getStyle('display') == 'none' || $elem.getStyle('visibility') == 'hidden' ) {
        //elem is set through CSS stylesheet or inline to invisible
        return false;
    }

    //Now check for the elem being outside of the viewport
    var $elemOffset = $elem.viewportOffset();
    if ($elemOffset.left < 0 || $elemOffset.top < 0) {
        //elem is left of or above viewport
        return false;
    }
    var vp = document.viewport.getDimensions();
    if ($elemOffset.left > vp.width || $elemOffset.top > vp.height) {
        //elem is below or right of vp
        return false;
    }

    //Now check for elements positioned on top:
    //TODO: Build check for this using Prototype...
    //Neither of these was true, so the elem was visible:
    return true;
}
3
ответ дан 24 November 2019 в 02:09
поделиться

Интересный вопрос.

Это мой подход.

  1. Сначала проверьте, что element.style.visibility! == 'hidden' && element.style.display! == ' none '
  2. Затем проверьте с помощью document.elementFromPoint (element.offsetLeft, element.offsetTop), если возвращаемый элемент является элементом, который я ожидал, это сложно определить, полностью ли перекрывает один элемент другой.
  3. Наконец, проверьте, не перекрывается ли offsetTop и offsetLeft расположены в области просмотра с учетом смещения прокрутки.

Надеюсь, это поможет.

3
ответ дан 24 November 2019 в 02:09
поделиться

Ответ на первый вопрос довольно прост, если вы все еще можете использовать prototype (prototypejs):

$('HtmlElementID').visible(); returns: true|false
-2
ответ дан 24 November 2019 в 02:09
поделиться

Я не думаю, что проверка собственной видимости и свойств отображения элемента достаточно для выполнения требования №1, даже если вы используете currentStyle / getComputedStyle. Вы также должны проверить предков элемента. Если предок скрыт, скрывается и элемент.

0
ответ дан 24 November 2019 в 02:09
поделиться

I don't know how much of this is supported in older or not-so-modern browsers, but I'm using something like this (without the neeed for any libraries):

function visible(element) {
  if (element.offsetWidth === 0 || element.offsetHeight === 0) return false;
  var height = document.documentElement.clientHeight,
      rects = element.getClientRects(),
      on_top = function(r) {
        var x = (r.left + r.right)/2, y = (r.top + r.bottom)/2;
        return document.elementFromPoint(x, y) === element;
      };
  for (var i = 0, l = rects.length; i < l; i++) {
    var r = rects[i],
        in_viewport = r.top > 0 ? r.top <= height : (r.bottom > 0 && r.bottom <= height);
    if (in_viewport && on_top(r)) return true;
  }
  return false;
}

It checks that the element has an area > 0 and then it checks if any part of the element is within the viewport and that it is not hidden "under" another element (actually I only check on a single point in the center of the element, so it's not 100% assured -- but you could just modify the script to itterate over all the points of the element, if you really need to...).

Update

Modified on_top function that check every pixel:

on_top = function(r) {
  for (var x = Math.floor(r.left), x_max = Math.ceil(r.right); x <= x_max; x++)
  for (var y = Math.floor(r.top), y_max = Math.ceil(r.bottom); y <= y_max; y++) {
    if (document.elementFromPoint(x, y) === element) return true;
  }
  return false;
};

Don't know about the performance :)

37
ответ дан 24 November 2019 в 02:09
поделиться

Как указал jkl, проверки видимости или отображения элемента недостаточно. Необходимо проверить его предков. Selenium делает это, когда проверяет видимость элемента.

Проверьте метод Selenium.prototype.isVisible в файле selenium-api.js.

http://svn.openqa.org/svn/selenium-on-rails/selenium-on-rails/selenium-core/scripts/selenium-api.js

7
ответ дан 24 November 2019 в 02:09
поделиться
Другие вопросы по тегам:

Похожие вопросы: