2016-03-11 18 views
19

Ho questa situazione in cui ho bisogno di scorrere un elemento nel viewport. Il problema è che non so quale elemento è scorrevole. Ad esempio, in Portrait il corpo è scorrevole e in Landscape è un altro elemento (e ci sono più situazioni che cambiano l'elemento scorrevole)Trova il primo genitore scrollabile

Ora la domanda, dato un elemento che deve essere fatto scorrere nel viewport, che cos'è il modo migliore per trovare il suo primo genitore scorrevole?

Ho installato una demo here. Con il pulsante è possibile commutare tra due diverse situazioni

<div class="outer"> 
    <div class="inner"> 
     <div class="content"> 
      ... 
      <span>Scroll me into view</span> 
     </div> 
    </div> 
</div> 

Il corpo è scorrevole o .outer

Qualche suggerimento?

risposta

22

Basta verificare se la barra di scorrimento è visibile, se non guardare al genitore.

function getScrollParent(node) { 
    if (node == null) { 
    return null; 
    } 

    if (node.scrollHeight > node.clientHeight) { 
    return node; 
    } else { 
    return getScrollParent(node.parentNode); 
    } 
} 
+0

Se il nodo ha un genitore 'inline',' clientHeight' sarà 0 e sarà restituita Qui. Meglio ignorare i nodi con 'clientHeight' di 0. –

+2

Questo è bello ma non funziona per i nodi che stanno straripando ma non possono ancora scorrere. Se si aggiunge un controllo per il [valore di overflowY] (https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollHeight#Determine_if_an_element_has_been_totally_scrolled), sembra funzionare bene. 'overflowY = window.getComputedStyle (node) .overflowY;' 'let isScrollable = overflowY! == 'visible' && overflowY! == 'hidden';' 'if (isScrollable && node.scrollHeight> node.clientHeight { – RustyToms

+0

Secondo @RustyToms e OP, riscrivo questo: https://gist.github.com/twxia/bb20843c495a49644be6ea3804c0d775 – twxia

1

Penso che tu voglia questo.

$('button').click(function() { 
 
    $("body").addClass("body"); 
 
    $('.outer').toggleClass('scroller'); 
 
    check($(".content")); 
 
}); 
 

 
function check(el) { 
 
    var overflowY = el.css("overflow-y"); 
 
    if (overflowY == "scroll") { 
 
    alert(el.attr("class") + " has"); 
 
    } else { 
 
    if(el.parent().length > 0) 
 
    \t check(el.parent()); 
 
    else 
 
     return false; 
 
    } 
 
}
body { 
 
    height: 450px; 
 
    overflow-y: scroll; 
 
} 
 

 
div.inner { 
 
    width: 200px; 
 
    height: 400px; 
 
    border: 1px solid #000; 
 
} 
 

 
div.outer { 
 
    width: 200px; 
 
    height: 200px; 
 
} 
 

 
div.outer.scroller { 
 
    overflow-y: scroll; 
 
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> 
 
<button> 
 
    toggle 
 
</button> 
 
<div class="outer"> 
 
    <div class="inner"> 
 
    <div class="content"> 
 
     "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor 
 
     in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum." adipiscing elit, sed do eiusmod tempor incididunt ut 
 
     labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur 
 
     sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum." 
 
    </div> 
 
    </div> 
 
</div>

8

Se si utilizza l'interfaccia utente di jQuery, è possibile utilizzare il metodo scrollParent. Dai uno sguardo allo API o allo source.

Dal API:

.scrollParent(): Ottenere l'elemento antenato più vicino che è scorrevole

Questo metodo non accetta alcun argomento. Questo metodo trova l'antenato più vicino che consente lo scorrimento. In altre parole, il metodo trova l'elemento che l'elemento attualmente selezionato scorrerà all'interno.

Nota: questo metodo funziona solo su oggetti jQuery contenenti un elemento.

Se non si utilizza jQuery UI, ma si utilizza jQuery, poi ci sono le librerie indipendenti alternative che forniscono funzionalità simili, come ad esempio:

jquery-scrollparent

+1

Ho portato questo a JS vanilla qui: http://stackoverflow.com/questions/35939886/ find-prima-scorrevole-genitore # 42543908 –

16

Questo è un porto puro JS dell'interfaccia utente jQuery Metodo scrollParent che cweston spoke of. Sono andato con questa soluzione piuttosto che la soluzione accettata che non troverà il genitore scroll se non c'è ancora un overflow di contenuti.

L'unica differenza con la mia porta è che, se non viene trovato alcun genitore con il valore corretto per la proprietà CSS overflow, restituisco l'elemento <body>. L'interfaccia utente di JQuery, invece, ha restituito l'oggetto document. Questo è strano poiché valori come .scrollTop possono essere recuperati dallo <body> ma non dallo document.

function getScrollParent(element, includeHidden) { 
    var style = getComputedStyle(element); 
    var excludeStaticParent = style.position === "absolute"; 
    var overflowRegex = includeHidden ? /(auto|scroll|hidden)/ : /(auto|scroll)/; 

    if (style.position === "fixed") return document.body; 
    for (var parent = element; (parent = parent.parentElement);) { 
     style = getComputedStyle(parent); 
     if (excludeStaticParent && style.position === "static") { 
      continue; 
     } 
     if (overflowRegex.test(style.overflow + style.overflowY + style.overflowX)) return parent; 
    } 

    return document.body; 
} 
0

la risposta con la maggior parte votazione non funzionano in tutti i casi che possono essere scrollHeight > clientHeighttrue anche se non hanno una barra di scorrimento, ho trovato questa soluzione succo https://github.com/olahol/scrollparent.js/blob/master/scrollparent.js#L13

^totale del credito al https://github.com/olahol chi ha scritto il codice.

ho riscritta a es6:

export const getScrollParent = (node) => { 
    const regex = /(auto|scroll)/; 
    const parents = (_node, ps) => { 
    if (_node.parentNode === null) { return ps; } 
    return parents(_node.parentNode, ps.concat([_node])); 
    }; 

    const style = (_node, prop) => getComputedStyle(_node, null).getPropertyValue(prop); 
    const overflow = _node => style(_node, 'overflow') + style(_node, 'overflow-y') + style(_node, 'overflow-x'); 
    const scroll = _node => regex.test(overflow(_node)); 

    /* eslint-disable consistent-return */ 
    const scrollParent = (_node) => { 
    if (!(_node instanceof HTMLElement || _node instanceof SVGElement)) { 
     return; 
    } 

    const ps = parents(_node.parentNode, []); 

    for (let i = 0; i < ps.length; i += 1) { 
     if (scroll(ps[i])) { 
     return ps[i]; 
     } 
    } 

    return document.scrollingElement || document.documentElement; 
    }; 

    return scrollParent(node); 
    /* eslint-enable consistent-return */ 
}; 

è possibile utilizzarlo come:

const $yourElement = document.querySelector('.your-class-or-selector'); 
getScrollParent($yourElement); 
Problemi correlati