AngularJS / ui-bootstrap手风琴 - 点击后滚动到活动(展开)手风琴的顶部

7
当打开一个面板时,我需要它滚动回刚刚点击的“.panel-title”的位置。我知道我可以创建一个指令来实现这个功能,比如(从this site中获取):
.directive( 'scrollTop', scrollTop );

  function scrollTop() {
      return {
          restrict: 'A',
          link: link
      };
  }

  function link( $scope, element ) {
      $scope.collapsing = false;
      $scope.$watch( function() {
          return $(element).find( '.panel-collapse' ).hasClass( 'collapsing' );
      }, function( status ) {
          if ( $scope.collapsing && !status ) {
              if ( $(element).hasClass( 'panel-open' ) ) {
                  $( 'html,body' ).animate({
                      scrollTop: $(element).offset().top - 20
                  }, 500 );
              }
          }
          $scope.collapsing = status;
      } );
  }

而在HTML中,我应该使用:

<div uib-accordion-group is-open="status.openPanel" scroll-top></div>

但这似乎行不通。当您单击第二个面板时,它会打开第一个和第二个面板,并且甚至在打开第三个面板时也不会滚动到顶部。
我只需要它滚动回点击的面板的“.panel-title”。我认为这似乎非常困难,因为大多数情况下面板内容可能会变得相当长,我认为大多数人在打开面板时都想滚动到信息的顶部。
我在这里看到了其他帖子,但它们似乎没有涉及AngularJS。我正在使用“ui-bootstrap-tpls-2.1.3”。
编辑 - {{link1:这是一个Plunker}},如果您愿意,可以尝试一下。
非常感谢任何帮助。

你是否考虑过监听shownhidden事件而不是使用你的观察器?我怀疑你的观察器触发得太早了。在你的函数上设置一个断点(或者在那里放置一个提示框或控制台日志,或者将bootstrap动画速度调整为较慢的值以夸大时机)。回报你找到的情况。 - adamdport
1个回答

1
这可能是一种快速而简单的方法,但能完美地运行。

angular.module('ui.bootstrap.demo', ['ngAnimate', 'ui.bootstrap'])
  .controller('AccordionDemoCtrl', function($scope) {
    $scope.oneAtATime = true;

    $scope.groups = [{
      title: 'Dynamic Group Header - 1',
      content: 'Dynamic Group Body - 1'
    }, {
      title: 'Dynamic Group Header - 2',
      content: 'Dynamic Group Body - 2 Dynamic Group Header - 2 Dynamic Group Header - 2 Dynamic Group Header - 2 Dynamic Group Header - 2 Dynamic Group Header - 2'
    }];

    $scope.items = ['Item 1', 'Item 2', 'Item 3'];

    $scope.addItem = function() {
      var newItemNo = $scope.items.length + 1;
      $scope.items.push('Item ' + newItemNo);
    };

    $scope.status = {
      isFirstOpen: true,
      isFirstDisabled: false
    };

    //scrolling  
    var accordion = $('.accordion'), timeOut;
    accordion.on('click', '.panel-heading', function(e) {
      if(e.target.nodeName != 'SPAN') return;
      var element = this;
      clearTimeout(timeOut);
      //since we dont know the exact offsetTop for dynamic content
      //using timeout 350 which let angular complete its render
      timeOut = setTimeout(function() {
        accordion.animate({
          scrollTop: element.offsetTop -2
        }, 300);
      }, 350);
    });
  });
.accordion {
  max-height: 220px;
  overflow: auto;
  padding: 2px; 8px 0 0;
}
*:focus { outline: none !important; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.0.0/jquery.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.6/angular.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.6/angular-animate.js"></script>
<script src="https://angular-ui.github.io/bootstrap/ui-bootstrap-tpls-0.14.0.js"></script>
<link href="https://netdna.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap.min.css" rel="stylesheet">
<div ng-app="ui.bootstrap.demo">
  <div ng-controller="AccordionDemoCtrl">
    <script type="text/ng-template" id="group-template.html">
      <div class="panel {{panelClass || 'panel-default'}}">
        <div class="panel-heading">
          <h4 class="panel-title" style="color:#fa39c3">
          <a href tabindex="0" class="accordion-toggle" ng-click="toggleOpen()" uib-accordion-transclude="heading"><span
            ng-class="{'text-muted': isDisabled}">{{heading}}</span></a>
        </h4>
        </div>
        <div class="panel-collapse collapse" uib-collapse="!isOpen">
          <div class="panel-body" style="text-align: right" ng-transclude></div>
        </div>
      </div>
    </script>

    <div class="accordion">
      <uib-accordion close-others="oneAtATime">
        <uib-accordion-group heading="Static Header, initially expanded" is-open="status.isFirstOpen" is-disabled="status.isFirstDisabled">
          This content is straight in the template.
        </uib-accordion-group>
        <uib-accordion-group heading="{{group.title}}" ng-repeat="group in groups">
          {{group.content}}
        </uib-accordion-group>
        <uib-accordion-group heading="Dynamic Body Content">
          <p>The body of the uib-accordion group grows to fit the contents</p>
          <button type="button" class="btn btn-default btn-sm" ng-click="addItem()">Add Item</button>
          <div ng-repeat="item in items">{{item}}</div>
        </uib-accordion-group>
        <uib-accordion-group heading="Custom template" template-url="group-template.html">
          Hello
        </uib-accordion-group>
        <uib-accordion-group heading="Delete account" panel-class="panel-danger">
          <p>Please, to delete your account, click the button below</p>
          <p>Please, to delete your account, click the button below</p>
          <p>Please, to delete your account, click the button below</p>
          <button class="btn btn-danger">Delete</button>
        </uib-accordion-group>
        <uib-accordion-group is-open="status.open">
          <uib-accordion-heading>
            I can have markup, too! <i class="pull-right glyphicon" ng-class="{'glyphicon-chevron-down': status.open, 'glyphicon-chevron-right': !status.open}"></i>
          </uib-accordion-heading>
          This is just some content to illustrate fancy headings.
        </uib-accordion-group>
      </uib-accordion>
    </div>
  </div>
</div>


这对我不起作用,但我的元素布局不同。就像我上面说的,我正在使用“ui-bootstrap-tpls-2.1.3”,而此示例正在使用“ui-bootstrap-tpls-0.14.0.js”。我不确定这是否有所不同,但可能会有所不同。无论如何,脚本都无法通过“if(e.target.nodeName!= 'SPAN')return;” - agon024
我在原帖中添加了一个 Plunker 链接 - https://plnkr.co/edit/etdG2OjUi8GxgUywSpvf?p=preview - agon024
1
我只是举了一个例子,使用 $('.accordion'),在你的情况下应该使用 $('body')。更新后的 Plunker - Ja9ad335h
嗯,这个对我还是不起作用。它可以到达body.animate,但不运行“scrollTop: element.offsetTop -2”,因为如果我将其更改为body.animate({opacity: 0}, 300);,它会将整个body淡出到0不透明度。所以我知道它正在运行动画部分。即使我将其更改为body.animate({scrollTop: '100px'}, 300);或者甚至是“scrollTop:0”,也没有任何滚动上去。 - agon024
我通过在CSS文件中删除body和html元素的height: 100%,使其正常工作。 - agon024

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接