2012-12-11 19 views
19

Jaki jest najbardziej elegancki sposób sprawdzenia, czy element jest w normalnym przepływie za pomocą jQuery?JQuery: sprawdź, czy element jest w normalnym przepływie

Według CSS3 specification,

okno należy do przepływu, jeżeli:

Zastosowana wartość jej 'display' jest 'block', 'list-item', „stół "lub szablon.

Użyta wartość "float" to "none".

Użyta wartość jego "pozycji" to "statyczny" lub "względny".

Jest to dziecko z korzenia przepływu lub dziecko z pudełka, które należy do przepływu.

Czy powinienem sprawdzić wszystkie te warunki, czy jest lepszy sposób?

+3

Moje pierwsze pytanie brzmi, dlaczego musisz to wiedzieć? Prawdopodobnie wystarczy przetestować jedną z tych cech w swojej aktualnej aplikacji. – Blazemonger

+0

Jeśli jest to definicja używana tylko w specyfikacji, najlepiej sprawdzić rzeczywiste warunki. – pimvdb

+0

Pracuję nad osobistym projektem strony, który polega na kopiowaniu i wklejaniu stylizowanej treści w przeglądarce. Chcę usunąć górny margines pierwszego elementu w przepływie i dolny margines ostatniego elementu w przepływie. – sbichenko

Odpowiedz

3

myślę kolejny „przepływu” wymogiem jest to, że overflow jest ustawione na visible.

From the CSS2 spec:

pływaków, elementy całkowicie umieszczone, pojemniki blokowe (np inline bloków, stół komórek i obrusy napisów), które nie blokują pola i pola bloku z „nadmiaru” innego niż "visible" (z wyjątkiem sytuacji, gdy ta wartość została przeniesiona do widoku), ustanawia nowe konteksty formatowania bloków dla ich zawartości.

Na podstawie wymagań ty cytowane i wymogu overflow, jest to jeden ze sposobów, aby to zrobić z jQuery:

function isInFlow(elm, ctxRoot) { 

    ctxRoot = ctxRoot || document.body; 

    var $elm = $(elm), 
     ch = -1, 
     h; 

    if (!$elm.length) { 
     return false; 
    } 

    while ($elm[0] !== document.body) { 
     h = $elm.height(); 
     if (h < ch || !okProps($elm)) { 
      return false; 
     } 
     ch = h; 
     $elm = $elm.parent(); 

     if (!$elm.length) { 
      // not attached to the DOM 
      return false; 
     } 
     if ($elm[0] === ctxRoot) { 
      // encountered the ctxRoot and has been 
      // inflow the whole time 
      return true; 
     } 
    } 
    // should only get here if elm 
    // is not a child of ctxRoot 
    return false; 
} 

function okProps($elm) { 

    if ($elm.css('float') !== 'none'){ 
     return false;  
    } 
    if ($elm.css('overflow') !== 'visible'){ 
     return false;  
    } 
    switch ($elm.css('position')) { 
     case 'static': 
     case 'relative': 
      break; 
     default: 
      return false; 
    } 
    switch ($elm.css('display')) { 
     case 'block': 
     case 'list-item': 
     case 'table': 
      return true; 
    } 
    return false; 
} 
​ 

Zobacz ten jsFiddle dla przypadków testowych.

Nie jestem pewien, czy lepiej byłoby użyć window.getComputedStyle(), czy też nie.

Funkcja sprawdza, czy elm jest w kontekście formatowania przepływu lub blokowania ctxRoot (jak było wcześniej nazywane, myślę). Jeśli ctxRoot nie zostanie dostarczony, sprawdzi to przed elementem body. Nie sprawdza to, aby upewnić się, że ctxRoot jest w ruchu. Tak, z tym HTML

<div id="b" style="overflow: hidden;"> 
    <div id="ba">ba 
     <p id="baa">baa</p> 
     <span id="bab">bab</span> 
     <span id="bac" style="display:block;">bac</span> 
    </div> 
</div> 

Przypadki testowe są:

var b = $('#b')[0]; 
console.log('no ',isInFlow(b)); 
console.log('no ',isInFlow('#ba')); 
console.log('yes ',isInFlow('#ba', b)); 
console.log('no ',isInFlow('#baa')); 
console.log('yes ',isInFlow('#baa', b)); 
console.log('no ',isInFlow('#bab')); 
console.log('no ',isInFlow('#bab', b)); 
console.log('no ',isInFlow('#bac')); 
console.log('yes ',isInFlow('#bac', b)); 
+0

Zaakceptowany w przypadku dogłębnej analizy i przypadków testowych. Inne rozwiązanie okazało się błędne w niektórych przypadkach. – sbichenko

4

I wątpliwości jest tam lepiej sposób, ale w inny sposób może być:

1) otaczają element z owijki

2) porównuje długość i szerokość owijki owinięta elementem

na przykład:

$('#elementToTest').clone().addClass('clone').wrap('<div></div>') 
if($('#elementToTest.clone').height()>$('#elementToTest.clone').parent().height()){ 
    //outside the normal flow 
} 
+0

Czy mógłbyś wyjaśnić, jak dokładnie to zadziała? – sbichenko

+0

dodał przykład –

+0

Przepraszam, mam na myśli: w jaki sposób to sprawdzi, czy element jest w normalnym przepływie? – sbichenko

0

Zamiast patrząc na niego z mocą wsteczną, można uprzedzać potrzeby to za pomocą adnotacji danych. Za każdym razem, gdy tworzysz lub definiujesz element, ustaw jego atrybut data-flow na true lub false.

Na przykład:

var newDiv = document.createElement("div"); 
newDiv.style.position = "absolute"; 
newDiv.setAttribute("data-flow","false"); 

Albo w html

<div style="position:absolute;" data-flow="false"></div> 

I wtedy można po prostu wybrać te elementy z selektora:

$('*[data-flow=false]') 
Powiązane problemy