模态关闭时出现溢出问题

时间:2018-08-24 09:22:23

标签: javascript html css angularjs

我的应用可以滑动以在列表上显示隐藏的操作,用户可以决定删除列表中的项目。

它使用HammerJS处理滑动事件,并使用SweetAlert2确认操作。

问题是当SweetAlert弹出窗口被关闭时。一旦用户单击“取消”并关闭模式,所有按钮都会突然可见。整个文档都移到左侧。

我创建了一个复制它的JSFiddle

复制步骤:

  • 在其中一个项目上从右向左滑动以显示操作;
  • 单击“ x”以删除该项目;
  • 点击取消。

我还将粘贴以下代码的内容以供参考:

HTML:

<div ng-app="app" ng-controller="mainCtrl" class="wrapper">
  <div class="items" swipe>
    <div ng-repeat="item in items" class="item">
       <div>
         <div class="item-wrapper">
           <div class="logo">
             <img src="http://2.bp.blogspot.com/-Y2XrnrXJmXs/Uf5Y_bfr4jI/AAAAAAAAALk/ydouC9lEmDE/s1600/Logogap+Logobb.jpg" />
           </div>
           <div class="info">
             <div class="title">
               {{item.title}}
             </div>
             <div class="description">
               {{item.description}}
             </div>
           </div>
         </div>
         <div class="offset-action">
           <button ng-click="delete()">
             X
           </button>
         </div>
       </div>
    </div>
  </div>
</div>

CSS:

body {
  overflow: hidden;
}

.wrapper {
  border: 1px solid grey;
  min-width: 350px;
  max-width: 800px;
}

.items {
  overflow: hidden;
  position: relative;
}

.item {
  padding: 10px 15px;
  position: relative;
  transition: transform 250ms ease-in-out;
}

.item.show-actions {
  transform: translateX(-70px);
}

.item-wrapper {
  align-items: center;
  display: flex;
}

.logo {
  width: 80px;
}

.logo img {
  margin: auto;
  width: 80px;
  height: auto;
}

.offset-action {
  align-items: center;
  background: #B11A1F;
  display: flex;
  position: absolute;
  top: 0;
  bottom: 0;
  text-align: center;
  right: -70px;
  width: 70px;
}

button {
  background: transparent;
  border: none;
  color: white;
  width: 100%;
  height: 100%;
}

Javascript:

angular.module('app', [])

.controller('mainCtrl', function($scope) {
    $scope.items = [
    {title: 'Lorem Ipsum', description: 'Consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore.'},
    {title: 'Lorem Ipsum', description: 'Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.'},
    {title: 'Lorem Ipsum', description: 'Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.'},
    {title: 'Lorem Ipsum', description: 'Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.'}
  ];

  $scope.delete = function() {
    swal({
        title: 'Lorem Ipsum',
      text: 'Dolor sit amet?',
      type: 'error',
      showCancelButton: true
    }).then(function(action) {
        if (action.value) {
        console.log('success');
      } else {
        swal.noop;
      }
    })
  }
})  

.directive('swipe', function() {
    return function(scope) {
    scope.$watch('items', function() {
      var $items = $('.item');
      var show_action = 'show-actions';

      function hideActions() {
        $items.removeClass(show_action);
      }

      $items.each(function() {
        var $item = $(this);

        $item.hammer().on('swipeleft', function() {
          var $this = $(this);
          $items.removeClass(show_action);
          if (!$this.hasClass(show_action)) {
            $this.addClass(show_action);
          }
        });

        $item.hammer().on('tap', hideActions);
      });
    });
  };
});

4 个答案:

答案 0 :(得分:3)

SweetAlert CSS样式与您的CSS样式之间存在冲突,从而导致此问题。

一个简单的解决方法是将此CSS添加到CSS文件的末尾:

.offset-action {
  display: none;
}

.show-actions .offset-action {
  display: flex;
}

https://jsfiddle.net/saeedahmadi/1L7zc25b/

拉兹万的答案也可以通过在关闭模式后摆脱焦点来完成工作:

https://stackoverflow.com/a/52028143/5939933

“在delete()方法的顶部添加document.activeElement.blur();”

答案 1 :(得分:2)

在致电document.activeElement.blur();之前添加swal()

https://jsfiddle.net/yd3gpsvL/

似乎是由于弹出窗口关闭后焦点返回到按钮引起的。有一个discussion about it here


或者,您可以使用div代替button(可选地与role="button"一起使用)以避免按钮的焦点功能。

答案 2 :(得分:0)

您的JavaScript需要稍微刷一下,并在delete()方法的顶部document.activeElement.blur();

angular.module('app', [])

