2014-12-31 5 views
3

내부 텍스트 만 알고있는 여러 중첩 요소의 공통 상위를 선택하려고합니다. 다음 코드에서 예를 들어jQuery와 CSS 선택기로 중첩 된 요소의 공통 상위/조상을 선택하십시오.

:

<unknown>  
    <unknown class="unknown"> 
     .... 
     <unknown> 
      <unknown>Sometext</unknown> 
     </unknown> 
     <unknown> 
      <unknown>Sometext</unknown> 
     </unknown> 
     <unknown> 
      <unknown>Sometext</unknown> 
     </unknown> 
     .... 
    </unknown> 
</unknown> 
나는이 시나리오에서 알 수없는 클래스가 가장 가까운 요소 (공통 부모를) 좀하고 싶습니다

. 나는 실제 태그 나 클래스 이름을 모른다. 나는 둥지 요소가 "본질적"을 포함한다는 것을 알고 있습니다. jQuery/Javascript를 사용하여 루프를 통해이 작업을 수행 할 수 있다는 것을 알고 있지만 jQuery와 함께 사용할 수있는 CSS 선택기가 있습니까? closest(), parents(), parentsUntil()의 조합을 사용하여 시도했지만이 요소에 연결할 수없는 것 같습니다.

감사합니다.

+0

첫 번째 "상 텍스트"에'class = "unknown"이 (가)있는 상위 항목이있는 경우 해당 항목을 무시하고 여전히 최상위 항목으로 이동합니다. 이는 모든 "상 텍스트" 에스? – Rhumborl

+0

예, 맞습니다. –

답변

3

첫째, 당신은 당신 만 리프 노드 (자식 노드와 노드)를 일치 확인, 그래서 사용할 필요가 (그냥 잎 노드), 사용 :

var matches = $(':not(:has(*))').filter(function() { 
    return $(this).text() == "Sometext"; 
}); 

또는 단지 결합을 사용하여 (0 어린이를위한 추가 검사 포함) 모든 요소에 D 필터 :

var matches = $('*').filter(function() { 
    return !$(this).children().length && $(this).text() == "Sometext"; 
}); 

참고 :은 아직이 두 가지 옵션 중 가장 빠른 인 테스트하지 않았습니다.

var commonparent = matches.first().parents().filter(function() { 
    return $(this).find(matches).length == matches.length; 
}).first(); 

JSFiddle :http://jsfiddle.net/TrueBlueAussie/v4gr1ykg/

여기에 데이비드 토마스의 제안에 기초

그러면 당신은 모든 경기를 포함, (첫 경기의) 최초의 조상을 찾을 필요 앞으로는 사람들에게 유용 할 수있는 jQuery 확장 (commonParents()commonParent()) 쌍이 될 것입니다.

JQuery와 컬렉션 사용 'commonParents의 월 부모() :

$.fn.commonParents = function(){ 
    var cachedThis = this; 
    return cachedThis.first().parents().filter(function() { 
     return $(this).find(cachedThis).length === cachedThis.length; 
    }); 
}; 

JSFiddle : (commonParents는) :

$.fn.commonParent = function(){ 
    return $(this).commonParents().first(); 
}; 
:
http://jsfiddle.net/TrueBlueAussie/v4gr1ykg/3/

는 jQuery를 수집 사용의 가장 가까운 공통 부모 commonParent()를 찾으려면

JSFiddle : (commonParent) :http://jsfiddle.net/TrueBlueAussie/v4gr1ykg/2/

주 :

  • jQuery를이 commonParentsfilter()으로 commonParentfirst()의 결합 된 사용을 최적화하고 단지 commonParents의 코드를 호출하는 첫 번째 일치가되어까지 , 그래서 commonParent가 될 필요가 없습니다 더 효율적입니다.
+0

