web-dev-qa-db-fra.com

jQuery Accordion - fera-t-il défiler vers le haut de l'élément ouvert?

Avec le contrôle accordéon jQuery, comment puis-je le faire défiler jusqu'à un élément que j'ai sélectionné lorsqu'il est hors de l'écran?

Quand:

  • J'ai un article en accordéon avec un contenu plus grand que la fenêtre visible
  • Je fais défiler l'écran jusqu'au deuxième article accordéon
  • Je clique sur le deuxième élément accordéon pour l'afficher
  • La première option d'accordéon est réduite et la seconde s'ouvre, mais elle glisse hors de l'écran.

Y a-t-il une option pour l'accordéon de faire défiler jusqu'au deuxième élément?

27
y0mbo

Vous pouvez essayer d’utiliser le plugin scrollTo jQuery . Cela vous permet de faire des choses comme ceci:

$.scrollTo('div#foo'); // scroll the browser window so div#foo is in view
$('div#foo').('#bar'); // scroll within div#foo so #bar is in view

Liez ScrollTo() à l'événement accordionactivate, comme ceci:

$('#youraccordion').bind('accordionactivate', function(event, ui) {
  /* In here, ui.newHeader = the newly active header as a jQ object
              ui.newContent = the newly active content area */
  $( ui.newHeader ).ScrollTo(); // or ui.newContent, if you prefer
});

Quand l'événement accordionactivate est-il déclenché?

