我使用以下Angular指令在用户点击或触摸外部时隐藏div元素。
https://github.com/TheSharpieOne/angular-off-click
它正在按预期工作,但是当您在按钮上单击div的外部时,可以切换div,即可实现“角度关闭”。触发回调以隐藏容器,但随后调用附加到按钮的切换功能,重新打开div。
' off-click-filter'通过添加在调用hide函数之前使用css选择器进行检查的异常来解决这个问题。但是这被删除了,因为我们不希望在html标记中出现额外的css类异常。
当您单击容器外部
时,所需的功能是切换按钮不会触发其处理程序更新 这只是触摸设备上的一个问题,默认情况下有300毫秒的延迟。因此,这意味着触发回调以隐藏容器,然后切换功能在300ms后运行,重新打开容器。在桌面上,单击鼠标,首先触发切换功能,然后触发回调
/* Styles go here */
.container {
background: blue;
color: #fff;
height: 300px;
width: 300px;
}

<!DOCTYPE html>
<html>
<head>
<script src="https://code.angularjs.org/1.4.0/angular.js"></script>
<link rel="stylesheet" href="style.css" />
</head>
<body data-ng-app="myApp">
<h1>Hello Plunker!</h1>
<div data-ng-controller="myAppController">
<button data-ng-click="toggleContainer()">Toggle Container</button>
<div class="container" data-ng-show="showContainer" data-off-click="hideContainer()" data-off-click-if="showContainer">
This is the container
</div>
</div>
</body>
</html>
&#13;
public static void main(String[] args)throws IOException {
String s ="12312a";
int x = Integer.parseInt(s);
System.out.println (x+2);
}
&#13;
答案 0 :(得分:1)
问题在于,当您单击按钮时,两个功能都会触发:
hideContainer
。toggleContainer
(再次显示div
)。解决方案
在评估hide
回调之前添加event.stopPropagation();
。
你是怎么做到的?
data-off-click="hideContainer($event)"
。$event
hideContainer
函数的定义中添加$scope
param,如下所示:$scope.hideContainer = function($event)
完整代码:
// Angular App Code
var app = angular.module('myApp', ['offClick']);
app.controller('myAppController', ['$scope', '$timeout', function($scope,$timeout) {
$scope.showContainer = false;
$scope.toggleContainer = function() {
$timeout(function() {
$scope.showContainer = !$scope.showContainer;
}, 300);
};
$scope.hideContainer = function($event) {
$event.stopPropagation();
$timeout(function(){
$scope.showContainer = false;
});
};
}]);
// Off Click Directive Code
angular.module('offClick', [])
.directive('offClick', ['$rootScope', '$parse', function ($rootScope, $parse) {
var id = 0;
var listeners = {};
// add variable to detect touch users moving..
var touchMove = false;
// Add event listeners to handle various events. Destop will ignore touch events
document.addEventListener("touchmove", offClickEventHandler, true);
document.addEventListener("touchend", offClickEventHandler, true);
document.addEventListener('click', offClickEventHandler, true);
function targetInFilter(target, elms) {
if (!target || !elms) return false;
var elmsLen = elms.length;
for (var i = 0; i < elmsLen; ++i) {
var currentElem = elms[i];
var containsTarget = false;
try {
containsTarget = currentElem.contains(target);
} catch (e) {
// If the node is not an Element (e.g., an SVGElement) node.contains() throws Exception in IE,
// see https://connect.microsoft.com/IE/feedback/details/780874/node-contains-is-incorrect
// In this case we use compareDocumentPosition() instead.
if (typeof currentElem.compareDocumentPosition !== 'undefined') {
containsTarget = currentElem === target || Boolean(currentElem.compareDocumentPosition(target) & 16);
}
}
if (containsTarget) {
return true;
}
}
return false;
}
function offClickEventHandler(event) {
// If event is a touchmove adjust touchMove state
if( event.type === 'touchmove' ){
touchMove = true;
// And end function
return false;
}
// This will always fire on the touchend after the touchmove runs...
if( touchMove ){
// Reset touchmove to false
touchMove = false;
// And end function
return false;
}
var target = event.target || event.srcElement;
angular.forEach(listeners, function (listener, i) {
if (!(listener.elm.contains(target) || targetInFilter(target, listener.offClickFilter))) {
//$rootScope.$evalAsync(function () {
listener.cb(listener.scope, {
$event: event
});
//});
}
});
}
return {
restrict: 'A',
compile: function ($element, attr) {
var fn = $parse(attr.offClick);
return function (scope, element) {
var elmId = id++;
var offClickFilter;
var removeWatcher;
offClickFilter = document.querySelectorAll(scope.$eval(attr.offClickFilter));
if (attr.offClickIf) {
removeWatcher = $rootScope.$watch(function () {
return $parse(attr.offClickIf)(scope);
}, function (newVal) {
if (newVal) {
on();
} else if (!newVal) {
off();
}
});
} else {
on();
}
attr.$observe('offClickFilter', function (value) {
offClickFilter = document.querySelectorAll(scope.$eval(value));
});
scope.$on('$destroy', function () {
off();
if (removeWatcher) {
removeWatcher();
}
element = null;
});
function on() {
listeners[elmId] = {
elm: element[0],
cb: fn,
scope: scope,
offClickFilter: offClickFilter
};
}
function off() {
listeners[elmId] = null;
delete listeners[elmId];
}
};
}
};
}]);
.container {
background: blue;
color: #fff;
height: 300px;
width: 300px;
}
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
</head>
<body data-ng-app="myApp">
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.0/angular.min.js"></script>
<h1>Hello Plunker!</h1>
<div data-ng-controller="myAppController">
<button data-ng-click="toggleContainer()">Toggle Container</button>
<div class="container" data-ng-show="showContainer" data-off-click="hideContainer($event)" data-off-click-if="showContainer">
This is the container
</div>
</div>
</body>
</html>