ng-context-menu-0.1.4.js 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108
  1. /**
  2. * ng-context-menu - v0.1.4 - An AngularJS directive to display a context menu when a right-click event is triggered
  3. *
  4. * @author Ian Kennington Walter (http://ianvonwalter.com)
  5. */
  6. angular
  7. .module('ng-context-menu', [])
  8. .factory('ContextMenuService', function() {
  9. return {
  10. element: null,
  11. menuElement: null,
  12. container: null
  13. };
  14. })
  15. .directive('contextMenu', ['$document', 'ContextMenuService', function($document, ContextMenuService) {
  16. return {
  17. restrict: 'A',
  18. scope: {
  19. 'callback': '&contextMenu',
  20. 'disabled': '&contextMenuDisabled'
  21. },
  22. link: function($scope, $element, $attrs) {
  23. var opened = false;
  24. function open(event, menuElement, container) {
  25. menuElement.addClass('open');
  26. if (container) {
  27. container.append(menuElement);
  28. }
  29. var doc = $document[0].documentElement;
  30. var docLeft = (window.pageXOffset || doc.scrollLeft) - (doc.clientLeft || 0),
  31. docTop = (window.pageYOffset || doc.scrollTop) - (doc.clientTop || 0),
  32. elementHeight = menuElement[0].scrollHeight;
  33. var docHeight = doc.clientHeight + docTop,
  34. totalHeight = elementHeight + event.pageY,
  35. top = Math.max(event.pageY - docTop, 0);
  36. if (totalHeight > docHeight) {
  37. top = top - (totalHeight - docHeight);
  38. }
  39. menuElement.css('top', top + 'px');
  40. menuElement.css('left', Math.max(event.pageX - docLeft, 0) + 'px');
  41. opened = true;
  42. }
  43. function close(menuElement) {
  44. menuElement.removeClass('open');
  45. opened = false;
  46. }
  47. $element.bind('contextmenu', function(event) {
  48. if (!$scope.disabled()) {
  49. if (ContextMenuService.menuElement !== null) {
  50. close(ContextMenuService.menuElement);
  51. }
  52. ContextMenuService.menuElement = angular.element(document.getElementById($attrs.target));
  53. if (typeof($attrs.contextMenuContainer) != "undefined") {
  54. ContextMenuService.container = angular.element($attrs.contextMenuContainer)
  55. }
  56. ContextMenuService.element = event.target;
  57. // console.log('set', ContextMenuService.element);
  58. event.preventDefault();
  59. event.stopPropagation();
  60. $scope.$apply(function() {
  61. $scope.callback({ $event: event });
  62. open(event, ContextMenuService.menuElement, ContextMenuService.container);
  63. });
  64. }
  65. });
  66. function handleKeyUpEvent(event) {
  67. //console.log('keyup');
  68. if (!$scope.disabled() && opened && event.keyCode === 27) {
  69. $scope.$apply(function() {
  70. close(ContextMenuService.menuElement);
  71. });
  72. }
  73. }
  74. function handleClickEvent(event) {
  75. if (!$scope.disabled() &&
  76. opened &&
  77. (event.button !== 2 || event.target !== ContextMenuService.element)) {
  78. $scope.$apply(function() {
  79. close(ContextMenuService.menuElement);
  80. });
  81. }
  82. }
  83. $document.bind('keyup', handleKeyUpEvent);
  84. // Firefox treats a right-click as a click and a contextmenu event while other browsers
  85. // just treat it as a contextmenu event
  86. $document.bind('click', handleClickEvent);
  87. $document.bind('contextmenu', handleClickEvent);
  88. $scope.$on('$destroy', function() {
  89. //console.log('destroy');
  90. $document.unbind('keyup', handleKeyUpEvent);
  91. $document.unbind('click', handleClickEvent);
  92. $document.unbind('contextmenu', handleClickEvent);
  93. });
  94. }
  95. };
  96. }]);