2017-11-02 1 views
0

JSFiddle ist überfüllt: https://jsfiddle.net/1fLmtyoj/15/A Funktion zu bestimmen, ob LI

Ich folge dieses Beispiel zu sehen, ob ein Element ist überfüllt, aber etwas nicht funktioniert, dann ist dies für einen DIV: Check with jquery if div has overflowing elements und https://stackoverflow.com/a/7668692/1005607

Ich habe ein <LI> Etikett mit <SPAN> s. Von der obigen Antwort ist es notwendig zu überprüfen (1) Überlauf aktiv, (2) halb sichtbare Teile. Ich habe sie in die folgende Funktion kombiniert.

function isOverflowing(element) { 

    // 1. Main Part for overflow check 
    if (element.offsetHeight < element.scrollHeight || 
    element.offsetWidth < element.scrollWidth) { 
    return true; 
    } 

    // 2. Partially invisible items 
    var invisibleItems = []; 
    for(var i=0; i<element.childElementCount; i++){ 
    if (element.children[i].offsetTop + element.children[i].offsetHeight > 
     element.offsetTop + element.offsetHeight || 
     element.children[i].offsetLeft + element.children[i].offsetWidth > 
     element.offsetLeft + element.offsetWidth){ 

      invisibleItems.push(element.children[i]); 
     } 

    } 

    if (invisibleItems.length) { 
    return true; 
    } 
    // Otherwise, neither Part 1 nor 2, return FALSE 
    return false; 
} 

Im JSFiddle ist die erwartete Ausgabe dass 3 # 1 und # quillt über nicht, aber # 2 und # 4 sind überfüllt. Aber alle 4 sind als nicht überfüllt dargestellt.

+1

Kurz gesagt, Ihr Selektor '$ ('li: eq (0)')' gibt ein Array zurück. Sie müssen sich 'element [0]' anschauen - zum Beispiel gibt 'element [0] .childElementCount' das wieder, wonach Sie suchen. – Snowmonkey

Antwort

1

Wenn Sie das Element über die Konsole anzeigen würden, würden Sie sehen, dass dieses Element nicht das Attribut childElementCount hat - aber das erste Mitglied des Element-Arrays. Also beziehen Sie sich für alle Attribute auf das Element [0] und es verhält sich wie erwartet. Ich denke, das liegt an dem Selektor, den Sie verwendet haben.

function isOverflowing(element) { 
 

 
    // 1. Main Part for overflow check 
 
    if (element.offsetHeight < element.scrollHeight || 
 
    element.offsetWidth < element.scrollWidth) { 
 
    return true; 
 
    } 
 
    
 
    // 2. Partially invisible items 
 
    var invisibleItems = []; 
 
    for(var i=0; i<element[0].childElementCount; i++){ 
 

 
    if (element[0].children[i].offsetTop + element[0].children[i].offsetHeight > 
 
     element[0].offsetTop + element[0].offsetHeight || 
 
     element[0].children[i].offsetLeft + element[0].children[i].offsetWidth > 
 
     element[0].offsetLeft + element[0].offsetWidth){ 
 

 
      invisibleItems.push(element[0].children[i]); 
 
     } 
 

 
    } 
 
    
 
    if (invisibleItems.length) { 
 
    \t return true; 
 
    } 
 
    // Otherwise, neither Part 1 nor 2, return FALSE 
 
    return false; 
 
} 
 

 
$('#result').html('#1? ' + isOverflowing($('li:eq(0)')) + 
 
     '#2? ' + isOverflowing($('li:eq(1)')) + 
 
     '#3? ' + isOverflowing($('li:eq(2)')) + 
 
     '#4? ' + isOverflowing($('li:eq(3)')) 
 
);
.type1 { 
 
    border: 1px solid black; 
 
    width: 130px; 
 
    height: 30px; 
 
    margin-bottom: 5px; 
 
} 
 

 
.type2 { 
 
    border: 1px dotted red; 
 
    width: 50px; 
 
    height: 25px; 
 
    margin-bottom: 45px; 
 
} 
 

 
.type3 { 
 
    border: 1px dashed blue; 
 
    width: 200px; 
 
    height: 40px; 
 
    margin-bottom: 5px; 
 
} 
 

 
.type4 { 
 
    border: 1px dashed green; 
 
    width: 100px; 
 
    height: 10px; 
 
    margin-bottom: 5px; 
 
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> 
 
<ul> 
 

 
    <li class="type1"><span>Some text in LI 1</span></li> 
 
    <li class="type2"><span>Some more text in LI 2</span></li> 
 
    <li class="type3"><span>A long string of text in LI3</span></li> 
 
    <li class="type4"><span>A much longer string of text in LI4</span></li> 
 

 
</ul> 
 

 
<br/> 
 
<br/> 
 
<br/> 
 
<br/> 
 
<p id="result"></p>

Wie Sie sagen, jedoch ist diese Lösung nicht allgemein genug - es ist nicht für verschachtelten DOM-Knoten erlaubt. Um dies zu beheben, würden wir eine rekursive Funktion wünschen. Probieren Sie das möglicherweise aus. Es funktioniert, denke ich, aber es hat mein Gehirn wirklich verletzt, rekursiv zu denken. ;)

