Skip to content
This repository was archived by the owner on Nov 3, 2019. It is now read-only.

Commit 97c59fa

Browse files
committed
fix: menu no longer sticks out the viewport
1 parent 978b8df commit 97c59fa

File tree

3 files changed

+98
-31
lines changed

3 files changed

+98
-31
lines changed

dist/contextmenu.js

Lines changed: 30 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.ngContextmenu = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(_dereq_,module,exports){
1+
(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
22
'use strict';
33

44
angular.module('io.dennis.contextmenu')
@@ -24,7 +24,7 @@ function ContainerCtrl($scope) {
2424
}
2525
}
2626

27-
},{}],2:[function(_dereq_,module,exports){
27+
},{}],2:[function(require,module,exports){
2828
'use strict';
2929

3030
angular.module('io.dennis.contextmenu')
@@ -86,22 +86,20 @@ function Contextmenu($window, $rootScope, $contextmenu) {
8686
contextmenu: '='
8787
},
8888
restrict: 'A',
89-
controller: ['$scope', '$window', '$rootScope', CotextmenuCtrl],
89+
controller: CotextmenuCtrl,
9090
link: link,
9191
priority: 100
9292
};
9393

94-
9594
function link(scope, element, attrs, ctrl) {
9695
scope.contextmenu = $contextmenu.$get();
9796
scope.contextmenu.setMenu(ctrl);
9897
ctrl.setElement(element);
9998
}
10099
}
101100

102-
function CotextmenuCtrl($scope, $window, $rootScope) {
103-
console.log('init contextmenu ctrl');
104-
101+
CotextmenuCtrl.$inject = ['$scope', '$window', '$rootScope', '$timeout'];
102+
function CotextmenuCtrl($scope, $window, $rootScope, $timeout) {
105103
var pub = this;
106104
var $element;
107105
$scope.$on('contextmenu.close', close);
@@ -112,10 +110,25 @@ function CotextmenuCtrl($scope, $window, $rootScope) {
112110

113111
function open(item, x, y) {
114112
broadcastClose();
115-
$element.css({top: y, left: x})
116-
.toggleClass('dropup', isDropup(y))
113+
114+
$element
117115
.toggleClass('open', true)
116+
.toggleClass('dropup', isDropup(y))
117+
.css('visibility', 'hidden')
118118
.toggleClass('ng-hide', false);
119+
120+
$timeout(function() {
121+
var width = $element.children().width();
122+
123+
x = (x + width > $window.innerWidth) ?
124+
$window.innerWidth - (width + 5) : x;
125+
126+
$element.css({
127+
top: y + 'px',
128+
left: x + 'px',
129+
visibility: 'visible'
130+
});
131+
});
119132
}
120133

121134
function close() {
@@ -132,7 +145,7 @@ function CotextmenuCtrl($scope, $window, $rootScope) {
132145
}
133146
}
134147

135-
},{}],3:[function(_dereq_,module,exports){
148+
},{}],3:[function(require,module,exports){
136149
'use strict';
137150

138151
angular.module('io.dennis.contextmenu')
@@ -204,18 +217,18 @@ function Item() {
204217

205218
}
206219

207-
},{}],4:[function(_dereq_,module,exports){
220+
},{}],4:[function(require,module,exports){
208221
'use strict';
209222

210223
angular.module('io.dennis.contextmenu', []);
211224

212-
_dereq_('./service/service');
225+
require('./service/service');
213226

214-
_dereq_('./directive/contextmenu');
215-
_dereq_('./directive/container');
216-
_dereq_('./directive/item');
227+
require('./directive/contextmenu');
228+
require('./directive/container');
229+
require('./directive/item');
217230

218-
},{"./directive/container":1,"./directive/contextmenu":2,"./directive/item":3,"./service/service":5}],5:[function(_dereq_,module,exports){
231+
},{"./directive/container":1,"./directive/contextmenu":2,"./directive/item":3,"./service/service":5}],5:[function(require,module,exports){
219232
'use strict';
220233

221234
angular.module('io.dennis.contextmenu')
@@ -352,5 +365,4 @@ function Contextmenu() {
352365
}
353366
}
354367

355-
},{}]},{},[4])(4)
356-
});
368+
},{}]},{},[4]);

spec/contextmenu.spec.js

