diff --git a/bower.json b/bower.json index e486af6..20a1886 100644 --- a/bower.json +++ b/bower.json @@ -1,6 +1,6 @@ { "name": "angular-context-menu", - "version": "0.1.2", + "version": "0.1.6", "description": "An AngularJS directive to set up and open a context menu when a right-click or click event is triggered", "keywords": [ "angular-context-menu", @@ -12,7 +12,8 @@ "authors": [ "Ian Kennington Walter (http://ianvonwalter.com)", "Briant Ford", - "Till Breuer (https://github.com/tilt)" + "Till Breuer (https://github.com/tilt)", + "Gelu Timoficiuc (https://github.com/tgelu)" ], "license": "MIT", "main": [ diff --git a/dist/angular-context-menu.js b/dist/angular-context-menu.js index 2db59d1..ed0383a 100644 --- a/dist/angular-context-menu.js +++ b/dist/angular-context-menu.js @@ -1,10 +1,10 @@ /** * @license - * angular-context-menu - v0.1.2 - An AngularJS directive to display a context menu + * angular-context-menu - v0.1.6 - An AngularJS directive to display a context menu * (c) 2014 * License: MIT * - * @authors Brian Ford (http://briantford.com), Ian Kennington Walter (http://ianvonwalter.com), Till Breuer (https://github.com/tilt) + * @authors Brian Ford (http://briantford.com), Ian Kennington Walter (http://ianvonwalter.com), Till Breuer (https://github.com/tilt), Gelu Timoficiuc (https://github.com/tgelu) */ angular.module('ng-context-menu', []) @@ -12,12 +12,13 @@ angular.module('ng-context-menu', []) .factory('ngContextMenu', [ '$q', '$http', + '$timeout', '$compile', '$templateCache', '$animate', '$rootScope', '$controller', - function($q, $http, $compile, $templateCache, $animate, $rootScope, $controller) { + function($q, $http, $timeout, $compile, $templateCache, $animate, $rootScope, $controller) { return function contextMenuFactory(config) { if (!(!config.template ^ !config.templateUrl)) { @@ -57,12 +58,11 @@ angular.module('ng-context-menu', []) if (css) { element.css(css); } - + adjustPosition(element); return element; }); } - function attach (html, locals) { container = angular.element(config.container || document.body); element = angular.element(html); @@ -104,6 +104,19 @@ angular.module('ng-context-menu', []) return deferred.promise; } + function adjustPosition(element) { + var windowHeight = 'innerHeight' in window ? window.innerHeight : document.documentElement.offsetHeight; + var windowWidth = 'innerWidth' in window ? window.innerWidth : document.documentElement.offsetWidth; + $timeout(function() { + if (windowHeight < element[0].offsetTop + element[0].offsetHeight) { + element.css('top', element[0].offsetTop - element[0].offsetHeight + 'px'); + } + if (windowWidth < element[0].offsetLeft + element[0].offsetWidth) { + element.css('left', element[0].offsetLeft - element[0].offsetWidth + 'px'); + } + }, 0); + } + function active () { return !!element; } @@ -119,16 +132,16 @@ angular.module('ng-context-menu', []) .directive('hasContextMenu', [ '$injector', - '$window', + '$document', '$parse', - function($injector, $window, $parse) { + function($injector, $document, $parse) { return { restrict: 'A', link: function(scope, element, attrs) { var openTarget, contextMenu = $injector.get(attrs.target), locals = {}, - win = angular.element($window), + doc = angular.element($document), menuElement, triggerOnEvent = attrs.triggerOnEvent || 'contextmenu'; @@ -138,10 +151,9 @@ angular.module('ng-context-menu', []) // prepare locals, these define properties to be passed on to the context menu scope if (attrs.locals) { - var localKeys = attrs.locals.split(',').map(function(local) { - return local.trim(); - }); + var localKeys = attrs.locals.split(','); angular.forEach(localKeys, function(key) { + key = key.trim(); locals[key] = scope[key]; }); } @@ -157,9 +169,16 @@ angular.module('ng-context-menu', []) } function getCssPositionProperties(event) { + if (event.pageX || event.pageY) { + clickX = event.pageX; + clickY = event.pageY; + } else { + clickX = event.clientX + document.documentElement.scrollLeft; + clickY = event.clientY + document.documentElement.scrollTop; + } return { - top: Math.max(event.pageY, 0) + 'px', - left: Math.max(event.pageX, 0) + 'px' + left: Math.max(clickX, 0) + 'px', + top: Math.max(clickY, 0) + 'px' }; } @@ -173,7 +192,7 @@ angular.module('ng-context-menu', []) }); }); - win.bind('keyup', function(event) { + doc.bind('keyup', function(event) { if (contextMenu.active() && event.keyCode === 27) { scope.$apply(function() { close(); @@ -192,8 +211,8 @@ angular.module('ng-context-menu', []) // Firefox treats a right-click as a click and a contextmenu event while other browsers // just treat it as a contextmenu event - win.bind('click', handleWindowClickEvent); - win.bind(triggerOnEvent, handleWindowClickEvent); + doc.bind('click', handleWindowClickEvent); + doc.bind(triggerOnEvent, handleWindowClickEvent); } }; }]); diff --git a/dist/angular-context-menu.min.js b/dist/angular-context-menu.min.js index fc4aa50..c37ddfc 100644 --- a/dist/angular-context-menu.min.js +++ b/dist/angular-context-menu.min.js @@ -1 +1 @@ -angular.module("ng-context-menu",[]).factory("ngContextMenu",["$q","$http","$compile","$templateCache","$animate","$rootScope","$controller",function(e,t,n,o,r,a,l){return function(c){function i(e,t){return g&&e&&p(e),s.then(function(n){return $||u(n,e),t&&$.css(t),$})}function u(e,t){if(h=angular.element(c.container||document.body),$=angular.element(e),0===$.length)throw new Error("The template contains no elements; you need to wrap text nodes");r.enter($,h),g=a.$new(),t&&p(t);var o=l(v,{$scope:g});d&&(g[d]=o),n($)(g)}function p(e){for(var t in e)g[t]=e[t]}function f(){var t=e.defer();return $?r.leave($,function(){g.$destroy(),$=null,t.resolve()}):t.resolve(),t.promise}function m(){return!!$}if(!(!c.template^!c.templateUrl))throw new Error("Expected context menu to have exacly one of either `template` or `templateUrl`");var s,g,v=(c.template,c.controller||angular.noop),d=c.controllerAs,$=null,h=null;if(c.template){var x=e.defer();x.resolve(c.template),s=x.promise}else s=t.get(c.templateUrl,{cache:o}).then(function(e){return e.data});return{open:i,close:f,active:m}}}]).directive("hasContextMenu",["$injector","$window","$parse",function(e,t){return{restrict:"A",link:function(n,o,r){function a(e){p.open(f,c(e))}function l(){p.close()}function c(e){return{top:Math.max(e.pageY,0)+"px",left:Math.max(e.pageX,0)+"px"}}function i(e){p.active()&&u&&2!==e.button&&n.$apply(function(){l()})}var u,p=e.get(r.target),f={},m=angular.element(t),s=r.triggerOnEvent||"contextmenu";if(r.locals){var g=r.locals.split(",").map(function(e){return e.trim()});angular.forEach(g,function(e){f[e]=n[e]})}o.bind(s,function(e){u=e.target,e.preventDefault(),e.stopPropagation(),n.$apply(function(){a(e)})}),m.bind("keyup",function(e){p.active()&&27===e.keyCode&&n.$apply(function(){l()})}),m.bind("click",i),m.bind(s,i)}}}]); \ No newline at end of file +angular.module("ng-context-menu",[]).factory("ngContextMenu",["$q","$http","$timeout","$compile","$templateCache","$animate","$rootScope","$controller",function(e,t,n,o,r,c,i,l){return function(a){function u(e,t){return h&&e&&p(e),g.then(function(n){return w||f(n,e),t&&w.css(t),s(w),w})}function f(e,t){if(x=angular.element(a.container||document.body),w=angular.element(e),0===w.length)throw new Error("The template contains no elements; you need to wrap text nodes");c.enter(w,x),h=i.$new(),t&&p(t);var n=l(v,{$scope:h});$&&(h[$]=n),o(w)(h)}function p(e){for(var t in e)h[t]=e[t]}function m(){var t=e.defer();return w?c.leave(w,function(){h.$destroy(),w=null,t.resolve()}):t.resolve(),t.promise}function s(e){var t="innerHeight"in window?window.innerHeight:document.documentElement.offsetHeight,o="innerWidth"in window?window.innerWidth:document.documentElement.offsetWidth;n(function(){t