Development Tip

jQuery없이 가장 가까운 요소 찾기

yourdevel 2020. 10. 6. 19:32
반응형

jQuery없이 가장 가까운 요소 찾기


jquery없이 특정 태그 이름을 가진 가장 가까운 요소를 찾으려고합니다. 를 클릭하면 해당 테이블에 대한 <th>액세스 권한을 얻고 싶습니다 <tbody>. 제안? 오프셋에 대해 읽었지만 너무 많이 이해하지 못했습니다. 그냥 사용해야할까요?

th가 이미 클릭 된 요소로 설정되어 있다고 가정합니다.

th.offsetParent.getElementsByTagName('tbody')[0]

파티에 조금 늦었지만 그럼에도 불구하고. 이것은 트릭을 해야합니다 .

function closest(el, selector) {
    var matchesFn;

    // find vendor prefix
    ['matches','webkitMatchesSelector','mozMatchesSelector','msMatchesSelector','oMatchesSelector'].some(function(fn) {
        if (typeof document.body[fn] == 'function') {
            matchesFn = fn;
            return true;
        }
        return false;
    })

    var parent;

    // traverse parents
    while (el) {
        parent = el.parentElement;
        if (parent && parent[matchesFn](selector)) {
            return parent;
        }
        el = parent;
    }

    return null;
}

매우 간단합니다.

el.closest('tbody')

IE를 제외한 모든 브라우저에서 지원됩니다.
업데이트 : Edge도 지원합니다.

jQuery가 필요 없습니다. 더 이상 교체 jQuery를이다 $(this).closest('tbody')$(this.closest('tbody'))요소가 발견되지 크게하면 성능을 향상시킬 것입니다.

IE 용 Polyfill :

if (!Element.prototype.matches) Element.prototype.matches = Element.prototype.msMatchesSelector;
if (!Element.prototype.closest) Element.prototype.closest = function (selector) {
    var el = this;
    while (el) {
        if (el.matches(selector)) {
            return el;
        }
        el = el.parentElement;
    }
};

return요소를 찾을 수 없는 경우가 없으며 undefined가장 가까운 요소를 찾을 수 없을 때 효과적으로 반환 됩니다.

자세한 내용은 https://developer.mozilla.org/en-US/docs/Web/API/Element/closest를 참조하십시오.


다음은 jQuery없이 태그 이름으로 가장 가까운 요소를 가져 오는 방법입니다.

function getClosest(el, tag) {
  // this is necessary since nodeName is always in upper case
  tag = tag.toUpperCase();
  do {
    if (el.nodeName === tag) {
      // tag name is found! let's return it. :)
      return el;
    }
  } while (el = el.parentNode);

  // not found :(
  return null;
}

getClosest(th, 'tbody');

function closest(el, sel) {
    if (el != null)
        return el.matches(sel) ? el 
            : (el.querySelector(sel) 
                || closest(el.parentNode, sel));
}

이 솔루션은 HTML 5 사양의 최신 기능 중 일부를 사용하며 이전 / 호환되지 않는 브라우저 (읽기 : Internet Explorer)에서이를 사용하려면 폴리 필이 필요합니다.

Element.prototype.matches = (Element.prototype.matches || Element.prototype.mozMatchesSelector 
    || Element.prototype.msMatchesSelector || Element.prototype.oMatchesSelector 
    || Element.prototype.webkitMatchesSelector || Element.prototype.webkitMatchesSelector);

이를 수행하는 표준화 된 함수가 있습니다 : Element.closest . IE11을 제외한 대부분의 브라우저에서 지원합니다 ( caniuse.com의 세부 정보 ). MDN 워드 프로세서는 또한 이전 버전의 브라우저를 대상으로 할 경우에 polyfill을 포함한다.

tbody주어진 가장 가까운 부모 를 찾으려면 th다음을 수행하십시오.

th.closest('tbody');

직접 함수를 작성하려는 경우-여기에 내가 생각 해낸 것이 있습니다.

function findClosestParent (startElement, fn) {
  var parent = startElement.parentElement;
  if (!parent) return undefined;
  return fn(parent) ? parent : findClosestParent(parent, fn);
}

태그 이름으로 가장 가까운 부모를 찾으려면 다음과 같이 사용할 수 있습니다.

findClosestParent(x, element => return element.tagName === "SECTION");

내가 사용하는 간단한 기능은 다음과 같습니다.

function closest(el, selector) {
    var matches = el.webkitMatchesSelector ? 'webkitMatchesSelector' : (el.msMatchesSelector ? 'msMatchesSelector' : 'matches');

    while (el.parentElement) {
        if (el[matches](selector)) return el;

        el = el.parentElement;
    }

    return null;
}

@SalmanPK 답변을 확장하려면

마우스 오버와 같은 이벤트로 작업 할 때 유용한 선택기로 노드를 사용할 수 있습니다.