Lines changed: 48 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,23 @@ describe('io.dennis.contextmenu', function() {
55
var ae = angular.element;
66

77
describe('directive:contextmenu', function() {
8-
var $injector, $compile, $rootScope;
8+
var mockWindow;
9+
var $injector, $compile, $rootScope, $timeout;
910
var $scope;
1011
var elementSpy;
1112

12-
beforeEach(mock.module('io.dennis.contextmenu'));
13-
beforeEach(inject(function(_$injector_, _$compile_, _$rootScope_) {
13+
beforeEach(mock.module('io.dennis.contextmenu', function($provide) {
14+
mockWindow = {
15+
innerWidth: 1024,
16+
innerHeight: 768
17+
};
18+
$provide.value('$window', mockWindow);
19+
}));
20+
beforeEach(inject(function(_$injector_, _$compile_, _$rootScope_, _$timeout_) {
1421
$injector = _$injector_;
1522
$compile = _$compile_;
1623
$rootScope = _$rootScope_;
24+
$timeout = _$timeout_;
1725

1826
var configService = $injector.get('$contextmenu');
1927
configService.set('DEBOUNCE_BROADCAST_TIME', 0);
@@ -79,11 +87,8 @@ describe('io.dennis.contextmenu', function() {
7987
}
8088

8189
});
82-
83-
8490
});
8591

86-
8792
it('should be able to register two independant menus', function() {
8893
var html = '<div contextmenu="some.menu"></div>';
8994
html += '<div contextmenu="other.menu"></div>';
@@ -116,6 +121,43 @@ describe('io.dennis.contextmenu', function() {
116121
}, 1);
117122
});
118123

124+
describe('', function() {
125+
126+
var $element;
127+
128+
beforeEach(function() {
129+
var html = '<div contextmenu="some.menu"></div>';
130+
var element = angular.element(html);
131+
var compiled = $compile(element)($scope);
132+
$rootScope.$apply();
133+
$element = ae(compiled['0']);
134+
});
135+
136+
it('should open upwards if below the page mid', function() {
137+
var belowPageMid = (mockWindow.innerHeight / 2) + 1;
138+
$element.controller('contextmenu').open(null, 0, belowPageMid);
139+
$timeout.flush();
140+
expect($element.hasClass('dropup')).toEqual(true);
141+
});
142+
143+
it('should not stick out of the viewport', function() {
144+
var html = '<div contextmenu="some.menu"><div style="width:100px;"></div></div>';
145+
var element = angular.element(html);
146+
var compiled = $compile(element)($scope);
147+
$rootScope.$apply();
148+
$element = ae(compiled['0']);
149+
150+
var setX = mockWindow.innerWidth;
151+
$element.controller('contextmenu').open(null, setX, 0);
152+
$timeout.flush();
153+
154+
var elementX = parseFloat($element.css('left'))
155+
expect(elementX < setX + mockWindow.innerWidth).toEqual(true);
156+
});
157+
158+
});
159+
160+
119161
});
120162

121163
});

src/directive/contextmenu.js

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -59,22 +59,20 @@ function Contextmenu($window, $rootScope, $contextmenu) {
5959
contextmenu: '='
6060
},
6161
restrict: 'A',
62-
controller: ['$scope', '$window', '$rootScope', CotextmenuCtrl],
62+
controller: CotextmenuCtrl,
6363
link: link,
6464
priority: 100
6565
};
6666

67-
6867
function link(scope, element, attrs, ctrl) {
6968
scope.contextmenu = $contextmenu.$get();
7069
scope.contextmenu.setMenu(ctrl);
7170
ctrl.setElement(element);
7271
}
7372
}
7473

75-
function CotextmenuCtrl($scope, $window, $rootScope) {
76-
console.log('init contextmenu ctrl');
77-
74+
CotextmenuCtrl.$inject = ['$scope', '$window', '$rootScope', '$timeout'];
75+
function CotextmenuCtrl($scope, $window, $rootScope, $timeout) {
7876
var pub = this;
7977
var $element;
8078
$scope.$on('contextmenu.close', close);
@@ -85,10 +83,25 @@ function CotextmenuCtrl($scope, $window, $rootScope) {
8583

8684
function open(item, x, y) {
8785
broadcastClose();
88-
$element.css({top: y + 'px', left: x + 'px'})
89-
.toggleClass('dropup', isDropup(y))
86+
87+
$element
9088
.toggleClass('open', true)
89+
.toggleClass('dropup', isDropup(y))
90+
.css('visibility', 'hidden')
9191
.toggleClass('ng-hide', false);
92+
93+
$timeout(function() {
94+
var width = $element.children().width();
95+
96+
x = (x + width > $window.innerWidth) ?
97+
$window.innerWidth - (width + 5) : x;
98+
99+
$element.css({
100+
top: y + 'px',
101+
left: x + 'px',
102+
visibility: 'visible'
103+
});
104+
});
92105
}
93106

94107
function close() {

0 commit comments

Comments
 (0)