繁体   English   中英

如何使用angularJS将可拖动指令应用于bootstrap模式?

[英]How can i apply a draggable directive to bootstrap modal using angularJS?

我在我的Angular应用程序中使用bootstrap模式,它工作正常。 我需要使它可拖动和可调整大小,所以我已经定义了一个指令。 现在的问题是它被应用于模态窗口内的内容,因此模态窗口变得透明。

如何在打开窗口时将可拖动指令分配给模态窗口? 这是代码,

HTML:

<div ng-controller="CustomWidgetCtrl">
    <div class="box-header-btns pull-right" style="top:10px" >
        <a title="settings" ng-click="openSettings(widget)"><i class="glyphicon glyphicon-cog"></i></a>
</div>
</div>

App.js:

var routerApp = angular.module('DiginRt',  ['ui.bootstrap','ngRoute']);
routerApp.controller('CustomWidgetCtrl', ['$scope', '$modal',
  function($scope, $modal) {

    $scope.openSettings = function(widget) {
          $modal.open({
            scope: $scope,
            templateUrl: 'chart_settings.html',
            controller: 'chartSettingsCtrl',        
            resolve: {
              widget: function() {
                return widget;
              }
            }
          });
        };
    }
    ])

图表设置是另一个HTML页面。 这是我的Draggable指令。

更新:

我已经用Plunker更新了这个问题

问题: 在此输入图像描述

我找不到将指令添加到ui-bootstrap打开的模式的方法,因为它使用模态对话框包装模板。

所以我所做的是使用以下代码将拖动事件设置为模态对话框本身(而不是指令)。

我知道将事件添加到指令中的另一个元素不是最好的做法,但在这样的情况下也不是坏习惯,在这种情况下你不能直接向元素设置指令。

这样做的原因是因为ui-bootstrap没有提供一种方法来向modal.open函数的modal-dialog添加指令

这是在指令开头放置的代码:

element= angular.element(document.getElementsByClassName("modal-dialog"));

傻瓜

我赞成@ Naeem_Shaikh的答案,这基本上是对标准角度指令的改进。

但是,我能够解决的标准角度可拖动指令存在另一个问题。

标准指令在整个对话框中强加了可拖动性。 一方面,这就是我们想要的。 我们想拖动整个对话框。 但这有一个令人遗憾的副作用,即对话框中各种编辑字段的点击不起作用:默认行为被阻止! 不知何故,按钮已在bootstrap中编码以克服此问题,但不是文本编辑字段。 我猜这些作者没有考虑我的用例。 但对话不仅仅是按钮!

这很棘手,因为它是需要拖动的整个对话框,但您只需要通过标题“hotspot”中的点击启动拖动。 换句话说,启动拖动的热点是要拖动的区域的子集。

Naeem的修复使我能够使它工作,所以只有标题中的点击启动拖动。 没有他的修复,坐标转换就变得混乱了。

function clickedWithinHeader(event) {
    var target = event.currentTarget;
    var hotspot = null;
    var hotspots = target.getElementsByClassName("modal-header");
    if (hotspots.length > 0) {
        hotspot = hotspots.item(0);
    }
    if (hotspot !== null) {
        var eY = event.clientY;
        var tOT = target.offsetTop;
        var y = eY - tOT;
        var hH = hotspot.offsetHeight;
        // since the header occupies the full width across the top
        // no need to check X.  Note that this assumes the header
        // is on the top, which should be a safe assumption
        var within = (y <= hH);
        return within;
    } else {
        return true;
    }
}


