单击ace编辑器时阻止模态窗口向上滚动

时间:2017-05-02 13:06:24

标签: javascript angularjs angular-ui ace-editor

我有一个modal窗口,其中包含ace editor。当模态窗口打开时,我向下滚动并在ace editor内单击以添加一些文本。然后突然窗口自动向上滚动。我再次向下滚动,在编辑器内单击,然后再次向上滚动。最后,在第三次,我能够在编辑器中插入文本。当模态足够高并且编辑器不可见时,它会发生,除非你向下滚动它。

为什么?如何防止这种自动滚动行为?

以下是plunker:http://plnkr.co/edit/NHHkUtrw8SIDIzViNiqw?p=preview

控制器:

angular.module('ui.bootstrap.demo', ['ui.bootstrap', 'ui.ace']);
angular.module('ui.bootstrap.demo').controller('ModalDemoCtrl', function ($scope, $modal, $log) {

  $scope.items = ['item1', 'item2', 'item3'];

  $scope.open = function (size) {

    var modalInstance = $modal.open({
      templateUrl: 'myModalContent.html',
      controller: 'ModalInstanceCtrl',
      size: size,
      resolve: {
        items: function () {
          return $scope.items;
        }
      }
    });

    modalInstance.result.then(function (selectedItem) {
      $scope.selected = selectedItem;
    }, function () {
      $log.info('Modal dismissed at: ' + new Date());
    });
  };
});

// Please note that $modalInstance represents a modal window (instance) dependency.
// It is not the same as the $modal service used above.

angular.module('ui.bootstrap.demo').controller('ModalInstanceCtrl', function ($scope, $modalInstance, items) {

  $scope.items = items;
  $scope.selected = {
    item: $scope.items[0]
  };

  $scope.editor = {
    text: 'Hello, how are you getting on?'
  };

  $scope.aceOptions = function (mode) {
    return {
      mode: mode,
      onLoad: function (_ace) {
        // HACK to have the ace instance in the scope...
        $scope.modeChanged = function () {
          _ace.getSession().setMode("ace/mode/" + mode);
        };
      }
    };
  };

  $scope.ok = function () {
    $modalInstance.close($scope.selected.item);
  };

  $scope.cancel = function () {
    $modalInstance.dismiss('cancel');
  };
});

HTML:

<!doctype html>
<html ng-app="ui.bootstrap.demo">
  <head>
    <script src="//ajax.googleapis.com/ajax/libs/angularjs/1.2.16/angular.js"></script>
    <script src="//angular-ui.github.io/bootstrap/ui-bootstrap-tpls-0.12.0.js"></script>
    <script src="//rawgit.com/ajaxorg/ace-builds/v1.2.6/src-min-noconflict/ace.js"></script>
    <script src="//rawgithub.com/ajaxorg/ace-builds/master/src-min-noconflict/mode-css.js"></script>
    <script src="//rawgithub.com/angular-ui/ui-ace/bower/ui-ace.min.js"></script>
    <script src="example.js"></script>
    <link href="//netdna.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap.min.css" rel="stylesheet">
  </head>
  <body>

<div ng-controller="ModalDemoCtrl">
    <script type="text/ng-template" id="myModalContent.html">
        <div class="modal-header">
            <h3 class="modal-title">I'm a modal!</h3>
        </div>
        <div class="modal-body">
            <ul>
                <li ng-repeat="item in items">
                    <a ng-click="selected.item = item">{{ item }}</a>
                </li>
            </ul>
            Selected: <b>{{ selected.item }}</b>
            <p>
            Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo. Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit, sed quia non numquam eius modi tempora incidunt ut labore et dolore magnam aliquam quaerat voluptatem. Ut enim ad minima veniam, quis nostrum exercitationem ullam corporis suscipit laboriosam, nisi ut aliquid ex ea commodi consequatur? Quis autem vel eum iure reprehenderit qui in ea voluptate velit esse quam nihil molestiae consequatur, vel illum qui dolorem eum fugiat quo voluptas nulla pariatur?
            </p>
            <p>Editor:</p>
            <div ui-ace="{
              useWrapMode : true,
              showGutter: true,
              theme:'twilight',
              mode: 'markdown',
              rendererOptions: {
                maxLines: 5,
                minLines: 3
              }
            }" ng-model="editor.text"></div>

        </div>
        <div class="modal-footer">
            <button class="btn btn-primary" ng-click="ok()">OK</button>
            <button class="btn btn-warning" ng-click="cancel()">Cancel</button>
        </div>
    </script>

    <button class="btn btn-default" ng-click="open()">Open me!</button>
    <button class="btn btn-default" ng-click="open('lg')">Large modal</button>
    <button class="btn btn-default" ng-click="open('sm')">Small modal</button>
    <div ng-show="selected">Selection from a modal: {{ selected }}</div>
</div>
  </body>
</html>

2 个答案:

答案 0 :(得分:4)

浏览器在聚焦时将textarea滚动到视图中。这会导致溢出的各种问题:隐藏元素滚动,单击时编辑器跳转。

Ace试图阻止这种情况,通过设置位置固定以确保textarea在屏幕上,但是位置规范中有一个错误:fixed,https://bugs.chromium.org/p/chromium/issues/detail?id=20574这使得postion:固定工作就像位置:绝对与转化元素有关。

如果你没有办法从ace的父元素中删除转换,最好的解决方法是添加css以使.ace_text-input始终绝对定位。

TLDR将以下css添加到您的页面

.ace_text-input {
    position: absolute!important;
}

答案 1 :(得分:0)

如果您手动设置焦点,它似乎没有跳跃(在Chrome 58上测试)。初始化后,您可以手动将焦点设置在元素上。

onLoad事件添加到ui-ace选项,然后将其添加到ModalInstanceCtrl

$scope.focusEditor = function(editor) {
  editor.focus();
}