function isOverflowing(element) { 
 
    /******* 
 
    * This is going to be a recursive function -- first, 
 
    * it'll check if there are children elements and, 
 
    * if not, simply return true. In the event there 
 
    * are child elements, it should recurse over each 
 
    * to see if any child overflows, whether partially 
 
    * invis or not. 
 
    ******/ 
 
    var elOverflows; 
 
    var el = element[0]; 
 

 
    // On the first iteration, we initialize these. On every 
 
    // recursive iteration, we simply preserve them 
 
    var mainHeight = el.offsetTop + el.offsetHeight, 
 
    mainOffsetHeight = el.offsetHeight, 
 
    mainWidth = el.offsetLeft + el.offsetWidth, 
 
    mainOffsetWidth = el.offsetWidth; 
 

 
    // 1. Main Part for overflow check 
 
    if (mainOffsetHeight < el.scrollHeight || 
 
    mainOffsetWidth < el.scrollWidth) { 
 
    elOverflows = true; 
 
    return elOverflows; 
 
    } 
 

 
    /*** 
 
    * 2. If the current element doesn't contain any 
 
    *  children, and the above check didn't return, 
 
    *  then we don't have any overflow. 
 
    ***/ 
 
    if (el.childElementCount == 0) { 
 
    elOverflows = false; 
 
    return elOverflows; 
 
    } else { 
 
    // Here, we have child elements. We want to iterate 
 
    // over each of them and re-call isOverflowing() on 
 
    // each one. This is the recursion, allowing us to 
 
    // have any number of nested child elements. 
 
    $(el.children).each(function() { 
 
     elOverflows = isOverflowing($(this)); 
 
    }); 
 

 
    return elOverflows; 
 

 
    } 
 

 
} 
 

 
$("#container li").each(function() { 
 
    $("#result").append("<p>#" + $(this).index() + ": " + isOverflowing($(this))); 
 
})
.type1 { 
 
    border: 1px solid black; 
 
    width: 130px; 
 
    height: 30px; 
 
    margin-bottom: 5px; 
 
} 
 

 
.type2 { 
 
    border: 1px dotted red; 
 
    width: 50px; 
 
    height: 25px; 
 
    margin-bottom: 45px; 
 
} 
 

 
.type3 { 
 
    border: 1px dashed blue; 
 
    width: 200px; 
 
    height: 40px; 
 
    margin-bottom: 5px; 
 
} 
 

 
.type4 { 
 
    border: 1px dashed green; 
 
    width: 100px; 
 
    height: 10px; 
 
    margin-bottom: 5px; 
 
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> 
 
<ul id='container'> 
 
    <li class="type1"><span>Some text in LI 1</span></li> 
 
    <li class="type2"><span>Some more text in LI 2</span></li> 
 
    <li class="type3"><span>A long string <span>containing A much longer string </span> in its center bit.</span> 
 
    </li> 
 
    <li class="type4"><span>A much longer string of text in LI4</span></li> 
 

 
</ul> 
 

 
<br/> 
 
<br/> 
 
<br/> 
 
<br/> 
 
<p id="result"></p>

Ich habe isOverflowing rekursiv gemacht, und für jedes Kind-Knoten des aktuellen Knotens, ich kann es einfach wieder neu rufen, bis es keine weiteren untergeordneten Knoten sind. Wenn der Rückgabewert an den ersten Aufruf übergeben wird, können wir feststellen, ob einer der untergeordneten Knoten die Grenzen des anfänglichen Knotens überschreitet.

Hoffe, das hilft!

+0

Diese allgemeine Lösung funktioniert nicht, wenn wir keine Annahmen über die Struktur des übergeordneten Elements machen. Angenommen, ich hätte Tags in einem LI verschachtelt - dann würde die gesamte Traversierung von children [i] fehlschlagen. Ich vermute, ich fragte mich, ob es eine generische Möglichkeit gäbe, nach IRGENDEINEN Kindern/Unter-Kindern zu suchen, die den Elternteil überlaufen. –

+0

@geneb. - Probieren Sie das für die Größe aus. Um das zu tun, was Sie tun möchten, betrachten Sie die Rekursion durch alle untergeordneten DOM-Knoten. Ich habe das isOverflowing umgeschrieben, um das zu unterstützen. Freundliche Grüße! – Snowmonkey

Verwandte Themen