// Draggable directive from: http://docs.angularjs.org/guide/compiler
// Modified so that only clicks in the dialog header trigger drag behavior.
// Otherwise clicking on dialog widgets did not give them focus.
angular.module('drag', []).directive('draggable', function($document) {
"use strict";
return function(scope, element) {
    var startX = 0, startY = 0, x = 0, y = 0;
    element= angular.element(document.getElementsByClassName("modal-dialog"));
    element.css({
        position : 'fixed',
        cursor : 'move',
    });
    element.on('mousedown', function(event) {
//      // OK, where did they touch?  Only want to do this
//      // when they clicked on the header.
        if (!clickedWithinHeader(event)) {
            return;
        }
        // Prevent default dragging of selected content
        event.preventDefault();
        ...

请注意,clickedWithinHeader()逻辑仅适用于Naeem的改进。 可能有更好的方法,但这是有效的。 只有标题中的点击才会启动拖动并点击其他位置执行他们应该执行的操作。

然而,这不是整个答案,因为标准指令也将移动光标强加在整个对话框上,这非常令人不安,即使,或者特别是如果你不能拖动它出现的地方。

从指令中的element.css中删除它:

element.css({
    position : 'fixed',
});

并使用CSS将移动光标仅绑定到模态标题

.modal-header 
{
    cursor: move;
}

提供完整的解决方案。

我在这里整合了各种代码片段,并提出了一个更简单的解决方案。 这个不依赖于检测click事件是否发生在modal-header中,因为mousedown事件特定地绑定到头部。

此解决方案也不依赖于在整个DOM中搜索模态对话框类,因为它在父级中搜索模态对话框元素。 这将允许您在屏幕上有多个对话框,只有一个是可拖动的。

我还创建了一个要点 ,以防止对话框移动到可见边界之外。

(function (angular) {
    "use strict";

    angular.module('MyModule')
        .directive('modalDraggable', ['$document', modalDraggable]);

    function modalDraggable($document) {
        return function (scope, element) {
            var startX = 0,
                startY = 0,
                x = 0,
                y = 0;

            var draggable = angular.element(element.parents('.modal-dialog')[0]);

            draggable.find('.modal-header')
                .css('cursor', 'move')
                .on('mousedown', function (event) {
                    // Prevent default dragging of selected content
                    event.preventDefault();
                    startX = event.screenX - x;
                    startY = event.screenY - y;

                    $document.on('mousemove', mousemove);
                    $document.on('mouseup', mouseup);
                });

            function mousemove(event) {
                y = event.screenY - startY;
                x = event.screenX - startX;

                draggable.css({
                    top: y + 'px',
                    left: x + 'px'
                });
            }

            function mouseup() {
                $document.unbind('mousemove', mousemove);
                $document.unbind('mouseup', mouseup);
            }
        };
    }
}(window.angular));

我将现有解决方案更改为屏幕上的多个模式。

Html:....

要么

... //模态标题,正文,页脚。

JS调用模式:var modalInstance = $ uibModal.open({animation:true,controller:'ModalAndamentoController',controllerAs:'vm',windowClass:'center-modal',size:'lg',templateUrl:'modalAndamento.html'
});

指令JS :( function(){'use strict';

angular .module('app')。direire('draggable',draggableDirective);

/ ** @ngInject * / function draggableDirective($ document){

  //busca pelo elemento var serachElement = function (parentElement, element) { //se o elemento pai corrente é igual ao elemento, então este foi encontrado if (parentElement == element[0]) { return true; } //aprofunda mais um nível na árvore procurando pelo elemento var i = 0; for (i = 0; i < parentElement.childNodes.length; i++) { return serachElement(parentElement.childNodes[i], element); } return false; }; //recupera o elemento referente ao dialog var getDialogFromElement = function (element) { //recupera todos os dialogs da tela var dialogs = document.getElementsByClassName("modal-dialog") //se tiver apenas um, então esse é o dialog procurado eo mesmo é retornado if (dialogs.length == 1) { return angular.element(dialogs[0]); } //senão, varre todos os dialogs, procurando por aquele que contém o elemento corrente na sua árvore de elementos var i = 0; for (i = 0; i < dialogs.length; i++) { //se encontrar o elemento correte, então esse é o dialog procurado if (serachElement(dialogs[i], element)) { return angular.element(dialogs[i]); } } }; //movimenta o dialog correspondente ao elemento informado (element) //O elemento que chega aqui é aquele que contém o atributo draggable return function (scope, element) { var startX = 0, startY = 0, x = 0, y = 0; //recupera o dialog correspondente ao element corrente element = getDialogFromElement(element); //coloca o cursor de movimento no header var header = angular.element(document.getElementsByClassName("modal-header")); header.css({ cursor: 'move' }); element.on('mousedown', function (event) { // Prevent default dragging of selected content //event.preventDefault(); startX = event.screenX - x; startY = event.screenY - y; $document.on('mousemove', mousemove); $document.on('mouseup', mouseup); }); function mousemove(event) { y = event.screenY - startY; x = event.screenX - startX; element.css({ top: y + 'px', left: x + 'px' }); } function mouseup() { $document.unbind('mousemove', mousemove); $document.unbind('mouseup', mouseup); } }; 

})();

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM