[javascript] 요소가 DOM에 보이는지 확인

순수 JS (jQuery 없음)에서 요소가 표시되는지 확인할 수있는 방법이 있습니까?

따라서 예를 들어 Performance Bikes 페이지에서 거래 (상단 메뉴의 거래) 위로 마우스를 가져 가면 거래 창이 표시되지만 처음에는 표시되지 않았습니다. HTML에 있지만 표시되지 않습니다.

따라서 DOM 요소가 주어지면 표시 여부를 어떻게 확인할 수 있습니까? 나는 시도했다 :

window.getComputedStyle(my_element)['display']);

그러나 작동하지 않는 것 같습니다. 어떤 속성을 확인해야하는지 궁금합니다. 내 마음에 온다 :

display !== 'none'
visibility !== 'hidden'

내가 잃어버린 다른 사람이 있습니까?



답변

이 MDN documentation 에 따르면 요소 또는 그 부모가 표시 스타일 속성을 통해 숨겨 질 때마다 요소의 offsetParent속성이 반환 null됩니다. 요소가 고정되어 있지 않은지 확인하십시오. position: fixed;페이지에 요소 가없는 경우이를 확인하는 스크립트 는 다음과 같습니다.

// Where el is the DOM element you'd like to test for visibility
function isHidden(el) {
    return (el.offsetParent === null)
}

당신이 다른 한편, 만약 않는 이 검색에 잡힐 수있는 위치에 고정 요소를 가지고, 당신은 슬프게도 (천천히) 사용해야합니다 window.getComputedStyle(). 이 경우의 기능은 다음과 같습니다.

// Where el is the DOM element you'd like to test for visibility
function isHidden(el) {
    var style = window.getComputedStyle(el);
    return (style.display === 'none')
}

옵션 # 2는 더 많은 경우를 설명하기 때문에 좀 더 간단 할 것입니다. 그러나 나는 그것도 상당히 느리게 베팅합니다. 따라서이 작업을 여러 번 반복해야한다면 피하는 것이 가장 좋습니다.


답변

다른 모든 솔루션은 나를 위해 어떤 상황을 겪었습니다 ..

다음에서 승리하는 답변보기 :

http://plnkr.co/edit/6CSCA2fe4Gqt4jCBP2wu?p=preview

결국, 나는 최선의 해결책이라고 결정했다. $(elem).is(':visible')그러나 이것은 순수한 자바 스크립트가 아니다. jquery입니다.

그래서 나는 그들의 출처를 들여다보고 내가 원하는 것을 찾았습니다.

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

이것은 소스입니다 : https://github.com/jquery/jquery/blob/master/src/css/hiddenVisibleSelectors.js


답변

사용자가 관심을 보인 경우 :

function isVisible(elem) {
    if (!(elem instanceof Element)) throw Error('DomUtil: elem is not an element.');
    const style = getComputedStyle(elem);
    if (style.display === 'none') return false;
    if (style.visibility !== 'visible') return false;
    if (style.opacity < 0.1) return false;
    if (elem.offsetWidth + elem.offsetHeight + elem.getBoundingClientRect().height +
        elem.getBoundingClientRect().width === 0) {
        return false;
    }
    const elemCenter   = {
        x: elem.getBoundingClientRect().left + elem.offsetWidth / 2,
        y: elem.getBoundingClientRect().top + elem.offsetHeight / 2
    };
    if (elemCenter.x < 0) return false;
    if (elemCenter.x > (document.documentElement.clientWidth || window.innerWidth)) return false;
    if (elemCenter.y < 0) return false;
    if (elemCenter.y > (document.documentElement.clientHeight || window.innerHeight)) return false;
    let pointContainer = document.elementFromPoint(elemCenter.x, elemCenter.y);
    do {
        if (pointContainer === elem) return true;
    } while (pointContainer = pointContainer.parentNode);
    return false;
}

테스트 ( 모카 용어 사용) :

