2014-06-23 12:25:45 -04:00
|
|
|
/**
|
|
|
|
* ng-context-menu - v0.1.4 - An AngularJS directive to display a context menu when a right-click event is triggered
|
|
|
|
*
|
|
|
|
* @author Ian Kennington Walter (http://ianvonwalter.com)
|
|
|
|
*/
|
|
|
|
angular
|
|
|
|
.module('ng-context-menu', [])
|
|
|
|
.factory('ContextMenuService', function() {
|
|
|
|
return {
|
|
|
|
element: null,
|
|
|
|
menuElement: null,
|
|
|
|
container: null
|
|
|
|
};
|
|
|
|
})
|
|
|
|
.directive('contextMenu', ['$document', 'ContextMenuService', function($document, ContextMenuService) {
|
|
|
|
return {
|
|
|
|
restrict: 'A',
|
|
|
|
scope: {
|
|
|
|
'callback': '&contextMenu',
|
|
|
|
'disabled': '&contextMenuDisabled'
|
|
|
|
},
|
|
|
|
link: function($scope, $element, $attrs) {
|
|
|
|
var opened = false;
|
|
|
|
|
|
|
|
function open(event, menuElement, container) {
|
|
|
|
menuElement.addClass('open');
|
|
|
|
|
|
|
|
if (container) {
|
|
|
|
container.append(menuElement);
|
|
|
|
}
|
|
|
|
|
|
|
|
var doc = $document[0].documentElement;
|
|
|
|
var docLeft = (window.pageXOffset || doc.scrollLeft) - (doc.clientLeft || 0),
|
|
|
|
docTop = (window.pageYOffset || doc.scrollTop) - (doc.clientTop || 0),
|
|
|
|
elementHeight = menuElement[0].scrollHeight;
|
|
|
|
var docHeight = doc.clientHeight + docTop,
|
|
|
|
totalHeight = elementHeight + event.pageY,
|
|
|
|
top = Math.max(event.pageY - docTop, 0);
|
|
|
|
|
|
|
|
if (totalHeight > docHeight) {
|
|
|
|
top = top - (totalHeight - docHeight);
|
|
|
|
}
|
|
|
|
|
|
|
|
menuElement.css('top', top + 'px');
|
|
|
|
menuElement.css('left', Math.max(event.pageX - docLeft, 0) + 'px');
|
|
|
|
opened = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
function close(menuElement) {
|
|
|
|
menuElement.removeClass('open');
|
|
|
|
opened = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
$element.bind('contextmenu', function(event) {
|
|
|
|
if (!$scope.disabled()) {
|
|
|
|
if (ContextMenuService.menuElement !== null) {
|
|
|
|
close(ContextMenuService.menuElement);
|
|
|
|
}
|
|
|
|
ContextMenuService.menuElement = angular.element(document.getElementById($attrs.target));
|
|
|
|
if (typeof($attrs.contextMenuContainer) != "undefined") {
|
|
|
|
ContextMenuService.container = angular.element($attrs.contextMenuContainer)
|
|
|
|
}
|
|
|
|
ContextMenuService.element = event.target;
|
2014-07-31 09:20:56 -04:00
|
|
|
// console.log('set', ContextMenuService.element);
|
2014-06-23 12:25:45 -04:00
|
|
|
|
|
|
|
event.preventDefault();
|
|
|
|
event.stopPropagation();
|
|
|
|
$scope.$apply(function() {
|
|
|
|
$scope.callback({ $event: event });
|
|
|
|
open(event, ContextMenuService.menuElement, ContextMenuService.container);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
function handleKeyUpEvent(event) {
|
|
|
|
//console.log('keyup');
|
|
|
|
if (!$scope.disabled() && opened && event.keyCode === 27) {
|
|
|
|
$scope.$apply(function() {
|
|
|
|
close(ContextMenuService.menuElement);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
function handleClickEvent(event) {
|
|
|
|
if (!$scope.disabled() &&
|
|
|
|
opened &&
|
|
|
|
(event.button !== 2 || event.target !== ContextMenuService.element)) {
|
|
|
|
$scope.$apply(function() {
|
|
|
|
close(ContextMenuService.menuElement);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
$document.bind('keyup', handleKeyUpEvent);
|
|
|
|
// Firefox treats a right-click as a click and a contextmenu event while other browsers
|
|
|
|
// just treat it as a contextmenu event
|
|
|
|
$document.bind('click', handleClickEvent);
|
|
|
|
$document.bind('contextmenu', handleClickEvent);
|
|
|
|
|
|
|
|
$scope.$on('$destroy', function() {
|
|
|
|
//console.log('destroy');
|
|
|
|
$document.unbind('keyup', handleKeyUpEvent);
|
|
|
|
$document.unbind('click', handleClickEvent);
|
|
|
|
$document.unbind('contextmenu', handleClickEvent);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
};
|
|
|
|
}]);
|