잘 했어, 여기 플러그인 형식으로 재 작성된 접근법이있다 : [JS Fiddle demo] (http://jsfiddle.net/davidThomas/v4gr1ykg/1/). –

+0

@ David At Thomas : 멋지게 확장 기능으로 포장되었습니다. 이 기능을 확장 프로그램으로 만들기에 충분할 정도로 자주 고려하지는 않았지만 답변에 내 확장 기능을 추가 할 것입니다. –

+0

그래, 아마 비교적 드물게 일어날 것 같은데, 내가 상상할 수도 있겠지만, 나는 네 답을 보았고 몇 순간을 보냈다. 이제 너는 네 답에 긴 검색 어구를 쓸 수 있다면 이것은 인상적이어야합니다. :) –

0

이 작업을 수행해야합니다. 당신은 기본적으로 모든 일치하는 요소의 모든 관련 부모를 찾고, 그 각각의 집합의 교차점을 얻은 다음 가장 중첩 된 공통 부모를 얻기 위해 첫 번째 것을 가져옵니다.

jquery 플러그인처럼 포장 할 수도 있습니다. 그래서

:not(:has(*)) 

모든 정확히 일치를 찾을 수 :

if(console && console.clear) console.clear(); 
 

 
// create a handy intersection method for Arrays 
 
// see http://stackoverflow.com/a/16227294/1901857 
 
Array.prototype.intersect = function(arr) { 
 
    var a = this, b = arr; 
 
    var t; 
 
    if (b.length > a.length) t = b, b = a, a = t; // indexOf to loop over shorter 
 
    return a.filter(function (e) { 
 
     return b.indexOf(e) > -1; 
 
    }); 
 
}; 
 

 
;(function($) { 
 
    $.fn.commonParents = function(selector) { 
 
     // find all relevant parents for each element and get set intersection 
 
     // pushStack means you can use end() etc in chaining correctly 
 
     return this.pushStack(sometexts.get().reduce(function(prevParents, el) { 
 
      // common parents for this element - note the lowest level parent is first 
 
      var parents = $(el).parents(selector || '*').get(); 
 

 
      // intersect with the previous value (or itself if first) 
 
      return (prevParents || parents).intersect(parents); 
 
     }, null), "commonParents", arguments); 
 
    }; 
 
})(jQuery); 
 

 

 
// text to search for 
 
var search = "Sometext"; 
 
// parent selector to filter parents by e.g. '.unknown' - use null for all parents 
 
var parentSelector = null; 
 

 
// find everything containing search 
 
var sometexts = $(":contains('" + search + "')").filter(function() { return $(this).text() == search; }); 
 

 
// grab the first common parent - the lowest level one - or null if there isn't one 
 
var commonParent = sometexts.commonParents(parentSelector).get(0); 
 

 
console.log(commonParent);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script> 
 
<div> 
 
    <div class="unknown test"> 
 
     <div class="unknown test2"> 
 
      <div class="unknown"> 
 
       <div>Sometext</div> 
 
      </div> 
 
      <div> 
 
       <div>Sometext</div> 
 
      </div> 
 
      <div> 
 
       <div>Sometext</div> 
 
      </div> 
 
     </div> 
 
    </div> 
 
</div>

+0

감사합니다. 이것은 실제로 학부모의 수업을 알고있는 경우에 효과가 있습니다. 그러나, 그것이 다양하기 때문에 나는 불명이라고했다. 이것은 내가 필요로하는 것을 얻기 위해 생각한 것이지만 개선/리팩토링 될 수 있다고 생각하고 있습니다 :'var jq = $ ('*'). find (': last : contains ("Sometext")); var prnt = $ (jq [0]); jq.each (function() { prnt = prnt.parents(). (prnt) .has (this) .last(); }}); return prnt; ' –

+0

아, 그렇다면 클래스 비트는 실제로 관련이 없습니다. _the_ 공통 상위를 원하면 parentClass를'*'로 설정하십시오. – Rhumborl