describe.only('visibility', function () {
    let div, visible, notVisible, inViewport, leftOfViewport, rightOfViewport, aboveViewport,
        belowViewport, notDisplayed, zeroOpacity, zIndex1, zIndex2;
    before(() => {
        div = document.createElement('div');
        document.querySelector('body').appendChild(div);
        div.appendChild(visible = document.createElement('div'));
        visible.style       = 'border: 1px solid black; margin: 5px; display: inline-block;';
        visible.textContent = 'visible';
        div.appendChild(inViewport = visible.cloneNode(false));
        inViewport.textContent = 'inViewport';
        div.appendChild(notDisplayed = visible.cloneNode(false));
        notDisplayed.style.display = 'none';
        notDisplayed.textContent   = 'notDisplayed';
        div.appendChild(notVisible = visible.cloneNode(false));
        notVisible.style.visibility = 'hidden';
        notVisible.textContent      = 'notVisible';
        div.appendChild(leftOfViewport = visible.cloneNode(false));
        leftOfViewport.style.position = 'absolute';
        leftOfViewport.style.right = '100000px';
        leftOfViewport.textContent = 'leftOfViewport';
        div.appendChild(rightOfViewport = leftOfViewport.cloneNode(false));
        rightOfViewport.style.right       = '0';
        rightOfViewport.style.left       = '100000px';
        rightOfViewport.textContent = 'rightOfViewport';
        div.appendChild(aboveViewport = leftOfViewport.cloneNode(false));
        aboveViewport.style.right       = '0';
        aboveViewport.style.bottom       = '100000px';
        aboveViewport.textContent = 'aboveViewport';
        div.appendChild(belowViewport = leftOfViewport.cloneNode(false));
        belowViewport.style.right       = '0';
        belowViewport.style.top       = '100000px';
        belowViewport.textContent = 'belowViewport';
        div.appendChild(zeroOpacity = visible.cloneNode(false));
        zeroOpacity.textContent   = 'zeroOpacity';
        zeroOpacity.style.opacity = '0';
        div.appendChild(zIndex1 = visible.cloneNode(false));
        zIndex1.textContent = 'zIndex1';
        zIndex1.style.position = 'absolute';
        zIndex1.style.left = zIndex1.style.top = zIndex1.style.width = zIndex1.style.height = '100px';
        zIndex1.style.zIndex = '1';
        div.appendChild(zIndex2 = zIndex1.cloneNode(false));
        zIndex2.textContent = 'zIndex2';
        zIndex2.style.left = zIndex2.style.top = '90px';
        zIndex2.style.width = zIndex2.style.height = '120px';
        zIndex2.style.backgroundColor = 'red';
        zIndex2.style.zIndex = '2';
    });
    after(() => {
        div.parentNode.removeChild(div);
    });
    it('isVisible = true', () => {
        expect(isVisible(div)).to.be.true;
        expect(isVisible(visible)).to.be.true;
        expect(isVisible(inViewport)).to.be.true;
        expect(isVisible(zIndex2)).to.be.true;
    });
    it('isVisible = false', () => {
        expect(isVisible(notDisplayed)).to.be.false;
        expect(isVisible(notVisible)).to.be.false;
        expect(isVisible(document.createElement('div'))).to.be.false;
        expect(isVisible(zIndex1)).to.be.false;
        expect(isVisible(zeroOpacity)).to.be.false;
        expect(isVisible(leftOfViewport)).to.be.false;
        expect(isVisible(rightOfViewport)).to.be.false;
        expect(isVisible(aboveViewport)).to.be.false;
        expect(isVisible(belowViewport)).to.be.false;
    });
});


답변

도움이 될 수 있습니다 :
가장 왼쪽 위치에 배치하여 요소를 숨기고 offsetLeft 속성을 확인하십시오. jQuery를 사용하려면 : visible 선택기 를 확인 하고 요소의 가시성 상태를 얻을 수 있습니다 .

HTML :

<div id="myDiv">Hello</div>

CSS :

<!-- for javaScript-->
#myDiv{
   position:absolute;
   left : -2000px;
}

<!-- for jQuery -->
#myDiv{
    visibility:hidden;
}

자바 스크립트 :

var myStyle = document.getElementById("myDiv").offsetLeft;

if(myStyle < 0){
     alert("Div is hidden!!");
}

jQuery :

if(  $("#MyElement").is(":visible") == true )
{
     alert("Div is visible!!");
}

jsFiddle


답변

jQuery와 동일한 코드를 사용하십시오.

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

따라서 함수에서 :

function isVisible(e) {
    return !!( e.offsetWidth || e.offsetHeight || e.getClientRects().length );
}

내 Win / IE10, Linux / Firefox.45, Linux / Chrome.52의 매력처럼 작동합니다 …

jQuery가없는 jQuery에 감사드립니다!


답변

위의 몇 가지 답변을 결합하면 :

function isVisible (ele) {
    var style = window.getComputedStyle(ele);
    return  style.width !== "0" &&
    style.height !== "0" &&
    style.opacity !== "0" &&
    style.display!=='none' &&
    style.visibility!== 'hidden';
}

AlexZ가 말했듯이, 찾고있는 것을 더 구체적으로 알고 있다면 다른 옵션보다 느릴 수 있지만 요소가 숨겨지는 모든 주요 방법을 포착해야합니다.

그러나 그것은 또한 당신에게 보이는 것으로 계산됩니다. 예를 들어, div의 높이는 0px로 설정할 수 있지만 오버플로 속성에 따라 내용이 계속 표시됩니다. 또는 div의 내용을 배경과 같은 색으로 만들어 사용자가 볼 수는 없지만 여전히 페이지에 렌더링 할 수 있습니다. 또는 div가 화면 밖으로 이동하거나 다른 div 뒤에 숨겨 지거나 내용이 표시되지 않지만 테두리가 여전히 표시 될 수 있습니다. 어느 정도 “가시적”은 주관적인 용어입니다.


답변

위치가 ‘고정 된’요소를 가질 때 AlexZ의 getComputedStyle () 솔루션과 비교하여 성능이 뛰어난 솔루션을 얻었습니다. 일부 사례를 무시하려는 경우 (주석 확인) :

function isVisible(el) {
    /* offsetParent would be null if display 'none' is set.
       However Chrome, IE and MS Edge returns offsetParent as null for elements
       with CSS position 'fixed'. So check whether the dimensions are zero.

       This check would be inaccurate if position is 'fixed' AND dimensions were
       intentionally set to zero. But..it is good enough for most cases.*/
    if (!el.offsetParent && el.offsetWidth === 0 && el.offsetHeight === 0) {
        return false;
    }
    return true;
}

참고 : 엄밀히 말하면 “가시성”을 먼저 정의해야합니다. 필자의 경우, 불투명도가 0이거나 CSS 가시성 속성이 ‘숨겨진’등에도 문제없이 모든 DOM 메소드 / 속성을 실행할 수있는 한 요소를 볼 수 있습니다.