function closest(el, selector) {
    if (typeof selector === 'string') {
        matches = el.webkitMatchesSelector ? 'webkitMatchesSelector' : (el.msMatchesSelector ? 'msMatchesSelector' : 'matches');
        while (el.parentElement) {
            if (el[matches](selector)) {
                return el
            };
            el = el.parentElement;
        }
    } else {
        while (el.parentElement) {
            if (el === selector) {
                return el
            };
            el = el.parentElement;
        }
    }

    return null;
}

요약:

특정 조상을 찾기 위해 다음을 사용할 수 있습니다.

Element.closest();

이 함수는 CSS 선택기 문자열을 인수로 사용합니다. 그런 다음 인수에 전달 된 CSS 선택자와 일치하는 현재 요소 (또는 요소 자체)의 가장 가까운 조상을 반환합니다. 조상이 없으면 반환 null됩니다.

예:

const child = document.querySelector('.child');
// select the child

console.dir(child.closest('.parent').className);
// check if there is any ancestor called parent
<div class="parent">
  <div></div>
  <div>
    <div></div>
    <div class="child"></div>
  </div>
</div>


클래스, ID, 데이터 속성 또는 태그가 포함 된 트리에서 가장 가까운 DOM 요소를 가져옵니다. 요소 자체를 포함합니다. IE6에서 다시 지원됩니다.

var getClosest = function (elem, selector) {

    var firstChar = selector.charAt(0);

    // Get closest match
    for ( ; elem && elem !== document; elem = elem.parentNode ) {

        // If selector is a class
        if ( firstChar === '.' ) {
            if ( elem.classList.contains( selector.substr(1) ) ) {
                return elem;
            }
        }

        // If selector is an ID
        if ( firstChar === '#' ) {
            if ( elem.id === selector.substr(1) ) {
                return elem;
            }
        } 

        // If selector is a data attribute
        if ( firstChar === '[' ) {
            if ( elem.hasAttribute( selector.substr(1, selector.length - 2) ) ) {
                return elem;
            }
        }

        // If selector is a tag
        if ( elem.tagName.toLowerCase() === selector ) {
            return elem;
        }

    }

    return false;

};

var elem = document.querySelector('#some-element');
var closest = getClosest(elem, '.some-class');
var closestLink = getClosest(elem, 'a');
var closestExcludingElement = getClosest(elem.parentNode, '.some-class');

Here.

function findNearest(el, tag) {
    while( el && el.tagName && el.tagName !== tag.toUpperCase()) {
        el = el.nextSibling;     
    } return el;
} 

Only finds siblings further down the tree. Use previousSibling to go the other way Or use variables to traverse both ways and return whichever is found first. You get the general idea, but if you want to traverse through parentNodes or children if a sibling doesn't match you may as-well use jQuery. At that point it's easily worth it.


Find nearest Elements childNodes.

closest:function(el, selector,userMatchFn) {
var matchesFn;

// find vendor prefix
['matches','webkitMatchesSelector','mozMatchesSelector','msMatchesSelector','oMatchesSelector'].some(function(fn) {
    if (typeof document.body[fn] == 'function') {
        matchesFn = fn;
        return true;
    }
    return false;
});
function findInChilds(el){
    if(!el) return false;
    if(el && el[matchesFn] && el[matchesFn](selector)

    && userMatchFn(el) ) return [el];
    var resultAsArr=[];
    if(el.childNodes && el.childNodes.length){
        for(var i=0;i< el.childNodes.length;i++)
        {
             var child=el.childNodes[i];
             var resultForChild=findInChilds(child);
            if(resultForChild instanceof Array){
                for(var j=0;j<resultForChild.length;j++)
                {
                    resultAsArr.push(resultForChild[j]);
                }
            } 
        }

    }
    return resultAsArr.length?resultAsArr: false;
}

var parent;
if(!userMatchFn || arguments.length==2) userMatchFn=function(){return true;}
while (el) {
    parent = el.parentElement;
    result=findInChilds(parent);
    if (result)     return result;

    el = parent;
}

return null;

}


A little late to the party, but as I was passing by and just answer back a very similar question, I drop here my solution - we can say it's the JQuery closest() approach, but in plain good ol' JavaScript.

It doesn't need any pollyfills and it's older browsers, and IE (:-) ) friendly: https://stackoverflow.com/a/48726873/2816279


I think The easiest code to catch with jquery closest:

<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<script>
    $(document).ready(function () {
        $(".add").on("click", function () {
            var v = $(this).closest(".division").find("input[name='roll']").val();
            alert(v);
        });
    });
</script>
<?php

for ($i = 1; $i <= 5; $i++) {
    echo'<div class = "division">'
        . '<form method="POST" action="">'
        . '<p><input type="number" name="roll" placeholder="Enter Roll"></p>'
        . '<p><input type="button" class="add" name = "submit" value = "Click"></p>'
        . '</form></div>';
}
?>

Thanks much.

참고URL : https://stackoverflow.com/questions/18663941/finding-closest-element-without-jquery

반응형