.controller('mainCtrl', function($scope) {
    $scope.items = [
    {title: 'Lorem Ipsum', description: 'Consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore.'},
    {title: 'Lorem Ipsum', description: 'Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.'},
    {title: 'Lorem Ipsum', description: 'Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.'},
    {title: 'Lorem Ipsum', description: 'Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.'}
  ];

  $scope.delete = function() {
  document.activeElement.blur();
    swal({
        title: 'Lorem Ipsum',
      text: 'Dolor sit amet?',
      type: 'error',
      showCancelButton: true
    }).then(function(action) {
        if (action.value) {
        console.log('success');
      } else {
        swal.noop;
      }
    })
  }
})  

.directive('swipe', function() {
    return function(scope) {
    scope.$watch('items', function() {
      var $items = $('.item');
      var show_action = 'show-actions';

      function showActions() {
          var $this = $(this);
          $items.removeClass(show_action);
          if (!$this.hasClass(show_action)) {
            $this.addClass(show_action);
          }
        }

      function hideActions() {
        $items.removeClass(show_action);
      }

      $items.each(function() {
        var $item = $(this);

        $item.hammer().on('swipeleft', showActions);

        $item.hammer().on('tap', hideActions);
      });
    });
  };
});

这是您的jsFiddle的更新。

答案 3 :(得分:0)

  

一旦用户单击“取消”并关闭模式,所有按钮都会突然可见...

为了克服这一点,我建议仅在swal关闭时才删除该类:

  • 删除此行:$item.hammer().on('tap', hideActions);
  • 在删除调用中添加索引参数:html中的ng-click =“ delete($ index)”和js中的$scope.delete = function (idx) {
  • 在数毫秒后关闭swal上的课程:

    setTimeout(function(){
      $('.item').eq(idx).removeClass('show-actions');
    }, 200);
    

更新后的fiddle

更新

  

感谢您的回答,很遗憾,我需要点击才能隐藏按钮

我更新了fiddle,删除了jQuery和Hammer的jQuery。

为了隐藏swal close上的按钮,我将当前按钮隐藏在 tap 上,然后再次显示在 swipeleft 上。

angular.module('app', []).controller('mainCtrl', function ($scope) {
    $scope.items = [{title: 'Lorem Ipsum', description: 'Consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore.'},
        {title: 'Lorem Ipsum', description: 'Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.'},
        {title: 'Lorem Ipsum', description: 'Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.'},
        {title: 'Lorem Ipsum', description: 'Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.'}];
    $scope.delete = function () {
        swal({
            title: 'Lorem Ipsum',
            text: 'Dolor sit amet?',
            type: 'error',
            showCancelButton: true
        }).then(function (action) {
            if (action.value) {
                console.log('success');
            } else {
                swal.noop;
            }
        })
    }
}).directive('swipe', function () {
    return function (scope) {
        scope.$watch('items', function () {
            document.querySelectorAll('.item').forEach(function (ele, idx) {
                var mc = new Hammer(ele);
                mc.on("swipeleft", function (e) {
                    e.target.closest('.item').classList.add('show-actions');
                    e.target.closest('.item').querySelector('.offset-action').style.display = '';
                }).on("tap", function (e) {
                    e.target.closest('.item').classList.remove('show-actions');
                    e.target.closest('.item').querySelector('.offset-action').style.display = 'none';
                });
            });
        });
    };
});
body {
    overflow: hidden;
}

.wrapper {
    border: 1px solid grey;
    min-width: 350px;
    max-width: 800px;
}

.items {
    overflow: hidden;
    position: relative;
}

.item {
    padding: 10px 15px;
    position: relative;
    transition: transform 250ms ease-in-out;
}

.item.show-actions {
    transform: translateX(-70px);
}

.item-wrapper {
    align-items: center;
    display: flex;
}

.logo {
    width: 80px;
}

.logo img {
    margin: auto;
    width: 80px;
    height: auto;
}

.offset-action {
    align-items: center;
    background: #B11A1F;
    display: flex;
    position: absolute;
    top: 0;
    bottom: 0;
    text-align: center;
    right: -70px;
    width: 70px;
}

button {
    background: transparent;
    border: none;
    color: white;
    width: 100%;
    height: 100%;
}
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/limonte-sweetalert2/7.26.11/sweetalert2.css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.4.8/angular.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/hammer.js/2.0.8/hammer.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/limonte-sweetalert2/7.26.11/sweetalert2.all.js"></script>

<div ng-app="app" ng-controller="mainCtrl" class="wrapper">
    <div class="items" swipe>
        <div ng-repeat="item in items" class="item">
            <div>
                <div class="item-wrapper">
                    <div class="logo">
                        <img src="http://2.bp.blogspot.com/-Y2XrnrXJmXs/Uf5Y_bfr4jI/AAAAAAAAALk/ydouC9lEmDE/s1600/Logogap+Logobb.jpg"/>
                    </div>
                    <div class="info">
                        <div class="title">
                            {{item.title}}
                        </div>
                        <div class="description">
                            {{item.description}}
                        </div>
                    </div>
                </div>
                <div class="offset-action">
                    <button ng-click="delete()">
                        X
                    </button>
                </div>
            </div>
        </div>
    </div>
</div>