PageSourceSearch

https://eternarussia.ru/bitrix/js/ui/notification/ui.notification.stack.js?17469568848731

js eternarussia.ru collected 2026-10-08 09:22:22 UTC 8,731 bytes, 443 lines download raw bytes

1(function() {
2
3"use strict";
4
5BX.namespace("BX.UI.Notification");
6
7/**
8 *
9 * @enum {string}
10 */
11BX.UI.Notification.Position = {
12	TOP_LEFT: "top-left",
13	TOP_CENTER: "top-center",
14	TOP_RIGHT: "top-right",
15	BOTTOM_LEFT: "bottom-left",
16	BOTTOM_CENTER: "bottom-center",
17	BOTTOM_RIGHT: "bottom-right"
18};
19
20/**
21 * @typedef {object} BX.UI.Notification.StackOptions
22 * @property {BX.UI.Notification.Position} [position]
23 * @property {number} [spacing=20]
24 * @property {number} [offsetX=25]
25 * @property {number} [offsetY=25]
26 * @property {boolean} [newestOnTop=false]
27 * @property {string} [balloonType]
28 * @property {string} [id]
29 */
30
31/**
32 *
33 * @param {BX.UI.Notification.StackOptions} options
34 * @constructor
35 */
36BX.UI.Notification.Stack = function(options)
37{
38	options = BX.type.isPlainObject(options) ? options : Object.create(null);
39
40	/**
41	 *
42	 * @type {BX.UI.Notification.Balloon[]}
43	 */
44	this.balloons = [];
45
46	/**
47	 *
48	 * @type {BX.UI.Notification.Balloon[]}
49	 */
50	this.queueStack = [];
51
52	this.id = BX.type.isNotEmptyString(options.id) ? options.id : BX.util.getRandomString(8).toLowerCase();
53	this.position = BX.UI.Notification.Stack.getPositionCode(options.position) ? options.position : "top-right";
54
55	this.spacing = 20;
56	this.offsetX = 25;
57	this.offsetY = 25;
58	this.newestOnTop = false;
59	this.balloonType = BX.UI.Notification.Balloon;
60
61	this.setOptions(options);
62
63	BX.addCustomEvent(BX.UI.Notification.Event.getFullName("onClose"), this.handleBalloonClose.bind(this));
64};
65
66BX.UI.Notification.Stack.getPositionCode = function(position)
67{
68	for (var code in BX.UI.Notification.Position)
69	{
70		if (BX.UI.Notification.Position[code] === position)
71		{
72			return code;
73		}
74	}
75
76	return null;
77};
78
79BX.UI.Notification.Stack.prototype =
80{
81	/**
82	 * @public
83	 * @param {BX.UI.Notification.Balloon} [balloon]
84	 */
85	adjustPosition: function(balloon)
86	{
87		var offset = 0;
88		this.getBalloons().forEach(function(currentBalloon) {
89
90			if (!balloon || balloon === currentBalloon)
91			{
92				if (currentBalloon.doNotAdjustPosition)
93				{
94					return;
95				}
96
97				switch (this.getPosition())
98				{
99					case BX.UI.Notification.Position.TOP_LEFT:
100						currentBalloon.getContainer().style.left = this.getOffsetX() + "px";
101						currentBalloon.getContainer().style.top = offset + this.getOffsetY() + "px";
102						break;
103					case BX.UI.Notification.Position.TOP_CENTER:
104						currentBalloon.getContainer().style.left = "50%";
105						currentBalloon.getContainer().style.transform = "translateX(-50%)";
106						currentBalloon.getContainer().style.top = offset + this.getOffsetY() + "px";
107						break;
108					case BX.UI.Notification.Position.TOP_RIGHT:
109						currentBalloon.getContainer().style.right = this.getOffsetX() + "px";
110						currentBalloon.getContainer().style.top = offset + this.getOffsetY() + "px";
111						break;
112					case BX.UI.Notification.Position.BOTTOM_LEFT:
113						currentBalloon.getContainer().style.left = this.getOffsetX() + "px";
114						currentBalloon.getContainer().style.bottom = offset + this.getOffsetY() + "px";
115						break;
116					case BX.UI.Notification.Position.BOTTOM_CENTER:
117						currentBalloon.getContainer().style.left = "50%";
118						currentBalloon.getContainer().style.transform = "translateX(-50%)";
119						currentBalloon.getContainer().style.bottom = offset + this.getOffsetY() + "px";
120						break;
121					case BX.UI.Notification.Position.BOTTOM_RIGHT:
122						currentBalloon.getContainer().style.right = this.getOffsetX() + "px";
123						currentBalloon.getContainer().style.bottom = offset + this.getOffsetY() + "px";
124						break;
125				}
126			}
127
128			offset += this.getSpacing() + currentBalloon.getHeight();
129
130		}, this);
131
132	},
133
134	/**
135	 * @public
136	 * @param {BX.UI.Notification.Balloon} balloon
137	 */
138	add: function(balloon)
139	{
140		if (this.getBalloons().length > 0 && (this.getQueue().length > 0 || !this.isBalloonFitToViewport(balloon)))
141		{
142			this.queue(balloon);
143		}
144		else
145		{
146			this.push(balloon);
147		}
148	},
149
150	clear()
151	{
152		const balloons = [...this.balloons, ...this.queueStack];
153		this.queueStack = [];
154		this.balloons = [];
155
156		balloons.forEach((balloon) => {
157			return balloon.close();
158		});
159	},
160
161	/**
162	 * @private
163	 * @param {BX.UI.Notification.Balloon} balloon
164	 */
165	push: function(balloon)
166	{
167		if (!(balloon instanceof BX.UI.Notification.Balloon))
168		{
169			throw new Error("'balloon' must be an instance of BX.UI.Notification.Balloon.");
170		}
171
172		if (this.balloons.indexOf(balloon) === -1)
173		{
174			if (this.isNewestOnTop())
175			{
176				this.balloons.splice(0, 0, balloon);
177			}
178			else
179			{
180				this.balloons.push(balloon);
181			}
182		}
183	},
184
185	/**
186	 * @private
187	 * @param {BX.UI.Notification.Balloon} balloon
188	 */
189	queue: function(balloon)
190	{
191		if (!(balloon instanceof BX.UI.Notification.Balloon))
192		{
193			throw new Error("'balloon' must be an instance of BX.UI.Notification.Balloon.");
194		}
195
196		if (this.queueStack.indexOf(balloon) === -1)
197		{
198			balloon.setState(BX.UI.Notification.State.QUEUED);
199			this.queueStack.push(balloon);
200		}
201	},
202
203	/**
204	 * @private
205	 */
206	checkQueue: function()
207	{
208		var queue = this.queueStack.slice();
209		for (var i = 0; i < queue.length; i++)
210		{
211			var balloon = queue[i];
212			if (!this.isBalloonFitToViewport(balloon) && this.getBalloons().length > 0)
213			{
214				break;
215			}
216
217			balloon.setState(BX.UI.Notification.State.INIT);
218			this.queueStack.shift();
219			this.push(balloon);
220
221			balloon.show();
222		}
223	},
224
225	/**
226	 * @private
227	 * @return {BX.UI.Notification.Balloon[]}
228	 */
229	getQueue: function()
230	{
231		return this.queueStack;
232	},
233
234	/**
235	 * @private
236	 * @param {BX.UI.Notification.Balloon} balloon
237	 * @return {boolean}
238	 */
239	isBalloonFitToViewport: function(balloon)
240	{
241		var viewportHeight = document.documentElement.clientHeight;
242		var balloonHeight = this.getSpacing() + balloon.getHeight();
243
244		return this.getHeight() + balloonHeight <= viewportHeight;
245	},
246
247	/**
248	 * @private
249	 * @param {BX.UI.Notification.Event} event
250	 */
251	handleBalloonClose: function(event)
252	{
253		const closingBalloon = event.getBalloon();
254		if (closingBalloon.getStack() !== this)
255		{
256			return;
257		}
258
259		this.balloons = this.balloons.filter((balloon) => {
260			return closingBalloon !== balloon;
261		});
262
263		this.adjustPosition();
264		this.checkQueue();
265	},
266
267	/**
268	 * @package
269	 * @param {BX.UI.Notification.StackOptions} options
270	 */
271	setOptions: function(options)
272	{
273		options = options || {};
274
275		this.setSpacing(options.spacing);
276		this.setOffsetX(options.offsetX);
277		this.setOffsetY(options.offsetY);
278		this.setNewestOnTop(options.newestOnTop);
279		this.setBalloonType(options.balloonType);
280	},
281
282	/**
283	 *
284	 * @return {string}
285	 */
286	getId: function()
287	{
288		return this.id;
289	},
290
291	/**
292	 * @public
293	 * @return {BX.UI.Notification.Balloon[]}
294	 */
295	getBalloons: function()
296	{
297		return this.balloons;
298	},
299
300	/**
301	 * @public
302	 * @return {BX.UI.Notification.Position}
303	 */
304	getPosition: function()
305	{
306		return this.position;
307	},
308
309	/**
310	 * @public
311	 * @return {number}
312	 */
313	getSpacing: function()
314	{
315		return this.spacing;
316	},
317
318	/**
319	 * @public
320	 * @param {number} spacing
321	 */
322	setSpacing: function(spacing)
323	{
324		if (BX.type.isNumber(spacing))
325		{
326			this.spacing = spacing;
327		}
328	},
329
330	/**
331	 * @public
332	 * @return {number}
333	 */
334	getOffsetX: function()
335	{
336		return this.offsetX;
337	},
338
339	/**
340	 * @public
341	 * @param {number} offsetX
342	 */
343	setOffsetX: function(offsetX)
344	{
345		if (BX.type.isNumber(offsetX))
346		{
347			this.offsetX = offsetX;
348		}
349	},
350
351	/**
352	 * @public
353	 * @return {number}
354	 */
355	getOffsetY: function()
356	{
357		return this.offsetY;
358	},
359
360	/**
361	 * @public
362	 * @param {number} offsetY
363	 */
364	setOffsetY: function(offsetY)
365	{
366		if (BX.type.isNumber(offsetY))
367		{
368			this.offsetY = offsetY;
369		}
370	},
371
372	/**
373	 * @public
374	 * @return {number}
375	 */
376	getHeight: function()
377	{
378		return this.getBalloons().reduce(function(height, balloon) {
379			return height + balloon.getHeight() + this.getSpacing();
380		}.bind(this), this.getOffsetY());
381	},
382
383	/**
384	 *
385	 * @param {string} [className]
386	 * @return {BX.UI.Notification.Balloon}
387	 */
388	getBalloonType: function(className)
389	{
390		if (BX.type.isFunction(className))
391		{
392			return className;
393		}
394
395		var classFn = BX.getClass(className);
396
397		if (BX.type.isFunction(classFn))
398		{
399			return classFn;
400		}
401
402		return this.balloonType || BX.UI.Notification.Balloon;
403	},
404
405	setBalloonType: function(balloonType)
406	{
407		if (BX.type.isFunction(balloonType))
408		{
409			this.balloonType = balloonType;
410		}
411		else if (BX.type.isNotEmptyString(balloonType))
412		{
413			var classFn = BX.getClass(balloonType);
414			if (BX.type.isFunction(classFn))
415			{
416				this.balloonType = classFn;
417			}
418		}
419	},
420
421	/**
422	 * @public
423	 * @return {boolean}
424	 */
425	isNewestOnTop: function()
426	{
427		return this.newestOnTop;
428	},
429
430	/**
431	 * @public
432	 * @param {boolean} onTop
433	 */
434	setNewestOnTop: function(onTop)
435	{
436		if (BX.type.isBoolean(onTop))
437		{
438			this.newestOnTop = onTop;
439		}
440	}
441};
442
443}
vendor: 5 bytes, line 443
443)();

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.