/** * 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; // console.log('set', ContextMenuService.element); 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); }); } }; }]);