UNPKG

14 kBJavaScriptView Raw
1/**
2 * ag-grid - Advanced Data Grid / Data Table supporting Javascript / React / AngularJS / Web Components
3 * @version v18.1.2
4 * @link http://www.ag-grid.com/
5 * @license MIT
6 */
7"use strict";
8var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
9 var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
10 if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
11 else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
12 return c > 3 && r && Object.defineProperty(target, key, r), r;
13};
14var __metadata = (this && this.__metadata) || function (k, v) {
15 if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
16};
17Object.defineProperty(exports, "__esModule", { value: true });
18var utils_1 = require("../utils");
19var constants_1 = require("../constants");
20var context_1 = require("../context/context");
21var gridCore_1 = require("../gridCore");
22var gridOptionsWrapper_1 = require("../gridOptionsWrapper");
23var environment_1 = require("../environment");
24var PopupService = (function () {
25 function PopupService() {
26 this.activePopupElements = [];
27 }
28 PopupService.prototype.getPopupParent = function () {
29 var ePopupParent = this.gridOptionsWrapper.getPopupParent();
30 if (ePopupParent) {
31 // user provided popup parent, may not have the right theme applied
32 return ePopupParent;
33 }
34 else {
35 return this.gridCore.getRootGui();
36 }
37 };
38 PopupService.prototype.positionPopupForMenu = function (params) {
39 var sourceRect = params.eventSource.getBoundingClientRect();
40 var parentRect = this.getPopupParent().getBoundingClientRect();
41 var y = sourceRect.top - parentRect.top;
42 y = this.keepYWithinBounds(params, y);
43 var minWidth = (params.ePopup.clientWidth > 0) ? params.ePopup.clientWidth : 200;
44 var widthOfParent = parentRect.right - parentRect.left;
45 var maxX = widthOfParent - minWidth;
46 // the x position of the popup depends on RTL or LTR. for normal cases, LTR, we put the child popup
47 // to the right, unless it doesn't fit and we then put it to the left. for RTL it's the other way around,
48 // we try place it first to the left, and then if not to the right.
49 var x;
50 if (this.gridOptionsWrapper.isEnableRtl()) {
51 // for RTL, try left first
52 x = xLeftPosition();
53 if (x < 0) {
54 x = xRightPosition();
55 }
56 if (x > maxX) {
57 x = 0;
58 }
59 }
60 else {
61 // for LTR, try right first
62 x = xRightPosition();
63 if (x > maxX) {
64 x = xLeftPosition();
65 }
66 if (x < 0) {
67 x = 0;
68 }
69 }
70 params.ePopup.style.left = x + "px";
71 params.ePopup.style.top = y + "px";
72 function xRightPosition() {
73 return sourceRect.right - parentRect.left - 2;
74 }
75 function xLeftPosition() {
76 return sourceRect.left - parentRect.left - minWidth;
77 }
78 };
79 PopupService.prototype.positionPopupUnderMouseEvent = function (params) {
80 var parentRect = this.getPopupParent().getBoundingClientRect();
81 this.positionPopup({
82 ePopup: params.ePopup,
83 x: params.mouseEvent.clientX - parentRect.left,
84 y: params.mouseEvent.clientY - parentRect.top,
85 keepWithinBounds: true
86 });
87 this.callPostProcessPopup(params.ePopup, null, params.mouseEvent, params.type, params.column, params.rowNode);
88 };
89 PopupService.prototype.positionPopupUnderComponent = function (params) {
90 var sourceRect = params.eventSource.getBoundingClientRect();
91 var parentRect = this.getPopupParent().getBoundingClientRect();
92 this.positionPopup({
93 ePopup: params.ePopup,
94 minWidth: params.minWidth,
95 nudgeX: params.nudgeX,
96 nudgeY: params.nudgeY,
97 x: sourceRect.left - parentRect.left,
98 y: sourceRect.top - parentRect.top + sourceRect.height,
99 keepWithinBounds: params.keepWithinBounds
100 });
101 this.callPostProcessPopup(params.ePopup, params.eventSource, null, params.type, params.column, params.rowNode);
102 };
103 PopupService.prototype.callPostProcessPopup = function (ePopup, eventSource, mouseEvent, type, column, rowNode) {
104 var callback = this.gridOptionsWrapper.getPostProcessPopupFunc();
105 if (callback) {
106 var params = {
107 column: column,
108 rowNode: rowNode,
109 ePopup: ePopup,
110 type: type,
111 eventSource: eventSource,
112 mouseEvent: mouseEvent
113 };
114 callback(params);
115 }
116 };
117 PopupService.prototype.positionPopupOverComponent = function (params) {
118 var sourceRect = params.eventSource.getBoundingClientRect();
119 var parentRect = this.getPopupParent().getBoundingClientRect();
120 this.positionPopup({
121 ePopup: params.ePopup,
122 minWidth: params.minWidth,
123 nudgeX: params.nudgeX,
124 nudgeY: params.nudgeY,
125 x: sourceRect.left - parentRect.left,
126 y: sourceRect.top - parentRect.top,
127 keepWithinBounds: params.keepWithinBounds
128 });
129 this.callPostProcessPopup(params.ePopup, params.eventSource, null, params.type, params.column, params.rowNode);
130 };
131 PopupService.prototype.positionPopup = function (params) {
132 var x = params.x;
133 var y = params.y;
134 if (params.nudgeX) {
135 x += params.nudgeX;
136 }
137 if (params.nudgeY) {
138 y += params.nudgeY;
139 }
140 // if popup is overflowing to the bottom, move it up
141 if (params.keepWithinBounds) {
142 x = this.keepXWithinBounds(params, x);
143 y = this.keepYWithinBounds(params, y);
144 }
145 params.ePopup.style.left = x + "px";
146 params.ePopup.style.top = y + "px";
147 };
148 PopupService.prototype.keepYWithinBounds = function (params, y) {
149 var parentRect = this.getPopupParent().getBoundingClientRect();
150 var minHeight;
151 if (params.ePopup.clientHeight > 0) {
152 minHeight = params.ePopup.clientHeight;
153 }
154 else {
155 minHeight = 200;
156 }
157 var heightOfParent = parentRect.bottom - parentRect.top;
158 var maxY = heightOfParent - minHeight - 5;
159 if (y > maxY) {
160 return maxY;
161 }
162 else if (y < 0) {
163 return 0;
164 }
165 else {
166 return y;
167 }
168 };
169 PopupService.prototype.keepXWithinBounds = function (params, x) {
170 var parentRect = this.getPopupParent().getBoundingClientRect();
171 var minWidth;
172 if (params.minWidth > 0) {
173 minWidth = params.minWidth;
174 }
175 else if (params.ePopup.clientWidth > 0) {
176 minWidth = params.ePopup.clientWidth;
177 }
178 else {
179 minWidth = 200;
180 }
181 var widthOfParent = parentRect.right - parentRect.left;
182 var maxX = widthOfParent - minWidth - 5;
183 if (x > maxX) {
184 return maxX;
185 }
186 else if (x < 0) {
187 return 0;
188 }
189 else {
190 return x;
191 }
192 };
193 //adds an element to a div, but also listens to background checking for clicks,
194 //so that when the background is clicked, the child is removed again, giving
195 //a model look to popups.
196 PopupService.prototype.addAsModalPopup = function (eChild, closeOnEsc, closedCallback, click) {
197 var _this = this;
198 var eBody = this.gridOptionsWrapper.getDocument();
199 if (!eBody) {
200 console.warn('ag-grid: could not find the body of the document, document.body is empty');
201 return;
202 }
203 eChild.style.top = '0px';
204 eChild.style.left = '0px';
205 var popupAlreadyShown = utils_1.Utils.isVisible(eChild);
206 if (popupAlreadyShown) {
207 return;
208 }
209 var ePopupParent = this.getPopupParent();
210 // add env CSS class to child, in case user provided a popup parent, which means
211 // theme class may be missing
212 var eWrapper = document.createElement('div');
213 utils_1.Utils.addCssClass(eWrapper, this.environment.getTheme());
214 eWrapper.appendChild(eChild);
215 ePopupParent.appendChild(eWrapper);
216 this.activePopupElements.push(eChild);
217 var popupHidden = false;
218 var hidePopupOnKeyboardEvent = function (event) {
219 var key = event.which || event.keyCode;
220 if (key === constants_1.Constants.KEY_ESCAPE) {
221 hidePopup(null);
222 }
223 };
224 var hidePopupOnMouseEvent = function (event) {
225 hidePopup(event);
226 };
227 var hidePopupOnTouchEvent = function (event) {
228 hidePopup(null, event);
229 };
230 var hidePopup = function (mouseEvent, touchEvent) {
231 // we don't hide popup if the event was on the child, or any
232 // children of this child
233 if (_this.isEventFromCurrentPopup(mouseEvent, touchEvent, eChild)) {
234 return;
235 }
236 // if the event to close is actually the open event, then ignore it
237 if (_this.isEventSameChainAsOriginalEvent(click, mouseEvent, touchEvent)) {
238 return;
239 }
240 // this method should only be called once. the client can have different
241 // paths, each one wanting to close, so this method may be called multiple times.
242 if (popupHidden) {
243 return;
244 }
245 popupHidden = true;
246 ePopupParent.removeChild(eWrapper);
247 utils_1.Utils.removeFromArray(_this.activePopupElements, eChild);
248 eBody.removeEventListener('keydown', hidePopupOnKeyboardEvent);
249 eBody.removeEventListener('click', hidePopupOnMouseEvent);
250 eBody.removeEventListener('touchstart', hidePopupOnTouchEvent);
251 eBody.removeEventListener('contextmenu', hidePopupOnMouseEvent);
252 if (closedCallback) {
253 closedCallback();
254 }
255 };
256 // if we add these listeners now, then the current mouse
257 // click will be included, which we don't want
258 setTimeout(function () {
259 if (closeOnEsc) {
260 eBody.addEventListener('keydown', hidePopupOnKeyboardEvent);
261 }
262 eBody.addEventListener('click', hidePopupOnMouseEvent);
263 eBody.addEventListener('touchstart', hidePopupOnTouchEvent);
264 eBody.addEventListener('contextmenu', hidePopupOnMouseEvent);
265 }, 0);
266 return hidePopup;
267 };
268 PopupService.prototype.isEventFromCurrentPopup = function (mouseEvent, touchEvent, eChild) {
269 var event = mouseEvent ? mouseEvent : touchEvent;
270 if (event) {
271 var indexOfThisChild = this.activePopupElements.indexOf(eChild);
272 for (var i = indexOfThisChild; i < this.activePopupElements.length; i++) {
273 var element = this.activePopupElements[i];
274 if (utils_1.Utils.isElementInEventPath(element, event)) {
275 return true;
276 }
277 }
278 }
279 return false;
280 };
281 // in some browsers, the context menu event can be fired before the click event, which means
282 // the context menu event could open the popup, but then the click event closes it straight away.
283 PopupService.prototype.isEventSameChainAsOriginalEvent = function (originalClick, mouseEvent, touchEvent) {
284 // we check the coordinates of the event, to see if it's the same event. there is a 1 / 1000 chance that
285 // the event is a different event, however that is an edge case that is not very relevant (the user clicking
286 // twice on the same location isn't a normal path).
287 // event could be mouse event or touch event.
288 var mouseEventOrTouch;
289 if (mouseEvent) {
290 // mouse event can be used direction, it has coordinates
291 mouseEventOrTouch = mouseEvent;
292 }
293 else if (touchEvent) {
294 // touch event doesn't have coordinates, need it's touch object
295 mouseEventOrTouch = touchEvent.touches[0];
296 }
297 if (mouseEventOrTouch && originalClick) {
298 // for x, allow 4px margin, to cover iPads, where touch (which opens menu) is followed
299 // by browser click (when you life finger up, touch is interrupted as click in browser)
300 var xMatch = Math.abs(originalClick.screenX - mouseEvent.screenX) < 5;
301 var yMatch = Math.abs(originalClick.screenY - mouseEvent.screenY) < 5;
302 if (xMatch && yMatch) {
303 return true;
304 }
305 }
306 return false;
307 };
308 __decorate([
309 context_1.Autowired('gridCore'),
310 __metadata("design:type", gridCore_1.GridCore)
311 ], PopupService.prototype, "gridCore", void 0);
312 __decorate([
313 context_1.Autowired('gridOptionsWrapper'),
314 __metadata("design:type", gridOptionsWrapper_1.GridOptionsWrapper)
315 ], PopupService.prototype, "gridOptionsWrapper", void 0);
316 __decorate([
317 context_1.Autowired('environment'),
318 __metadata("design:type", environment_1.Environment)
319 ], PopupService.prototype, "environment", void 0);
320 PopupService = __decorate([
321 context_1.Bean('popupService')
322 ], PopupService);
323 return PopupService;
324}());
325exports.PopupService = PopupService;