Déclenché après l'activation d'un panneau (une fois l'animation terminée). Si l'accordéon a déjà été réduit, ui.oldHeader et ui.oldPanel seront des objets jQuery vides. Si l'accordéon est en train de se réduire, ui.newHeader et ui.newPanel seront des objets jQuery vides.

Références: Accordéon jQuery UI

20
Ken Redler

Cela fonctionne pour moi et testé,

$( "#accordion" ).accordion({
    heightStyle: "content",
    collapsible: true,
    active: false,
    activate: function( event, ui ) {
        if(!$.isEmptyObject(ui.newHeader.offset())) {
            $('html:not(:animated), body:not(:animated)').animate({ scrollTop: ui.newHeader.offset().top }, 'slow');
        }
    }
});

http://jsfiddle.net/ilyasnone/aqw613em/

21
iliyas Safi

Comme je veux que la réduction soit vraie, j'ai ajouté un test if pour annuler l'erreur de tous les éléments en cours de réduction. Je ne voulais pas non plus que l'en-tête se trouve exactement en haut de la page. J'ai donc abaissé l'emplacement de scrollTop de 100:

  $(document).ready(function() {
    $(".ui-accordion").bind("accordionchange", function(event, ui) {
      if ($(ui.newHeader).offset() != null) {
        ui.newHeader, // $ object, activated header
        $("html, body").animate({scrollTop: ($(ui.newHeader).offset().top)-100}, 500);
      }
    });
  });
11
Martin

Je sais que cette question est ancienne, mais aucune des solutions ci-dessus n'a fonctionné comme je le souhaitais. C'est comme ça que je l'ai accompli. Le -50 était juste au cas où cela allait apparaître dans une application web iPad ou iPhone, de sorte que la page ne défile pas en haut de l'en-tête de l'accordéon derrière la barre d'état.

$('#accordion').accordion({
  collapsible: true,
  autoHeight: false,
  animated: false
});
$('.ui-accordion-header').bind('click',function(){
    theOffset = $(this).offset();
    $(window).scrollTop(theOffset.top - 50);
});
7
nobody

S'il vous plaît se référer this répondre par techfoobar

$(function() {
    $("#accordion").accordion({
        autoHeight: false,
        collapsible: true,
        heightStyle: "content",
        active: 0,
        animate: 300 // collapse will take 300ms
    });
    $('#accordion h3').bind('click',function(){
        var self = this;
        setTimeout(function() {
            theOffset = $(self).offset();
            $('body,html').animate({ scrollTop: theOffset.top - 100 });
        }, 310); // ensure the collapse animation is done
    });
});

Cela fonctionne pour moi avec la modification ci-dessus.

$("#accordion").accordion({
                    heightStyle: "content",
                    collapsible: true,
                    activate: function (event, ui) {

                        try
                        {
                            var self = this;
                            theOffset = $(self).offset();
                            $('body,html').animate({ scrollTop: theOffset.top - 100 });
                        } catch (e) {
                            alert(e);
                        }
                    }
                }); 
3
Pranav Labhe

La solution de Martin fonctionne très bien. Cependant, lorsque vous ajoutez ce code, il défilera toujours vers le haut, que votre accordéon soit visible sur la page ou non.

Si vous souhaitez faire défiler vers le haut uniquement lorsque le contenu de votre accordéon est supérieur à la fenêtre visible, utilisez le code suivant:

$(document).ready(function() {

    function isScrolledIntoView(elem)
    {
        var docViewTop = $(window).scrollTop();
        var docViewBottom = docViewTop + $(window).height();

        var elemTop = $(elem).offset().top;
        var elemBottom = elemTop + $(elem).height();

        return ((elemBottom <= docViewBottom) && (elemTop >= docViewTop));
    }

    $(".accordion-inner").bind("accordionchange", function(event, ui) {
      if ($(ui.newHeader).offset() != null) {
        if (!isScrolledIntoView(ui.newHeader))
        {
            ui.newHeader, // $ object, activated header
            $("html, body").animate({scrollTop: ($(ui.newHeader).offset().top)-100}, 500);
        }
      }
    });
  });
1
Stan Kroshchenko

J'ai eu des problèmes avec la liaison de l'événement lorsque vous avez utilisé l'accordéon pour fermer la fonction. L'ajout d'une seule instruction if l'a corrigé.

$('#accordion').bind('accordionchange', function(event, ui) {
    if(!ui.newHeader.length) { return; }
  /* In here, ui.newHeader = the newly active header as a jQ object
              ui.newContent = the newly active content area */
  $.scrollTo( ui.newHeader ); // or ui.newContent, if you prefer
});  
1
carcus88

J'ai implémenté la première réponse et ai préféré cette option car c'est une fonction pour tous les panneaux d'accordéon. Mais, j'ai remarqué que je n'arrivais pas à obtenir une erreur lorsque j'essayais de (re) fermer le même panneau d'accordéon - cela arrêterait le script à cette ligne du plugin ScrollTo:

attr[key] = val.slice && val.slice(-1) == '%' ? 

Le val retournait vide, alors j'ai trouvé une autre réponse ici qui disait de vérifier si elle était vide et a ajouté/remplacé cette fonction - donc ça marche maintenant.

else{
var val = targ[pos];
// Handle percentage values
if(val) {
    attr[key] = val.slice && val.slice(-1) == '%' ?
    parseFloat(val) / 100 * max
    : val;
    }
}
0
Charles Harmon

Il n'est pas nécessaire que le plugin scrollTo, vous pouvez le faire:

$('.accordionNormalitzador').bind('accordionactivate', function(event, ui) {
        $( ui.newHeader )[0].scrollIntoView(); 
    });
0
Xavi Solà

Utilisez simplement cette fonction sur window.load 

$(function() {
    var icons = {
    header: "ui-icon-circle-plus",
    activeHeader: "ui-icon-circle-minus"
    };
    $( "#accordion" ).accordion({
    icons: icons, autoHeight: false, collapsible: true, active: false,
    activate: function(event, ui){
        var scrollTop = $(".accordion").scrollTop();
        var top = $(ui.newHeader).offset().top;
     //do magic to scroll the user to the correct location

     //works in IE, firefox chrome and safari
        $("html,body").animate({ scrollTop: scrollTop + top -35 }, "fast");
       },



    });

    });

fonctionne parfaitement

0
adnan dogar

Hey a eu le même problème. Voici ce qui a fonctionné pour moi au moins ce qui semble être le moyen le plus simple . Utiliser le plugin scrollTo.

<script type="text/javascript">
    $(function(){
        $('#youraccordionheader').click(function(){
            $.scrollTo(this)                                                 
        })
    });
</script>

J'espère que cela pourrait être utile à quelqu'un.

0
cris